Add Arrowheads to Arrows (#2452)

Co-authored-by: dwelle <luzar.david@gmail.com>
Co-authored-by: Lipis <lipiridis@gmail.com>
This commit is contained in:
Steve Ruiz 2020-12-08 15:02:55 +00:00 committed by GitHub
parent bd8e860d7f
commit c291edfc44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 711 additions and 101 deletions

View file

@ -4,15 +4,19 @@ import {
ExcalidrawTextElement,
TextAlign,
FontFamily,
ExcalidrawLinearElement,
Arrowhead,
} from "../element/types";
import {
getCommonAttributeOfSelectedElements,
isSomeElementSelected,
getTargetElements,
canChangeSharpness,
canHaveArrowheads,
} from "../scene";
import { ButtonSelect } from "../components/ButtonSelect";
import { ButtonIconSelect } from "../components/ButtonIconSelect";
import { ButtonIconCycle } from "../components/ButtonIconCycle";
import {
isTextElement,
redrawTextBoundingBox,
@ -39,6 +43,7 @@ import {
SloppinessArchitectIcon,
SloppinessArtistIcon,
SloppinessCartoonistIcon,
ArrowArrowheadIcon,
} from "../components/icons";
import { EVENT_CHANGE, trackEvent } from "../analytics";
import colors from "../colors";
@ -622,3 +627,110 @@ export const actionChangeSharpness = register({
</fieldset>
),
});
export const actionChangeArrowhead = register({
name: "changeArrowhead",
perform: (
elements,
appState,
value: { position: "start" | "end"; type: Arrowhead },
) => {
return {
elements: changeProperty(elements, appState, (el) => {
if (isLinearElement(el)) {
trackEvent(
EVENT_CHANGE,
`arrowhead ${value.position}`,
value.type || "none",
);
const { position, type } = value;
if (position === "start") {
const element: ExcalidrawLinearElement = newElementWith(el, {
startArrowhead: type,
});
return element;
} else if (position === "end") {
const element: ExcalidrawLinearElement = newElementWith(el, {
endArrowhead: type,
});
return element;
}
}
return el;
}),
appState: {
...appState,
currentItemArrowheads: {
...appState.currentItemArrowheads,
[value.position]: value.type,
},
},
commitToHistory: true,
};
},
PanelComponent: ({ elements, appState, updateData }) => (
<fieldset>
<legend>{t("labels.arrowheads")}</legend>
<div className="buttonList buttonListIcon">
<ButtonIconCycle
group="arrowhead_start"
options={[
{
value: null,
text: t("labels.arrowhead_none"),
icon: <StrokeStyleSolidIcon appearance={appState.appearance} />,
},
{
value: "arrow",
text: t("labels.arrowhead_arrow"),
icon: (
<ArrowArrowheadIcon
appearance={appState.appearance}
flip={true}
/>
),
},
]}
value={getFormValue<Arrowhead | null>(
elements,
appState,
(element) =>
isLinearElement(element) && canHaveArrowheads(element.type)
? element.startArrowhead
: appState.currentItemArrowheads.start,
appState.currentItemArrowheads.start,
)}
onChange={(value) => updateData({ position: "start", type: value })}
/>
<ButtonIconCycle
group="arrowhead_end"
options={[
{
value: null,
text: t("labels.arrowhead_none"),
icon: <StrokeStyleSolidIcon appearance={appState.appearance} />,
},
{
value: "arrow",
text: t("labels.arrowhead_arrow"),
icon: <ArrowArrowheadIcon appearance={appState.appearance} />,
},
]}
value={getFormValue<Arrowhead | null>(
elements,
appState,
(element) =>
isLinearElement(element) && canHaveArrowheads(element.type)
? element.endArrowhead
: appState.currentItemArrowheads.end,
appState.currentItemArrowheads.end,
)}
onChange={(value) => updateData({ position: "end", type: value })}
/>
</div>
</fieldset>
),
});

View file

@ -35,6 +35,7 @@ export type ActionName =
| "changeStrokeWidth"
| "changeSloppiness"
| "changeStrokeStyle"
| "changeArrowhead"
| "changeOpacity"
| "changeFontSize"
| "toggleCanvasMenu"
@ -99,9 +100,7 @@ export interface Action {
}
export interface ActionsManagerInterface {
actions: {
[actionName in ActionName]: Action;
};
actions: Record<ActionName, Action>;
registerAction: (action: Action) => void;
handleKeyDown: (event: KeyboardEvent) => boolean;
getContextMenuItems: (