Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag cells to move #1332

Merged
merged 18 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions quadratic-client/src/app/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ interface EventTypes {
resizeHeadingColumn: (column: number) => void;

offlineTransactions: (transactions: number, operations: number) => void;

cellMoving: (move: boolean) => void;
}

export const events = new EventEmitter<EventTypes>();
17 changes: 15 additions & 2 deletions quadratic-client/src/app/gridGL/UI/Cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class Cursor extends Graphics {
startCell: CursorCell;
endCell: CursorCell;

// cursor rectangle for normal cells
cursorRectangle?: Rectangle;

constructor() {
super();
this.indicator = new Rectangle();
Expand Down Expand Up @@ -78,8 +81,14 @@ export class Cursor extends Graphics {
}

// hide cursor if code editor is open and CodeCursor is in the same cell
if (editorInteractionState.showCodeEditor && editor_selected_cell.x === cell.x && editor_selected_cell.y === cell.y)
if (
editorInteractionState.showCodeEditor &&
editor_selected_cell.x === cell.x &&
editor_selected_cell.y === cell.y
) {
this.cursorRectangle = undefined;
return;
}

// draw cursor
this.lineStyle({
Expand All @@ -102,6 +111,9 @@ export class Cursor extends Graphics {
alignment: 1,
});
this.drawRect(x, y, width, height);
this.cursorRectangle = undefined;
} else {
this.cursorRectangle = new Rectangle(x, y, x + width, y + height);
}
}

Expand All @@ -114,12 +126,13 @@ export class Cursor extends Graphics {
this.beginFill(colors.cursorCell, FILL_ALPHA);
this.startCell = sheet.getCellOffsets(cursor.originPosition.x, cursor.originPosition.y);
this.endCell = sheet.getCellOffsets(cursor.terminalPosition.x, cursor.terminalPosition.y);
this.drawRect(
this.cursorRectangle = new Rectangle(
this.startCell.x,
this.startCell.y,
this.endCell.x + this.endCell.width - this.startCell.x,
this.endCell.y + this.endCell.height - this.startCell.y
);
this.drawShape(this.cursorRectangle);
} else {
this.startCell = sheet.getCellOffsets(cursor.cursorPosition.x, cursor.cursorPosition.y);
this.endCell = sheet.getCellOffsets(cursor.cursorPosition.x, cursor.cursorPosition.y);
Expand Down
54 changes: 54 additions & 0 deletions quadratic-client/src/app/gridGL/UI/UICellMoving.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { sheets } from '@/app/grid/controller/Sheets';
import { pixiApp } from '@/app/gridGL/pixiApp/PixiApp';
import { colors } from '@/app/theme/colors';
import { BitmapText, Container, Graphics } from 'pixi.js';

const MOVING_THICKNESS = 3;

export class UICellMoving extends Container {
private graphics: Graphics;
private location: BitmapText;

dirty = false;

constructor() {
super();
this.graphics = this.addChild(new Graphics());
this.location = this.addChild(new BitmapText('', { fontName: 'OpenSans', fontSize: 12 }));
this.visible = false;
}

private drawMove() {
const moving = pixiApp.pointer.pointerCellMoving.moving;
if (!moving) {
throw new Error('Expected moving to be defined in drawMove');
}
this.visible = true;
this.graphics.clear();
this.graphics.lineStyle(1, colors.movingCells, MOVING_THICKNESS);
const offsets = sheets.sheet.offsets;
const start = offsets.getCellOffsets(moving.toColumn, moving.toRow);
const end = offsets.getCellOffsets(moving.toColumn + moving.width, moving.toRow + moving.height);
this.graphics.drawRect(start.x, start.y, end.x + end.w - start.x, end.y + end.h - start.y);
}

update() {
if (this.dirty) {
this.dirty = false;
switch (pixiApp.pointer.pointerCellMoving.state) {
case 'hover':
if (this.visible) {
this.visible = false;
}
break;
case 'move':
this.drawMove();
break;
default:
davidfig marked this conversation as resolved.
Show resolved Hide resolved
if (this.visible) {
this.visible = false;
}
}
}
}
}
25 changes: 20 additions & 5 deletions quadratic-client/src/app/gridGL/interaction/pointer/Pointer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PointerCellMoving } from '@/app/gridGL/interaction/pointer/PointerCellMoving';
import { pixiAppSettings } from '@/app/gridGL/pixiApp/PixiAppSettings';
import { multiplayer } from '@/app/web-workers/multiplayerWebWorker/multiplayer';
import { Viewport } from 'pixi-viewport';
Expand All @@ -15,13 +16,15 @@ export class Pointer {
pointerHtmlCells: PointerHtmlCells;
pointerCursor: PointerCursor;
pointerDown: PointerDown;
pointerCellMoving: PointerCellMoving;

constructor(viewport: Viewport) {
this.pointerHeading = new PointerHeading();
this.pointerAutoComplete = new PointerAutoComplete();
this.pointerDown = new PointerDown();
this.pointerCursor = new PointerCursor();
this.pointerHtmlCells = new PointerHtmlCells();
this.pointerCellMoving = new PointerCellMoving();

viewport.on('pointerdown', this.handlePointerDown);
viewport.on('pointermove', this.pointerMove);
Expand Down Expand Up @@ -75,32 +78,43 @@ export class Pointer {
if (this.isMoreThanOneTouch(e)) return;
const world = pixiApp.viewport.toWorld(e.data.global);
const event = e.data.originalEvent as PointerEvent;
this.pointerHtmlCells.pointerDown(e) ||
this.pointerCellMoving.pointerDown(event) ||
this.pointerHtmlCells.pointerDown(e) ||
this.pointerHeading.pointerDown(world, event) ||
this.pointerAutoComplete.pointerDown(world) ||
this.pointerDown.pointerDown(world, event);

this.updateCursor();
};

private pointerMove = (e: InteractionEvent): void => {
if (this.isMoreThanOneTouch(e) || this.isOverCodeEditor(e)) return;
const world = pixiApp.viewport.toWorld(e.data.global);
this.pointerHtmlCells.pointerMove(e) ||
const event = e.data.originalEvent as PointerEvent;
this.pointerCellMoving.pointerMove(event, world) ||
this.pointerHtmlCells.pointerMove(e) ||
this.pointerHeading.pointerMove(world) ||
this.pointerAutoComplete.pointerMove(world) ||
this.pointerDown.pointerMove(world) ||
this.pointerCursor.pointerMove(world);

// change the cursor based on pointer priority
this.updateCursor();
};

// change the cursor based on pointer priority
private updateCursor() {
const cursor =
pixiApp.pointer.pointerCellMoving.cursor ??
pixiApp.pointer.pointerHtmlCells.cursor ??
pixiApp.pointer.pointerHeading.cursor ??
pixiApp.pointer.pointerAutoComplete.cursor;
pixiApp.canvas.style.cursor = cursor ?? 'unset';
};
}

private pointerUp = (e: InteractionEvent): void => {
if (this.isMoreThanOneTouch(e)) return;
this.pointerHtmlCells.pointerUp() ||
this.pointerCellMoving.pointerUp() ||
this.pointerHtmlCells.pointerUp() ||
this.pointerHeading.pointerUp() ||
this.pointerAutoComplete.pointerUp() ||
this.pointerDown.pointerUp();
Expand All @@ -116,6 +130,7 @@ export class Pointer {
return true;
}
return (
this.pointerCellMoving.handleEscape() ||
this.pointerHtmlCells.handleEscape() ||
this.pointerHeading.handleEscape() ||
this.pointerAutoComplete.handleEscape()
Expand Down