Comparing version 0.2.1 to 0.3.0-next.04f191a3
@@ -40,3 +40,3 @@ "use strict"; | ||
this.postponedActions = []; | ||
var initialCommand = new set_model_1.SetModelCommand(new set_model_1.SetModelAction(smodel_factory_1.EMPTY_ROOT, true)); | ||
var initialCommand = new set_model_1.SetModelCommand(new set_model_1.SetModelAction(smodel_factory_1.EMPTY_ROOT)); | ||
this.blockUntilActionKind = initialCommand.blockUntilActionKind; | ||
@@ -43,0 +43,0 @@ this.commandStack.execute(initialCommand); |
@@ -99,2 +99,3 @@ import { ILogger } from "../../utils/logging"; | ||
protected offStack: SystemCommand[]; | ||
protected readonly currentModel: Promise<SModelRoot>; | ||
executeAll(commands: ICommand[]): Promise<SModelRoot>; | ||
@@ -101,0 +102,0 @@ execute(command: ICommand): Promise<SModelRoot>; |
@@ -91,2 +91,9 @@ "use strict"; | ||
} | ||
Object.defineProperty(CommandStack.prototype, "currentModel", { | ||
get: function () { | ||
return this.currentPromise.then(function (state) { return state.root; }); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
CommandStack.prototype.executeAll = function (commands) { | ||
@@ -211,3 +218,3 @@ var _this = this; | ||
}); | ||
return this.currentPromise.then(function (state) { return state.root; }); | ||
return this.currentModel; | ||
}; | ||
@@ -214,0 +221,0 @@ /** |
@@ -87,3 +87,3 @@ "use strict"; | ||
needsServerLayout: false, | ||
popupOpenDelay: 700, | ||
popupOpenDelay: 1000, | ||
popupCloseDelay: 300 | ||
@@ -90,0 +90,0 @@ }); |
@@ -15,3 +15,3 @@ import { VNode } from "snabbdom/vnode"; | ||
protected actionDispatcher: IActionDispatcher; | ||
rootAndVnode: [SModelRoot, VNode] | undefined; | ||
protected rootAndVnode: [SModelRoot, VNode] | undefined; | ||
constructor(actionDispatcher: IActionDispatcher); | ||
@@ -35,3 +35,2 @@ decorate(vnode: VNode, element: SModelElement): VNode; | ||
static readonly KIND: string; | ||
private oldCanvasBounds; | ||
private newCanvasBounds; | ||
@@ -38,0 +37,0 @@ constructor(action: InitializeCanvasBoundsAction); |
@@ -100,3 +100,2 @@ "use strict"; | ||
InitializeCanvasBoundsCommand.prototype.execute = function (context) { | ||
this.oldCanvasBounds = context.root.canvasBounds; | ||
this.newCanvasBounds = this.action.newCanvasBounds; | ||
@@ -103,0 +102,0 @@ context.root.canvasBounds = this.newCanvasBounds; |
@@ -24,5 +24,4 @@ import { Action } from "../actions/action"; | ||
readonly newRoot: SModelRootSchema; | ||
readonly isInitial: boolean; | ||
readonly kind: string; | ||
constructor(newRoot: SModelRootSchema, isInitial?: boolean); | ||
constructor(newRoot: SModelRootSchema); | ||
} | ||
@@ -38,3 +37,3 @@ export declare class SetModelCommand extends Command { | ||
redo(context: CommandExecutionContext): SModelRoot; | ||
readonly blockUntilActionKind: string | undefined; | ||
readonly blockUntilActionKind: string; | ||
} |
@@ -29,3 +29,2 @@ "use strict"; | ||
var inversify_1 = require("inversify"); | ||
var geometry_1 = require("../../utils/geometry"); | ||
var command_1 = require("../commands/command"); | ||
@@ -51,6 +50,4 @@ var initialize_canvas_1 = require("./initialize-canvas"); | ||
var SetModelAction = /** @class */ (function () { | ||
function SetModelAction(newRoot, isInitial) { | ||
if (isInitial === void 0) { isInitial = false; } | ||
function SetModelAction(newRoot) { | ||
this.newRoot = newRoot; | ||
this.isInitial = isInitial; | ||
this.kind = SetModelCommand.KIND; | ||
@@ -71,5 +68,2 @@ } | ||
this.newRoot = context.modelFactory.createRoot(this.action.newRoot); | ||
if (geometry_1.isValidDimension(this.oldRoot.canvasBounds)) { | ||
this.newRoot.canvasBounds = this.oldRoot.canvasBounds; | ||
} | ||
return this.newRoot; | ||
@@ -85,6 +79,3 @@ }; | ||
get: function () { | ||
if (this.action.isInitial) | ||
return initialize_canvas_1.InitializeCanvasBoundsCommand.KIND; | ||
else | ||
return undefined; | ||
return initialize_canvas_1.InitializeCanvasBoundsCommand.KIND; | ||
}, | ||
@@ -91,0 +82,0 @@ enumerable: true, |
@@ -5,6 +5,6 @@ import { Bounds, Dimension, Point } from "../../utils/geometry"; | ||
import { Locateable } from '../move/model'; | ||
export declare const boundsFeature: symbol; | ||
export declare const layoutContainerFeature: symbol; | ||
export declare const layoutableChildFeature: symbol; | ||
export declare const alignFeature: symbol; | ||
export declare const boundsFeature: unique symbol; | ||
export declare const layoutContainerFeature: unique symbol; | ||
export declare const layoutableChildFeature: unique symbol; | ||
export declare const alignFeature: unique symbol; | ||
/** | ||
@@ -22,6 +22,7 @@ * Model elements that implement this interface have a position and a size. | ||
} | ||
export declare type ModelLayoutOptions = { | ||
[key: string]: string | number | boolean; | ||
}; | ||
export interface LayoutableChild extends SModelExtension, BoundsAware { | ||
layoutOptions?: { | ||
[key: string]: string | number | boolean; | ||
}; | ||
layoutOptions?: ModelLayoutOptions; | ||
} | ||
@@ -48,3 +49,3 @@ /** | ||
children?: SModelElementSchema[]; | ||
layoutOptions?: any; | ||
layoutOptions?: ModelLayoutOptions; | ||
} | ||
@@ -54,6 +55,6 @@ /** | ||
*/ | ||
export declare abstract class SShapeElement extends SChildElement implements BoundsAware, Locateable { | ||
export declare abstract class SShapeElement extends SChildElement implements BoundsAware, Locateable, LayoutableChild { | ||
position: Point; | ||
size: Dimension; | ||
layoutOptions?: any; | ||
layoutOptions?: ModelLayoutOptions; | ||
bounds: Bounds; | ||
@@ -60,0 +61,0 @@ localToParent(point: Point | Bounds): Bounds; |
@@ -31,5 +31,5 @@ "use strict"; | ||
function isLayoutContainer(element) { | ||
return 'layout' in element | ||
&& isBoundsAware(element) | ||
&& element.hasFeature(exports.layoutContainerFeature); | ||
return isBoundsAware(element) | ||
&& element.hasFeature(exports.layoutContainerFeature) | ||
&& 'layout' in element; | ||
} | ||
@@ -47,4 +47,4 @@ exports.isLayoutContainer = isLayoutContainer; | ||
function isAlignable(element) { | ||
return 'alignment' in element | ||
&& element.hasFeature(exports.alignFeature); | ||
return element.hasFeature(exports.alignFeature) | ||
&& 'alignment' in element; | ||
} | ||
@@ -64,2 +64,6 @@ exports.isAlignable = isAlignable; | ||
} | ||
else if (element instanceof smodel_1.SModelRoot) { | ||
var canvasBounds = element.canvasBounds; | ||
return { x: 0, y: 0, width: canvasBounds.width, height: canvasBounds.height }; | ||
} | ||
else { | ||
@@ -66,0 +70,0 @@ return geometry_1.EMPTY_BOUNDS; |
import { SModelElement } from "../../base/model/smodel"; | ||
import { SModelExtension } from "../../base/model/smodel-extension"; | ||
export declare const expandFeature: symbol; | ||
export declare const expandFeature: unique symbol; | ||
/** | ||
@@ -5,0 +5,0 @@ * Model elements that implement this interface can be expanded/collapsed |
@@ -11,5 +11,5 @@ "use strict"; | ||
function isExpandable(element) { | ||
return 'expanded' in element && element.hasFeature(exports.expandFeature); | ||
return element.hasFeature(exports.expandFeature) && 'expanded' in element; | ||
} | ||
exports.isExpandable = isExpandable; | ||
//# sourceMappingURL=model.js.map |
import { SModelElement } from '../../base/model/smodel'; | ||
import { SModelExtension } from '../../base/model/smodel-extension'; | ||
export declare const exportFeature: symbol; | ||
export declare const exportFeature: unique symbol; | ||
export interface Exportable extends SModelExtension { | ||
@@ -5,0 +5,0 @@ export: boolean; |
import { SModelElement } from "../../base/model/smodel"; | ||
import { SModelExtension } from "../../base/model/smodel-extension"; | ||
export declare const fadeFeature: symbol; | ||
export declare const fadeFeature: unique symbol; | ||
export interface Fadeable extends SModelExtension { | ||
@@ -5,0 +5,0 @@ opacity: number; |
@@ -71,3 +71,4 @@ import { SModelElement, SModelRoot, SModelRootSchema } from "../../base/model/smodel"; | ||
export declare class HoverMouseListener extends AbstractHoverMouseListener { | ||
protected calculatePopupPosition(target: SModelElement, mousePosition: Point): Point; | ||
protected computePopupBounds(target: SModelElement, mousePosition: Point): Bounds; | ||
protected allowSidePosition(target: SModelElement, side: 'above' | 'below' | 'left' | 'right', distance: number): boolean; | ||
protected startMouseOverTimer(target: SModelElement, event: MouseEvent): Promise<Action>; | ||
@@ -77,2 +78,3 @@ mouseOver(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[]; | ||
mouseMove(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[]; | ||
protected closeOnMouseMove(target: SModelElement, event: MouseEvent): boolean; | ||
} | ||
@@ -79,0 +81,0 @@ export declare class PopupHoverMouseListener extends AbstractHoverMouseListener { |
@@ -33,2 +33,3 @@ "use strict"; | ||
var types_1 = require("../../base/types"); | ||
var smodel_1 = require("../../base/model/smodel"); | ||
var mouse_tool_1 = require("../../base/views/mouse-tool"); | ||
@@ -174,5 +175,5 @@ var command_1 = require("../../base/commands/command"); | ||
} | ||
HoverMouseListener.prototype.calculatePopupPosition = function (target, mousePosition) { | ||
HoverMouseListener.prototype.computePopupBounds = function (target, mousePosition) { | ||
// Default position: below the mouse cursor | ||
var offset = { x: -5, y: 20 }; | ||
var maxDist = 150; | ||
var targetBounds = model_1.getAbsoluteBounds(target); | ||
@@ -183,6 +184,8 @@ var canvasBounds = target.root.canvasBounds; | ||
var distBottom = boundsInWindow.y + boundsInWindow.height - mousePosition.y; | ||
if (distBottom <= distRight && distBottom < maxDist) { | ||
if (distBottom <= distRight && this.allowSidePosition(target, 'below', distBottom)) { | ||
// Put the popup below the target element | ||
offset = { x: -5, y: Math.round(distBottom + 5) }; | ||
} | ||
else if (distRight <= distBottom && distRight < maxDist) { | ||
else if (distRight <= distBottom && this.allowSidePosition(target, 'right', distRight)) { | ||
// Put the popup right of the target element | ||
offset = { x: Math.round(distRight + 5), y: -5 }; | ||
@@ -200,4 +203,7 @@ } | ||
} | ||
return { x: leftPopupPosition, y: topPopupPosition }; | ||
return { x: leftPopupPosition, y: topPopupPosition, width: -1, height: -1 }; | ||
}; | ||
HoverMouseListener.prototype.allowSidePosition = function (target, side, distance) { | ||
return !(target instanceof smodel_1.SModelRoot) && distance <= 150; | ||
}; | ||
HoverMouseListener.prototype.startMouseOverTimer = function (target, event) { | ||
@@ -208,9 +214,4 @@ var _this = this; | ||
_this.state.mouseOverTimer = window.setTimeout(function () { | ||
var popupPosition = _this.calculatePopupPosition(target, { x: event.pageX, y: event.pageY }); | ||
resolve(new RequestPopupModelAction(target.id, { | ||
x: popupPosition.x, | ||
y: popupPosition.y, | ||
width: -1, | ||
height: -1 | ||
})); | ||
var popupBounds = _this.computePopupBounds(target, { x: event.pageX, y: event.pageY }); | ||
resolve(new RequestPopupModelAction(target.id, popupBounds)); | ||
_this.state.popupOpen = true; | ||
@@ -222,7 +223,6 @@ _this.state.previousPopupElement = target; | ||
HoverMouseListener.prototype.mouseOver = function (target, event) { | ||
var state = this.state; | ||
var result = []; | ||
var popupTarget = smodel_utils_1.findParent(target, model_2.hasPopupFeature); | ||
if (state.popupOpen && (popupTarget === undefined || | ||
state.previousPopupElement !== undefined && state.previousPopupElement.id !== popupTarget.id)) { | ||
if (this.state.popupOpen && (popupTarget === undefined || | ||
this.state.previousPopupElement !== undefined && this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOutTimer()); | ||
@@ -235,3 +235,3 @@ } | ||
if (popupTarget !== undefined && | ||
(state.previousPopupElement === undefined || state.previousPopupElement.id !== popupTarget.id)) { | ||
(this.state.previousPopupElement === undefined || this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOverTimer(popupTarget, event)); | ||
@@ -246,4 +246,9 @@ } | ||
var result = []; | ||
if (!this.state.popupOpen) | ||
this.stopMouseOverTimer(); | ||
if (this.state.popupOpen) { | ||
var popupTarget = smodel_utils_1.findParent(target, model_2.hasPopupFeature); | ||
if (this.state.previousPopupElement !== undefined && popupTarget !== undefined | ||
&& this.state.previousPopupElement.id === popupTarget.id) | ||
result.push(this.startMouseOutTimer()); | ||
} | ||
this.stopMouseOverTimer(); | ||
var hoverTarget = smodel_utils_1.findParentByFeature(target, model_2.isHoverable); | ||
@@ -255,5 +260,16 @@ if (hoverTarget !== undefined) | ||
HoverMouseListener.prototype.mouseMove = function (target, event) { | ||
var result = []; | ||
if (this.state.previousPopupElement !== undefined && this.closeOnMouseMove(this.state.previousPopupElement, event)) { | ||
result.push(this.startMouseOutTimer()); | ||
} | ||
var popupTarget = smodel_utils_1.findParent(target, model_2.hasPopupFeature); | ||
return this.state.popupOpen || popupTarget === undefined ? [] : [this.startMouseOverTimer(popupTarget, event)]; | ||
if (popupTarget !== undefined && (this.state.previousPopupElement === undefined | ||
|| this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOverTimer(popupTarget, event)); | ||
} | ||
return result; | ||
}; | ||
HoverMouseListener.prototype.closeOnMouseMove = function (target, event) { | ||
return target instanceof smodel_1.SModelRoot; | ||
}; | ||
HoverMouseListener = __decorate([ | ||
@@ -260,0 +276,0 @@ inversify_1.injectable() |
import { SModelElement } from "../../base/model/smodel"; | ||
import { SModelExtension } from "../../base/model/smodel-extension"; | ||
export declare const hoverFeedbackFeature: symbol; | ||
export declare const hoverFeedbackFeature: unique symbol; | ||
export interface Hoverable extends SModelExtension { | ||
@@ -8,3 +8,3 @@ hoverFeedback: boolean; | ||
export declare function isHoverable(element: SModelElement): element is SModelElement & Hoverable; | ||
export declare const popupFeature: symbol; | ||
export declare const popupFeature: unique symbol; | ||
export declare function hasPopupFeature(element: SModelElement): boolean; |
import { Point } from "../../utils/geometry"; | ||
import { SModelElement } from "../../base/model/smodel"; | ||
import { SModelExtension } from "../../base/model/smodel-extension"; | ||
export declare const moveFeature: symbol; | ||
export declare const moveFeature: unique symbol; | ||
/** | ||
@@ -6,0 +6,0 @@ * An element that can be placed at a specific location using its position |
import { SModelElement } from "../../base/model/smodel"; | ||
export declare const openFeature: symbol; | ||
export declare const openFeature: unique symbol; | ||
export declare function isOpenable(element: SModelElement): element is SModelElement; |
import { SModelElement } from "../../base/model/smodel"; | ||
import { SModelExtension } from "../../base/model/smodel-extension"; | ||
export declare const selectFeature: symbol; | ||
export declare const selectFeature: unique symbol; | ||
export interface Selectable extends SModelExtension { | ||
@@ -5,0 +5,0 @@ selected: boolean; |
@@ -14,7 +14,7 @@ import { Animation } from '../../base/animations/animation'; | ||
export declare class UpdateModelAction implements Action { | ||
readonly newRoot: SModelRootSchema | undefined; | ||
readonly animate: boolean; | ||
readonly kind: string; | ||
matches?: Match[]; | ||
animate?: boolean; | ||
constructor(newRoot?: SModelRootSchema | undefined); | ||
readonly newRoot?: SModelRootSchema; | ||
readonly matches?: Match[]; | ||
constructor(input: SModelRootSchema | Match[], animate?: boolean); | ||
} | ||
@@ -21,0 +21,0 @@ export interface UpdateAnimationData { |
@@ -47,6 +47,10 @@ "use strict"; | ||
var UpdateModelAction = /** @class */ (function () { | ||
function UpdateModelAction(newRoot) { | ||
this.newRoot = newRoot; | ||
function UpdateModelAction(input, animate) { | ||
if (animate === void 0) { animate = true; } | ||
this.animate = animate; | ||
this.kind = UpdateModelCommand.KIND; | ||
this.animate = true; | ||
if (input.id !== undefined) | ||
this.newRoot = input; | ||
else | ||
this.matches = input; | ||
} | ||
@@ -61,4 +65,2 @@ return UpdateModelAction; | ||
_this.action = action; | ||
if (action.animate === undefined) | ||
action.animate = true; | ||
return _this; | ||
@@ -81,3 +83,3 @@ } | ||
UpdateModelCommand.prototype.performUpdate = function (oldRoot, newRoot, context) { | ||
if (this.action.animate && oldRoot.id === newRoot.id) { | ||
if ((this.action.animate === undefined || this.action.animate) && oldRoot.id === newRoot.id) { | ||
var matchResult = void 0; | ||
@@ -98,3 +100,4 @@ if (this.action.matches === undefined) { | ||
else { | ||
newRoot.canvasBounds = oldRoot.canvasBounds; | ||
if (oldRoot.type === newRoot.type && geometry_1.isValidDimension(oldRoot.canvasBounds)) | ||
newRoot.canvasBounds = oldRoot.canvasBounds; | ||
return newRoot; | ||
@@ -101,0 +104,0 @@ } |
@@ -36,7 +36,7 @@ import { Bounds } from "../../utils/geometry"; | ||
oldViewport: Viewport; | ||
newViewport: Viewport; | ||
newViewport?: Viewport; | ||
constructor(animate: boolean); | ||
protected initialize(model: SModelRoot): void; | ||
protected boundsInViewport(element: SModelElement, bounds: Bounds, viewport: SModelRoot & Viewport): Bounds; | ||
protected abstract getNewViewport(bounds: Bounds, model: SModelRoot): Viewport; | ||
protected abstract getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined; | ||
protected abstract getElementIds(): string[]; | ||
@@ -53,9 +53,3 @@ execute(context: CommandExecutionContext): SModelRoot | Promise<SModelRoot>; | ||
getElementIds(): string[]; | ||
getNewViewport(bounds: Bounds, model: SModelRoot): { | ||
scroll: { | ||
x: number; | ||
y: number; | ||
}; | ||
zoom: number; | ||
}; | ||
getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined; | ||
} | ||
@@ -67,9 +61,3 @@ export declare class FitToScreenCommand extends BoundsAwareViewportCommand { | ||
getElementIds(): string[]; | ||
getNewViewport(bounds: Bounds, model: SModelRoot): { | ||
scroll: { | ||
x: number; | ||
y: number; | ||
}; | ||
zoom: number; | ||
}; | ||
getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined; | ||
} | ||
@@ -76,0 +64,0 @@ export declare class CenterKeyboardListener extends KeyListener { |
@@ -94,5 +94,7 @@ "use strict"; | ||
} | ||
var bounds = allBounds_1.reduce(function (b0, b1) { return b0 === undefined ? b1 : geometry_1.combine(b0, b1); }, undefined); | ||
if (geometry_1.isValidDimension(bounds)) | ||
this.newViewport = this.getNewViewport(bounds, model); | ||
if (allBounds_1.length !== 0) { | ||
var bounds = allBounds_1.reduce(function (b0, b1) { return geometry_1.combine(b0, b1); }); | ||
if (geometry_1.isValidDimension(bounds)) | ||
this.newViewport = this.getNewViewport(bounds, model); | ||
} | ||
} | ||
@@ -112,3 +114,3 @@ }; | ||
var model = context.root; | ||
if (model_3.isViewport(model) && this.newViewport && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (model_3.isViewport(model) && this.newViewport !== undefined && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (this.animate) | ||
@@ -125,3 +127,3 @@ return new viewport_1.ViewportAnimation(model, this.newViewport, this.oldViewport, context).start(); | ||
var model = context.root; | ||
if (model_3.isViewport(model) && this.newViewport && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (model_3.isViewport(model) && this.newViewport !== undefined && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (this.animate) { | ||
@@ -154,2 +156,5 @@ return new viewport_1.ViewportAnimation(model, this.oldViewport, this.newViewport, context).start(); | ||
CenterCommand.prototype.getNewViewport = function (bounds, model) { | ||
if (!geometry_1.isValidDimension(model.canvasBounds)) { | ||
return undefined; | ||
} | ||
var c = geometry_1.center(bounds); | ||
@@ -179,2 +184,5 @@ return { | ||
FitToScreenCommand.prototype.getNewViewport = function (bounds, model) { | ||
if (!geometry_1.isValidDimension(model.canvasBounds)) { | ||
return undefined; | ||
} | ||
var c = geometry_1.center(bounds); | ||
@@ -181,0 +189,0 @@ var delta = this.action.padding === undefined |
import { SModelElement, SModelRoot } from "../../base/model/smodel"; | ||
import { Scrollable } from "./scroll"; | ||
import { Zoomable } from "./zoom"; | ||
export declare const viewportFeature: symbol; | ||
export declare const viewportFeature: unique symbol; | ||
export interface Viewport extends Scrollable, Zoomable { | ||
} | ||
export declare function isViewport(element: SModelElement): element is SModelRoot & Viewport; |
import { SChildElement, SModelElementSchema, SModelRootSchema } from '../base/model/smodel'; | ||
import { Alignable } from '../features/bounds/model'; | ||
import { Alignable, ModelLayoutOptions } from '../features/bounds/model'; | ||
import { Fadeable } from '../features/fade/model'; | ||
@@ -17,3 +17,3 @@ import { Hoverable } from '../features/hover/model'; | ||
zoom?: number; | ||
layoutOptions?: any; | ||
layoutOptions?: ModelLayoutOptions; | ||
} | ||
@@ -24,3 +24,3 @@ /** | ||
export declare class SGraph extends ViewportRootElement { | ||
layoutOptions?: any; | ||
layoutOptions?: ModelLayoutOptions; | ||
} | ||
@@ -32,2 +32,5 @@ /** | ||
layout?: string; | ||
selected?: boolean; | ||
hoverFeedback?: boolean; | ||
opacity?: number; | ||
} | ||
@@ -40,9 +43,6 @@ /** | ||
export declare class SNode extends SShapeElement implements Selectable, Fadeable, Hoverable { | ||
hoverFeedback: boolean; | ||
children: SChildElement[]; | ||
layout?: string; | ||
layoutOptions?: { | ||
[key: string]: string | number | boolean; | ||
}; | ||
selected: boolean; | ||
hoverFeedback: boolean; | ||
opacity: number; | ||
@@ -55,2 +55,4 @@ hasFeature(feature: symbol): boolean; | ||
export interface SPortSchema extends SShapeElementSchema { | ||
selected?: boolean; | ||
opacity?: number; | ||
} | ||
@@ -73,2 +75,3 @@ /** | ||
routingPoints?: Point[]; | ||
opacity?: number; | ||
} | ||
@@ -75,0 +78,0 @@ /** |
@@ -48,4 +48,4 @@ "use strict"; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this.selected = false; | ||
_this.hoverFeedback = false; | ||
_this.selected = false; | ||
_this.opacity = 1; | ||
@@ -52,0 +52,0 @@ return _this; |
@@ -41,3 +41,4 @@ import { Bounds, Point } from "../utils/geometry"; | ||
clientId: string; | ||
currentRoot: SModelRootSchema; | ||
protected currentRoot: SModelRootSchema; | ||
protected lastSubmittedModelType: string; | ||
constructor(actionDispatcher: IActionDispatcher, actionHandlerRegistry: ActionHandlerRegistry, viewerOptions: ViewerOptions, storage: SModelStorage, logger: ILogger); | ||
@@ -44,0 +45,0 @@ protected initialize(registry: ActionHandlerRegistry): void; |
@@ -109,4 +109,4 @@ "use strict"; | ||
if (!object.clientId || object.clientId === this.clientId) { | ||
object.action[receivedFromServerProperty] = true; | ||
this.logger.log(this, 'receiving', object); | ||
object.action[receivedFromServerProperty] = true; | ||
this.actionDispatcher.dispatch(object.action, this.storeNewModel.bind(this)); | ||
@@ -147,2 +147,5 @@ } | ||
this.currentRoot = newRoot; | ||
if (action.kind === set_model_1.SetModelCommand.KIND || action.kind === update_model_1.UpdateModelCommand.KIND) { | ||
this.lastSubmittedModelType = newRoot.type; | ||
} | ||
this.storage.store(this.currentRoot); | ||
@@ -162,3 +165,4 @@ } | ||
var index = new smodel_1.SModelIndex(); | ||
index.add(this.currentRoot); | ||
var root = this.currentRoot; | ||
index.add(root); | ||
for (var _i = 0, _a = action.bounds; _i < _a.length; _i++) { | ||
@@ -178,3 +182,9 @@ var b = _a[_i]; | ||
} | ||
this.actionDispatcher.dispatch(new update_model_1.UpdateModelAction(this.currentRoot)); | ||
if (root.type === this.lastSubmittedModelType) { | ||
this.actionDispatcher.dispatch(new update_model_1.UpdateModelAction(root)); | ||
} | ||
else { | ||
this.actionDispatcher.dispatch(new set_model_1.SetModelAction(root)); | ||
} | ||
this.lastSubmittedModelType = root.type; | ||
return false; | ||
@@ -181,0 +191,0 @@ } |
@@ -27,2 +27,3 @@ import { Bounds, Point } from "../utils/geometry"; | ||
protected currentRoot: SModelRootSchema; | ||
protected lastSubmittedModelType: string; | ||
model: SModelRootSchema; | ||
@@ -36,2 +37,3 @@ protected onModelSubmitted: (newRoot: SModelRootSchema) => void; | ||
protected submitModel(newRoot: SModelRootSchema, update: boolean): void; | ||
protected doSubmitModel(newRoot: SModelRootSchema, update: boolean): void; | ||
applyMatches(matches: Match[]): void; | ||
@@ -38,0 +40,0 @@ addElements(elements: (SModelElementSchema | { |
@@ -106,13 +106,17 @@ "use strict"; | ||
else { | ||
if (update) { | ||
this.actionDispatcher.dispatch(new update_model_1.UpdateModelAction(newRoot)); | ||
} | ||
else { | ||
this.actionDispatcher.dispatch(new set_model_1.SetModelAction(newRoot)); | ||
} | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(newRoot); | ||
} | ||
this.doSubmitModel(newRoot, update); | ||
} | ||
}; | ||
LocalModelSource.prototype.doSubmitModel = function (newRoot, update) { | ||
if (update && newRoot.type === this.lastSubmittedModelType) { | ||
this.actionDispatcher.dispatch(new update_model_1.UpdateModelAction(newRoot)); | ||
} | ||
else { | ||
this.actionDispatcher.dispatch(new set_model_1.SetModelAction(newRoot)); | ||
} | ||
this.lastSubmittedModelType = newRoot.type; | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(newRoot); | ||
} | ||
}; | ||
LocalModelSource.prototype.applyMatches = function (matches) { | ||
@@ -125,5 +129,5 @@ var root = this.currentRoot; | ||
else { | ||
var update = new update_model_1.UpdateModelAction(); | ||
update.matches = matches; | ||
var update = new update_model_1.UpdateModelAction(matches); | ||
this.actionDispatcher.dispatch(update); | ||
this.lastSubmittedModelType = root.type; | ||
if (this.onModelSubmitted !== undefined) { | ||
@@ -203,2 +207,4 @@ this.onModelSubmitted(root); | ||
LocalModelSource.prototype.handleRequestModel = function (action) { | ||
if (this.modelProvider) | ||
this.currentRoot = this.modelProvider.getModel(this.diagramState, this.currentRoot); | ||
this.submitModel(this.currentRoot, false); | ||
@@ -224,6 +230,3 @@ }; | ||
} | ||
this.actionDispatcher.dispatch(new update_model_1.UpdateModelAction(root)); | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(root); | ||
} | ||
this.doSubmitModel(root, true); | ||
}; | ||
@@ -230,0 +233,0 @@ LocalModelSource.prototype.applyBounds = function (element, newBounds) { |
@@ -25,3 +25,3 @@ import { Action } from "../base/actions/action"; | ||
export declare abstract class ModelSource implements IActionHandler { | ||
protected actionDispatcher: IActionDispatcher; | ||
readonly actionDispatcher: IActionDispatcher; | ||
protected viewerOptions: ViewerOptions; | ||
@@ -28,0 +28,0 @@ constructor(actionDispatcher: IActionDispatcher, actionHandlerRegistry: ActionHandlerRegistry, viewerOptions: ViewerOptions); |
@@ -13,2 +13,16 @@ /** | ||
/** | ||
* Adds two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The sum of the two points | ||
*/ | ||
export declare function add(p1: Point, p2: Point): Point; | ||
/** | ||
* Subtracts two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The difference of the two points | ||
*/ | ||
export declare function subtract(p1: Point, p2: Point): Point; | ||
/** | ||
* The Dimension of an object is composed of its width and height. | ||
@@ -15,0 +29,0 @@ */ |
@@ -17,2 +17,28 @@ "use strict"; | ||
/** | ||
* Adds two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The sum of the two points | ||
*/ | ||
function add(p1, p2) { | ||
return { | ||
x: p1.x + p2.x, | ||
y: p1.y + p2.y | ||
}; | ||
} | ||
exports.add = add; | ||
/** | ||
* Subtracts two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The difference of the two points | ||
*/ | ||
function subtract(p1, p2) { | ||
return { | ||
x: p1.x - p2.x, | ||
y: p1.y - p2.y | ||
}; | ||
} | ||
exports.subtract = subtract; | ||
/** | ||
* A dimension with both width and height set to a negative value, which is considered as undefined. | ||
@@ -19,0 +45,0 @@ */ |
{ | ||
"name": "sprotty", | ||
"version": "0.2.1", | ||
"version": "0.3.0-next.04f191a3", | ||
"description": "A next-gen framework for graphical views", | ||
@@ -65,5 +65,7 @@ "license": "Apache-2.0", | ||
"@types/node": "^8.0.14", | ||
"bootstrap": "^3.3.7", | ||
"chai": "^4.1.0", | ||
"circular-dependency-plugin": "^2.0.0", | ||
"core-js": "^2.5.1", | ||
"dom4": "^1.8.5", | ||
"jenkins-mocha": "^4.1.2", | ||
@@ -70,0 +72,0 @@ "jsdom": "9.12.0", |
@@ -39,3 +39,3 @@ /* | ||
this.postponedActions = [] | ||
const initialCommand = new SetModelCommand(new SetModelAction(EMPTY_ROOT, true)) | ||
const initialCommand = new SetModelCommand(new SetModelAction(EMPTY_ROOT)) | ||
this.blockUntilActionKind = initialCommand.blockUntilActionKind | ||
@@ -42,0 +42,0 @@ this.commandStack.execute(initialCommand) |
@@ -131,2 +131,8 @@ /* | ||
protected get currentModel(): Promise<SModelRoot> { | ||
return this.currentPromise.then( | ||
state => state.root | ||
) | ||
} | ||
executeAll(commands: ICommand[]): Promise<SModelRoot> { | ||
@@ -266,5 +272,3 @@ commands.forEach( | ||
) | ||
return this.currentPromise.then( | ||
state => state.root | ||
) | ||
return this.currentModel | ||
} | ||
@@ -271,0 +275,0 @@ |
@@ -93,3 +93,3 @@ /* | ||
needsServerLayout: false, | ||
popupOpenDelay: 700, | ||
popupOpenDelay: 1000, | ||
popupCloseDelay: 300 | ||
@@ -96,0 +96,0 @@ }) |
@@ -26,3 +26,3 @@ /* | ||
rootAndVnode: [SModelRoot, VNode] | undefined | ||
protected rootAndVnode: [SModelRoot, VNode] | undefined | ||
@@ -77,3 +77,2 @@ constructor(@inject(TYPES.IActionDispatcher) protected actionDispatcher: IActionDispatcher) {} | ||
private oldCanvasBounds: Bounds | ||
private newCanvasBounds: Bounds | ||
@@ -86,3 +85,2 @@ | ||
execute(context: CommandExecutionContext) { | ||
this.oldCanvasBounds = context.root.canvasBounds | ||
this.newCanvasBounds = this.action.newCanvasBounds | ||
@@ -89,0 +87,0 @@ context.root.canvasBounds = this.newCanvasBounds |
@@ -10,3 +10,2 @@ /* | ||
import { Action } from "../actions/action" | ||
import { isValidDimension } from "../../utils/geometry" | ||
import { SModelRoot, SModelRootSchema } from "../model/smodel" | ||
@@ -35,4 +34,3 @@ import { Command, CommandExecutionContext } from "../commands/command" | ||
constructor(public readonly newRoot: SModelRootSchema, | ||
public readonly isInitial: boolean = false) { | ||
constructor(public readonly newRoot: SModelRootSchema) { | ||
} | ||
@@ -55,5 +53,2 @@ } | ||
this.newRoot = context.modelFactory.createRoot(this.action.newRoot) | ||
if (isValidDimension(this.oldRoot.canvasBounds)) { | ||
this.newRoot.canvasBounds = this.oldRoot.canvasBounds | ||
} | ||
return this.newRoot | ||
@@ -71,7 +66,4 @@ } | ||
get blockUntilActionKind() { | ||
if (this.action.isInitial) | ||
return InitializeCanvasBoundsCommand.KIND | ||
else | ||
return undefined | ||
return InitializeCanvasBoundsCommand.KIND | ||
} | ||
} |
@@ -9,3 +9,3 @@ /* | ||
import { Bounds, EMPTY_BOUNDS, EMPTY_DIMENSION, Dimension, isBounds, ORIGIN_POINT, Point } from "../../utils/geometry" | ||
import { SModelElement, SModelElementSchema, SParentElement, SChildElement } from "../../base/model/smodel" | ||
import { SModelElement, SModelElementSchema, SParentElement, SChildElement, SModelRoot } from "../../base/model/smodel" | ||
import { SModelExtension } from "../../base/model/smodel-extension" | ||
@@ -34,4 +34,6 @@ import { findParentByFeature } from '../../base/model/smodel-utils' | ||
export type ModelLayoutOptions = {[key: string]: string | number | boolean} | ||
export interface LayoutableChild extends SModelExtension, BoundsAware { | ||
layoutOptions?: {[key: string]: string | number | boolean} | ||
layoutOptions?: ModelLayoutOptions | ||
} | ||
@@ -52,5 +54,5 @@ | ||
export function isLayoutContainer(element: SModelElement): element is SParentElement & LayoutContainer { | ||
return 'layout' in element | ||
&& isBoundsAware(element) | ||
return isBoundsAware(element) | ||
&& element.hasFeature(layoutContainerFeature) | ||
&& 'layout' in element | ||
} | ||
@@ -68,4 +70,4 @@ | ||
export function isAlignable(element: SModelElement): element is SModelElement & Alignable { | ||
return 'alignment' in element | ||
&& element.hasFeature(alignFeature) | ||
return element.hasFeature(alignFeature) | ||
&& 'alignment' in element | ||
} | ||
@@ -84,2 +86,5 @@ | ||
return bounds | ||
} else if (element instanceof SModelRoot) { | ||
const canvasBounds = element.canvasBounds | ||
return { x: 0, y: 0, width: canvasBounds.width, height: canvasBounds.height } | ||
} else { | ||
@@ -97,3 +102,3 @@ return EMPTY_BOUNDS | ||
children?: SModelElementSchema[] | ||
layoutOptions?: any | ||
layoutOptions?: ModelLayoutOptions | ||
} | ||
@@ -104,6 +109,6 @@ | ||
*/ | ||
export abstract class SShapeElement extends SChildElement implements BoundsAware, Locateable { | ||
export abstract class SShapeElement extends SChildElement implements BoundsAware, Locateable, LayoutableChild { | ||
position: Point = ORIGIN_POINT | ||
size: Dimension = EMPTY_DIMENSION | ||
layoutOptions?: any | ||
layoutOptions?: ModelLayoutOptions | ||
@@ -110,0 +115,0 @@ get bounds(): Bounds { |
@@ -21,3 +21,3 @@ /* | ||
export function isExpandable(element: SModelElement): element is SModelElement & Expandable { | ||
return 'expanded' in element && element.hasFeature(expandFeature) | ||
return element.hasFeature(expandFeature) && 'expanded' in element | ||
} |
@@ -154,5 +154,5 @@ /* | ||
protected calculatePopupPosition(target: SModelElement, mousePosition: Point): Point { | ||
let offset: Point = {x: -5, y: 20} | ||
const maxDist = 150 | ||
protected computePopupBounds(target: SModelElement, mousePosition: Point): Bounds { | ||
// Default position: below the mouse cursor | ||
let offset: Point = { x: -5, y: 20 } | ||
@@ -164,6 +164,8 @@ const targetBounds = getAbsoluteBounds(target) | ||
const distBottom = boundsInWindow.y + boundsInWindow.height - mousePosition.y | ||
if (distBottom <= distRight && distBottom < maxDist) { | ||
offset = {x: -5, y: Math.round(distBottom + 5)} | ||
} else if (distRight <= distBottom && distRight < maxDist) { | ||
offset = {x: Math.round(distRight + 5), y: -5} | ||
if (distBottom <= distRight && this.allowSidePosition(target, 'below', distBottom)) { | ||
// Put the popup below the target element | ||
offset = { x: -5, y: Math.round(distBottom + 5) } | ||
} else if (distRight <= distBottom && this.allowSidePosition(target, 'right', distRight)) { | ||
// Put the popup right of the target element | ||
offset = { x: Math.round(distRight + 5), y: -5 } | ||
} | ||
@@ -180,5 +182,9 @@ let leftPopupPosition = mousePosition.x + offset.x | ||
} | ||
return {x: leftPopupPosition, y: topPopupPosition} | ||
return { x: leftPopupPosition, y: topPopupPosition, width: -1, height: -1 } | ||
} | ||
protected allowSidePosition(target: SModelElement, side: 'above' | 'below' | 'left' | 'right', distance: number): boolean { | ||
return !(target instanceof SModelRoot) && distance <= 150 | ||
} | ||
protected startMouseOverTimer(target: SModelElement, event: MouseEvent): Promise<Action> { | ||
@@ -188,10 +194,4 @@ this.stopMouseOverTimer() | ||
this.state.mouseOverTimer = window.setTimeout(() => { | ||
const popupPosition = this.calculatePopupPosition(target, {x: event.pageX, y: event.pageY}) | ||
resolve(new RequestPopupModelAction(target.id, | ||
{ | ||
x: popupPosition.x, | ||
y: popupPosition.y, | ||
width: -1, | ||
height: -1 | ||
})) | ||
const popupBounds = this.computePopupBounds(target, {x: event.pageX, y: event.pageY}) | ||
resolve(new RequestPopupModelAction(target.id, popupBounds)) | ||
@@ -205,8 +205,7 @@ this.state.popupOpen = true | ||
mouseOver(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[] { | ||
const state = this.state | ||
const result: (Action | Promise<Action>)[] = [] | ||
const popupTarget = findParent(target, hasPopupFeature) | ||
if (state.popupOpen && (popupTarget === undefined || | ||
state.previousPopupElement !== undefined && state.previousPopupElement.id !== popupTarget.id)) { | ||
if (this.state.popupOpen && (popupTarget === undefined || | ||
this.state.previousPopupElement !== undefined && this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOutTimer()) | ||
@@ -218,3 +217,3 @@ } else { | ||
if (popupTarget !== undefined && | ||
(state.previousPopupElement === undefined || state.previousPopupElement.id !== popupTarget.id)) { | ||
(this.state.previousPopupElement === undefined || this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOverTimer(popupTarget, event)) | ||
@@ -233,4 +232,9 @@ } | ||
if (!this.state.popupOpen) | ||
this.stopMouseOverTimer() | ||
if (this.state.popupOpen) { | ||
const popupTarget = findParent(target, hasPopupFeature) | ||
if (this.state.previousPopupElement !== undefined && popupTarget !== undefined | ||
&& this.state.previousPopupElement.id === popupTarget.id) | ||
result.push(this.startMouseOutTimer()) | ||
} | ||
this.stopMouseOverTimer() | ||
@@ -245,5 +249,21 @@ const hoverTarget = findParentByFeature(target, isHoverable) | ||
mouseMove(target: SModelElement, event: MouseEvent): (Action | Promise<Action>)[] { | ||
const result: (Action | Promise<Action>)[] = [] | ||
if (this.state.previousPopupElement !== undefined && this.closeOnMouseMove(this.state.previousPopupElement, event)) { | ||
result.push(this.startMouseOutTimer()) | ||
} | ||
const popupTarget = findParent(target, hasPopupFeature) | ||
return this.state.popupOpen || popupTarget === undefined ? [] : [this.startMouseOverTimer(popupTarget, event)] | ||
if (popupTarget !== undefined && (this.state.previousPopupElement === undefined | ||
|| this.state.previousPopupElement.id !== popupTarget.id)) { | ||
result.push(this.startMouseOverTimer(popupTarget, event)) | ||
} | ||
return result | ||
} | ||
protected closeOnMouseMove(target: SModelElement, event: MouseEvent): boolean { | ||
return target instanceof SModelRoot | ||
} | ||
} | ||
@@ -250,0 +270,0 @@ |
@@ -102,2 +102,3 @@ /* | ||
kind: UpdateModelCommand.KIND, | ||
animate: true, | ||
newRoot: { | ||
@@ -146,2 +147,3 @@ type: 'graph', | ||
kind: UpdateModelCommand.KIND, | ||
animate: true, | ||
newRoot: { | ||
@@ -178,2 +180,3 @@ type: 'graph', | ||
kind: UpdateModelCommand.KIND, | ||
animate: true, | ||
newRoot: { | ||
@@ -218,2 +221,3 @@ type: 'graph', | ||
kind: UpdateModelCommand.KIND, | ||
animate: true, | ||
newRoot: { | ||
@@ -220,0 +224,0 @@ type: 'graph', |
@@ -30,6 +30,12 @@ /* | ||
readonly kind = UpdateModelCommand.KIND | ||
matches?: Match[] | ||
animate?: boolean = true | ||
constructor(public readonly newRoot?: SModelRootSchema) { | ||
public readonly newRoot?: SModelRootSchema | ||
public readonly matches?: Match[] | ||
constructor(input: SModelRootSchema | Match[], | ||
public readonly animate: boolean = true) { | ||
if ((input as SModelRootSchema).id !== undefined) | ||
this.newRoot = input as SModelRootSchema | ||
else | ||
this.matches = input as Match[] | ||
} | ||
@@ -53,4 +59,2 @@ } | ||
super() | ||
if (action.animate === undefined) | ||
action.animate = true | ||
} | ||
@@ -73,3 +77,3 @@ | ||
protected performUpdate(oldRoot: SModelRoot, newRoot: SModelRoot, context: CommandExecutionContext): CommandResult { | ||
if (this.action.animate && oldRoot.id === newRoot.id) { | ||
if ((this.action.animate === undefined || this.action.animate) && oldRoot.id === newRoot.id) { | ||
let matchResult: MatchResult | ||
@@ -88,3 +92,4 @@ if (this.action.matches === undefined) { | ||
} else { | ||
newRoot.canvasBounds = oldRoot.canvasBounds | ||
if (oldRoot.type === newRoot.type && isValidDimension(oldRoot.canvasBounds)) | ||
newRoot.canvasBounds = oldRoot.canvasBounds | ||
return newRoot | ||
@@ -91,0 +96,0 @@ } |
@@ -53,3 +53,3 @@ /* | ||
oldViewport: Viewport | ||
newViewport: Viewport | ||
newViewport?: Viewport | ||
@@ -90,5 +90,7 @@ constructor(protected readonly animate: boolean) { | ||
} | ||
const bounds = allBounds.reduce((b0, b1) => b0 === undefined ? b1 : combine(b0, b1), undefined) | ||
if (isValidDimension(bounds)) | ||
this.newViewport = this.getNewViewport(bounds, model) | ||
if (allBounds.length !== 0) { | ||
const bounds = allBounds.reduce((b0, b1) => combine(b0, b1)) | ||
if (isValidDimension(bounds)) | ||
this.newViewport = this.getNewViewport(bounds, model) | ||
} | ||
} | ||
@@ -104,3 +106,3 @@ } | ||
protected abstract getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | ||
protected abstract getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined | ||
@@ -116,3 +118,3 @@ protected abstract getElementIds(): string[] | ||
const model = context.root | ||
if (isViewport(model) && this.newViewport && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (isViewport(model) && this.newViewport !== undefined && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (this.animate) | ||
@@ -130,3 +132,3 @@ return new ViewportAnimation(model, this.newViewport, this.oldViewport, context).start() | ||
const model = context.root | ||
if (isViewport(model) && this.newViewport && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (isViewport(model) && this.newViewport !== undefined && !this.equal(this.newViewport, this.oldViewport)) { | ||
if (this.animate) { | ||
@@ -158,3 +160,6 @@ return new ViewportAnimation(model, this.oldViewport, this.newViewport, context).start() | ||
getNewViewport(bounds: Bounds, model: SModelRoot) { | ||
getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined { | ||
if (!isValidDimension(model.canvasBounds)) { | ||
return undefined | ||
} | ||
const c = center(bounds) | ||
@@ -182,3 +187,6 @@ return { | ||
getNewViewport(bounds: Bounds, model: SModelRoot) { | ||
getNewViewport(bounds: Bounds, model: SModelRoot): Viewport | undefined { | ||
if (!isValidDimension(model.canvasBounds)) { | ||
return undefined | ||
} | ||
const c = center(bounds) | ||
@@ -185,0 +193,0 @@ const delta = this.action.padding === undefined |
@@ -22,3 +22,3 @@ /* | ||
hasFeature(feature: symbol) { | ||
hasFeature(feature: symbol): boolean { | ||
return feature === viewportFeature || feature === exportFeature | ||
@@ -25,0 +25,0 @@ } |
@@ -9,3 +9,3 @@ /* | ||
import { SChildElement, SModelElementSchema, SModelRootSchema } from '../base/model/smodel' | ||
import { boundsFeature, layoutContainerFeature, layoutableChildFeature, Alignable, alignFeature } from '../features/bounds/model' | ||
import { boundsFeature, layoutContainerFeature, layoutableChildFeature, Alignable, alignFeature, ModelLayoutOptions } from '../features/bounds/model' | ||
import { Fadeable, fadeFeature } from '../features/fade/model' | ||
@@ -27,3 +27,3 @@ import { Hoverable, hoverFeedbackFeature, popupFeature } from '../features/hover/model' | ||
zoom?: number | ||
layoutOptions?: any | ||
layoutOptions?: ModelLayoutOptions | ||
} | ||
@@ -35,3 +35,3 @@ | ||
export class SGraph extends ViewportRootElement { | ||
layoutOptions?: any | ||
layoutOptions?: ModelLayoutOptions | ||
} | ||
@@ -44,2 +44,5 @@ | ||
layout?: string | ||
selected?: boolean | ||
hoverFeedback?: boolean | ||
opacity?: number | ||
} | ||
@@ -53,7 +56,6 @@ | ||
export class SNode extends SShapeElement implements Selectable, Fadeable, Hoverable { | ||
hoverFeedback: boolean = false | ||
children: SChildElement[] | ||
layout?: string | ||
layoutOptions?: {[key: string]: string | number | boolean} | ||
selected: boolean = false | ||
hoverFeedback: boolean = false | ||
opacity: number = 1 | ||
@@ -72,2 +74,4 @@ | ||
export interface SPortSchema extends SShapeElementSchema { | ||
selected?: boolean | ||
opacity?: number | ||
} | ||
@@ -96,2 +100,3 @@ | ||
routingPoints?: Point[] | ||
opacity?: number | ||
} | ||
@@ -98,0 +103,0 @@ |
@@ -19,3 +19,3 @@ /* | ||
import { ViewerOptions } from "../base/views/viewer-options" | ||
import { SetModelCommand } from "../base/features/set-model" | ||
import { SetModelCommand, SetModelAction } from "../base/features/set-model" | ||
import { UpdateModelCommand, UpdateModelAction } from "../features/update/update-model" | ||
@@ -66,3 +66,3 @@ import { ComputedBoundsAction, RequestBoundsCommand } from '../features/bounds/bounds-manipulation' | ||
currentRoot: SModelRootSchema = { | ||
protected currentRoot: SModelRootSchema = { | ||
type: 'NONE', | ||
@@ -72,2 +72,4 @@ id: 'ROOT' | ||
protected lastSubmittedModelType: string | ||
constructor(@inject(TYPES.IActionDispatcher) actionDispatcher: IActionDispatcher, | ||
@@ -116,4 +118,4 @@ @inject(TYPES.ActionHandlerRegistry) actionHandlerRegistry: ActionHandlerRegistry, | ||
if (!object.clientId || object.clientId === this.clientId) { | ||
this.logger.log(this, 'receiving', object); | ||
(object.action as any)[receivedFromServerProperty] = true | ||
this.logger.log(this, 'receiving', object) | ||
this.actionDispatcher.dispatch(object.action, this.storeNewModel.bind(this)) | ||
@@ -155,2 +157,5 @@ } | ||
this.currentRoot = newRoot as SModelRootSchema | ||
if (action.kind === SetModelCommand.KIND || action.kind === UpdateModelCommand.KIND) { | ||
this.lastSubmittedModelType = newRoot.type | ||
} | ||
this.storage.store(this.currentRoot) | ||
@@ -170,3 +175,4 @@ } | ||
const index = new SModelIndex() | ||
index.add(this.currentRoot) | ||
const root = this.currentRoot | ||
index.add(root) | ||
for (const b of action.bounds) { | ||
@@ -184,3 +190,8 @@ const element = index.getById(b.elementId) | ||
} | ||
this.actionDispatcher.dispatch(new UpdateModelAction(this.currentRoot)) | ||
if (root.type === this.lastSubmittedModelType) { | ||
this.actionDispatcher.dispatch(new UpdateModelAction(root)) | ||
} else { | ||
this.actionDispatcher.dispatch(new SetModelAction(root)) | ||
} | ||
this.lastSubmittedModelType = root.type | ||
return false | ||
@@ -187,0 +198,0 @@ } |
@@ -99,8 +99,3 @@ /* | ||
elementId: 'child1', | ||
newBounds: { | ||
x: 10, | ||
y: 10, | ||
width: 20, | ||
height: 20 | ||
} | ||
newBounds: { x: 10, y: 10, width: 20, height: 20 } | ||
} | ||
@@ -119,9 +114,15 @@ ])) | ||
modelSource.updateModel(root2) | ||
modelSource.handle(new ComputedBoundsAction([ | ||
{ | ||
elementId: 'bar', | ||
newBounds: { x: 10, y: 10, width: 20, height: 20 } | ||
} | ||
])) | ||
expect(dispatcher.actions).to.have.lengthOf(3) | ||
expect(dispatcher.actions).to.have.lengthOf(4) | ||
const action0 = dispatcher.actions[0] as RequestBoundsAction | ||
expect(action0).to.be.instanceOf(RequestBoundsAction) | ||
expect(action0.newRoot).to.equal(root1) | ||
const action1 = dispatcher.actions[1] as UpdateModelAction | ||
expect(action1).to.be.instanceOf(UpdateModelAction) | ||
const action1 = dispatcher.actions[1] as SetModelAction | ||
expect(action1).to.be.instanceOf(SetModelAction) | ||
expect(action1.newRoot).to.deep.equal({ | ||
@@ -142,2 +143,4 @@ type: 'root', | ||
expect(action2.newRoot).to.equal(root2) | ||
const action3 = dispatcher.actions[3] as UpdateModelAction | ||
expect(action3).to.be.instanceOf(UpdateModelAction) | ||
}) | ||
@@ -144,0 +147,0 @@ |
@@ -47,2 +47,4 @@ /* | ||
protected lastSubmittedModelType: string | ||
get model(): SModelRootSchema { | ||
@@ -105,13 +107,18 @@ return this.currentRoot | ||
} else { | ||
if (update) { | ||
this.actionDispatcher.dispatch(new UpdateModelAction(newRoot)) | ||
} else { | ||
this.actionDispatcher.dispatch(new SetModelAction(newRoot)) | ||
} | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(newRoot) | ||
} | ||
this.doSubmitModel(newRoot, update) | ||
} | ||
} | ||
protected doSubmitModel(newRoot: SModelRootSchema, update: boolean): void { | ||
if (update && newRoot.type === this.lastSubmittedModelType) { | ||
this.actionDispatcher.dispatch(new UpdateModelAction(newRoot)) | ||
} else { | ||
this.actionDispatcher.dispatch(new SetModelAction(newRoot)) | ||
} | ||
this.lastSubmittedModelType = newRoot.type | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(newRoot) | ||
} | ||
} | ||
applyMatches(matches: Match[]): void { | ||
@@ -123,5 +130,5 @@ const root = this.currentRoot | ||
} else { | ||
const update = new UpdateModelAction() | ||
update.matches = matches | ||
const update = new UpdateModelAction(matches) | ||
this.actionDispatcher.dispatch(update) | ||
this.lastSubmittedModelType = root.type | ||
if (this.onModelSubmitted !== undefined) { | ||
@@ -203,2 +210,4 @@ this.onModelSubmitted(root) | ||
protected handleRequestModel(action: RequestModelAction): void { | ||
if (this.modelProvider) | ||
this.currentRoot = this.modelProvider.getModel(this.diagramState, this.currentRoot) | ||
this.submitModel(this.currentRoot, false) | ||
@@ -223,6 +232,3 @@ } | ||
} | ||
this.actionDispatcher.dispatch(new UpdateModelAction(root)) | ||
if (this.onModelSubmitted !== undefined) { | ||
this.onModelSubmitted(root) | ||
} | ||
this.doSubmitModel(root, true) | ||
} | ||
@@ -229,0 +235,0 @@ |
@@ -39,3 +39,3 @@ /* | ||
constructor(@inject(TYPES.IActionDispatcher) protected actionDispatcher: IActionDispatcher, | ||
constructor(@inject(TYPES.IActionDispatcher) readonly actionDispatcher: IActionDispatcher, | ||
@inject(TYPES.ActionHandlerRegistry) actionHandlerRegistry: ActionHandlerRegistry, | ||
@@ -42,0 +42,0 @@ @inject(TYPES.ViewerOptions) protected viewerOptions: ViewerOptions) { |
@@ -25,2 +25,28 @@ /* | ||
/** | ||
* Adds two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The sum of the two points | ||
*/ | ||
export function add(p1: Point, p2: Point): Point { | ||
return { | ||
x: p1.x + p2.x, | ||
y: p1.y + p2.y | ||
} | ||
} | ||
/** | ||
* Subtracts two points. | ||
* @param {Point} p1 - First point | ||
* @param {Point} p2 - Second point | ||
* @returns {Point} The difference of the two points | ||
*/ | ||
export function subtract(p1: Point, p2: Point): Point { | ||
return { | ||
x: p1.x - p2.x, | ||
y: p1.y - p2.y | ||
} | ||
} | ||
/** | ||
* The Dimension of an object is composed of its width and height. | ||
@@ -27,0 +53,0 @@ */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1137032
21207
25