Skip to content

Commit

Permalink
ability to move and set properties for multiple selected elements
Browse files Browse the repository at this point in the history
  • Loading branch information
williamstein committed Feb 3, 2022
1 parent ade1dfe commit 8efe74d
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 24 deletions.
35 changes: 34 additions & 1 deletion src/packages/frontend/frame-editors/whiteboard-editor/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
useRef,
useState,
} from "react";
import { Element, Point } from "./types";
import { Element, ElementType, Point } from "./types";
import { Tool, TOOLS } from "./tools/spec";
import RenderElement from "./elements/render";
import Focused, { SELECTED_BORDER_COLOR } from "./focused";
Expand Down Expand Up @@ -256,6 +256,8 @@ export default function Canvas({
key={id}
canvasScale={canvasScale}
element={element}
allElements={elements}
selectedElements={[element]}
transforms={transforms}
>
{elt}
Expand Down Expand Up @@ -289,6 +291,37 @@ export default function Canvas({
v.push(processElement(element));
}

if (selection != null && selection.size > 1) {
// create a virtual selection element that
// contains the region spanned by all elements
// in the selection.
// TODO: This could be optimized with better data structures...
const selectedElements = elements.filter((element) =>
selection.has(element.id)
);
const { xMin, yMin, xMax, yMax } = getPageSpan(selectedElements, 0);
const element = {
type: "selection" as ElementType,
id: "selection",
x: xMin,
y: yMin,
w: xMax - xMin + 1,
h: yMax - yMin + 1,
};
v.push(
<Focused
key={"selection"}
canvasScale={canvasScale}
element={element}
allElements={elements}
selectedElements={selectedElements}
transforms={transforms}
>
<RenderElement element={element} canvasScale={canvasScale} focused />
</Focused>
);
}

if (isNavigator) {
// The navigator rectangle
const visible = frame.desc.get("visibleWindow")?.toJS();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Frame from "./frame";
import Generic from "./generic";
import Pen from "./pen";
import Stopwatch from "./stopwatch";
import Selection from "./selection";

interface Props {
element: Element;
Expand All @@ -33,6 +34,8 @@ export default function Render(props: Props) {
return <Pen {...props} />;
case "stopwatch":
return <Stopwatch {...props} />;
case "selection":
return <Selection {...props} />;
default:
return <Generic {...props} />;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SELECTED_BORDER_COLOR } from "../focused";

export default function Selection({ canvasScale }) {
return (
<div
style={{
border: `${2 / canvasScale}px solid ${SELECTED_BORDER_COLOR}`,
width: "100%",
height: "100%",
}}
></div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,25 @@ export default function DragHandle({
setOffset,
canvasScale,
element,
selectedElements,
}: {
top: boolean;
left: boolean;
setOffset: (offset: { x: number; y: number; w: number; h: number }) => void;
canvasScale: number;
element: Element;
selectedElements: Element[];
}) {
const [position, setPosition] = useState<{ x: number; y: number }>({
x: 0,
y: 0,
});
const frame = useFrameContext();

if (selectedElements.length > 1) {
return null;
}

const style = {
pointerEvents: "all", // because we turn off pointer events for containing div
cursor: dragHandleCursors[`${top}-${left}`],
Expand Down
18 changes: 13 additions & 5 deletions src/packages/frontend/frame-editors/whiteboard-editor/focused.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ interface Props {
children: ReactNode;
canvasScale: number;
element: Element;
selectedElements: Element[];
allElements: Element[];
transforms;
}

export default function Focused({
children,
canvasScale,
element,
selectedElements,
transforms,
allElements,
}: Props) {
const frame = useFrameContext();
const rectRef = useRef<any>(null);
Expand Down Expand Up @@ -72,6 +76,7 @@ export default function Focused({
left={left}
canvasScale={canvasScale}
element={element}
selectedElements={selectedElements}
setOffset={setOffset}
/>
);
Expand Down Expand Up @@ -120,6 +125,7 @@ export default function Focused({
}
}
setTimeout(() => {
if (id == "selection") return; // todo
frame.actions.setElement({ id, rotate });
setRotating(undefined);
}, 0);
Expand Down Expand Up @@ -198,7 +204,7 @@ export default function Focused({
transformOrigin: "top left",
}}
>
<EditBar elements={[element]} />
<EditBar elements={selectedElements} allElements={allElements} />
</div>
</div>
<Draggable
Expand All @@ -210,10 +216,12 @@ export default function Focused({
}}
onStop={(_, data) => {
setDragging(false);
const { id } = element;
const x = element.x + data.x;
const y = element.y + data.y;
frame.actions.setElement({ id, x, y });
for (const elt of selectedElements) {
const { id } = elt;
const x = elt.x + data.x;
const y = elt.y + data.y;
frame.actions.setElement({ id, x, y });
}
}}
>
<div
Expand Down
20 changes: 10 additions & 10 deletions src/packages/frontend/frame-editors/whiteboard-editor/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ export function getPageSpan(
zMin: number;
zMax: number;
} {
let xMin = 0,
yMin = 0,
xMax = 0,
yMax = 0,
zMin = 0,
zMax = 0;
for (const element of elements) {
const x = element.x ?? 0;
const y = element.y ?? 0;
const z = element.z ?? 0;
let xMin = elements[0]?.x ?? 0,
xMax = elements[0]?.x ?? 0,
yMin = elements[0]?.y ?? 0,
yMax = elements[0]?.y ?? 0,
zMin = elements[0]?.z ?? 0,
zMax = elements[0]?.z ?? 0;
for (const element of elements.slice(1)) {
const x = element.x ?? xMin;
const y = element.y ?? yMin;
const z = element.z ?? zMin;
const w = element.w ?? DEFAULT_WIDTH;
const h = element.h ?? DEFAULT_HEIGHT;
if (x < xMin) xMin = x;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Props {
}

export default function Position({ children, x, y, z, w, h, style }: Props) {
console.log("z = ", z);
const posStyle: CSSProperties = {
position: "absolute",
left: x,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import {
} from "./defaults";

interface Props {
elements: Element[];
elements: Element[]; // selected ones
allElements: Element[]; // all of them
}

export default function EditBar({ elements }: Props) {
export default function EditBar({ elements, allElements }: Props) {
const { actions } = useFrameContext();
if (elements.length == 0) return null;
return (
Expand All @@ -44,7 +45,11 @@ export default function EditBar({ elements }: Props) {
<FontSize actions={actions} elements={elements} />
<ColorButton actions={actions} elements={elements} />
<DeleteButton actions={actions} elements={elements} />
<OtherOperations actions={actions} elements={elements} />
<OtherOperations
actions={actions}
elements={elements}
allElements={allElements}
/>
</div>
</div>
);
Expand Down Expand Up @@ -225,13 +230,13 @@ function getFontFamily(elements: Element[]): string | undefined {
return DEFAULT_FONT_FAMILY;
}

function OtherOperations({ actions, elements }: ButtonProps) {
function OtherOperations({ actions, elements, allElements }) {
const frame = useFrameContext();
const menu = (
<Menu
onClick={({ key }) => {
if (key == "bring-to-front") {
const { zMax } = getPageSpan(elements);
const { zMax } = getPageSpan(allElements);
let z = zMax + 1;
for (const element of elements) {
actions.setElement({ ...element, z }, false);
Expand All @@ -240,9 +245,8 @@ function OtherOperations({ actions, elements }: ButtonProps) {
actions.syncstring_commit();
actions.clearSelection(frame.id);
} else if (key == "send-to-back") {
const { zMin } = getPageSpan(elements);
const { zMin } = getPageSpan(allElements);
let z = zMin - 1;
console.log("zMin = ", zMin, " z = ", z);
for (const element of elements) {
actions.setElement({ ...element, z }, false);
z -= 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export type ElementType =
| "terminal"
| "stopwatch"
| "timer"
| "frame";
| "frame"
| "selection";

export type Point = { x: number; y: number };

Expand Down

0 comments on commit 8efe74d

Please sign in to comment.