Skip to content

Commit

Permalink
can now resize notes using their handles
Browse files Browse the repository at this point in the history
  • Loading branch information
EliCDavis committed Sep 8, 2024
1 parent cf1ce61 commit ec60b25
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 51 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
## Editting
*Right-click* on this note and select "Edit Note > Contents" to put your text here!
*Right-click* on this note and select "Edit Note" to put your text here!
## Support
Expand Down
102 changes: 78 additions & 24 deletions src/notes/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ export interface FlowNoteConfig {
width?: number;
}

export enum DragHandle {
None,
Left,
Right
};

const boundsSpacing = 20;
const boxSize = 10;

export class FlowNote {

#originalText: string;
Expand All @@ -30,21 +39,24 @@ export class FlowNote {

#position: Vector2;

#lastMousePosition: Vector2;
#handleSelected: DragHandle;

#edittingLayout: boolean;

#lastRenderedBox: Box;

#hovering: boolean;

// ========================================================================

constructor(config?: FlowNoteConfig) {
this.#hovering = false;
this.#edittingLayout = false;
this.#width = config?.width === undefined ? 500 : config.width;
this.#position = config?.position === undefined ? { x: 0, y: 0 } : config.position;
this.#lastMousePosition = { x: 0, y: 0 }
this.setText(config?.text === undefined ? "" : config?.text);
this.#lastRenderedBox = { Position: { x: 0, y: 0 }, Size: { x: 0, y: 0 } };
this.#handleSelected = DragHandle.None;

this.#edittingStyle = new BoxStyle({
border: {
Expand All @@ -64,35 +76,43 @@ export class FlowNote {
this.#position.y += delta.y;
}

handleSelected(): DragHandle {
return this.#handleSelected;
}

selectHandle(handle: DragHandle): void {
this.#handleSelected = handle;
}

#tempPosition: Vector2 = { x: 0, y: 0 };

render(ctx: CanvasRenderingContext2D, graphPosition: Vector2, scale: number, mousePosition: Vector2 | undefined): void {
if (this.#edittingLayout) {
if (this.#edittingLayout && (this.#hovering || this.#handleSelected !== DragHandle.None)) {

if (mousePosition) {
CopyVector2(this.#lastMousePosition, mousePosition);
this.#width = Math.max(mousePosition.x - (this.#position.x + graphPosition.x), 1)
}
if (this.#handleSelected === DragHandle.Right) {

const leftPosition = (this.#position.x * scale) + graphPosition.x;
this.#width = Math.max((mousePosition.x - leftPosition) / scale, 1)

const boxSize = 10;
const spacing = 20;
} else if (this.#handleSelected === DragHandle.Left) {

const smallBox: Box = {
Position: {
x: this.#lastRenderedBox.Position.x - spacing - (boxSize / 2),
y: this.#lastRenderedBox.Position.y + (this.#lastRenderedBox.Size.y / 2) - (boxSize / 2),
},
Size: { x: boxSize, y: boxSize, }
const scaledWidth = this.#width * scale;
const rightPosition = (this.#position.x * scale) + graphPosition.x + scaledWidth;
this.#width = Math.max((rightPosition - mousePosition.x) / scale, 1)
this.#position.x = rightPosition - (this.#width * scale) - graphPosition.x;
this.#position.x /= scale;
}
}
this.#edittingStyle.Outline(ctx, smallBox, scale, 2);
smallBox.Position.x += this.#lastRenderedBox.Size.x + (spacing * 2);
this.#edittingStyle.Outline(ctx, smallBox, scale, 2);

this.#edittingStyle.Outline(ctx, this.leftResizeHandleBox(), scale, 2);
this.#edittingStyle.Outline(ctx, this.rightResizeHandleBox(), scale, 2);

ctx.beginPath();
const left = this.#lastRenderedBox.Position.x - spacing;
const right = this.#lastRenderedBox.Position.x + spacing + this.#lastRenderedBox.Size.x;
const bottom = this.#lastRenderedBox.Position.y - spacing;
const top = this.#lastRenderedBox.Position.y + spacing + this.#lastRenderedBox.Size.y;
const left = this.#lastRenderedBox.Position.x;
const right = this.#lastRenderedBox.Position.x + this.#lastRenderedBox.Size.x;
const bottom = this.#lastRenderedBox.Position.y;
const top = this.#lastRenderedBox.Position.y + this.#lastRenderedBox.Size.y;
ctx.moveTo(left, bottom + (this.#lastRenderedBox.Size.y / 2) - (boxSize));
ctx.lineTo(left, bottom);
ctx.lineTo(right, bottom);
Expand Down Expand Up @@ -120,8 +140,38 @@ export class FlowNote {
this.#tempPosition.y += text.render(ctx, this.#tempPosition, scale, this.#width) + lineSpacing;
}

this.#lastRenderedBox.Size.x = scale * this.#width;
this.#lastRenderedBox.Size.y = this.#tempPosition.y - startY;
this.#lastRenderedBox.Position.x -= boundsSpacing
this.#lastRenderedBox.Position.y -= boundsSpacing
this.#lastRenderedBox.Size.x = scale * this.#width + (boundsSpacing * 2);
this.#lastRenderedBox.Size.y = this.#tempPosition.y - startY + (boundsSpacing * 2);
}

leftResizeHandleBox(): Box {
return {
Position: {
x: this.#lastRenderedBox.Position.x - (boxSize / 2),
y: this.#lastRenderedBox.Position.y + (this.#lastRenderedBox.Size.y / 2) - (boxSize / 2),
},
Size: { x: boxSize, y: boxSize, }
};
}

rightResizeHandleBox(): Box {
return {
Position: {
x: this.#lastRenderedBox.Position.x - (boxSize / 2) + this.#lastRenderedBox.Size.x,
y: this.#lastRenderedBox.Position.y + (this.#lastRenderedBox.Size.y / 2) - (boxSize / 2),
},
Size: { x: boxSize, y: boxSize, }
};
}

edittingLayout(): boolean {
return this.#edittingLayout;
}

setHovering(hovering): void {
this.#hovering = hovering;
}

editContent(): void {
Expand Down Expand Up @@ -151,7 +201,11 @@ export class FlowNote {
popup.Show();
}

editLayout(): void {
lock(): void {
this.#edittingLayout = false;
}

unlock(): void {
this.#edittingLayout = true;
}

Expand Down
92 changes: 66 additions & 26 deletions src/notes/subsystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { ContextMenuConfig } from "../contextMenu";
import { RenderResults } from "../graphSubsystem";
import { InBox } from "../types/box";
import { Vector2 } from "../types/vector2";
import { FlowNote, FlowNoteConfig } from './note';
import { DragHandle, FlowNote, FlowNoteConfig } from './note';


export class NoteSubsystem {

Expand All @@ -12,9 +13,13 @@ export class NoteSubsystem {

#noteSelected: FlowNote | null;

#hoveringHandle: DragHandle;

constructor(notes?: Array<FlowNoteConfig>) {
this.#hoveringHandle = DragHandle.None;
this.#notes = [];
this.#noteHovering = null;
this.#noteSelected = null;

if (notes !== undefined) {
for (let i = 0; i < notes.length; i++) {
Expand Down Expand Up @@ -49,49 +54,65 @@ export class NoteSubsystem {

if (this.#noteHovering !== null) {
const noteToReview = this.#noteHovering;
result.subMenus?.push({
name: "Edit Note",
group: group,
items: [
{
name: "Contents",
callback: noteToReview.editContent.bind(noteToReview),
},
{
name: "Layout",
callback: noteToReview.editLayout.bind(noteToReview),
result.items?.push(
{
name: "Delete Note",
group: group,
callback: () => {
this.#removeNote(noteToReview);
}
]
});

result.items?.push({
name: "Delete Note",
group: group,
callback: () => {
this.#removeNote(noteToReview);
}
});
},
{
name: "Edit Note",
group: group,
callback: noteToReview.editContent.bind(noteToReview),
},
);

if (!noteToReview.edittingLayout()) {
result.items?.push({
name: "Unlock Note",
group: group,
callback: noteToReview.unlock.bind(noteToReview),
})
} else {
result.items?.push({
name: "Lock Note",
group: group,
callback: noteToReview.lock.bind(noteToReview),
})
}
}

return result;
}

clickStart(mousePosition: Vector2, ctrlKey: boolean): boolean {
if (this.#noteHovering !== null) {
if (this.#noteHovering !== null && this.#noteHovering.edittingLayout()) {
this.#noteSelected = this.#noteHovering;
this.#noteSelected.selectHandle(this.#hoveringHandle);
return true;
}
return false;
}

clickEnd(): void {
if (this.#noteSelected !== null) {
this.#noteSelected.selectHandle(DragHandle.None);
}
this.#noteSelected = null;
}

mouseDragEvent(delta: Vector2, scale: number): boolean {
if (this.#noteSelected === null) {
return false;
}

// Return early so we don't translate since we're moving a drag handle
if (this.#noteSelected.handleSelected()) {
return true;
}

this.#noteSelected.translate({
x: delta.x * (1 / scale),
y: delta.y * (1 / scale)
Expand All @@ -110,15 +131,34 @@ export class NoteSubsystem {

render(ctx: CanvasRenderingContext2D, scale: number, position: Vector2, mousePosition: Vector2 | undefined): RenderResults | undefined {
this.#noteHovering = null;
for (let i = 0; i < this.#notes.length; i++) {
this.#notes[i].render(ctx, position, scale, mousePosition);
this.#hoveringHandle = DragHandle.None;

if (mousePosition) {
// Set hovering to false on everything
if (mousePosition) {
for (let i = 0; i < this.#notes.length; i++) {
this.#notes[i].setHovering(false);
if (InBox(this.#notes[i].bounds(), mousePosition)) {
this.#noteHovering = this.#notes[i];
}
}
}

// The note on top of everything is the one that get's to be in a
// hover state
if (this.#noteHovering != null) {
this.#noteHovering.setHovering(true);
if (mousePosition) {
if (InBox(this.#noteHovering.leftResizeHandleBox(), mousePosition)) {
this.#hoveringHandle = DragHandle.Left;
} else if (InBox(this.#noteHovering.rightResizeHandleBox(), mousePosition)) {
this.#hoveringHandle = DragHandle.Right;
}
}
}

for (let i = 0; i < this.#notes.length; i++) {
this.#notes[i].render(ctx, position, scale, mousePosition);
}
return;
}
}

0 comments on commit ec60b25

Please sign in to comment.