You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
7.3 KiB
TypeScript

/*
* Copyright (C) 2019 Intel Corporation
* SPDX-License-Identifier: MIT
*/
import { MasterImpl } from './master';
export interface Size {
width: number;
height: number;
}
export interface Position {
x: number;
y: number;
}
export interface Geometry {
image: Size;
canvas: Size;
top: number;
left: number;
scale: number;
offset: number;
angle: number;
}
export enum FrameZoom {
MIN = 0.1,
MAX = 10,
}
export enum Rotation {
ANTICLOCKWISE90,
CLOCKWISE90,
}
export enum UpdateReasons {
IMAGE = 'image',
OBJECTS = 'objects',
ZOOM = 'zoom',
FIT = 'fit',
MOVE = 'move',
}
export interface CanvasModel extends MasterImpl {
readonly image: string;
readonly objects: any[];
geometry: Geometry;
imageSize: Size;
canvasSize: Size;
zoom(x: number, y: number, direction: number): void;
move(topOffset: number, leftOffset: number): void;
setup(frameData: any, objectStates: any[]): void;
activate(clientID: number, attributeID: number): void;
rotate(rotation: Rotation, remember: boolean): void;
focus(clientID: number, padding: number): void;
fit(): void;
grid(stepX: number, stepY: number): void;
draw(enabled: boolean, shapeType: string, numberOfPoints: number, initialState: any): any;
split(enabled: boolean): any;
group(enabled: boolean): any;
merge(enabled: boolean): any;
cancel(): void;
}
export class CanvasModelImpl extends MasterImpl implements CanvasModel {
private data: {
image: string;
objects: any[];
imageSize: Size;
canvasSize: Size;
imageOffset: number;
scale: number;
top: number;
left: number;
angle: number;
rememberAngle: boolean;
};
public constructor() {
super();
this.data = {
angle: 0,
canvasSize: {
height: 0,
width: 0,
},
image: '',
imageOffset: 0,
imageSize: {
height: 0,
width: 0,
},
left: 0,
objects: [],
rememberAngle: false,
scale: 1,
top: 0,
};
}
public zoom(x: number, y: number, direction: number): void {
const oldScale: number = this.data.scale;
const newScale: number = direction > 0 ? oldScale * 6 / 5 : oldScale * 5 / 6;
this.data.scale = Math.min(Math.max(newScale, FrameZoom.MIN), FrameZoom.MAX);
this.data.left += (x * (oldScale / this.data.scale - 1)) * this.data.scale;
this.data.top += (y * (oldScale / this.data.scale - 1)) * this.data.scale;
this.notify(UpdateReasons.ZOOM);
}
public move(topOffset: number, leftOffset: number): void {
this.data.top += topOffset;
this.data.left += leftOffset;
this.notify(UpdateReasons.MOVE);
}
public setup(frameData: any, objectStates: any[]): void {
frameData.data(
(): void => {
this.data.image = '';
this.notify(UpdateReasons.IMAGE);
},
).then((data: string): void => {
this.data.imageSize = {
height: (frameData.height as number),
width: (frameData.width as number),
};
if (!this.data.rememberAngle) {
this.data.angle = 0;
}
this.data.image = data;
this.notify(UpdateReasons.IMAGE);
this.data.objects = objectStates;
this.notify(UpdateReasons.OBJECTS);
}).catch((exception: any): void => {
console.log(exception.toString());
});
console.log(objectStates);
}
public activate(clientID: number, attributeID: number): void {
console.log(clientID, attributeID);
}
public rotate(rotation: Rotation, remember: boolean = false): void {
if (rotation === Rotation.CLOCKWISE90) {
this.data.angle += 90;
} else {
this.data.angle -= 90;
}
this.data.angle %= 360;
this.data.rememberAngle = remember;
this.fit();
}
public focus(clientID: number, padding: number): void {
console.log(clientID, padding);
}
public fit(): void {
const { angle } = this.data;
if ((angle / 90) % 2) {
// 90, 270, ..
this.data.scale = Math.min(
this.data.canvasSize.width / this.data.imageSize.height,
this.data.canvasSize.height / this.data.imageSize.width,
);
} else {
this.data.scale = Math.min(
this.data.canvasSize.width / this.data.imageSize.width,
this.data.canvasSize.height / this.data.imageSize.height,
);
}
this.data.scale = Math.min(
Math.max(this.data.scale, FrameZoom.MIN),
FrameZoom.MAX,
);
this.data.top = (this.data.canvasSize.height
- this.data.imageSize.height * this.data.scale) / 2;
this.data.left = (this.data.canvasSize.width
- this.data.imageSize.width * this.data.scale) / 2;
this.notify(UpdateReasons.FIT);
}
public grid(stepX: number, stepY: number): void {
console.log(stepX, stepY);
}
public draw(enabled: boolean, shapeType: string,
numberOfPoints: number, initialState: any): any {
return {
enabled,
initialState,
numberOfPoints,
shapeType,
};
}
public split(enabled: boolean): any {
return enabled;
}
public group(enabled: boolean): any {
return enabled;
}
public merge(enabled: boolean): any {
return enabled;
}
public cancel(): void {
console.log('hello');
}
public get geometry(): Geometry {
return {
angle: this.data.angle,
canvas: {
height: this.data.canvasSize.height,
width: this.data.canvasSize.width,
},
image: {
height: this.data.imageSize.height,
width: this.data.imageSize.width,
},
left: this.data.left,
offset: this.data.imageOffset,
scale: this.data.scale,
top: this.data.top,
};
}
public get image(): string {
return this.data.image;
}
public get objects(): any[] {
return this.data.objects;
}
public set imageSize(value: Size) {
this.data.imageSize = {
height: value.height,
width: value.width,
};
}
public get imageSize(): Size {
return {
height: this.data.imageSize.height,
width: this.data.imageSize.width,
};
}
public set canvasSize(value: Size) {
this.data.canvasSize = {
height: value.height,
width: value.width,
};
this.data.imageOffset = Math.floor(Math.max(
this.data.canvasSize.height / FrameZoom.MIN,
this.data.canvasSize.width / FrameZoom.MIN,
));
}
public get canvasSize(): Size {
return {
height: this.data.canvasSize.height,
width: this.data.canvasSize.width,
};
}
}