Replace Selection interface with CanvasRange
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
b64f0b4daa
commit
3dcc1edc62
|
@ -49,8 +49,8 @@ const initialState: State = {
|
||||||
viewport: { start: 0, end: 0 },
|
viewport: { start: 0, end: 0 },
|
||||||
overviewPeaks: from([]),
|
overviewPeaks: from([]),
|
||||||
waveformPeaks: from([]),
|
waveformPeaks: from([]),
|
||||||
selectionCanvas: { start: 0, end: 0 },
|
selectionCanvas: { x1: 0, x2: 0 },
|
||||||
viewportCanvas: { start: 0, end: 0 },
|
viewportCanvas: { x1: 0, x2: 0 },
|
||||||
position: { currentTime: 0, frame: 0, percent: 0 },
|
position: { currentTime: 0, frame: 0, percent: 0 },
|
||||||
audioSrc: '',
|
audioSrc: '',
|
||||||
videoSrc: '',
|
videoSrc: '',
|
||||||
|
|
|
@ -9,8 +9,8 @@ const initialState: State = {
|
||||||
viewport: { start: 0, end: 441000 },
|
viewport: { start: 0, end: 441000 },
|
||||||
overviewPeaks: from([]),
|
overviewPeaks: from([]),
|
||||||
waveformPeaks: from([]),
|
waveformPeaks: from([]),
|
||||||
selectionCanvas: { start: 0, end: 0 },
|
selectionCanvas: { x1: 0, x2: 0 },
|
||||||
viewportCanvas: { start: 0, end: CanvasLogicalWidth },
|
viewportCanvas: { x1: 0, x2: CanvasLogicalWidth },
|
||||||
position: { currentTime: 0, frame: 0, percent: 0 },
|
position: { currentTime: 0, frame: 0, percent: 0 },
|
||||||
audioSrc: '',
|
audioSrc: '',
|
||||||
videoSrc: '',
|
videoSrc: '',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { MediaSet } from './generated/media_set';
|
import { MediaSet } from './generated/media_set';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { SelectionChangeEvent } from './HudCanvas';
|
import { SelectionChangeEvent } from './HudCanvas';
|
||||||
import { SelectionMode, CanvasLogicalWidth } from './HudCanvasState';
|
import { CanvasRange, SelectionMode, CanvasLogicalWidth } from './HudCanvasState';
|
||||||
import { PlayState } from './Player';
|
import { PlayState } from './Player';
|
||||||
import { zoomViewportIn, zoomViewportOut } from './helpers/zoom';
|
import { zoomViewportIn, zoomViewportOut } from './helpers/zoom';
|
||||||
import frameToWaveformCanvasX from './helpers/frameToWaveformCanvasX';
|
import frameToWaveformCanvasX from './helpers/frameToWaveformCanvasX';
|
||||||
|
@ -15,12 +15,6 @@ export interface FrameRange {
|
||||||
end: number;
|
end: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename to x1, x2
|
|
||||||
interface CanvasRange {
|
|
||||||
start: number;
|
|
||||||
end: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Position {
|
interface Position {
|
||||||
currentTime: number;
|
currentTime: number;
|
||||||
frame: number;
|
frame: number;
|
||||||
|
@ -224,10 +218,10 @@ function setViewport(state: State, { viewport }: SetViewportAction): State {
|
||||||
...state,
|
...state,
|
||||||
viewport: viewport,
|
viewport: viewport,
|
||||||
viewportCanvas: {
|
viewportCanvas: {
|
||||||
start: Math.round(
|
x1: Math.round(
|
||||||
(viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth
|
(viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth
|
||||||
),
|
),
|
||||||
end: Math.round(
|
x2: Math.round(
|
||||||
(viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth
|
(viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -298,10 +292,10 @@ function handleViewportChanged(
|
||||||
|
|
||||||
const newViewport = {
|
const newViewport = {
|
||||||
start: Math.round(
|
start: Math.round(
|
||||||
mediaSet.audioFrames * (canvasRange.start / CanvasLogicalWidth)
|
mediaSet.audioFrames * (canvasRange.x1 / CanvasLogicalWidth)
|
||||||
),
|
),
|
||||||
end: Math.round(
|
end: Math.round(
|
||||||
mediaSet.audioFrames * (canvasRange.end / CanvasLogicalWidth)
|
mediaSet.audioFrames * (canvasRange.x2 / CanvasLogicalWidth)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -331,8 +325,8 @@ function handleWaveformSelectionChanged(
|
||||||
|
|
||||||
const framesPerPixel = (viewport.end - viewport.start) / CanvasLogicalWidth;
|
const framesPerPixel = (viewport.end - viewport.start) / CanvasLogicalWidth;
|
||||||
const newSelection = {
|
const newSelection = {
|
||||||
start: Math.round(viewport.start + canvasRange.start * framesPerPixel),
|
start: Math.round(viewport.start + canvasRange.x1 * framesPerPixel),
|
||||||
end: Math.round(viewport.start + canvasRange.end * framesPerPixel),
|
end: Math.round(viewport.start + canvasRange.x2 * framesPerPixel),
|
||||||
};
|
};
|
||||||
|
|
||||||
let currentTime = state.currentTime;
|
let currentTime = state.currentTime;
|
||||||
|
@ -433,8 +427,8 @@ function selectionToWaveformCanvasRange(
|
||||||
);
|
);
|
||||||
|
|
||||||
if (x1 == x2) {
|
if (x1 == x2) {
|
||||||
return { start: 0, end: 0 };
|
return { x1: 0, x2: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { start: x1 || 0, end: x2 || CanvasLogicalWidth };
|
return { x1: x1 || 0, x2: x2 || CanvasLogicalWidth };
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import {
|
||||||
State,
|
State,
|
||||||
SelectionMode,
|
SelectionMode,
|
||||||
HoverState,
|
HoverState,
|
||||||
Selection,
|
|
||||||
EmptySelectionAction,
|
EmptySelectionAction,
|
||||||
|
CanvasRange,
|
||||||
} from './HudCanvasState';
|
} from './HudCanvasState';
|
||||||
import constrainNumeric from './helpers/constrainNumeric';
|
import constrainNumeric from './helpers/constrainNumeric';
|
||||||
export { EmptySelectionAction } from './HudCanvasState';
|
export { EmptySelectionAction } from './HudCanvasState';
|
||||||
|
@ -24,17 +24,17 @@ interface Props {
|
||||||
emptySelectionAction: EmptySelectionAction;
|
emptySelectionAction: EmptySelectionAction;
|
||||||
styles: Styles;
|
styles: Styles;
|
||||||
position: number | null;
|
position: number | null;
|
||||||
selection: Selection;
|
selection: CanvasRange;
|
||||||
onSelectionChange: (selectionState: SelectionChangeEvent) => void;
|
onSelectionChange: (selectionState: SelectionChangeEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectionChangeEvent {
|
export interface SelectionChangeEvent {
|
||||||
selection: Selection;
|
selection: CanvasRange;
|
||||||
mode: SelectionMode;
|
mode: SelectionMode;
|
||||||
prevMode: SelectionMode;
|
prevMode: SelectionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emptySelection: Selection = { start: 0, end: 0 };
|
const emptySelection: CanvasRange = { x1: 0, x2: 0 };
|
||||||
|
|
||||||
const initialState: State = {
|
const initialState: State = {
|
||||||
width: 0,
|
width: 0,
|
||||||
|
@ -134,9 +134,9 @@ export const HudCanvas: React.FC<Props> = ({
|
||||||
state.hoverState == HoverState.OverSelection ? '0.15' : '0.13';
|
state.hoverState == HoverState.OverSelection ? '0.15' : '0.13';
|
||||||
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
|
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
|
||||||
ctx.rect(
|
ctx.rect(
|
||||||
currentSelection.start,
|
currentSelection.x1,
|
||||||
borderLineWidth,
|
borderLineWidth,
|
||||||
currentSelection.end - currentSelection.start,
|
currentSelection.x2 - currentSelection.x1,
|
||||||
canvas.height - borderLineWidth * 2
|
canvas.height - borderLineWidth * 2
|
||||||
);
|
);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
@ -146,8 +146,8 @@ export const HudCanvas: React.FC<Props> = ({
|
||||||
|
|
||||||
const hoverX = state.hoverX;
|
const hoverX = state.hoverX;
|
||||||
if (
|
if (
|
||||||
(hoverX != 0 && hoverX < currentSelection.start) ||
|
(hoverX != 0 && hoverX < currentSelection.x1) ||
|
||||||
hoverX > currentSelection.end
|
hoverX > currentSelection.x2
|
||||||
) {
|
) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.strokeStyle = hoverPositionStrokeStyle;
|
ctx.strokeStyle = hoverPositionStrokeStyle;
|
||||||
|
|
|
@ -9,8 +9,8 @@ const initialState = {
|
||||||
width: 5000,
|
width: 5000,
|
||||||
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
||||||
hoverX: 0,
|
hoverX: 0,
|
||||||
selection: { start: 0, end: 0 },
|
selection: { x1: 0, x2: 0 },
|
||||||
origSelection: { start: 0, end: 0 },
|
origSelection: { x1: 0, x2: 0 },
|
||||||
mousedownX: 0,
|
mousedownX: 0,
|
||||||
mode: SelectionMode.Normal,
|
mode: SelectionMode.Normal,
|
||||||
prevMode: SelectionMode.Normal,
|
prevMode: SelectionMode.Normal,
|
||||||
|
@ -24,9 +24,9 @@ describe('stateReducer', () => {
|
||||||
it('sets the selection', () => {
|
it('sets the selection', () => {
|
||||||
const state = stateReducer(
|
const state = stateReducer(
|
||||||
{ ...initialState },
|
{ ...initialState },
|
||||||
{ type: 'setselection', x: 0, selection: { start: 100, end: 200 } }
|
{ type: 'setselection', x: 0, selection: { x1: 100, x2: 200 } }
|
||||||
);
|
);
|
||||||
expect(state.selection).toEqual({ start: 100, end: 200 });
|
expect(state.selection).toEqual({ x1: 100, x2: 200 });
|
||||||
expect(state.shouldPublish).toBeFalsy();
|
expect(state.shouldPublish).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -35,30 +35,30 @@ describe('stateReducer', () => {
|
||||||
{
|
{
|
||||||
name: 'entering resizing start',
|
name: 'entering resizing start',
|
||||||
x: 995,
|
x: 995,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
wantMode: SelectionMode.ResizingStart,
|
wantMode: SelectionMode.ResizingStart,
|
||||||
wantSelection: { start: 1000, end: 2000 },
|
wantSelection: { x1: 1000, x2: 2000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'entering resizing end',
|
name: 'entering resizing end',
|
||||||
x: 2003,
|
x: 2003,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
wantMode: SelectionMode.ResizingEnd,
|
wantMode: SelectionMode.ResizingEnd,
|
||||||
wantSelection: { start: 1000, end: 2000 },
|
wantSelection: { x1: 1000, x2: 2000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'entering dragging',
|
name: 'entering dragging',
|
||||||
x: 1500,
|
x: 1500,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
wantMode: SelectionMode.Dragging,
|
wantMode: SelectionMode.Dragging,
|
||||||
wantSelection: { start: 1000, end: 2000 },
|
wantSelection: { x1: 1000, x2: 2000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'entering selecting',
|
name: 'entering selecting',
|
||||||
x: 10,
|
x: 10,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
wantMode: SelectionMode.Selecting,
|
wantMode: SelectionMode.Selecting,
|
||||||
wantSelection: { start: 10, end: 10 },
|
wantSelection: { x1: 10, x2: 10 },
|
||||||
},
|
},
|
||||||
])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => {
|
])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => {
|
||||||
test(`${name} generates the expected state`, () => {
|
test(`${name} generates the expected state`, () => {
|
||||||
|
@ -77,24 +77,24 @@ describe('stateReducer', () => {
|
||||||
{
|
{
|
||||||
name: 're-entering normal mode',
|
name: 're-entering normal mode',
|
||||||
x: 1200,
|
x: 1200,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
||||||
wantSelection: { start: 1000, end: 2000 },
|
wantSelection: { x1: 1000, x2: 2000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'when nothing is selected and emptySelectionAction is SelectNothing',
|
name: 'when nothing is selected and emptySelectionAction is SelectNothing',
|
||||||
x: 1200,
|
x: 1200,
|
||||||
selection: { start: 1000, end: 1000 },
|
selection: { x1: 1000, x2: 1000 },
|
||||||
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
emptySelectionAction: EmptySelectionAction.SelectNothing,
|
||||||
wantSelection: { start: 1200, end: 1200 },
|
wantSelection: { x1: 1200, x2: 1200 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO: broken
|
// TODO: broken
|
||||||
name: 'when nothing is selected and emptySelectionAction is SelectPrevious',
|
name: 'when nothing is selected and emptySelectionAction is SelectPrevious',
|
||||||
x: 1200,
|
x: 1200,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
emptySelectionAction: EmptySelectionAction.SelectPrevious,
|
emptySelectionAction: EmptySelectionAction.SelectPrevious,
|
||||||
wantSelection: { start: 1000, end: 2000 },
|
wantSelection: { x1: 1000, x2: 2000 },
|
||||||
},
|
},
|
||||||
])(
|
])(
|
||||||
'mouseup',
|
'mouseup',
|
||||||
|
@ -122,14 +122,14 @@ describe('stateReducer', () => {
|
||||||
const state = stateReducer(
|
const state = stateReducer(
|
||||||
{
|
{
|
||||||
...initialState,
|
...initialState,
|
||||||
selection: { start: 2000, end: 3000 },
|
selection: { x1: 2000, x2: 3000 },
|
||||||
mode: SelectionMode.Dragging,
|
mode: SelectionMode.Dragging,
|
||||||
mousedownX: 475,
|
mousedownX: 475,
|
||||||
},
|
},
|
||||||
{ type: 'mouseleave', x: 500 }
|
{ type: 'mouseleave', x: 500 }
|
||||||
);
|
);
|
||||||
expect(state.mode).toEqual(SelectionMode.Dragging);
|
expect(state.mode).toEqual(SelectionMode.Dragging);
|
||||||
expect(state.selection).toEqual({ start: 2000, end: 3000 });
|
expect(state.selection).toEqual({ x1: 2000, x2: 3000 });
|
||||||
expect(state.mousedownX).toEqual(475);
|
expect(state.mousedownX).toEqual(475);
|
||||||
expect(state.hoverX).toEqual(0);
|
expect(state.hoverX).toEqual(0);
|
||||||
expect(state.shouldPublish).toBeFalsy();
|
expect(state.shouldPublish).toBeFalsy();
|
||||||
|
@ -143,7 +143,7 @@ describe('stateReducer', () => {
|
||||||
name: 'hovering over selection start',
|
name: 'hovering over selection start',
|
||||||
mode: SelectionMode.Normal,
|
mode: SelectionMode.Normal,
|
||||||
x: 997,
|
x: 997,
|
||||||
selection: { start: 1000, end: 3000 },
|
selection: { x1: 1000, x2: 3000 },
|
||||||
wantHoverState: HoverState.OverSelectionStart,
|
wantHoverState: HoverState.OverSelectionStart,
|
||||||
shouldPublish: false,
|
shouldPublish: false,
|
||||||
},
|
},
|
||||||
|
@ -151,7 +151,7 @@ describe('stateReducer', () => {
|
||||||
name: 'hovering over selection end',
|
name: 'hovering over selection end',
|
||||||
mode: SelectionMode.Normal,
|
mode: SelectionMode.Normal,
|
||||||
x: 3009,
|
x: 3009,
|
||||||
selection: { start: 1000, end: 3000 },
|
selection: { x1: 1000, x2: 3000 },
|
||||||
wantHoverState: HoverState.OverSelectionEnd,
|
wantHoverState: HoverState.OverSelectionEnd,
|
||||||
shouldPublish: false,
|
shouldPublish: false,
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,7 @@ describe('stateReducer', () => {
|
||||||
name: 'hovering over selection',
|
name: 'hovering over selection',
|
||||||
mode: SelectionMode.Normal,
|
mode: SelectionMode.Normal,
|
||||||
x: 1200,
|
x: 1200,
|
||||||
selection: { start: 1000, end: 3000 },
|
selection: { x1: 1000, x2: 3000 },
|
||||||
wantHoverState: HoverState.OverSelection,
|
wantHoverState: HoverState.OverSelection,
|
||||||
shouldPublish: false,
|
shouldPublish: false,
|
||||||
},
|
},
|
||||||
|
@ -167,7 +167,7 @@ describe('stateReducer', () => {
|
||||||
name: 'hovering elsewhere',
|
name: 'hovering elsewhere',
|
||||||
mode: SelectionMode.Normal,
|
mode: SelectionMode.Normal,
|
||||||
x: 300,
|
x: 300,
|
||||||
selection: { start: 1000, end: 3000 },
|
selection: { x1: 1000, x2: 3000 },
|
||||||
wantHoverState: HoverState.Normal,
|
wantHoverState: HoverState.Normal,
|
||||||
shouldPublish: false,
|
shouldPublish: false,
|
||||||
},
|
},
|
||||||
|
@ -177,8 +177,8 @@ describe('stateReducer', () => {
|
||||||
mode: SelectionMode.Selecting,
|
mode: SelectionMode.Selecting,
|
||||||
x: 3005,
|
x: 3005,
|
||||||
mousedownX: 2000,
|
mousedownX: 2000,
|
||||||
selection: { start: 2000, end: 3000 },
|
selection: { x1: 2000, x2: 3000 },
|
||||||
wantSelection: { start: 2000, end: 3005 },
|
wantSelection: { x1: 2000, x2: 3005 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -186,8 +186,8 @@ describe('stateReducer', () => {
|
||||||
mode: SelectionMode.Selecting,
|
mode: SelectionMode.Selecting,
|
||||||
x: 1995,
|
x: 1995,
|
||||||
mousedownX: 2000,
|
mousedownX: 2000,
|
||||||
selection: { start: 2000, end: 2002 },
|
selection: { x1: 2000, x2: 2002 },
|
||||||
wantSelection: { start: 1995, end: 2000 },
|
wantSelection: { x1: 1995, x2: 2000 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
// Dragging mode
|
// Dragging mode
|
||||||
|
@ -196,9 +196,9 @@ describe('stateReducer', () => {
|
||||||
mode: SelectionMode.Dragging,
|
mode: SelectionMode.Dragging,
|
||||||
x: 1220,
|
x: 1220,
|
||||||
mousedownX: 1200,
|
mousedownX: 1200,
|
||||||
selection: { start: 1000, end: 1500 },
|
selection: { x1: 1000, x2: 1500 },
|
||||||
origSelection: { start: 1000, end: 1500 },
|
origSelection: { x1: 1000, x2: 1500 },
|
||||||
wantSelection: { start: 1020, end: 1520 },
|
wantSelection: { x1: 1020, x2: 1520 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -206,9 +206,9 @@ describe('stateReducer', () => {
|
||||||
mode: SelectionMode.Dragging,
|
mode: SelectionMode.Dragging,
|
||||||
x: 30,
|
x: 30,
|
||||||
mousedownX: 50,
|
mousedownX: 50,
|
||||||
selection: { start: 10, end: 210 },
|
selection: { x1: 10, x2: 210 },
|
||||||
origSelection: { start: 10, end: 210 },
|
origSelection: { x1: 10, x2: 210 },
|
||||||
wantSelection: { start: 0, end: 200 },
|
wantSelection: { x1: 0, x2: 200 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -216,9 +216,9 @@ describe('stateReducer', () => {
|
||||||
mode: SelectionMode.Dragging,
|
mode: SelectionMode.Dragging,
|
||||||
x: 1400,
|
x: 1400,
|
||||||
mousedownX: 1250,
|
mousedownX: 1250,
|
||||||
selection: { start: 4800, end: 4900 },
|
selection: { x1: 4800, x2: 4900 },
|
||||||
origSelection: { start: 4800, end: 4900 },
|
origSelection: { x1: 4800, x2: 4900 },
|
||||||
wantSelection: { start: 4900, end: 5000 },
|
wantSelection: { x1: 4900, x2: 5000 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
// ResizingStart mode
|
// ResizingStart mode
|
||||||
|
@ -226,18 +226,18 @@ describe('stateReducer', () => {
|
||||||
name: 'when not crossing over',
|
name: 'when not crossing over',
|
||||||
mode: SelectionMode.ResizingStart,
|
mode: SelectionMode.ResizingStart,
|
||||||
x: 2020,
|
x: 2020,
|
||||||
selection: { start: 2000, end: 3000 },
|
selection: { x1: 2000, x2: 3000 },
|
||||||
origSelection: { start: 2000, end: 3000 },
|
origSelection: { x1: 2000, x2: 3000 },
|
||||||
wantSelection: { start: 2020, end: 3000 },
|
wantSelection: { x1: 2020, x2: 3000 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'when crossing over',
|
name: 'when crossing over',
|
||||||
mode: SelectionMode.ResizingStart,
|
mode: SelectionMode.ResizingStart,
|
||||||
x: 2010,
|
x: 2010,
|
||||||
selection: { start: 2000, end: 2002 },
|
selection: { x1: 2000, x2: 2002 },
|
||||||
origSelection: { start: 2000, end: 2002 },
|
origSelection: { x1: 2000, x2: 2002 },
|
||||||
wantSelection: { start: 2002, end: 2010 },
|
wantSelection: { x1: 2002, x2: 2010 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
// ResizingEnd mode
|
// ResizingEnd mode
|
||||||
|
@ -245,18 +245,18 @@ describe('stateReducer', () => {
|
||||||
name: 'when not crossing over',
|
name: 'when not crossing over',
|
||||||
mode: SelectionMode.ResizingEnd,
|
mode: SelectionMode.ResizingEnd,
|
||||||
x: 2007,
|
x: 2007,
|
||||||
selection: { start: 1000, end: 2000 },
|
selection: { x1: 1000, x2: 2000 },
|
||||||
origSelection: { start: 1000, end: 2000 },
|
origSelection: { x1: 1000, x2: 2000 },
|
||||||
wantSelection: { start: 1000, end: 2007 },
|
wantSelection: { x1: 1000, x2: 2007 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'when crossing over',
|
name: 'when crossing over',
|
||||||
mode: SelectionMode.ResizingEnd,
|
mode: SelectionMode.ResizingEnd,
|
||||||
x: 1995,
|
x: 1995,
|
||||||
selection: { start: 2000, end: 2002 },
|
selection: { x1: 2000, x2: 2002 },
|
||||||
origSelection: { start: 2000, end: 2002 },
|
origSelection: { x1: 2000, x2: 2002 },
|
||||||
wantSelection: { start: 1995, end: 2000 },
|
wantSelection: { x1: 1995, x2: 2000 },
|
||||||
shouldPublish: true,
|
shouldPublish: true,
|
||||||
},
|
},
|
||||||
])(
|
])(
|
||||||
|
@ -267,7 +267,7 @@ describe('stateReducer', () => {
|
||||||
x,
|
x,
|
||||||
mousedownX = 0,
|
mousedownX = 0,
|
||||||
selection,
|
selection,
|
||||||
origSelection = { start: 0, end: 0 },
|
origSelection = { x1: 0, x2: 0 },
|
||||||
wantSelection = selection,
|
wantSelection = selection,
|
||||||
wantHoverState = HoverState.Normal,
|
wantHoverState = HoverState.Normal,
|
||||||
shouldPublish,
|
shouldPublish,
|
||||||
|
|
|
@ -3,6 +3,11 @@ import constrainNumeric from './helpers/constrainNumeric';
|
||||||
export const CanvasLogicalWidth = 2000;
|
export const CanvasLogicalWidth = 2000;
|
||||||
export const CanvasLogicalHeight = 500;
|
export const CanvasLogicalHeight = 500;
|
||||||
|
|
||||||
|
export interface CanvasRange {
|
||||||
|
x1: number;
|
||||||
|
x2: number;
|
||||||
|
}
|
||||||
|
|
||||||
export enum HoverState {
|
export enum HoverState {
|
||||||
Normal,
|
Normal,
|
||||||
OverSelectionStart,
|
OverSelectionStart,
|
||||||
|
@ -15,11 +20,6 @@ export enum EmptySelectionAction {
|
||||||
SelectPrevious,
|
SelectPrevious,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Selection {
|
|
||||||
start: number;
|
|
||||||
end: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SelectionMode {
|
export enum SelectionMode {
|
||||||
Normal,
|
Normal,
|
||||||
Selecting,
|
Selecting,
|
||||||
|
@ -32,8 +32,8 @@ export interface State {
|
||||||
width: number;
|
width: number;
|
||||||
emptySelectionAction: EmptySelectionAction;
|
emptySelectionAction: EmptySelectionAction;
|
||||||
hoverX: number;
|
hoverX: number;
|
||||||
selection: Selection;
|
selection: CanvasRange;
|
||||||
origSelection: Selection;
|
origSelection: CanvasRange;
|
||||||
mousedownX: number;
|
mousedownX: number;
|
||||||
mode: SelectionMode;
|
mode: SelectionMode;
|
||||||
prevMode: SelectionMode;
|
prevMode: SelectionMode;
|
||||||
|
@ -47,7 +47,7 @@ interface SelectionAction {
|
||||||
x: number;
|
x: number;
|
||||||
// TODO: selection is only used for the setselection SelectionAction. Improve
|
// TODO: selection is only used for the setselection SelectionAction. Improve
|
||||||
// the typing here.
|
// the typing here.
|
||||||
selection?: Selection;
|
selection?: CanvasRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stateReducer = (
|
export const stateReducer = (
|
||||||
|
@ -62,7 +62,7 @@ export const stateReducer = (
|
||||||
{ x, type, selection: selectionToSet }: SelectionAction
|
{ x, type, selection: selectionToSet }: SelectionAction
|
||||||
): State => {
|
): State => {
|
||||||
let mode: SelectionMode;
|
let mode: SelectionMode;
|
||||||
let newSelection: Selection;
|
let newSelection: CanvasRange;
|
||||||
let hoverX: number;
|
let hoverX: number;
|
||||||
let mousedownX: number;
|
let mousedownX: number;
|
||||||
let cursorClass: string;
|
let cursorClass: string;
|
||||||
|
@ -71,7 +71,7 @@ export const stateReducer = (
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'setselection':
|
case 'setselection':
|
||||||
newSelection = selectionToSet || { start: 0, end: 0 };
|
newSelection = selectionToSet || { x1: 0, x2: 0 };
|
||||||
mousedownX = prevMousedownX;
|
mousedownX = prevMousedownX;
|
||||||
mode = SelectionMode.Normal;
|
mode = SelectionMode.Normal;
|
||||||
cursorClass = 'cursor-auto';
|
cursorClass = 'cursor-auto';
|
||||||
|
@ -97,7 +97,7 @@ export const stateReducer = (
|
||||||
mode = SelectionMode.Dragging;
|
mode = SelectionMode.Dragging;
|
||||||
cursorClass = 'cursor-move';
|
cursorClass = 'cursor-move';
|
||||||
} else {
|
} else {
|
||||||
newSelection = { start: x, end: x };
|
newSelection = { x1: x, x2: x };
|
||||||
mode = SelectionMode.Selecting;
|
mode = SelectionMode.Selecting;
|
||||||
cursorClass = 'cursor-col-resize';
|
cursorClass = 'cursor-col-resize';
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,10 @@ export const stateReducer = (
|
||||||
hoverState = HoverState.Normal;
|
hoverState = HoverState.Normal;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
newSelection.start == newSelection.end &&
|
newSelection.x1 == newSelection.x2 &&
|
||||||
emptySelectionAction == EmptySelectionAction.SelectNothing
|
emptySelectionAction == EmptySelectionAction.SelectNothing
|
||||||
) {
|
) {
|
||||||
newSelection = { start: x, end: x };
|
newSelection = { x1: x, x2: x };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -161,13 +161,13 @@ export const stateReducer = (
|
||||||
mode = SelectionMode.Selecting;
|
mode = SelectionMode.Selecting;
|
||||||
if (x < prevMousedownX) {
|
if (x < prevMousedownX) {
|
||||||
newSelection = {
|
newSelection = {
|
||||||
start: x,
|
x1: x,
|
||||||
end: prevMousedownX,
|
x2: prevMousedownX,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
newSelection = {
|
newSelection = {
|
||||||
start: prevMousedownX,
|
x1: prevMousedownX,
|
||||||
end: x,
|
x2: x,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,15 +178,15 @@ export const stateReducer = (
|
||||||
cursorClass = 'cursor-move';
|
cursorClass = 'cursor-move';
|
||||||
|
|
||||||
const diff = x - prevMousedownX;
|
const diff = x - prevMousedownX;
|
||||||
const selectionWidth = origSelection.end - origSelection.start;
|
const selectionWidth = origSelection.x2 - origSelection.x1;
|
||||||
|
|
||||||
let start = Math.max(0, origSelection.start + diff);
|
let start = Math.max(0, origSelection.x1 + diff);
|
||||||
let end = start + selectionWidth;
|
let end = start + selectionWidth;
|
||||||
if (end > width) {
|
if (end > width) {
|
||||||
end = width;
|
end = width;
|
||||||
start = end - selectionWidth;
|
start = end - selectionWidth;
|
||||||
}
|
}
|
||||||
newSelection = { start: start, end: end };
|
newSelection = { x1: start, x2: end };
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -195,10 +195,10 @@ export const stateReducer = (
|
||||||
cursorClass = 'cursor-col-resize';
|
cursorClass = 'cursor-col-resize';
|
||||||
|
|
||||||
const start = constrainNumeric(x, width);
|
const start = constrainNumeric(x, width);
|
||||||
if (start > origSelection.end) {
|
if (start > origSelection.x2) {
|
||||||
newSelection = { start: origSelection.end, end: start };
|
newSelection = { x1: origSelection.x2, x2: start };
|
||||||
} else {
|
} else {
|
||||||
newSelection = { ...origSelection, start: start };
|
newSelection = { ...origSelection, x1: start };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -208,13 +208,13 @@ export const stateReducer = (
|
||||||
cursorClass = 'cursor-col-resize';
|
cursorClass = 'cursor-col-resize';
|
||||||
|
|
||||||
const end = constrainNumeric(x, width);
|
const end = constrainNumeric(x, width);
|
||||||
if (end < origSelection.start) {
|
if (end < origSelection.x1) {
|
||||||
newSelection = {
|
newSelection = {
|
||||||
start: end,
|
x1: end,
|
||||||
end: origSelection.start,
|
x2: origSelection.x1,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
newSelection = { ...origSelection, end: x };
|
newSelection = { ...origSelection, x2: x };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -250,14 +250,17 @@ export const stateReducer = (
|
||||||
|
|
||||||
const hoverOffset = 10;
|
const hoverOffset = 10;
|
||||||
|
|
||||||
const isHoveringSelectionStart = (x: number, selection: Selection): boolean => {
|
const isHoveringSelectionStart = (
|
||||||
return x > selection.start - hoverOffset && x < selection.start + hoverOffset;
|
x: number,
|
||||||
|
selection: CanvasRange
|
||||||
|
): boolean => {
|
||||||
|
return x > selection.x1 - hoverOffset && x < selection.x1 + hoverOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isHoveringSelectionEnd = (x: number, selection: Selection): boolean => {
|
const isHoveringSelectionEnd = (x: number, selection: CanvasRange): boolean => {
|
||||||
return x > selection.end - hoverOffset && x < selection.end + hoverOffset;
|
return x > selection.x2 - hoverOffset && x < selection.x2 + hoverOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isHoveringSelection = (x: number, selection: Selection): boolean => {
|
const isHoveringSelection = (x: number, selection: CanvasRange): boolean => {
|
||||||
return x >= selection.start && x <= selection.end;
|
return x >= selection.x1 && x <= selection.x2;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue