Comparing version 1.0.0 to 1.1.0
@@ -16,2 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import 'reflect-metadata'; | ||
import { Action } from "sprotty-protocol/lib/actions"; | ||
@@ -18,0 +19,0 @@ import { ILogger } from "../../utils/logging"; |
@@ -25,2 +25,3 @@ "use strict"; | ||
exports.ResetCommand = exports.SystemCommand = exports.PopupCommand = exports.HiddenCommand = exports.MergeableCommand = exports.Command = void 0; | ||
require("reflect-metadata"); | ||
const inversify_1 = require("inversify"); | ||
@@ -27,0 +28,0 @@ /** |
@@ -21,2 +21,4 @@ /******************************************************************************** | ||
import { CustomFeatures } from '../model/smodel-factory'; | ||
import { Point } from 'sprotty-protocol'; | ||
import { ILogger } from '../../utils/logging'; | ||
/** | ||
@@ -73,2 +75,3 @@ * Arguments for `IView` rendering. | ||
export declare class ViewRegistry extends InstanceRegistry<IView> { | ||
protected logger: ILogger; | ||
constructor(registrations: ViewRegistration[]); | ||
@@ -102,4 +105,6 @@ protected registerDefaults(): void; | ||
export declare class MissingView implements IView { | ||
private static positionMap; | ||
render(model: Readonly<SModelElementImpl>, context: RenderingContext): VNode; | ||
getPostion(type: string): Point; | ||
} | ||
//# sourceMappingURL=view.d.ts.map |
@@ -29,2 +29,3 @@ "use strict"; | ||
}; | ||
var MissingView_1; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -69,2 +70,3 @@ exports.MissingView = exports.EmptyView = exports.configureView = exports.configureModelElement = exports.ViewRegistry = exports.findArgValue = void 0; | ||
missing(key) { | ||
this.logger.warn(this, `no registered view for type '${key}', please configure a view in the ContainerModule`); | ||
return new MissingView(); | ||
@@ -74,2 +76,6 @@ } | ||
exports.ViewRegistry = ViewRegistry; | ||
__decorate([ | ||
(0, inversify_1.inject)(types_1.TYPES.ILogger), | ||
__metadata("design:type", Object) | ||
], ViewRegistry.prototype, "logger", void 0); | ||
exports.ViewRegistry = ViewRegistry = __decorate([ | ||
@@ -122,15 +128,25 @@ (0, inversify_1.injectable)(), | ||
*/ | ||
let MissingView = class MissingView { | ||
let MissingView = MissingView_1 = class MissingView { | ||
render(model, context) { | ||
const position = model.position || sprotty_protocol_1.Point.ORIGIN; | ||
const position = model.position || this.getPostion(model.type); | ||
return (0, jsx_1.svg)("text", { "class-sprotty-missing": true, x: position.x, y: position.y }, | ||
"?", | ||
model.id, | ||
"?"); | ||
"missing \"", | ||
model.type, | ||
"\" view"); | ||
} | ||
getPostion(type) { | ||
let position = MissingView_1.positionMap.get(type); | ||
if (!position) { | ||
position = sprotty_protocol_1.Point.ORIGIN; | ||
MissingView_1.positionMap.forEach(value => position = value.y >= position.y ? { x: 0, y: value.y + 20 } : position); | ||
MissingView_1.positionMap.set(type, position); | ||
} | ||
return position; | ||
} | ||
}; | ||
exports.MissingView = MissingView; | ||
exports.MissingView = MissingView = __decorate([ | ||
MissingView.positionMap = new Map(); | ||
exports.MissingView = MissingView = MissingView_1 = __decorate([ | ||
(0, inversify_1.injectable)() | ||
], MissingView); | ||
//# sourceMappingURL=view.js.map |
@@ -16,5 +16,5 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Bounds, Dimension, Point } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SParentElementImpl, SModelElementImpl, SChildElementImpl } from "../../base/model/smodel"; | ||
import { LayoutContainer } from "./model"; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { SParentElementImpl, SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { InternalLayoutContainer } from './model'; | ||
import { ILayout, StatefulLayouter } from './layout'; | ||
@@ -24,8 +24,8 @@ import { AbstractLayoutOptions, HAlignment, VAlignment } from './layout-options'; | ||
export declare abstract class AbstractLayout<T extends AbstractLayoutOptions> implements ILayout { | ||
layout(container: SParentElementImpl & LayoutContainer, layouter: StatefulLayouter): void; | ||
layout(container: SParentElementImpl & InternalLayoutContainer, layouter: StatefulLayouter): void; | ||
protected abstract layoutChild(child: SChildElementImpl, boundsData: BoundsData, bounds: Bounds, childOptions: T, containerOptions: T, currentOffset: Point, maxWidth: number, maxHeight: number): Point; | ||
protected getFinalContainerBounds(container: SParentElementImpl & LayoutContainer, lastOffset: Point, options: T, maxWidth: number, maxHeight: number): Bounds; | ||
protected getFinalContainerBounds(container: SParentElementImpl & InternalLayoutContainer, lastOffset: Point, options: T, maxWidth: number, maxHeight: number): Bounds; | ||
protected getFixedContainerBounds(container: SModelElementImpl, layoutOptions: T, layouter: StatefulLayouter): Bounds; | ||
protected abstract getChildrenSize(container: SParentElementImpl & LayoutContainer, containerOptions: T, layouter: StatefulLayouter): Dimension; | ||
protected layoutChildren(container: SParentElementImpl & LayoutContainer, layouter: StatefulLayouter, containerOptions: T, maxWidth: number, maxHeight: number): Point; | ||
protected abstract getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, containerOptions: T, layouter: StatefulLayouter): Dimension; | ||
protected layoutChildren(container: SParentElementImpl & InternalLayoutContainer, layouter: StatefulLayouter, containerOptions: T, maxWidth: number, maxHeight: number): Point; | ||
protected getDx(hAlign: HAlignment, bounds: Bounds, maxWidth: number): number; | ||
@@ -32,0 +32,0 @@ protected getDy(vAlign: VAlignment, bounds: Bounds, maxHeight: number): number; |
@@ -35,6 +35,6 @@ "use strict"; | ||
const maxWidth = options.paddingFactor * (options.resizeContainer | ||
? childrenSize.width | ||
? Math.max(childrenSize.width, options.minWidth) | ||
: Math.max(0, this.getFixedContainerBounds(container, options, layouter).width) - options.paddingLeft - options.paddingRight); | ||
const maxHeight = options.paddingFactor * (options.resizeContainer | ||
? childrenSize.height | ||
? Math.max(childrenSize.height, options.minHeight) | ||
: Math.max(0, this.getFixedContainerBounds(container, options, layouter).height) - options.paddingTop - options.paddingBottom); | ||
@@ -41,0 +41,0 @@ if (maxWidth > 0 && maxHeight > 0) { |
@@ -17,8 +17,9 @@ /******************************************************************************** | ||
import { Action, RequestBoundsAction, SetBoundsAction } from 'sprotty-protocol/lib/actions'; | ||
import { Alignable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { CommandExecutionContext, CommandResult, CommandReturn, HiddenCommand, SystemCommand } from '../../base/commands/command'; | ||
import { SModelElementImpl } from '../../base/model/smodel'; | ||
import { Alignable, BoundsAware } from './model'; | ||
import { InternalBoundsAware } from './model'; | ||
export interface ResolvedElementAndBounds { | ||
element: SModelElementImpl & BoundsAware; | ||
element: SModelElementImpl & InternalBoundsAware; | ||
oldBounds: Bounds; | ||
@@ -25,0 +26,0 @@ newPosition?: Point; |
@@ -21,3 +21,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer } from './model'; | ||
import { InternalLayoutContainer } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -33,3 +33,3 @@ export interface HBoxLayoutOptions extends AbstractLayoutOptions { | ||
static KIND: string; | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, containerOptions: HBoxLayoutOptions, layouter: StatefulLayouter): { | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, containerOptions: HBoxLayoutOptions, layouter: StatefulLayouter): { | ||
width: number; | ||
@@ -36,0 +36,0 @@ height: number; |
@@ -24,3 +24,3 @@ /******************************************************************************** |
import { Layouter } from './layout'; |
import { BoundsAware } from './model'; |
import { InternalBoundsAware } from './model'; |
export declare class BoundsData { |
@@ -61,3 +61,3 @@ vnode?: VNode; |
*/ |
protected getBounds(elm: Node, element: SModelElementImpl & BoundsAware): Bounds; |
protected getBounds(elm: Node, element: SModelElementImpl & InternalBoundsAware): Bounds; |
} |
@@ -64,0 +64,0 @@ /** |
@@ -21,3 +21,3 @@ /******************************************************************************** | ||
import { SParentElementImpl, SModelElementImpl } from "../../base/model/smodel"; | ||
import { LayoutContainer } from "./model"; | ||
import { InternalLayoutContainer } from "./model"; | ||
import { BoundsData } from "./hidden-bounds-updater"; | ||
@@ -45,6 +45,6 @@ export declare class LayoutRegistry extends InstanceRegistry<ILayout> { | ||
layout(): void; | ||
protected doLayout(element: SParentElementImpl & LayoutContainer): Bounds; | ||
protected doLayout(element: SParentElementImpl & InternalLayoutContainer): Bounds; | ||
} | ||
export interface ILayout { | ||
layout(container: SParentElementImpl & LayoutContainer, layouter: StatefulLayouter): void; | ||
layout(container: SParentElementImpl & InternalLayoutContainer, layouter: StatefulLayouter): void; | ||
} | ||
@@ -51,0 +51,0 @@ export declare function configureLayout(context: { |
@@ -16,2 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Locateable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -21,3 +22,2 @@ import { SChildElementImpl, SModelElementImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
import { ViewerOptions } from '../../base/views/viewer-options'; | ||
import type { Locateable } from '../move/model'; | ||
export declare const boundsFeature: unique symbol; | ||
@@ -34,11 +34,15 @@ export declare const layoutContainerFeature: unique symbol; | ||
*/ | ||
export interface BoundsAware { | ||
export interface InternalBoundsAware { | ||
bounds: Bounds; | ||
} | ||
/** @deprecated Use `InternalBoundsAware` instead. */ | ||
export type BoundsAware = InternalBoundsAware; | ||
/** | ||
* Used to identify model elements that specify a layout to apply to their children. | ||
*/ | ||
export interface LayoutContainer extends LayoutableChild { | ||
export interface InternalLayoutContainer extends InternalLayoutableChild { | ||
layout: string; | ||
} | ||
/** @deprecated Use `InternalLayoutContainer` instead. */ | ||
export type LayoutContainer = InternalLayoutContainer; | ||
export type ModelLayoutOptions = { | ||
@@ -50,10 +54,12 @@ [key: string]: string | number | boolean; | ||
*/ | ||
export interface LayoutableChild extends BoundsAware { | ||
export interface InternalLayoutableChild extends InternalBoundsAware { | ||
layoutOptions?: ModelLayoutOptions; | ||
} | ||
/** @deprecated Use `InternalLayoutableChild` instead. */ | ||
export type LayoutableChild = InternalLayoutableChild; | ||
/** | ||
* Feature extension interface for {@link alignFeature}. | ||
* Used to adjust elements whose bounding box is not at the origin, e.g. | ||
* labels, or pre-rendered SVG figures. | ||
* | ||
* Feature extension interface for {@link alignFeature}. | ||
* @deprecated use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -63,6 +69,6 @@ export interface Alignable { | ||
} | ||
export declare function isBoundsAware(element: SModelElementImpl): element is SModelElementImpl & BoundsAware; | ||
export declare function isLayoutContainer(element: SModelElementImpl): element is SParentElementImpl & LayoutContainer; | ||
export declare function isLayoutableChild(element: SModelElementImpl): element is SChildElementImpl & LayoutableChild; | ||
export declare function isSizeable(element: SModelElementImpl): element is SModelElementImpl & BoundsAware; | ||
export declare function isBoundsAware(element: SModelElementImpl): element is SModelElementImpl & InternalBoundsAware; | ||
export declare function isLayoutContainer(element: SModelElementImpl): element is SParentElementImpl & InternalLayoutContainer; | ||
export declare function isLayoutableChild(element: SModelElementImpl): element is SChildElementImpl & InternalLayoutableChild; | ||
export declare function isSizeable(element: SModelElementImpl): element is SModelElementImpl & InternalBoundsAware; | ||
export declare function isAlignable(element: SModelElementImpl): element is SModelElementImpl & Alignable; | ||
@@ -84,3 +90,3 @@ export declare function getAbsoluteBounds(element: SModelElementImpl): Bounds; | ||
*/ | ||
export declare abstract class SShapeElementImpl extends SChildElementImpl implements BoundsAware, Locateable, LayoutableChild { | ||
export declare abstract class SShapeElementImpl extends SChildElementImpl implements InternalBoundsAware, Locateable, InternalLayoutableChild { | ||
position: Point; | ||
@@ -87,0 +93,0 @@ size: Dimension; |
@@ -20,5 +20,5 @@ /******************************************************************************** | ||
import { CommandExecutionContext } from "../../base/commands/command"; | ||
import { BoundsAware } from './model'; | ||
import { InternalBoundsAware } from './model'; | ||
export interface ResolvedElementResize { | ||
element: SModelElementImpl & BoundsAware; | ||
element: SModelElementImpl & InternalBoundsAware; | ||
fromDimension: Dimension; | ||
@@ -25,0 +25,0 @@ toDimension: Dimension; |
@@ -21,3 +21,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer } from './model'; | ||
import { InternalLayoutContainer } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -31,3 +31,3 @@ export interface StackLayoutOptions extends AbstractLayoutOptions { | ||
static KIND: string; | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, options: StackLayoutOptions, layouter: StatefulLayouter): { | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, options: StackLayoutOptions, layouter: StatefulLayouter): { | ||
width: number; | ||
@@ -34,0 +34,0 @@ height: number; |
@@ -21,3 +21,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer } from './model'; | ||
import { InternalLayoutContainer } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -33,3 +33,3 @@ export interface VBoxLayoutOptions extends AbstractLayoutOptions { | ||
static KIND: string; | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, containerOptions: VBoxLayoutOptions, layouter: StatefulLayouter): { | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, containerOptions: VBoxLayoutOptions, layouter: StatefulLayouter): { | ||
width: number; | ||
@@ -36,0 +36,0 @@ height: number; |
@@ -18,3 +18,3 @@ /******************************************************************************** | ||
import { IViewArgs, IView, RenderingContext } from '../../base/views/view'; | ||
import { BoundsAware } from './model'; | ||
import { InternalBoundsAware } from './model'; | ||
import { SChildElementImpl } from '../../base/model/smodel'; | ||
@@ -27,5 +27,5 @@ export declare abstract class ShapeView implements IView { | ||
*/ | ||
isVisible(model: Readonly<SChildElementImpl & BoundsAware>, context: RenderingContext): boolean; | ||
isVisible(model: Readonly<SChildElementImpl & InternalBoundsAware>, context: RenderingContext): boolean; | ||
abstract render(model: Readonly<SChildElementImpl>, context: RenderingContext, args?: IViewArgs): VNode | undefined; | ||
} | ||
//# sourceMappingURL=views.d.ts.map |
@@ -18,2 +18,5 @@ /******************************************************************************** | ||
import { SShapeElementImpl } from '../bounds/model'; | ||
/** | ||
* @deprecated Use SButton from `sprotty-protocol` instead. | ||
*/ | ||
export interface SButtonSchema extends SShapeElement { | ||
@@ -20,0 +23,0 @@ pressed: boolean; |
@@ -25,3 +25,3 @@ "use strict"; | ||
const decorationModule = new inversify_1.ContainerModule((bind, _unbind, isBound) => { | ||
(0, view_1.configureModelElement)({ bind, isBound }, 'marker', model_1.SIssueMarker, views_1.IssueMarkerView); | ||
(0, view_1.configureModelElement)({ bind, isBound }, 'marker', model_1.SIssueMarkerImpl, views_1.IssueMarkerView); | ||
bind(decoration_placer_1.DecorationPlacer).toSelf().inSingletonScope(); | ||
@@ -28,0 +28,0 @@ bind(types_1.TYPES.IVNodePostprocessor).toService(decoration_placer_1.DecorationPlacer); |
@@ -16,2 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { SIssue as SIssueSchema } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl } from '../../base/model/smodel'; | ||
@@ -29,6 +30,14 @@ import { SShapeElementImpl } from '../bounds/model'; | ||
} | ||
export declare class SIssueMarkerImpl extends SDecoration { | ||
issues: SIssueSchema[]; | ||
} | ||
/** @deprecated Use SIssueMarkerImpl instead. */ | ||
export declare const SIssueMarker: typeof SIssueMarkerImpl; | ||
/** | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
export type SIssueSeverity = 'error' | 'warning' | 'info'; | ||
export declare class SIssueMarker extends SDecoration { | ||
issues: SIssue[]; | ||
} | ||
/** | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
export declare class SIssue { | ||
@@ -35,0 +44,0 @@ message: string; |
@@ -18,3 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SIssue = exports.SIssueMarker = exports.SDecoration = exports.isDecoration = exports.decorationFeature = void 0; | ||
exports.SIssue = exports.SIssueMarker = exports.SIssueMarkerImpl = exports.SDecoration = exports.isDecoration = exports.decorationFeature = void 0; | ||
const model_1 = require("../bounds/model"); | ||
@@ -31,5 +31,10 @@ const model_2 = require("../hover/model"); | ||
SDecoration.DEFAULT_FEATURES = [exports.decorationFeature, model_1.boundsFeature, model_2.hoverFeedbackFeature, model_2.popupFeature]; | ||
class SIssueMarker extends SDecoration { | ||
class SIssueMarkerImpl extends SDecoration { | ||
} | ||
exports.SIssueMarker = SIssueMarker; | ||
exports.SIssueMarkerImpl = SIssueMarkerImpl; | ||
/** @deprecated Use SIssueMarkerImpl instead. */ | ||
exports.SIssueMarker = SIssueMarkerImpl; | ||
/** | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
class SIssue { | ||
@@ -36,0 +41,0 @@ } |
@@ -18,8 +18,8 @@ /******************************************************************************** | ||
import { IView, RenderingContext } from '../../base/views/view'; | ||
import { SIssueMarker, SIssueSeverity } from './model'; | ||
import { SIssueMarkerImpl, SIssueSeverity } from './model'; | ||
export declare class IssueMarkerView implements IView { | ||
render(marker: SIssueMarker, context: RenderingContext): VNode; | ||
protected getMaxSeverity(marker: SIssueMarker): SIssueSeverity; | ||
render(marker: SIssueMarkerImpl, context: RenderingContext): VNode; | ||
protected getMaxSeverity(marker: SIssueMarkerImpl): SIssueSeverity; | ||
protected getPath(severity: SIssueSeverity): "M768 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm128 1247v-190q0-14-9-23.5t-22-9.5h-192q-13 0-23 10t-10 23v190q0 13 10 23t23 10h192q13 0 22-9.5t9-23.5zm-2-344l18-621q0-12-10-18-10-8-24-8h-220q-14 0-24 8-10 6-10 18l17 621q0 10 10 17.5t24 7.5h185q14 0 23.5-7.5t10.5-17.5z" | "M1024 1376v-160q0-14-9-23t-23-9h-96v-512q0-14-9-23t-23-9h-320q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896v-160q0-14-9-23t-23-9h-192q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"; | ||
} | ||
//# sourceMappingURL=views.d.ts.map |
@@ -16,14 +16,22 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { VNode } from "snabbdom"; | ||
import { Point } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SModelElementImpl } from "../../base/model/smodel"; | ||
import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; | ||
import { Orientation } from "../../utils/geometry"; | ||
import { BoundsAware } from "../bounds/model"; | ||
import { EdgeLayoutable, EdgePlacement } from "./model"; | ||
import { EdgeRouterRegistry } from "../routing/routing"; | ||
import { VNode } from 'snabbdom'; | ||
import { Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { EdgeLayoutable, EdgePlacement } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl } from '../../base/model/smodel'; | ||
import { IVNodePostprocessor } from '../../base/views/vnode-postprocessor'; | ||
import { Orientation } from '../../utils/geometry'; | ||
import { InternalBoundsAware } from '../bounds/model'; | ||
import { EdgeRouterRegistry } from '../routing/routing'; | ||
import { ILogger } from '../../utils/logging'; | ||
export declare class EdgeLayoutPostprocessor implements IVNodePostprocessor { | ||
edgeRouterRegistry: EdgeRouterRegistry; | ||
protected readonly logger: ILogger; | ||
/** | ||
* Decorates the vnode with the appropriate transformation based on the element's placement and bounds. | ||
* @param vnode - The vnode to decorate. | ||
* @param element - The SModelElementImpl to decorate. | ||
* @returns The decorated vnode. | ||
*/ | ||
decorate(vnode: VNode, element: SModelElementImpl): VNode; | ||
protected getRotatedAlignment(element: EdgeLayoutable & SModelElementImpl & BoundsAware, placement: EdgePlacement, flip: boolean): { | ||
protected getRotatedAlignment(element: EdgeLayoutable & SModelElementImpl & InternalBoundsAware, placement: EdgePlacement, flip: boolean): { | ||
x: number; | ||
@@ -33,3 +41,3 @@ y: number; | ||
protected getEdgePlacement(element: SModelElementImpl): EdgePlacement; | ||
protected getAlignment(label: EdgeLayoutable & SModelElementImpl & BoundsAware, placement: EdgePlacement, angle: number): Point; | ||
protected getAlignment(label: EdgeLayoutable & SModelElementImpl & InternalBoundsAware, placement: EdgePlacement, angle: number): Point; | ||
protected getQuadrant(angle: number): { | ||
@@ -36,0 +44,0 @@ orientation: Orientation; |
@@ -36,6 +36,16 @@ "use strict"; | ||
const routing_1 = require("../routing/routing"); | ||
const types_1 = require("../../base/types"); | ||
let EdgeLayoutPostprocessor = class EdgeLayoutPostprocessor { | ||
/** | ||
* Decorates the vnode with the appropriate transformation based on the element's placement and bounds. | ||
* @param vnode - The vnode to decorate. | ||
* @param element - The SModelElementImpl to decorate. | ||
* @returns The decorated vnode. | ||
*/ | ||
decorate(vnode, element) { | ||
var _a, _b; | ||
if ((0, model_2.isEdgeLayoutable)(element) && element.parent instanceof sgraph_1.SEdgeImpl) { | ||
if (element.bounds !== geometry_1.Bounds.EMPTY) { | ||
const actualBounds = element.bounds; | ||
const hasOwnPlacement = (0, model_2.checkEdgePlacement)(element); | ||
const placement = this.getEdgePlacement(element); | ||
@@ -45,26 +55,61 @@ const edge = element.parent; | ||
const router = this.edgeRouterRegistry.get(edge.routerKind); | ||
// point on edge derived from edgePlacement.position | ||
const pointOnEdge = router.pointAt(edge, position); | ||
const derivativeOnEdge = router.derivativeAt(edge, position); | ||
let transform = ''; | ||
if (pointOnEdge && derivativeOnEdge) { | ||
transform += `translate(${pointOnEdge.x}, ${pointOnEdge.y})`; | ||
const angle = (0, geometry_1.toDegrees)(Math.atan2(derivativeOnEdge.y, derivativeOnEdge.x)); | ||
if (placement.rotate) { | ||
let flippedAngle = angle; | ||
if (Math.abs(angle) > 90) { | ||
if (angle < 0) | ||
flippedAngle += 180; | ||
else if (angle > 0) | ||
flippedAngle -= 180; | ||
// Calculation of potential free movement. Just add the actual bounds to the point on edge. | ||
const freeTransform = `translate(${((_a = pointOnEdge === null || pointOnEdge === void 0 ? void 0 : pointOnEdge.x) !== null && _a !== void 0 ? _a : 0) + actualBounds.x}, ${((_b = pointOnEdge === null || pointOnEdge === void 0 ? void 0 : pointOnEdge.y) !== null && _b !== void 0 ? _b : 0) + actualBounds.y})`; | ||
// Check if edgeplacement is set. If not the label is freely movable if movefeature is enabled for such labels. | ||
if (hasOwnPlacement) { | ||
if (pointOnEdge) { | ||
let derivativeOnEdge; | ||
// handle different move modes | ||
if (placement.moveMode && placement.moveMode !== 'edge') { | ||
// get the relative position on segment | ||
derivativeOnEdge = router.derivativeAt(edge, position); | ||
// handle free move mode | ||
if (placement.moveMode === 'free') { | ||
transform += freeTransform; | ||
} | ||
else { | ||
// The moveMode is neither 'edge' nor 'free' so it is 'none'. Hence the label is not movable and gets the fixed point on edge. | ||
transform += `translate(${pointOnEdge.x}, ${pointOnEdge.y})`; | ||
} | ||
} | ||
transform += ` rotate(${flippedAngle})`; | ||
const alignment = this.getRotatedAlignment(element, placement, flippedAngle !== angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
else { | ||
// no movemode was set or set to 'edge': label movement is constrained to the edge | ||
// Find orthogonal intersection point on edge and use it as the label's position | ||
const orthogonalPoint = router.findOrthogonalIntersection(edge, geometry_1.Point.add(pointOnEdge, actualBounds)); | ||
if (orthogonalPoint) { | ||
derivativeOnEdge = orthogonalPoint.derivative; | ||
transform += `translate(${orthogonalPoint.point.x}, ${orthogonalPoint.point.y})`; | ||
} | ||
} | ||
if (derivativeOnEdge) { | ||
const angle = (0, geometry_1.toDegrees)(Math.atan2(derivativeOnEdge.y, derivativeOnEdge.x)); | ||
if (placement.rotate) { | ||
let flippedAngle = angle; | ||
// Flip angle if it exceeds 90 degrees | ||
if (Math.abs(angle) > 90) { | ||
if (angle < 0) | ||
flippedAngle += 180; | ||
else if (angle > 0) | ||
flippedAngle -= 180; | ||
} | ||
transform += ` rotate(${flippedAngle})`; | ||
// Get rotated alignment based on flipped angle | ||
const alignment = this.getRotatedAlignment(element, placement, flippedAngle !== angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} | ||
else { | ||
// Get alignment based on angle | ||
const alignment = this.getAlignment(element, placement, angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} | ||
} | ||
} | ||
else { | ||
const alignment = this.getAlignment(element, placement, angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} | ||
(0, vnode_utils_1.setAttr)(vnode, 'transform', transform); | ||
} | ||
else { | ||
transform += freeTransform; | ||
} | ||
(0, vnode_utils_1.setAttr)(vnode, 'transform', transform); | ||
} | ||
@@ -216,2 +261,6 @@ } | ||
], EdgeLayoutPostprocessor.prototype, "edgeRouterRegistry", void 0); | ||
__decorate([ | ||
(0, inversify_1.inject)(types_1.TYPES.ILogger), | ||
__metadata("design:type", Object) | ||
], EdgeLayoutPostprocessor.prototype, "logger", void 0); | ||
exports.EdgeLayoutPostprocessor = EdgeLayoutPostprocessor = __decorate([ | ||
@@ -218,0 +267,0 @@ (0, inversify_1.injectable)() |
@@ -16,13 +16,22 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import type { EdgePlacement as EdgePlacementSchema } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { BoundsAware } from '../bounds/model'; | ||
import { InternalBoundsAware } from '../bounds/model'; | ||
export declare const edgeLayoutFeature: unique symbol; | ||
/** | ||
* @deprecated Use EdgeLayoutable from sprotty-protocol instead | ||
* Feature extension interface for {@link edgeLayoutFeature}. | ||
*/ | ||
export interface EdgeLayoutable { | ||
edgePlacement: EdgePlacement; | ||
edgePlacement: EdgePlacementSchema; | ||
} | ||
export declare function isEdgeLayoutable<T extends SModelElementImpl>(element: T): element is T & SChildElementImpl & BoundsAware & EdgeLayoutable; | ||
export declare function isEdgeLayoutable<T extends SModelElementImpl>(element: T): element is T & SChildElementImpl & InternalBoundsAware & EdgeLayoutable; | ||
export declare function checkEdgePlacement(element: SChildElementImpl): element is SChildElementImpl & EdgeLayoutable; | ||
/** | ||
* @deprecated Use EdgeSide from sprotty-protocol instead | ||
*/ | ||
export type EdgeSide = 'left' | 'right' | 'top' | 'bottom' | 'on'; | ||
/** | ||
* @deprecated Use EdgePlacement from sprotty-protocol instead | ||
*/ | ||
export declare class EdgePlacement extends Object { | ||
@@ -45,4 +54,10 @@ /** | ||
offset: number; | ||
/** | ||
* where should the label be moved when move feature is enabled. | ||
* 'edge' means the label is moved along the edge, 'free' means the label is moved freely, 'none' means the label is not moved. | ||
* Default is 'edge'. | ||
*/ | ||
moveMode?: 'edge' | 'free' | 'none'; | ||
} | ||
export declare const DEFAULT_EDGE_PLACEMENT: EdgePlacement; | ||
export declare const DEFAULT_EDGE_PLACEMENT: EdgePlacementSchema; | ||
//# sourceMappingURL=model.d.ts.map |
@@ -18,3 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DEFAULT_EDGE_PLACEMENT = exports.EdgePlacement = exports.isEdgeLayoutable = exports.edgeLayoutFeature = void 0; | ||
exports.DEFAULT_EDGE_PLACEMENT = exports.EdgePlacement = exports.checkEdgePlacement = exports.isEdgeLayoutable = exports.edgeLayoutFeature = void 0; | ||
const smodel_1 = require("../../base/model/smodel"); | ||
@@ -27,3 +27,2 @@ const model_1 = require("../bounds/model"); | ||
&& element.parent instanceof model_2.SRoutableElementImpl | ||
&& checkEdgeLayoutable(element) | ||
&& (0, model_1.isBoundsAware)(element) | ||
@@ -33,5 +32,9 @@ && element.hasFeature(exports.edgeLayoutFeature); | ||
exports.isEdgeLayoutable = isEdgeLayoutable; | ||
function checkEdgeLayoutable(element) { | ||
function checkEdgePlacement(element) { | ||
return 'edgePlacement' in element; | ||
} | ||
exports.checkEdgePlacement = checkEdgePlacement; | ||
/** | ||
* @deprecated Use EdgePlacement from sprotty-protocol instead | ||
*/ | ||
class EdgePlacement extends Object { | ||
@@ -44,4 +47,5 @@ } | ||
position: 0.5, | ||
offset: 7 | ||
offset: 7, | ||
moveMode: 'edge' | ||
}; | ||
//# sourceMappingURL=model.js.map |
@@ -19,5 +19,5 @@ /******************************************************************************** | ||
/** | ||
* Feature extension interface for {@link expandFeature}. | ||
* Model elements that implement this interface can be expanded/collapsed | ||
* | ||
* Feature extension interface for {@link expandFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -24,0 +24,0 @@ export interface Expandable { |
@@ -37,5 +37,5 @@ /******************************************************************************** | ||
protected createSvg(svgElementOrig: SVGSVGElement, root: SModelRootImpl): string; | ||
protected copyStyles(source: Element, target: Element, skipedProperties: string[]): void; | ||
protected copyStyles(source: Element, target: Element, skippedProperties: string[]): void; | ||
protected getBounds(root: SModelRootImpl): Bounds; | ||
} | ||
//# sourceMappingURL=svg-exporter.d.ts.map |
@@ -48,8 +48,14 @@ "use strict"; | ||
if (typeof document !== 'undefined') { | ||
const div = document.getElementById(this.options.hiddenDiv); | ||
if (div !== null && div.firstElementChild && div.firstElementChild.tagName === 'svg') { | ||
const svgElement = div.firstElementChild; | ||
const svg = this.createSvg(svgElement, root); | ||
this.actionDispatcher.dispatch(ExportSvgAction.create(svg, request ? request.requestId : '')); | ||
const hiddenDiv = document.getElementById(this.options.hiddenDiv); | ||
if (hiddenDiv === null) { | ||
this.log.warn(this, `Element with id ${this.options.hiddenDiv} not found. Nothing to export.`); | ||
return; | ||
} | ||
const svgElement = hiddenDiv.querySelector('svg'); | ||
if (svgElement === null) { | ||
this.log.warn(this, `No svg element found in ${this.options.hiddenDiv} div. Nothing to export.`); | ||
return; | ||
} | ||
const svg = this.createSvg(svgElement, root); | ||
this.actionDispatcher.dispatch(ExportSvgAction.create(svg, request ? request.requestId : '')); | ||
} | ||
@@ -68,5 +74,6 @@ } | ||
docCopy.close(); | ||
const svgElementNew = docCopy.getElementById(svgElementOrig.id); | ||
const svgElementNew = docCopy.querySelector('svg'); | ||
svgElementNew.removeAttribute('opacity'); | ||
this.copyStyles(svgElementOrig, svgElementNew, ['width', 'height', 'opacity']); | ||
// inline-size copied from sprotty-hidden svg shrinks the svg so it is not visible. | ||
this.copyStyles(svgElementOrig, svgElementNew, ['width', 'height', 'opacity', 'inline-size']); | ||
svgElementNew.setAttribute('version', '1.1'); | ||
@@ -79,3 +86,3 @@ const bounds = this.getBounds(root); | ||
} | ||
copyStyles(source, target, skipedProperties) { | ||
copyStyles(source, target, skippedProperties) { | ||
const sourceStyle = getComputedStyle(source); | ||
@@ -86,3 +93,3 @@ const targetStyle = getComputedStyle(target); | ||
const key = sourceStyle[i]; | ||
if (skipedProperties.indexOf(key) === -1) { | ||
if (skippedProperties.indexOf(key) === -1) { | ||
const value = sourceStyle.getPropertyValue(key); | ||
@@ -96,3 +103,3 @@ if (targetStyle.getPropertyValue(key) !== value) { | ||
target.setAttribute('style', diffStyle); | ||
// IE doesn't retrun anything on source.children | ||
// IE doesn't return anything on source.children | ||
for (let i = 0; i < source.childNodes.length; ++i) { | ||
@@ -99,0 +106,0 @@ const sourceChild = source.childNodes[i]; |
@@ -16,8 +16,8 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { VNode } from "snabbdom"; | ||
import { Animation } from "../../base/animations/animation"; | ||
import { CommandExecutionContext } from "../../base/commands/command"; | ||
import { SModelRootImpl, SModelElementImpl } from "../../base/model/smodel"; | ||
import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; | ||
import { Fadeable } from "./model"; | ||
import { VNode } from 'snabbdom'; | ||
import { Fadeable } from 'sprotty-protocol/lib/model'; | ||
import { Animation } from '../../base/animations/animation'; | ||
import { CommandExecutionContext } from '../../base/commands/command'; | ||
import { SModelRootImpl, SModelElementImpl } from '../../base/model/smodel'; | ||
import { IVNodePostprocessor } from '../../base/views/vnode-postprocessor'; | ||
export interface ResolvedElementFade { | ||
@@ -24,0 +24,0 @@ element: SModelElementImpl & Fadeable; |
@@ -19,3 +19,4 @@ /******************************************************************************** | ||
/** | ||
* Feature extension interface for {@link fadeFeature}. | ||
* Feature extension interface for {@link fadeFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -22,0 +23,0 @@ export interface Fadeable { |
@@ -20,2 +20,3 @@ /******************************************************************************** | ||
* Feature extension interface for {@link hoverFeedbackFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -22,0 +23,0 @@ export interface Hoverable { |
@@ -20,6 +20,5 @@ /******************************************************************************** | ||
/** | ||
* An element that can be placed at a specific location using its position | ||
* property. | ||
* | ||
* An element that can be placed at a specific location using its position property. | ||
* Feature extension interface for {@link moveFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -26,0 +25,0 @@ export interface Locateable { |
@@ -19,5 +19,6 @@ "use strict"; | ||
exports.isMoveable = exports.isLocateable = exports.moveFeature = void 0; | ||
const object_1 = require("sprotty-protocol/lib/utils/object"); | ||
exports.moveFeature = Symbol('moveFeature'); | ||
function isLocateable(element) { | ||
return element['position'] !== undefined; | ||
return (0, object_1.hasOwnProperty)(element, 'position'); | ||
} | ||
@@ -24,0 +25,0 @@ exports.isLocateable = isLocateable; |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { VNode } from 'snabbdom'; | ||
import { Locateable } from 'sprotty-protocol/lib/model'; | ||
import { Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -28,3 +29,2 @@ import { Action, MoveAction } from 'sprotty-protocol/lib/actions'; | ||
import { EdgeMemento, EdgeRouterRegistry, RoutedPoint } from '../routing/routing'; | ||
import { Locateable } from './model'; | ||
import { ISnapper } from './snap'; | ||
@@ -31,0 +31,0 @@ export interface ElementMove { |
@@ -16,3 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Viewport } from 'sprotty-protocol/lib/model'; | ||
import { Projectable as ProjectableSchema, Viewport } from 'sprotty-protocol/lib/model'; | ||
import { Bounds } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -24,2 +24,3 @@ import { SChildElementImpl, SModelRootImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
* Otherwise model elements also have to be `BoundsAware` so their projections can be shown. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -30,3 +31,3 @@ export interface Projectable { | ||
} | ||
export declare function isProjectable(arg: unknown): arg is Projectable; | ||
export declare function isProjectable(arg: unknown): arg is ProjectableSchema; | ||
/** | ||
@@ -47,3 +48,3 @@ * A projection can be shown in a horizontal or vertical bar to display an overview of the diagram. | ||
*/ | ||
export declare function getProjectedBounds(model: Readonly<SChildElementImpl & Projectable>): Bounds | undefined; | ||
export declare function getProjectedBounds(model: Readonly<SChildElementImpl & ProjectableSchema>): Bounds | undefined; | ||
/** | ||
@@ -50,0 +51,0 @@ * Determine the total bounds of a model; this takes the viewport into consideration |
@@ -52,2 +52,6 @@ /******************************************************************************** | ||
protected abstract getOptions(edge: SRoutableElementImpl): LinearRouteOptions; | ||
findOrthogonalIntersection(edge: SRoutableElementImpl, point: Point): { | ||
point: Point; | ||
derivative: Point; | ||
}; | ||
pointAt(edge: SRoutableElementImpl, t: number): Point | undefined; | ||
@@ -54,0 +58,0 @@ derivativeAt(edge: SRoutableElementImpl, t: number): Point | undefined; |
@@ -79,2 +79,35 @@ "use strict"; | ||
let AbstractEdgeRouter = class AbstractEdgeRouter { | ||
findOrthogonalIntersection(edge, point) { | ||
const calcOrthogonalIntersectionForSegment = (p1, p2) => { | ||
// Calculate the direction vector d of the edge and vector pq from p1 to point q | ||
const d = geometry_1.Point.subtract(p2, p1); | ||
const pq = geometry_1.Point.subtract(point, p1); | ||
// Calculate the scalar t for the direction vector d | ||
const t = geometry_1.Point.dotProduct(pq, d) / geometry_1.Point.dotProduct(d, d); | ||
// Check if the intersection point lies on the edge segment | ||
if (t >= 0 && t <= 1) { | ||
// Calculate and return the intersection point x | ||
return geometry_1.Point.linear(p1, p2, t); | ||
} | ||
else if (t < 0) { | ||
return p1; | ||
} | ||
else { | ||
return p2; | ||
} | ||
}; | ||
// Calculate the intersection for each segment of the edge and return the closest one | ||
const routedPoints = this.route(edge); | ||
let intersectionPoint = routedPoints[0]; | ||
let index = 0; | ||
for (let i = 0; i < routedPoints.length - 1; ++i) { | ||
const intersection = calcOrthogonalIntersectionForSegment(routedPoints[i], routedPoints[i + 1]); | ||
if (geometry_1.Point.euclideanDistance(point, intersection) < geometry_1.Point.euclideanDistance(point, intersectionPoint)) { | ||
intersectionPoint = intersection; | ||
index = i; | ||
} | ||
} | ||
const derivative = geometry_1.Point.subtract(routedPoints[index + 1], routedPoints[index]); | ||
return { point: intersectionPoint, derivative }; | ||
} | ||
pointAt(edge, t) { | ||
@@ -274,2 +307,21 @@ const segments = this.calculateSegment(edge, t); | ||
edge.index.remove(edge); | ||
if (edge.id === model_1.edgeInProgressID) { | ||
// create a proper edge id after connecting the edge in progress | ||
const idGen = (counter) => `${edge.sourceId}_to_${edge.targetId}_${counter}`; | ||
let idx = 0; | ||
let newId = idGen(idx); | ||
while (edge.index.getById(newId) !== undefined) { | ||
newId = idGen(++idx); | ||
} | ||
edge.id = newId; | ||
const progressTargetHandle = edge.children.find(child => child.id === model_1.edgeInProgressTargetHandleID); | ||
if (progressTargetHandle instanceof model_1.SRoutingHandleImpl) { | ||
// remove in progress target handle | ||
edge.remove(progressTargetHandle); | ||
if (progressTargetHandle.danglingAnchor) { | ||
// remove dangling anchor | ||
progressTargetHandle.danglingAnchor.parent.remove(progressTargetHandle.danglingAnchor); | ||
} | ||
} | ||
} | ||
edge.index.add(edge); | ||
@@ -276,0 +328,0 @@ if (this.getSelfEdgeIndex(edge) > -1) { |
@@ -16,2 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Hoverable, Selectable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -21,4 +22,2 @@ import { SChildElementImpl, SModelElementImpl } from '../../base/model/smodel'; | ||
import { SShapeElementImpl } from '../bounds/model'; | ||
import { Selectable } from '../select/model'; | ||
import { Hoverable } from '../hover/model'; | ||
export declare abstract class SRoutableElementImpl extends SChildElementImpl { | ||
@@ -25,0 +24,0 @@ routerKind?: string; |
@@ -64,2 +64,13 @@ /******************************************************************************** | ||
/** | ||
* Finds the orthogonal intersection point between an edge and a given point in 2D space. | ||
* | ||
* @param edge - The edge to find the intersection point on. | ||
* @param point - The point to find the intersection with. | ||
* @returns The intersection point and its derivative on the respective edge segment. | ||
*/ | ||
findOrthogonalIntersection(edge: SRoutableElementImpl, point: Point): { | ||
point: Point; | ||
derivative: Point; | ||
} | undefined; | ||
/** | ||
* Calculates a point on the edge | ||
@@ -66,0 +77,0 @@ * |
@@ -20,2 +20,3 @@ /******************************************************************************** | ||
* Feature extension interface for {@link selectFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -22,0 +23,0 @@ export interface Selectable { |
@@ -18,2 +18,3 @@ /******************************************************************************** | ||
import { Action, GetSelectionAction, ResponseAction, SelectAction, SelectAllAction } from 'sprotty-protocol/lib/actions'; | ||
import { Selectable } from 'sprotty-protocol/lib/model'; | ||
import { Command, CommandExecutionContext } from '../../base/commands/command'; | ||
@@ -25,3 +26,2 @@ import { ModelRequestCommand } from '../../base/commands/request-command'; | ||
import { ButtonHandlerRegistry } from '../button/button-handler'; | ||
import { Selectable } from './model'; | ||
export declare class SelectCommand extends Command { | ||
@@ -51,2 +51,3 @@ action: SelectAction; | ||
hasDragged: boolean; | ||
isMouseDown: boolean; | ||
mouseDown(target: SModelElementImpl, event: MouseEvent): (Action | Promise<Action>)[]; | ||
@@ -53,0 +54,0 @@ protected collectElementsToDeselect(target: SModelElementImpl, selectableTarget: (SModelElementImpl & Selectable) | undefined): SModelElementImpl[]; |
@@ -145,2 +145,3 @@ "use strict"; | ||
this.hasDragged = false; | ||
this.isMouseDown = false; | ||
} | ||
@@ -151,2 +152,3 @@ mouseDown(target, event) { | ||
} | ||
this.isMouseDown = true; | ||
const buttonHandled = this.handleButton(target, event); | ||
@@ -166,17 +168,12 @@ if (buttonHandled) { | ||
} | ||
if (selectableTarget !== undefined) { | ||
if (!selectableTarget.selected) { | ||
this.wasSelected = false; | ||
return this.handleSelectTarget(selectableTarget, deselectedElements, event); | ||
} | ||
else if ((0, browser_1.isCtrlOrCmd)(event)) { | ||
this.wasSelected = false; | ||
return this.handleDeselectTarget(selectableTarget, event); | ||
} | ||
else { | ||
this.wasSelected = true; | ||
} | ||
if (!selectableTarget.selected) { | ||
this.wasSelected = false; | ||
return this.handleSelectTarget(selectableTarget, deselectedElements, event); | ||
} | ||
else if ((0, browser_1.isCtrlOrCmd)(event)) { | ||
this.wasSelected = false; | ||
return this.handleDeselectTarget(selectableTarget, event); | ||
} | ||
else { | ||
return this.handleDeselectAll(deselectedElements, event); | ||
this.wasSelected = true; | ||
} | ||
@@ -231,3 +228,3 @@ } | ||
mouseMove(target, event) { | ||
this.hasDragged = true; | ||
this.hasDragged = this.isMouseDown; | ||
return []; | ||
@@ -244,4 +241,4 @@ } | ||
} | ||
else if (target instanceof smodel_1.SModelRootImpl && !(0, scroll_1.findViewportScrollbar)(event)) { | ||
// Mouse up on root but not over ViewPort's scroll bars > deselect all | ||
else if ((target instanceof smodel_1.SModelRootImpl && !(0, scroll_1.findViewportScrollbar)(event)) || !(target instanceof smodel_1.SModelRootImpl)) { | ||
// Mouse up on everything that's not root or root but not over ViewPort's scroll bars > deselect all | ||
return this.handleDeselectAll(this.collectElementsToDeselect(target, undefined), event); | ||
@@ -251,2 +248,3 @@ } | ||
} | ||
this.isMouseDown = false; | ||
this.hasDragged = false; | ||
@@ -253,0 +251,0 @@ return []; |
@@ -19,3 +19,3 @@ /******************************************************************************** | ||
import { SModelRootImpl, ModelIndexImpl } from '../../base/model/smodel'; | ||
import { BoundsAware } from "../bounds/model"; | ||
import { InternalBoundsAware } from "../bounds/model"; | ||
/** | ||
@@ -25,3 +25,3 @@ * Model root element that defines a viewport, so it transforms the coordinate system with | ||
*/ | ||
export declare class ViewportRootElementImpl extends SModelRootImpl implements Viewport, BoundsAware { | ||
export declare class ViewportRootElementImpl extends SModelRootImpl implements Viewport, InternalBoundsAware { | ||
static readonly DEFAULT_FEATURES: symbol[]; | ||
@@ -28,0 +28,0 @@ scroll: Point; |
@@ -17,9 +17,6 @@ /******************************************************************************** | ||
import { Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { Alignable, EdgePlacement, Fadeable, Hoverable, Selectable } from 'sprotty-protocol/lib/model'; | ||
import { ModelIndexImpl, SChildElementImpl, SModelElementImpl } from '../base/model/smodel'; | ||
import { Alignable, BoundsAware, ModelLayoutOptions, SShapeElementImpl } from '../features/bounds/model'; | ||
import { EdgePlacement } from '../features/edge-layout/model'; | ||
import { Fadeable } from '../features/fade/model'; | ||
import { Hoverable } from '../features/hover/model'; | ||
import { InternalBoundsAware, ModelLayoutOptions, SShapeElementImpl } from '../features/bounds/model'; | ||
import { SConnectableElementImpl, SRoutableElementImpl } from '../features/routing/model'; | ||
import { Selectable } from '../features/select/model'; | ||
import { ViewportRootElementImpl } from '../features/viewport/viewport-root'; | ||
@@ -66,3 +63,3 @@ import { FluentIterable } from '../utils/iterable'; | ||
*/ | ||
export declare class SEdgeImpl extends SRoutableElementImpl implements Fadeable, Selectable, Hoverable, BoundsAware { | ||
export declare class SEdgeImpl extends SRoutableElementImpl implements Fadeable, Selectable, Hoverable, InternalBoundsAware { | ||
static readonly DEFAULT_FEATURES: symbol[]; | ||
@@ -69,0 +66,0 @@ selected: boolean; |
@@ -16,8 +16,6 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { SModelElement as SModelElementSchema, SModelRoot as SModelRootSchema } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SModelRootImpl, SChildElementImpl } from "../base/model/smodel"; | ||
import { BoundsAware, Alignable } from "../features/bounds/model"; | ||
import { Locateable } from "../features/move/model"; | ||
import { Selectable } from "../features/select/model"; | ||
import { Alignable, Locateable, Selectable, SModelElement, SModelRoot } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { SModelRootImpl, SChildElementImpl } from '../base/model/smodel'; | ||
import { InternalBoundsAware } from '../features/bounds/model'; | ||
import { SNodeImpl, SPortImpl } from '../graph/sgraph'; | ||
@@ -59,3 +57,3 @@ /** | ||
*/ | ||
export interface HtmlRootSchema extends SModelRootSchema { | ||
export interface HtmlRootSchema extends SModelRoot { | ||
classes?: string[]; | ||
@@ -76,3 +74,3 @@ } | ||
*/ | ||
export interface PreRenderedElementSchema extends SModelElementSchema { | ||
export interface PreRenderedElementSchema extends SModelElement { | ||
code: string; | ||
@@ -101,3 +99,3 @@ } | ||
*/ | ||
export declare class ShapedPreRenderedElementImpl extends PreRenderedElementImpl implements BoundsAware, Locateable, Selectable, Alignable { | ||
export declare class ShapedPreRenderedElementImpl extends PreRenderedElementImpl implements InternalBoundsAware, Locateable, Selectable, Alignable { | ||
static readonly DEFAULT_FEATURES: symbol[]; | ||
@@ -104,0 +102,0 @@ position: Point; |
@@ -16,9 +16,8 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { VNode } from "snabbdom"; | ||
import { IView, IViewArgs, RenderingContext } from "../base/views/view"; | ||
import { ViewportRootElementImpl } from "../features/viewport/viewport-root"; | ||
import { VNode } from 'snabbdom'; | ||
import { Hoverable, Selectable } from 'sprotty-protocol/lib/model'; | ||
import { IView, IViewArgs, RenderingContext } from '../base/views/view'; | ||
import { ViewportRootElementImpl } from '../features/viewport/viewport-root'; | ||
import { SShapeElementImpl } from '../features/bounds/model'; | ||
import { ShapeView } from '../features/bounds/views'; | ||
import { Hoverable } from '../features/hover/model'; | ||
import { Selectable } from '../features/select/model'; | ||
import { SModelElementImpl } from '../base/model/smodel'; | ||
@@ -25,0 +24,0 @@ export declare class SvgViewportView implements IView { |
{ | ||
"name": "sprotty", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "A next-gen framework for graphical views", | ||
@@ -25,3 +25,3 @@ "license": "(EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0)", | ||
"peerDependencies": { | ||
"inversify": "^6.0.1" | ||
"inversify": "~6.0.2" | ||
}, | ||
@@ -31,24 +31,21 @@ "dependencies": { | ||
"file-saver": "^2.0.5", | ||
"inversify": "~6.0.2", | ||
"snabbdom": "^3.5.1", | ||
"sprotty-protocol": "^1.0.0", | ||
"sprotty-protocol": "^1.1.0", | ||
"tinyqueue": "^2.0.3" | ||
}, | ||
"devDependencies": { | ||
"@types/chai": "^4.3.6", | ||
"@types/file-saver": "^2.0.5", | ||
"@types/jsdom": "^21.1.3", | ||
"@types/mocha": "^10.0.2", | ||
"chai": "^4.3.10", | ||
"jsdom": "^22.1.0", | ||
"mocha": "^10.2.0", | ||
"snabbdom-to-html": "^7.1.0", | ||
"ts-mocha": "^10.0.0" | ||
"happy-dom": "^12.10.3", | ||
"snabbdom-to-html": "^7.1.0" | ||
}, | ||
"volta": { | ||
"node": "18.19.0", | ||
"yarn": "1.22.21" | ||
}, | ||
"scripts": { | ||
"prepare": "yarn run clean && yarn run build", | ||
"clean": "rimraf lib artifacts", | ||
"build": "tsc -p ./tsconfig.json && yarn run lint", | ||
"watch": "tsc -w -p ./tsconfig.json", | ||
"lint": "eslint -c ../../configs/.eslintrc.js \"src/**/!(*.spec.ts*|test-helper.ts)\"", | ||
"test": "ts-mocha \"./src/**/*.spec.?(ts|tsx)\"" | ||
"clean": "shx rm -fr lib artifacts *.tsbuildinfo", | ||
"build": "tsc", | ||
"watch": "tsc --watch", | ||
"test": "vitest run --config ../../vite.config.ts" | ||
}, | ||
@@ -62,7 +59,3 @@ "files": [ | ||
"types": "lib/index", | ||
"eslintIgnore": [ | ||
"src/**/*.spec.?(ts|tsx)", | ||
"src/utils/test-helper.ts" | ||
], | ||
"gitHead": "3625d2d3e040972f24ba8ffbdbbe108ba09f7591" | ||
"gitHead": "f9439727fbb8b117767d661df5c93947fecf52ce" | ||
} |
@@ -30,4 +30,4 @@ # Sprotty | ||
- [Example: DSL in the Cloud](http://github.com/TypeFox/theia-xtext-sprotty-example) – an example using Xtext, Theia and Sprotty to create a DSL workbench in the cloud | ||
- [Example: npm dependencies](https://github.com/TypeFox/npm-dependency-graph) – discover dependencies of npm packages | ||
- [Yangster](https://github.com/theia-ide/yang-vscode) a VS Code extension for the YANG language | ||
- [Example: view filtering](https://github.com/TypeFox/sprotty-view-filtering) – using filtering to efficiently navigate a large dataset of publications and citations | ||
- [Example: nested graphs](https://github.com/TypeFox/sprotty-nested-demo) – expanding nested subgraphs in-place to efficiently navigate a large project with TypeScript modules | ||
- [Yangster](https://github.com/TypeFox/yang-vscode) – a VS Code extension for the YANG language |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest';; | ||
import { Container, injectable, interfaces } from "inversify"; | ||
@@ -22,0 +21,0 @@ import { Action, RedoAction, RejectAction, RequestModelAction, SetModelAction, UndoAction } from 'sprotty-protocol/lib/actions'; |
@@ -17,4 +17,3 @@ /******************************************************************************** | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { easeInOut } from "./easing"; | ||
@@ -21,0 +20,0 @@ |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container, injectable, inject } from "inversify"; | ||
@@ -22,0 +21,0 @@ import { TYPES } from "../types"; |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container, injectable } from "inversify"; | ||
@@ -22,0 +21,0 @@ import { TYPES } from "../types"; |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import { injectable } from "inversify"; | ||
@@ -19,0 +20,0 @@ import { Action } from "sprotty-protocol/lib/actions"; |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { CommandExecutionContext } from '../commands/command'; | ||
@@ -22,0 +21,0 @@ import { InitializeCanvasBoundsAction, InitializeCanvasBoundsCommand } from './initialize-canvas'; |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -34,3 +33,3 @@ import { TYPES } from '../types'; | ||
for (const p in expected) { | ||
if (expected.hasOwnProperty(p)) { | ||
if (Object.prototype.hasOwnProperty.call(expected, p)) { | ||
const expectedProp = (expected as any)[p]; | ||
@@ -40,3 +39,3 @@ const actualProp = (actual as any)[p]; | ||
for (const i in expectedProp) { | ||
if (expectedProp.hasOwnProperty(i)) { | ||
if (Object.prototype.hasOwnProperty.call(expectedProp, i)) { | ||
compare(expectedProp[i], actualProp[i]); | ||
@@ -43,0 +42,0 @@ } |
@@ -18,12 +18,12 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
import { Selectable } from 'sprotty-protocol/lib/model'; | ||
import { TYPES } from '../types'; | ||
import { ModelIndexImpl, SChildElementImpl } from './smodel'; | ||
import { SModelFactory } from "./smodel-factory"; | ||
import { SModelFactory } from './smodel-factory'; | ||
import { registerModelElement } from './smodel-utils'; | ||
import { selectFeature, Selectable } from '../../features/select/model'; | ||
import { selectFeature } from '../../features/select/model'; | ||
import { boundsFeature } from '../../features/bounds/model'; | ||
import defaultModule from "../di.config"; | ||
import defaultModule from '../di.config'; | ||
import { SModelElement } from 'sprotty-protocol'; | ||
@@ -30,0 +30,0 @@ |
@@ -17,4 +17,3 @@ /******************************************************************************** | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SChildElementImpl, ModelIndexImpl, SModelRootImpl } from './smodel'; | ||
@@ -21,0 +20,0 @@ |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -50,3 +49,3 @@ import { TYPES } from '../types'; | ||
const vnode = missingView.render(emptyRoot, context); | ||
expect(toHTML(vnode)).to.be.equal('<text class="sprotty-missing" x="0" y="0">?EMPTY?</text>'); | ||
expect(toHTML(vnode)).to.be.equal('<text class="sprotty-missing" x="0" y="0">missing "NONE" view</text>'); | ||
const model = new SNodeImpl(); | ||
@@ -62,3 +61,3 @@ model.bounds = { | ||
const vnode1 = missingView.render(model, context); | ||
expect(toHTML(vnode1)).to.be.equal('<text class="sprotty-missing" x="42" y="41">?foo?</text>'); | ||
expect(toHTML(vnode1)).to.be.equal('<text class="sprotty-missing" x="42" y="41">missing "type" view</text>'); | ||
}); | ||
@@ -65,0 +64,0 @@ }); |
@@ -17,9 +17,9 @@ /******************************************************************************** | ||
import { Bounds, Dimension, Point } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SParentElementImpl, SModelElementImpl, SChildElementImpl } from "../../base/model/smodel"; | ||
import { isLayoutContainer, isLayoutableChild, LayoutContainer, isBoundsAware } from "./model"; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { SParentElementImpl, SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { isLayoutContainer, isLayoutableChild, InternalLayoutContainer, isBoundsAware } from './model'; | ||
import { ILayout, StatefulLayouter } from './layout'; | ||
import { AbstractLayoutOptions, HAlignment, VAlignment } from './layout-options'; | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { injectable } from "inversify"; | ||
import { injectable } from 'inversify'; | ||
@@ -29,3 +29,3 @@ @injectable() | ||
layout(container: SParentElementImpl & LayoutContainer, | ||
layout(container: SParentElementImpl & InternalLayoutContainer, | ||
layouter: StatefulLayouter) { | ||
@@ -37,7 +37,7 @@ const boundsData = layouter.getBoundsData(container); | ||
options.resizeContainer | ||
? childrenSize.width | ||
? Math.max(childrenSize.width, options.minWidth) | ||
: Math.max(0, this.getFixedContainerBounds(container, options, layouter).width) - options.paddingLeft - options.paddingRight); | ||
const maxHeight = options.paddingFactor * ( | ||
options.resizeContainer | ||
? childrenSize.height | ||
? Math.max(childrenSize.height, options.minHeight) | ||
: Math.max(0, this.getFixedContainerBounds(container, options, layouter).height) - options.paddingTop - options.paddingBottom); | ||
@@ -56,3 +56,3 @@ if (maxWidth > 0 && maxHeight > 0) { | ||
protected getFinalContainerBounds(container: SParentElementImpl & LayoutContainer, | ||
protected getFinalContainerBounds(container: SParentElementImpl & InternalLayoutContainer, | ||
lastOffset: Point, | ||
@@ -92,7 +92,7 @@ options: T, | ||
protected abstract getChildrenSize(container: SParentElementImpl & LayoutContainer, | ||
protected abstract getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, | ||
containerOptions: T, | ||
layouter: StatefulLayouter): Dimension; | ||
protected layoutChildren(container: SParentElementImpl & LayoutContainer, | ||
protected layoutChildren(container: SParentElementImpl & InternalLayoutContainer, | ||
layouter: StatefulLayouter, | ||
@@ -99,0 +99,0 @@ containerOptions: T, |
@@ -19,2 +19,3 @@ /******************************************************************************** | ||
import { Action, ComputedBoundsAction, RequestBoundsAction, SetBoundsAction } from 'sprotty-protocol/lib/actions'; | ||
import { Alignable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -24,6 +25,6 @@ import { CommandExecutionContext, CommandResult, CommandReturn, HiddenCommand, SystemCommand } from '../../base/commands/command'; | ||
import { TYPES } from '../../base/types'; | ||
import { Alignable, BoundsAware, isBoundsAware } from './model'; | ||
import { InternalBoundsAware, isBoundsAware } from './model'; | ||
export interface ResolvedElementAndBounds { | ||
element: SModelElementImpl & BoundsAware | ||
element: SModelElementImpl & InternalBoundsAware | ||
oldBounds: Bounds | ||
@@ -30,0 +31,0 @@ newPosition?: Point |
@@ -17,6 +17,6 @@ /******************************************************************************** | ||
import { expect } from 'chai'; | ||
import { Container } from 'inversify'; | ||
import 'mocha'; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { AnimationFrameSyncer } from '../../base/animations/animation-frame-syncer'; | ||
@@ -23,0 +23,0 @@ import { CommandExecutionContext } from '../../base/commands/command'; |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelElementImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
@@ -21,0 +22,0 @@ import { createFeatureSet } from '../../base/model/smodel-factory'; |
@@ -23,3 +23,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer, isLayoutableChild } from './model'; | ||
import { InternalLayoutContainer, isLayoutableChild } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -40,3 +40,3 @@ | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, | ||
containerOptions: HBoxLayoutOptions, | ||
@@ -43,0 +43,0 @@ layouter: StatefulLayouter) { |
@@ -28,3 +28,3 @@ /******************************************************************************** |
import { Layouter } from './layout'; |
import { BoundsAware, isAlignable, isLayoutContainer, isSizeable } from './model'; |
import { InternalBoundsAware, isAlignable, isLayoutContainer, isSizeable } from './model'; |
@@ -57,3 +57,3 @@ export class BoundsData { |
private readonly element2boundsData: Map<SModelElementImpl & BoundsAware, BoundsData> = new Map; |
private readonly element2boundsData: Map<SModelElementImpl & InternalBoundsAware, BoundsData> = new Map; |
@@ -160,3 +160,3 @@ root: SModelRootImpl | undefined; |
*/ |
protected getBounds(elm: Node, element: SModelElementImpl & BoundsAware): Bounds { |
protected getBounds(elm: Node, element: SModelElementImpl & InternalBoundsAware): Bounds { |
if (!isSVGGraphicsElement(elm)) { |
@@ -163,0 +163,0 @@ this.logger.error(this, 'Not an SVG element:', elm); |
@@ -23,3 +23,3 @@ /******************************************************************************** | ||
import { SParentElementImpl, SModelElementImpl } from "../../base/model/smodel"; | ||
import { isLayoutContainer, LayoutContainer } from "./model"; | ||
import { isLayoutContainer, InternalLayoutContainer } from "./model"; | ||
import { BoundsData } from "./hidden-bounds-updater"; | ||
@@ -56,3 +56,3 @@ import { isInjectable } from "../../utils/inversify"; | ||
layout(element2boundsData: Map<SModelElementImpl , BoundsData>) { | ||
layout(element2boundsData: Map<SModelElementImpl, BoundsData>) { | ||
new StatefulLayouter(element2boundsData, this.layoutRegistry, this.logger).layout(); | ||
@@ -64,5 +64,5 @@ } | ||
private toBeLayouted: (SParentElementImpl & LayoutContainer)[]; | ||
private toBeLayouted: (SParentElementImpl & InternalLayoutContainer)[]; | ||
constructor(private readonly element2boundsData: Map<SModelElementImpl , BoundsData>, | ||
constructor(private readonly element2boundsData: Map<SModelElementImpl, BoundsData>, | ||
private readonly layoutRegistry: LayoutRegistry, | ||
@@ -102,3 +102,3 @@ public readonly log: ILogger) { | ||
protected doLayout(element: SParentElementImpl & LayoutContainer): Bounds { | ||
protected doLayout(element: SParentElementImpl & InternalLayoutContainer): Bounds { | ||
const index = this.toBeLayouted.indexOf(element); | ||
@@ -121,3 +121,3 @@ if (index >= 0) | ||
export interface ILayout { | ||
layout(container: SParentElementImpl & LayoutContainer, | ||
layout(container: SParentElementImpl & InternalLayoutContainer, | ||
layouter: StatefulLayouter): void | ||
@@ -124,0 +124,0 @@ } |
@@ -17,4 +17,3 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelRootImpl } from '../../base/model/smodel'; | ||
@@ -21,0 +20,0 @@ import { SShapeElementImpl, getAbsoluteBounds } from './model'; |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { Locateable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, isBounds, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -24,3 +25,2 @@ import { SChildElementImpl, SModelElementImpl, SModelRootImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
import { getWindowScroll } from '../../utils/browser'; | ||
import type { Locateable } from '../move/model'; | ||
@@ -39,13 +39,19 @@ export const boundsFeature = Symbol('boundsFeature'); | ||
*/ | ||
export interface BoundsAware { | ||
export interface InternalBoundsAware { | ||
bounds: Bounds | ||
} | ||
/** @deprecated Use `InternalBoundsAware` instead. */ | ||
export type BoundsAware = InternalBoundsAware; | ||
/** | ||
* Used to identify model elements that specify a layout to apply to their children. | ||
*/ | ||
export interface LayoutContainer extends LayoutableChild { | ||
export interface InternalLayoutContainer extends InternalLayoutableChild { | ||
layout: string | ||
} | ||
/** @deprecated Use `InternalLayoutContainer` instead. */ | ||
export type LayoutContainer = InternalLayoutContainer; | ||
export type ModelLayoutOptions = { [key: string]: string | number | boolean }; | ||
@@ -56,11 +62,14 @@ | ||
*/ | ||
export interface LayoutableChild extends BoundsAware { | ||
export interface InternalLayoutableChild extends InternalBoundsAware { | ||
layoutOptions?: ModelLayoutOptions | ||
} | ||
/** @deprecated Use `InternalLayoutableChild` instead. */ | ||
export type LayoutableChild = InternalLayoutableChild; | ||
/** | ||
* Feature extension interface for {@link alignFeature}. | ||
* Used to adjust elements whose bounding box is not at the origin, e.g. | ||
* labels, or pre-rendered SVG figures. | ||
* | ||
* Feature extension interface for {@link alignFeature}. | ||
* @deprecated use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -71,7 +80,7 @@ export interface Alignable { | ||
export function isBoundsAware(element: SModelElementImpl): element is SModelElementImpl & BoundsAware { | ||
export function isBoundsAware(element: SModelElementImpl): element is SModelElementImpl & InternalBoundsAware { | ||
return 'bounds' in element; | ||
} | ||
export function isLayoutContainer(element: SModelElementImpl): element is SParentElementImpl & LayoutContainer { | ||
export function isLayoutContainer(element: SModelElementImpl): element is SParentElementImpl & InternalLayoutContainer { | ||
return isBoundsAware(element) | ||
@@ -82,3 +91,3 @@ && element.hasFeature(layoutContainerFeature) | ||
export function isLayoutableChild(element: SModelElementImpl): element is SChildElementImpl & LayoutableChild { | ||
export function isLayoutableChild(element: SModelElementImpl): element is SChildElementImpl & InternalLayoutableChild { | ||
return isBoundsAware(element) | ||
@@ -88,3 +97,3 @@ && element.hasFeature(layoutableChildFeature); | ||
export function isSizeable(element: SModelElementImpl): element is SModelElementImpl & BoundsAware { | ||
export function isSizeable(element: SModelElementImpl): element is SModelElementImpl & InternalBoundsAware { | ||
return element.hasFeature(boundsFeature) && isBoundsAware(element); | ||
@@ -175,3 +184,3 @@ } | ||
*/ | ||
export abstract class SShapeElementImpl extends SChildElementImpl implements BoundsAware, Locateable, LayoutableChild { | ||
export abstract class SShapeElementImpl extends SChildElementImpl implements InternalBoundsAware, Locateable, InternalLayoutableChild { | ||
@@ -178,0 +187,0 @@ position: Point = Point.ORIGIN; |
@@ -21,6 +21,6 @@ /******************************************************************************** | ||
import { CommandExecutionContext } from "../../base/commands/command"; | ||
import { BoundsAware } from './model'; | ||
import { InternalBoundsAware } from './model'; | ||
export interface ResolvedElementResize { | ||
element: SModelElementImpl & BoundsAware | ||
element: SModelElementImpl & InternalBoundsAware | ||
fromDimension: Dimension | ||
@@ -27,0 +27,0 @@ toDimension: Dimension |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelElementImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
@@ -21,0 +22,0 @@ import { createFeatureSet } from '../../base/model/smodel-factory'; |
@@ -23,3 +23,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer, isLayoutableChild } from './model'; | ||
import { InternalLayoutContainer, isLayoutableChild } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -38,3 +38,3 @@ | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, | ||
options: StackLayoutOptions, | ||
@@ -41,0 +41,0 @@ layouter: StatefulLayouter) { |
@@ -17,4 +17,4 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelElementImpl, SParentElementImpl } from '../../base/model/smodel'; | ||
@@ -21,0 +21,0 @@ import { createFeatureSet } from '../../base/model/smodel-factory'; |
@@ -23,3 +23,3 @@ /******************************************************************************** | ||
import { BoundsData } from './hidden-bounds-updater'; | ||
import { LayoutContainer, isLayoutableChild } from './model'; | ||
import { InternalLayoutContainer, isLayoutableChild } from './model'; | ||
import { StatefulLayouter } from './layout'; | ||
@@ -40,3 +40,3 @@ | ||
protected getChildrenSize(container: SParentElementImpl & LayoutContainer, | ||
protected getChildrenSize(container: SParentElementImpl & InternalLayoutContainer, | ||
containerOptions: VBoxLayoutOptions, | ||
@@ -43,0 +43,0 @@ layouter: StatefulLayouter) { |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { IViewArgs, RenderingContext } from '../../base/views/view'; | ||
@@ -21,0 +22,0 @@ import { ViewportRootElementImpl } from '../viewport/viewport-root'; |
@@ -21,3 +21,3 @@ /******************************************************************************** | ||
import { IViewArgs, IView, RenderingContext } from '../../base/views/view'; | ||
import { getAbsoluteBounds, BoundsAware } from './model'; | ||
import { getAbsoluteBounds, InternalBoundsAware } from './model'; | ||
import { SChildElementImpl } from '../../base/model/smodel'; | ||
@@ -33,3 +33,3 @@ | ||
*/ | ||
isVisible(model: Readonly<SChildElementImpl & BoundsAware>, context: RenderingContext): boolean { | ||
isVisible(model: Readonly<SChildElementImpl & InternalBoundsAware>, context: RenderingContext): boolean { | ||
if (context.targetKind === 'hidden') { | ||
@@ -36,0 +36,0 @@ // Don't hide any element for hidden rendering |
@@ -21,2 +21,5 @@ /******************************************************************************** | ||
/** | ||
* @deprecated Use SButton from `sprotty-protocol` instead. | ||
*/ | ||
export interface SButtonSchema extends SShapeElement { | ||
@@ -23,0 +26,0 @@ pressed: boolean |
@@ -16,6 +16,6 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { ContextMenuProviderRegistry } from "./menu-providers"; | ||
@@ -22,0 +22,0 @@ import { SModelRootImpl } from "../../base/model/smodel"; |
@@ -19,3 +19,3 @@ /******************************************************************************** | ||
import { ContainerModule } from "inversify"; | ||
import { SIssueMarker } from "./model"; | ||
import { SIssueMarkerImpl } from "./model"; | ||
import { IssueMarkerView } from "./views"; | ||
@@ -26,3 +26,3 @@ import { TYPES } from "../../base/types"; | ||
const decorationModule = new ContainerModule((bind, _unbind, isBound) => { | ||
configureModelElement({ bind, isBound }, 'marker', SIssueMarker, IssueMarkerView); | ||
configureModelElement({ bind, isBound }, 'marker', SIssueMarkerImpl, IssueMarkerView); | ||
bind(DecorationPlacer).toSelf().inSingletonScope(); | ||
@@ -29,0 +29,0 @@ bind(TYPES.IVNodePostprocessor).toService(DecorationPlacer); |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { SIssue as SIssueSchema } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl } from '../../base/model/smodel'; | ||
@@ -38,8 +39,17 @@ import { SShapeElementImpl, boundsFeature } from '../bounds/model'; | ||
export class SIssueMarkerImpl extends SDecoration { | ||
issues: SIssueSchema[]; | ||
} | ||
/** @deprecated Use SIssueMarkerImpl instead. */ | ||
export const SIssueMarker = SIssueMarkerImpl; | ||
/** | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
export type SIssueSeverity = 'error' | 'warning' | 'info'; | ||
export class SIssueMarker extends SDecoration { | ||
issues: SIssue[]; | ||
} | ||
/** | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
export class SIssue { | ||
@@ -46,0 +56,0 @@ message: string; |
@@ -17,5 +17,4 @@ /******************************************************************************** | ||
import { expect } from "chai"; | ||
import "mocha"; | ||
import "reflect-metadata"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { EdgeRouting } from "../routing/routing"; | ||
@@ -22,0 +21,0 @@ import { IntersectionFinder } from "./intersection-finder"; |
@@ -17,13 +17,16 @@ /******************************************************************************** | ||
import { injectable, inject } from "inversify"; | ||
import { VNode } from "snabbdom"; | ||
import { Bounds, Point, toDegrees } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SModelElementImpl, SChildElementImpl } from "../../base/model/smodel"; | ||
import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; | ||
import { setAttr } from "../../base/views/vnode-utils"; | ||
import { SEdgeImpl } from "../../graph/sgraph"; | ||
import { Orientation } from "../../utils/geometry"; | ||
import { isAlignable, BoundsAware } from "../bounds/model"; | ||
import { DEFAULT_EDGE_PLACEMENT, isEdgeLayoutable, EdgeLayoutable, EdgePlacement } from "./model"; | ||
import { EdgeRouterRegistry } from "../routing/routing"; | ||
import { injectable, inject } from 'inversify'; | ||
import { VNode } from 'snabbdom'; | ||
import { Bounds, Point, toDegrees } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { EdgeLayoutable, EdgePlacement } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { IVNodePostprocessor } from '../../base/views/vnode-postprocessor'; | ||
import { setAttr } from '../../base/views/vnode-utils'; | ||
import { SEdgeImpl } from '../../graph/sgraph'; | ||
import { Orientation } from '../../utils/geometry'; | ||
import { isAlignable, InternalBoundsAware } from '../bounds/model'; | ||
import { DEFAULT_EDGE_PLACEMENT, isEdgeLayoutable, checkEdgePlacement } from './model'; | ||
import { EdgeRouterRegistry } from '../routing/routing'; | ||
import { TYPES } from '../../base/types'; | ||
import { ILogger } from '../../utils/logging'; | ||
@@ -34,6 +37,15 @@ @injectable() | ||
@inject(EdgeRouterRegistry) edgeRouterRegistry: EdgeRouterRegistry; | ||
@inject(TYPES.ILogger) protected readonly logger: ILogger; | ||
/** | ||
* Decorates the vnode with the appropriate transformation based on the element's placement and bounds. | ||
* @param vnode - The vnode to decorate. | ||
* @param element - The SModelElementImpl to decorate. | ||
* @returns The decorated vnode. | ||
*/ | ||
decorate(vnode: VNode, element: SModelElementImpl): VNode { | ||
if (isEdgeLayoutable(element) && element.parent instanceof SEdgeImpl) { | ||
if (element.bounds !== Bounds.EMPTY) { | ||
const actualBounds = element.bounds; | ||
const hasOwnPlacement = checkEdgePlacement(element); | ||
const placement = this.getEdgePlacement(element); | ||
@@ -43,25 +55,57 @@ const edge = element.parent; | ||
const router = this.edgeRouterRegistry.get(edge.routerKind); | ||
// point on edge derived from edgePlacement.position | ||
const pointOnEdge = router.pointAt(edge, position); | ||
const derivativeOnEdge = router.derivativeAt(edge, position); | ||
let transform = ''; | ||
if (pointOnEdge && derivativeOnEdge) { | ||
transform += `translate(${pointOnEdge.x}, ${pointOnEdge.y})`; | ||
const angle = toDegrees(Math.atan2(derivativeOnEdge.y, derivativeOnEdge.x)); | ||
if (placement.rotate) { | ||
let flippedAngle = angle; | ||
if (Math.abs(angle) > 90) { | ||
if (angle < 0) | ||
flippedAngle += 180; | ||
else if (angle > 0) | ||
flippedAngle -= 180; | ||
// Calculation of potential free movement. Just add the actual bounds to the point on edge. | ||
const freeTransform = `translate(${(pointOnEdge?.x ?? 0) + actualBounds.x}, ${(pointOnEdge?.y ?? 0) + actualBounds.y})`; | ||
// Check if edgeplacement is set. If not the label is freely movable if movefeature is enabled for such labels. | ||
if (hasOwnPlacement) { | ||
if (pointOnEdge) { | ||
let derivativeOnEdge: Point | undefined; | ||
// handle different move modes | ||
if (placement.moveMode && placement.moveMode !== 'edge') { | ||
// get the relative position on segment | ||
derivativeOnEdge = router.derivativeAt(edge, position); | ||
// handle free move mode | ||
if (placement.moveMode === 'free') { | ||
transform += freeTransform; | ||
} else { | ||
// The moveMode is neither 'edge' nor 'free' so it is 'none'. Hence the label is not movable and gets the fixed point on edge. | ||
transform += `translate(${pointOnEdge.x}, ${pointOnEdge.y})`; | ||
} | ||
} else { | ||
// no movemode was set or set to 'edge': label movement is constrained to the edge | ||
// Find orthogonal intersection point on edge and use it as the label's position | ||
const orthogonalPoint = router.findOrthogonalIntersection(edge, Point.add(pointOnEdge, actualBounds)); | ||
if (orthogonalPoint) { | ||
derivativeOnEdge = orthogonalPoint.derivative; | ||
transform += `translate(${orthogonalPoint.point.x}, ${orthogonalPoint.point.y})`; | ||
} | ||
} | ||
transform += ` rotate(${flippedAngle})`; | ||
const alignment = this.getRotatedAlignment(element, placement, flippedAngle !== angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} else { | ||
const alignment = this.getAlignment(element, placement, angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
if (derivativeOnEdge) { | ||
const angle = toDegrees(Math.atan2(derivativeOnEdge.y, derivativeOnEdge.x)); | ||
if (placement.rotate) { | ||
let flippedAngle = angle; | ||
// Flip angle if it exceeds 90 degrees | ||
if (Math.abs(angle) > 90) { | ||
if (angle < 0) | ||
flippedAngle += 180; | ||
else if (angle > 0) | ||
flippedAngle -= 180; | ||
} | ||
transform += ` rotate(${flippedAngle})`; | ||
// Get rotated alignment based on flipped angle | ||
const alignment = this.getRotatedAlignment(element, placement, flippedAngle !== angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} else { | ||
// Get alignment based on angle | ||
const alignment = this.getAlignment(element, placement, angle); | ||
transform += ` translate(${alignment.x}, ${alignment.y})`; | ||
} | ||
} | ||
} | ||
setAttr(vnode, 'transform', transform); | ||
} else { | ||
transform += freeTransform; | ||
} | ||
setAttr(vnode, 'transform', transform); | ||
} | ||
@@ -72,3 +116,3 @@ } | ||
protected getRotatedAlignment(element: EdgeLayoutable & SModelElementImpl & BoundsAware, placement: EdgePlacement, flip: boolean) { | ||
protected getRotatedAlignment(element: EdgeLayoutable & SModelElementImpl & InternalBoundsAware, placement: EdgePlacement, flip: boolean) { | ||
let x = isAlignable(element) ? element.alignment.x : 0; | ||
@@ -131,3 +175,3 @@ let y = isAlignable(element) ? element.alignment.y : 0; | ||
protected getAlignment(label: EdgeLayoutable & SModelElementImpl & BoundsAware, placement: EdgePlacement, angle: number): Point { | ||
protected getAlignment(label: EdgeLayoutable & SModelElementImpl & InternalBoundsAware, placement: EdgePlacement, angle: number): Point { | ||
const bounds = label.bounds; | ||
@@ -134,0 +178,0 @@ const x = isAlignable(label) ? label.alignment.x - bounds.width : 0; |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import type { EdgePlacement as EdgePlacementSchema } from 'sprotty-protocol/lib/model'; | ||
import { SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { BoundsAware, isBoundsAware } from '../bounds/model'; | ||
import { InternalBoundsAware, isBoundsAware } from '../bounds/model'; | ||
import { SRoutableElementImpl } from '../routing/model'; | ||
@@ -25,12 +26,12 @@ | ||
/** | ||
* @deprecated Use EdgeLayoutable from sprotty-protocol instead | ||
* Feature extension interface for {@link edgeLayoutFeature}. | ||
*/ | ||
export interface EdgeLayoutable { | ||
edgePlacement: EdgePlacement | ||
edgePlacement: EdgePlacementSchema | ||
} | ||
export function isEdgeLayoutable<T extends SModelElementImpl>(element: T): element is T & SChildElementImpl & BoundsAware & EdgeLayoutable { | ||
export function isEdgeLayoutable<T extends SModelElementImpl>(element: T): element is T & SChildElementImpl & InternalBoundsAware & EdgeLayoutable { | ||
return element instanceof SChildElementImpl | ||
&& element.parent instanceof SRoutableElementImpl | ||
&& checkEdgeLayoutable(element) | ||
&& isBoundsAware(element) | ||
@@ -40,8 +41,14 @@ && element.hasFeature(edgeLayoutFeature); | ||
function checkEdgeLayoutable(element: SChildElementImpl): element is SChildElementImpl & EdgeLayoutable { | ||
export function checkEdgePlacement(element: SChildElementImpl): element is SChildElementImpl & EdgeLayoutable { | ||
return 'edgePlacement' in element; | ||
} | ||
/** | ||
* @deprecated Use EdgeSide from sprotty-protocol instead | ||
*/ | ||
export type EdgeSide = 'left' | 'right' | 'top' | 'bottom' | 'on'; | ||
/** | ||
* @deprecated Use EdgePlacement from sprotty-protocol instead | ||
*/ | ||
export class EdgePlacement extends Object { | ||
@@ -67,9 +74,18 @@ /** | ||
offset: number; | ||
/** | ||
* where should the label be moved when move feature is enabled. | ||
* 'edge' means the label is moved along the edge, 'free' means the label is moved freely, 'none' means the label is not moved. | ||
* Default is 'edge'. | ||
*/ | ||
moveMode?: 'edge' | 'free' | 'none'; | ||
} | ||
export const DEFAULT_EDGE_PLACEMENT: EdgePlacement = { | ||
export const DEFAULT_EDGE_PLACEMENT: EdgePlacementSchema = { | ||
rotate: true, | ||
side: 'top', | ||
position: 0.5, | ||
offset: 7 | ||
offset: 7, | ||
moveMode: 'edge' | ||
}; |
@@ -22,5 +22,5 @@ /******************************************************************************** | ||
/** | ||
* Feature extension interface for {@link expandFeature}. | ||
* Model elements that implement this interface can be expanded/collapsed | ||
* | ||
* Feature extension interface for {@link expandFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -27,0 +27,0 @@ export interface Expandable { |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -22,0 +21,0 @@ import { TYPES } from '../../base/types'; |
@@ -53,8 +53,16 @@ /******************************************************************************** | ||
if (typeof document !== 'undefined') { | ||
const div = document.getElementById(this.options.hiddenDiv); | ||
if (div !== null && div.firstElementChild && div.firstElementChild.tagName === 'svg') { | ||
const svgElement = div.firstElementChild as SVGSVGElement; | ||
const svg = this.createSvg(svgElement, root); | ||
this.actionDispatcher.dispatch(ExportSvgAction.create(svg, request ? request.requestId : '')); | ||
const hiddenDiv = document.getElementById(this.options.hiddenDiv); | ||
if (hiddenDiv === null) { | ||
this.log.warn(this, `Element with id ${this.options.hiddenDiv} not found. Nothing to export.`); | ||
return; | ||
} | ||
const svgElement = hiddenDiv.querySelector('svg'); | ||
if (svgElement === null) { | ||
this.log.warn(this, `No svg element found in ${this.options.hiddenDiv} div. Nothing to export.`); | ||
return; | ||
} | ||
const svg = this.createSvg(svgElement, root); | ||
this.actionDispatcher.dispatch(ExportSvgAction.create(svg, request ? request.requestId : '')); | ||
} | ||
@@ -74,5 +82,6 @@ } | ||
docCopy.close(); | ||
const svgElementNew = docCopy.getElementById(svgElementOrig.id)!; | ||
const svgElementNew = docCopy.querySelector('svg')!; | ||
svgElementNew.removeAttribute('opacity'); | ||
this.copyStyles(svgElementOrig, svgElementNew, ['width', 'height', 'opacity']); | ||
// inline-size copied from sprotty-hidden svg shrinks the svg so it is not visible. | ||
this.copyStyles(svgElementOrig, svgElementNew, ['width', 'height', 'opacity', 'inline-size']); | ||
svgElementNew.setAttribute('version', '1.1'); | ||
@@ -86,3 +95,3 @@ const bounds = this.getBounds(root); | ||
protected copyStyles(source: Element, target: Element, skipedProperties: string[]) { | ||
protected copyStyles(source: Element, target: Element, skippedProperties: string[]) { | ||
const sourceStyle = getComputedStyle(source); | ||
@@ -93,3 +102,3 @@ const targetStyle = getComputedStyle(target); | ||
const key = sourceStyle[i]; | ||
if (skipedProperties.indexOf(key) === -1) { | ||
if (skippedProperties.indexOf(key) === -1) { | ||
const value = sourceStyle.getPropertyValue(key); | ||
@@ -103,3 +112,3 @@ if (targetStyle.getPropertyValue(key) !== value) { | ||
target.setAttribute('style', diffStyle); | ||
// IE doesn't retrun anything on source.children | ||
// IE doesn't return anything on source.children | ||
for (let i = 0; i < source.childNodes.length; ++i) { | ||
@@ -106,0 +115,0 @@ const sourceChild = source.childNodes[i]; |
@@ -17,10 +17,11 @@ /******************************************************************************** | ||
import { injectable } from "inversify"; | ||
import { VNode } from "snabbdom"; | ||
import { Animation } from "../../base/animations/animation"; | ||
import { CommandExecutionContext } from "../../base/commands/command"; | ||
import { SModelRootImpl, SModelElementImpl, SChildElementImpl } from "../../base/model/smodel"; | ||
import { IVNodePostprocessor } from "../../base/views/vnode-postprocessor"; | ||
import { setAttr } from "../../base/views/vnode-utils"; | ||
import { Fadeable, isFadeable } from "./model"; | ||
import { injectable } from 'inversify'; | ||
import { VNode } from 'snabbdom'; | ||
import { Fadeable } from 'sprotty-protocol/lib/model'; | ||
import { Animation } from '../../base/animations/animation'; | ||
import { CommandExecutionContext } from '../../base/commands/command'; | ||
import { SModelRootImpl, SModelElementImpl, SChildElementImpl } from '../../base/model/smodel'; | ||
import { IVNodePostprocessor } from '../../base/views/vnode-postprocessor'; | ||
import { setAttr } from '../../base/views/vnode-utils'; | ||
import { isFadeable } from './model'; | ||
@@ -27,0 +28,0 @@ export interface ResolvedElementFade { |
@@ -22,3 +22,4 @@ /******************************************************************************** | ||
/** | ||
* Feature extension interface for {@link fadeFeature}. | ||
* Feature extension interface for {@link fadeFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -25,0 +26,0 @@ export interface Fadeable { |
@@ -17,13 +17,13 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { Container } from "inversify"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
import { Action, HoverFeedbackAction } from 'sprotty-protocol/lib/actions'; | ||
import { TYPES } from "../../base/types"; | ||
import { SChildElementImpl, SModelElementImpl, SModelRootImpl } from "../../base/model/smodel"; | ||
import { HoverMouseListener } from "./hover"; | ||
import { Hoverable, hoverFeedbackFeature, popupFeature } from "./model"; | ||
import defaultModule from "../../base/di.config"; | ||
import hoverModule from "./di.config"; | ||
import { Hoverable } from 'sprotty-protocol/lib/model'; | ||
import { TYPES } from '../../base/types'; | ||
import { SChildElementImpl, SModelElementImpl, SModelRootImpl } from '../../base/model/smodel'; | ||
import { HoverMouseListener } from './hover'; | ||
import { hoverFeedbackFeature, popupFeature } from './model'; | ||
import defaultModule from '../../base/di.config'; | ||
import hoverModule from './di.config'; | ||
@@ -62,3 +62,3 @@ describe('hover', () => { | ||
protected override getElementFromEventPosition(event: MouseEvent) { | ||
protected override getElementFromEventPosition(_event: MouseEvent) { | ||
// the original implementation uses document which isn't available in unit testing | ||
@@ -78,3 +78,3 @@ return null; | ||
constructor(id: string = "1") { | ||
constructor(id: string = '1') { | ||
super(); | ||
@@ -110,4 +110,4 @@ this.id = id; | ||
it('resets the hover feedback on hovering over another element', () => { | ||
const target = new HoverableTarget("1"); | ||
const anotherTarget = new HoverableTarget("2"); | ||
const target = new HoverableTarget('1'); | ||
const anotherTarget = new HoverableTarget('2'); | ||
hoverListener.mouseOver(target, event); | ||
@@ -140,4 +140,4 @@ const mouseOverResult: (Action | Promise<Action>)[] = hoverListener.mouseOver(anotherTarget, event); | ||
hoverListener.resetLastHoverFeedbackElement(); | ||
const target = new HoverableTarget("1"); | ||
const anotherTarget = new HoverableTarget("2"); | ||
const target = new HoverableTarget('1'); | ||
const anotherTarget = new HoverableTarget('2'); | ||
hoverListener.mouseOver(target, event); | ||
@@ -144,0 +144,0 @@ const mouseOutResult: (Action | Promise<Action>)[] = hoverListener.mouseOut(anotherTarget, event); |
@@ -23,2 +23,3 @@ /******************************************************************************** | ||
* Feature extension interface for {@link hoverFeedbackFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -25,0 +26,0 @@ export interface Hoverable { |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { hasOwnProperty } from 'sprotty-protocol/lib/utils/object'; | ||
import { Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -24,6 +25,5 @@ import { SModelElementImpl } from '../../base/model/smodel'; | ||
/** | ||
* An element that can be placed at a specific location using its position | ||
* property. | ||
* | ||
* An element that can be placed at a specific location using its position property. | ||
* Feature extension interface for {@link moveFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -35,3 +35,3 @@ export interface Locateable { | ||
export function isLocateable(element: SModelElementImpl): element is SModelElementImpl & Locateable { | ||
return (element as any)['position'] !== undefined; | ||
return hasOwnProperty(element, 'position'); | ||
} | ||
@@ -38,0 +38,0 @@ |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -22,0 +21,0 @@ import { TYPES } from '../../base/types'; |
@@ -19,2 +19,3 @@ /******************************************************************************** | ||
import { VNode } from 'snabbdom'; | ||
import { Locateable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -41,3 +42,3 @@ import { Action, DeleteElementAction, ReconnectAction, SelectAction, SelectAllAction, MoveAction } from 'sprotty-protocol/lib/actions'; | ||
import { isViewport } from '../viewport/model'; | ||
import { isLocateable, isMoveable, Locateable } from './model'; | ||
import { isLocateable, isMoveable } from './model'; | ||
import { ISnapper } from './snap'; | ||
@@ -44,0 +45,0 @@ |
@@ -17,3 +17,3 @@ /******************************************************************************** | ||
import { Viewport } from 'sprotty-protocol/lib/model'; | ||
import { Projectable as ProjectableSchema, Viewport } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -29,2 +29,3 @@ import { hasOwnProperty } from 'sprotty-protocol/lib/utils/object'; | ||
* Otherwise model elements also have to be `BoundsAware` so their projections can be shown. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -36,3 +37,3 @@ export interface Projectable { | ||
export function isProjectable(arg: unknown): arg is Projectable { | ||
export function isProjectable(arg: unknown): arg is ProjectableSchema { | ||
return hasOwnProperty(arg, 'projectionCssClasses'); | ||
@@ -88,3 +89,3 @@ } | ||
*/ | ||
export function getProjectedBounds(model: Readonly<SChildElementImpl & Projectable>): Bounds | undefined { | ||
export function getProjectedBounds(model: Readonly<SChildElementImpl & ProjectableSchema>): Bounds | undefined { | ||
const parent = model.parent; | ||
@@ -91,0 +92,0 @@ if (model.projectedBounds) { |
@@ -91,2 +91,37 @@ /******************************************************************************** | ||
findOrthogonalIntersection(edge: SRoutableElementImpl, point: Point): {point: Point, derivative: Point} { | ||
const calcOrthogonalIntersectionForSegment = (p1: Point, p2: Point) => { | ||
// Calculate the direction vector d of the edge and vector pq from p1 to point q | ||
const d: Point = Point.subtract(p2, p1); | ||
const pq: Point = Point.subtract(point, p1); | ||
// Calculate the scalar t for the direction vector d | ||
const t: number = Point.dotProduct(pq, d) / Point.dotProduct(d, d); | ||
// Check if the intersection point lies on the edge segment | ||
if (t >= 0 && t <= 1) { | ||
// Calculate and return the intersection point x | ||
return Point.linear(p1, p2, t); | ||
} else if (t < 0) { | ||
return p1; | ||
} else { | ||
return p2; | ||
} | ||
}; | ||
// Calculate the intersection for each segment of the edge and return the closest one | ||
const routedPoints = this.route(edge); | ||
let intersectionPoint: Point = routedPoints[0]; | ||
let index = 0; | ||
for (let i = 0; i < routedPoints.length - 1; ++i) { | ||
const intersection = calcOrthogonalIntersectionForSegment(routedPoints[i], routedPoints[i + 1]); | ||
if (Point.euclideanDistance(point, intersection) < Point.euclideanDistance(point, intersectionPoint)) { | ||
intersectionPoint = intersection; | ||
index = i; | ||
} | ||
} | ||
const derivative = Point.subtract(routedPoints[index + 1], routedPoints[index]); | ||
return {point: intersectionPoint, derivative}; | ||
} | ||
pointAt(edge: SRoutableElementImpl, t: number): Point | undefined { | ||
@@ -111,3 +146,3 @@ const segments = this.calculateSegment(edge, t); | ||
protected calculateSegment(edge: SRoutableElementImpl, t: number): { segmentStart: Point, segmentEnd: Point, lambda: number} | undefined { | ||
protected calculateSegment(edge: SRoutableElementImpl, t: number): { segmentStart: Point, segmentEnd: Point, lambda: number } | undefined { | ||
if (t < 0 || t > 1) | ||
@@ -169,3 +204,3 @@ return undefined; | ||
return edge.target.position; | ||
else { | ||
else { | ||
return route[route.length - 1]; | ||
@@ -214,3 +249,3 @@ } | ||
protected getAnchorComputer(connectable: SConnectableElementImpl): IAnchorComputer { | ||
return this.anchorRegistry.get(this.kind, connectable.anchorKind); | ||
return this.anchorRegistry.get(this.kind, connectable.anchorKind); | ||
} | ||
@@ -304,2 +339,21 @@ | ||
edge.index.remove(edge); | ||
if (edge.id === edgeInProgressID) { | ||
// create a proper edge id after connecting the edge in progress | ||
const idGen = (counter: number) => `${edge.sourceId}_to_${edge.targetId}_${counter}`; | ||
let idx = 0; | ||
let newId = idGen(idx); | ||
while (edge.index.getById(newId) !== undefined) { | ||
newId = idGen(++idx); | ||
} | ||
edge.id = newId; | ||
const progressTargetHandle = edge.children.find(child => child.id === edgeInProgressTargetHandleID); | ||
if (progressTargetHandle instanceof SRoutingHandleImpl) { | ||
// remove in progress target handle | ||
edge.remove(progressTargetHandle); | ||
if (progressTargetHandle.danglingAnchor) { | ||
// remove dangling anchor | ||
progressTargetHandle.danglingAnchor.parent.remove(progressTargetHandle.danglingAnchor); | ||
} | ||
} | ||
} | ||
edge.index.add(edge); | ||
@@ -356,3 +410,3 @@ if (this.getSelfEdgeIndex(edge) > -1) { | ||
{ x: sourceAnchors.get(Side.LEFT).x - standardDist, y: sourceAnchors.get(Side.BOTTOM).y + standardDist }, | ||
{ x: sourceAnchors.get(Side.LEFT).x - standardDist, y: sourceAnchors.get(Side.LEFT).y + delta}, | ||
{ x: sourceAnchors.get(Side.LEFT).x - standardDist, y: sourceAnchors.get(Side.LEFT).y + delta }, | ||
]; | ||
@@ -359,0 +413,0 @@ case 2: |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelRootImpl } from '../../base/model/smodel'; | ||
@@ -21,0 +22,0 @@ import { SShapeElementImpl } from '../bounds/model'; |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { Hoverable, Selectable } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -23,4 +24,4 @@ import { SChildElementImpl, SModelElementImpl } from '../../base/model/smodel'; | ||
import { deletableFeature } from '../edit/delete'; | ||
import { Selectable, selectFeature } from '../select/model'; | ||
import { Hoverable, hoverFeedbackFeature } from '../hover/model'; | ||
import { selectFeature } from '../select/model'; | ||
import { hoverFeedbackFeature } from '../hover/model'; | ||
import { moveFeature } from '../move/model'; | ||
@@ -27,0 +28,0 @@ |
@@ -75,2 +75,11 @@ /******************************************************************************** | ||
/** | ||
* Finds the orthogonal intersection point between an edge and a given point in 2D space. | ||
* | ||
* @param edge - The edge to find the intersection point on. | ||
* @param point - The point to find the intersection with. | ||
* @returns The intersection point and its derivative on the respective edge segment. | ||
*/ | ||
findOrthogonalIntersection(edge: SRoutableElementImpl, point: Point): {point: Point, derivative: Point} | undefined | ||
/** | ||
* Calculates a point on the edge | ||
@@ -77,0 +86,0 @@ * |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { IViewArgs, RenderingContext } from '../../base/views/view'; | ||
@@ -21,0 +22,0 @@ import { SShapeElementImpl } from '../bounds/model'; |
@@ -23,2 +23,3 @@ /******************************************************************************** | ||
* Feature extension interface for {@link selectFeature}. | ||
* @deprecated Use the definition from `sprotty-protocol` instead. | ||
*/ | ||
@@ -25,0 +26,0 @@ export interface Selectable { |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -22,0 +21,0 @@ import { TYPES } from '../../base/types'; |
@@ -19,3 +19,6 @@ /******************************************************************************** | ||
import { VNode } from 'snabbdom'; | ||
import { Action, BringToFrontAction, GetSelectionAction, ResponseAction, SelectAction, SelectAllAction, SelectionResult } from 'sprotty-protocol/lib/actions'; | ||
import { | ||
Action, BringToFrontAction, GetSelectionAction, ResponseAction, SelectAction, SelectAllAction, SelectionResult | ||
} from 'sprotty-protocol/lib/actions'; | ||
import { Selectable } from 'sprotty-protocol/lib/model'; | ||
import { Command, CommandExecutionContext } from '../../base/commands/command'; | ||
@@ -38,3 +41,3 @@ import { ModelRequestCommand } from '../../base/commands/request-command'; | ||
import { findViewportScrollbar } from '../viewport/scroll'; | ||
import { isSelectable, Selectable } from './model'; | ||
import { isSelectable } from './model'; | ||
@@ -137,2 +140,3 @@ @injectable() | ||
hasDragged = false; | ||
isMouseDown = false; | ||
@@ -143,2 +147,3 @@ override mouseDown(target: SModelElementImpl, event: MouseEvent): (Action | Promise<Action>)[] { | ||
} | ||
this.isMouseDown = true; | ||
const buttonHandled = this.handleButton(target, event); | ||
@@ -158,14 +163,10 @@ if (buttonHandled) { | ||
} | ||
if (selectableTarget !== undefined) { | ||
if (!selectableTarget.selected) { | ||
this.wasSelected = false; | ||
return this.handleSelectTarget(selectableTarget, deselectedElements, event); | ||
} else if (isCtrlOrCmd(event)) { | ||
this.wasSelected = false; | ||
return this.handleDeselectTarget(selectableTarget, event); | ||
} else { | ||
this.wasSelected = true; | ||
} | ||
if (!selectableTarget.selected) { | ||
this.wasSelected = false; | ||
return this.handleSelectTarget(selectableTarget, deselectedElements, event); | ||
} else if (isCtrlOrCmd(event)) { | ||
this.wasSelected = false; | ||
return this.handleDeselectTarget(selectableTarget, event); | ||
} else { | ||
return this.handleDeselectAll(deselectedElements, event); | ||
this.wasSelected = true; | ||
} | ||
@@ -225,3 +226,3 @@ } | ||
override mouseMove(target: SModelElementImpl, event: MouseEvent): Action[] { | ||
this.hasDragged = true; | ||
this.hasDragged = this.isMouseDown; | ||
return []; | ||
@@ -236,6 +237,6 @@ } | ||
if (this.wasSelected) { | ||
return [SelectAction.create({selectedElementsIDs:[selectableTarget.id],deselectedElementsIDs:[]})]; | ||
return [SelectAction.create({ selectedElementsIDs: [selectableTarget.id], deselectedElementsIDs: [] })]; | ||
} | ||
} else if (target instanceof SModelRootImpl && !findViewportScrollbar(event)) { | ||
// Mouse up on root but not over ViewPort's scroll bars > deselect all | ||
} else if ((target instanceof SModelRootImpl && !findViewportScrollbar(event)) || !(target instanceof SModelRootImpl)) { | ||
// Mouse up on everything that's not root or root but not over ViewPort's scroll bars > deselect all | ||
return this.handleDeselectAll(this.collectElementsToDeselect(target, undefined), event); | ||
@@ -245,2 +246,3 @@ } | ||
} | ||
this.isMouseDown = false; | ||
this.hasDragged = false; | ||
@@ -247,0 +249,0 @@ return []; |
@@ -18,5 +18,4 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { SModelRootSchema } from "../../base/model/smodel"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SModelElement } from 'sprotty-protocol'; | ||
import { ModelMatcher } from "./model-matching"; | ||
@@ -27,7 +26,7 @@ | ||
const modelMatcher = new ModelMatcher(); | ||
const left: SModelRootSchema = { | ||
const left: SModelElement = { | ||
type: 't', | ||
id: 'root' | ||
}; | ||
const right: SModelRootSchema = { | ||
const right: SModelElement = { | ||
type: 't', | ||
@@ -68,3 +67,3 @@ id: 'root', | ||
const modelMatcher = new ModelMatcher(); | ||
const left: SModelRootSchema = { | ||
const left: SModelElement = { | ||
type: 't', | ||
@@ -83,3 +82,3 @@ id: 'root', | ||
}; | ||
const right: SModelRootSchema = { | ||
const right: SModelElement = { | ||
type: 't', | ||
@@ -110,3 +109,3 @@ id: 'root' | ||
const modelMatcher = new ModelMatcher(); | ||
const left: SModelRootSchema = { | ||
const left: SModelElement = { | ||
type: 't', | ||
@@ -127,3 +126,3 @@ id: 'root', | ||
}; | ||
const right: SModelRootSchema = { | ||
const right: SModelElement = { | ||
type: 't', | ||
@@ -130,0 +129,0 @@ id: 'root', |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -44,3 +43,3 @@ import { TYPES } from '../../base/types'; | ||
for (const p in expected) { | ||
if (expected.hasOwnProperty(p)) { | ||
if (Object.prototype.hasOwnProperty.call(expected, p)) { | ||
const expectedProp = (expected as any)[p]; | ||
@@ -50,3 +49,3 @@ const actualProp = (actual as any)[p]; | ||
for (const i in expectedProp) { | ||
if (expectedProp.hasOwnProperty(i)) { | ||
if (Object.prototype.hasOwnProperty.call(expectedProp, i)) { | ||
compare(expectedProp[i], actualProp[i]); | ||
@@ -53,0 +52,0 @@ } |
@@ -19,2 +19,3 @@ /******************************************************************************** | ||
import { UpdateModelAction } from 'sprotty-protocol/lib/actions'; | ||
import { Fadeable } from 'sprotty-protocol/lib/model'; | ||
import { almostEquals, Dimension } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -26,3 +27,3 @@ import { Animation, CompoundAnimation } from '../../base/animations/animation'; | ||
import { MoveAnimation, ResolvedElementMove, MorphEdgesAnimation } from '../move/move'; | ||
import { Fadeable, isFadeable } from '../fade/model'; | ||
import { isFadeable } from '../fade/model'; | ||
import { isLocateable } from '../move/model'; | ||
@@ -29,0 +30,0 @@ import { isSizeable } from '../bounds/model'; |
@@ -22,3 +22,3 @@ /******************************************************************************** | ||
import { exportFeature } from "../export/model"; | ||
import { BoundsAware } from "../bounds/model"; | ||
import { InternalBoundsAware } from "../bounds/model"; | ||
@@ -29,3 +29,3 @@ /** | ||
*/ | ||
export class ViewportRootElementImpl extends SModelRootImpl implements Viewport, BoundsAware { | ||
export class ViewportRootElementImpl extends SModelRootImpl implements Viewport, InternalBoundsAware { | ||
static readonly DEFAULT_FEATURES = [viewportFeature, exportFeature]; | ||
@@ -32,0 +32,0 @@ |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -22,0 +21,0 @@ import { TYPES } from '../../base/types'; |
@@ -18,4 +18,3 @@ /******************************************************************************** | ||
import 'reflect-metadata'; | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container } from 'inversify'; | ||
@@ -22,0 +21,0 @@ import { TYPES } from '../../base/types'; |
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { SRoutingHandleImpl } from '../features/routing/model'; | ||
@@ -21,0 +22,0 @@ import { RectangularNode, RectangularPort } from '../lib/model'; |
@@ -18,15 +18,16 @@ /******************************************************************************** | ||
import { Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { Alignable, EdgePlacement, Fadeable, Hoverable, Selectable } from 'sprotty-protocol/lib/model'; | ||
import { ModelIndexImpl, SChildElementImpl, SModelElementImpl } from '../base/model/smodel'; | ||
import { | ||
Alignable, alignFeature, BoundsAware, boundsFeature, layoutableChildFeature, layoutContainerFeature, | ||
alignFeature, InternalBoundsAware, boundsFeature, layoutableChildFeature, layoutContainerFeature, | ||
ModelLayoutOptions, SShapeElementImpl | ||
} from '../features/bounds/model'; | ||
import { edgeLayoutFeature, EdgePlacement } from '../features/edge-layout/model'; | ||
import { edgeLayoutFeature } from '../features/edge-layout/model'; | ||
import { deletableFeature } from '../features/edit/delete'; | ||
import { editFeature } from '../features/edit/model'; | ||
import { Fadeable, fadeFeature } from '../features/fade/model'; | ||
import { Hoverable, hoverFeedbackFeature, popupFeature } from '../features/hover/model'; | ||
import { fadeFeature } from '../features/fade/model'; | ||
import { hoverFeedbackFeature, popupFeature } from '../features/hover/model'; | ||
import { moveFeature } from '../features/move/model'; | ||
import { connectableFeature, SConnectableElementImpl, SRoutableElementImpl } from '../features/routing/model'; | ||
import { Selectable, selectFeature } from '../features/select/model'; | ||
import { selectFeature } from '../features/select/model'; | ||
import { ViewportRootElementImpl } from '../features/viewport/viewport-root'; | ||
@@ -121,3 +122,3 @@ import { FluentIterable, FluentIterableImpl } from '../utils/iterable'; | ||
*/ | ||
export class SEdgeImpl extends SRoutableElementImpl implements Fadeable, Selectable, Hoverable, BoundsAware { | ||
export class SEdgeImpl extends SRoutableElementImpl implements Fadeable, Selectable, Hoverable, InternalBoundsAware { | ||
static readonly DEFAULT_FEATURES = [editFeature, deletableFeature, selectFeature, fadeFeature, | ||
@@ -124,0 +125,0 @@ hoverFeedbackFeature]; |
@@ -17,10 +17,10 @@ /******************************************************************************** | ||
import { SModelElement as SModelElementSchema, SModelRoot as SModelRootSchema } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from "sprotty-protocol/lib/utils/geometry"; | ||
import { SModelRootImpl, SChildElementImpl } from "../base/model/smodel"; | ||
import { BoundsAware, boundsFeature, Alignable, alignFeature, isBoundsAware } from "../features/bounds/model"; | ||
import { Locateable, moveFeature } from "../features/move/model"; | ||
import { Selectable, selectFeature } from "../features/select/model"; | ||
import { Alignable, Locateable, Selectable, SModelElement, SModelRoot } from 'sprotty-protocol/lib/model'; | ||
import { Bounds, Dimension, Point } from 'sprotty-protocol/lib/utils/geometry'; | ||
import { SModelRootImpl, SChildElementImpl } from '../base/model/smodel'; | ||
import { InternalBoundsAware, boundsFeature, alignFeature, isBoundsAware } from '../features/bounds/model'; | ||
import { moveFeature } from '../features/move/model'; | ||
import { selectFeature } from '../features/select/model'; | ||
import { SNodeImpl, SPortImpl } from '../graph/sgraph'; | ||
import { RECTANGULAR_ANCHOR_KIND, DIAMOND_ANCHOR_KIND, ELLIPTIC_ANCHOR_KIND } from "../features/routing/anchor"; | ||
import { RECTANGULAR_ANCHOR_KIND, DIAMOND_ANCHOR_KIND, ELLIPTIC_ANCHOR_KIND } from '../features/routing/anchor'; | ||
@@ -77,3 +77,3 @@ /** | ||
*/ | ||
export interface HtmlRootSchema extends SModelRootSchema { | ||
export interface HtmlRootSchema extends SModelRoot { | ||
classes?: string[] | ||
@@ -97,3 +97,3 @@ } | ||
*/ | ||
export interface PreRenderedElementSchema extends SModelElementSchema { | ||
export interface PreRenderedElementSchema extends SModelElement { | ||
code: string | ||
@@ -126,3 +126,3 @@ } | ||
*/ | ||
export class ShapedPreRenderedElementImpl extends PreRenderedElementImpl implements BoundsAware, Locateable, Selectable, Alignable { | ||
export class ShapedPreRenderedElementImpl extends PreRenderedElementImpl implements InternalBoundsAware, Locateable, Selectable, Alignable { | ||
static readonly DEFAULT_FEATURES = [moveFeature, boundsFeature, selectFeature, alignFeature]; | ||
@@ -129,0 +129,0 @@ |
@@ -19,20 +19,17 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from 'chai'; | ||
import { h } from 'snabbdom'; | ||
import { describe, expect, it } from 'vitest'; | ||
import { VNode, h } from 'snabbdom'; | ||
import virtualize from './virtualize'; | ||
import setup from '../utils/test-helper'; | ||
/** | ||
* @vitest-environment happy-dom | ||
*/ | ||
describe("virtualize (happy path)", () => { | ||
before(() => { | ||
setup(); | ||
}); | ||
it("should convert a single node with no children", () => { | ||
expect(virtualize("<div />")).to.deep.equal(h("div")); | ||
expect(virtualizeHelper("<div />")).to.deep.equal(h("DIV")); | ||
}); | ||
it("should convert a node with text node", () => { | ||
expect(virtualize("<div> Test. </div>")).to.deep.equal( | ||
h("div", [" Test. "]) | ||
expect(virtualizeHelper("<div> Test. </div>")).to.deep.equal( | ||
h("DIV", [" Test. "]) | ||
); | ||
@@ -42,6 +39,6 @@ }); | ||
it("should convert nodes with children", () => { | ||
expect(virtualize("<div><span>a</span><span>b</span></div>")).to.deep.equal( | ||
h("div", [ | ||
h("span", ["a"]), | ||
h("span", ["b"]) | ||
expect(virtualizeHelper("<div><span>a</span><span>b</span></div>")).to.deep.equal( | ||
h("DIV", [ | ||
h("SPAN", ["a"]), | ||
h("SPAN", ["b"]) | ||
]) | ||
@@ -53,9 +50,9 @@ ); | ||
expect( | ||
virtualize( | ||
virtualizeHelper( | ||
"<book><title>The Three-Body Problem</title><author>Liu Cixin</author></book>" | ||
) | ||
).to.deep.equal( | ||
h("book", [ | ||
h("title", ["The Three-Body Problem"]), | ||
h("author", ["Liu Cixin"]), | ||
h("BOOK", [ | ||
h("TITLE", ["The Three-Body Problem"]), | ||
h("AUTHOR", ["Liu Cixin"]), | ||
]) | ||
@@ -68,4 +65,4 @@ ); | ||
'<div class="sprotty1 sprotty2" style="display: none !important; background-color: blue; font-weight: bold" data-test="test" />'; | ||
expect(virtualize(element)).to.deep.equal( | ||
h("div", { | ||
expect(virtualizeHelper(element)).to.deep.equal( | ||
h("DIV", { | ||
class: { | ||
@@ -88,4 +85,4 @@ sprotty1: true, | ||
it("should ignore empty attributes", () => { | ||
expect(virtualize("<span style='' />")).to.deep.equal(h("span")); | ||
expect(virtualize("<span class='' />")).to.deep.equal(h("span")); | ||
expect(virtualizeHelper("<span style='' />")).to.deep.equal(h("SPAN")); | ||
expect(virtualizeHelper("<span class='' />")).to.deep.equal(h("SPAN")); | ||
}); | ||
@@ -95,6 +92,6 @@ | ||
const input = "<textarea placeholder=' Test1, \n\n Test2 '></textarea>"; | ||
expect(virtualize(input)).to.deep.equal( | ||
h("textarea", { | ||
expect(virtualizeHelper(input)).to.deep.equal( | ||
h("TEXTAREA", { | ||
attrs: { | ||
placeholder: " Test1, Test2 ", | ||
placeholder: " Test1, \n\n Test2 ", | ||
}, | ||
@@ -108,4 +105,4 @@ }) | ||
"<textarea placeholder='& Test1, > Test2 '></textarea>"; | ||
expect(virtualize(input)).to.deep.equal( | ||
h("textarea", { | ||
expect(virtualizeHelper(input)).to.deep.equal( | ||
h("TEXTAREA", { | ||
attrs: { | ||
@@ -120,14 +117,13 @@ placeholder: "& Test1, > Test2 ", | ||
expect( | ||
virtualize( | ||
virtualizeHelper( | ||
"<div> <!-- comment A --> <span>Test1</span> <!-- Comment B --> Test2</div>" | ||
) | ||
).to.deep.equal(h("div", [" ", " ", h("span", ["Test1"]), " ", " Test2"])); | ||
).to.deep.equal(h("DIV", [" ", " ", h("SPAN", ["Test1"]), " ", " Test2"])); | ||
}); | ||
}); | ||
/** | ||
* @vitest-environment happy-dom | ||
*/ | ||
describe("virtualize (bad path)", () => { | ||
before(() => { | ||
setup(); | ||
}); | ||
it("should return null when given null or empty string", () => { | ||
@@ -139,12 +135,17 @@ expect(virtualize()).to.be.null; | ||
it("should return parser error when given a single text node", () => { | ||
const actual = virtualize("Text content!"); | ||
expect(actual?.sel).to.equal("parsererror"); | ||
const actual = virtualizeHelper("Text content!") as VNode; | ||
expect(actual?.sel).to.equal(undefined); | ||
}); | ||
}); | ||
it("should return parser error when gives multiple top-level nodes", () => { | ||
const actual = virtualize( | ||
"<div><h1>Something</h1></div><span>Something more</span>" | ||
); | ||
expect(actual?.sel).to.equal("parsererror"); | ||
}); | ||
}); | ||
function virtualizeHelper(html?: string) { | ||
const dom = virtualize(html); | ||
if (!dom) { | ||
return null; | ||
} | ||
const element = (dom.children![1] as VNode).children![0]; | ||
return element; | ||
} |
@@ -18,9 +18,8 @@ /******************************************************************************** | ||
import "reflect-metadata"; | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { Container, injectable } from "inversify"; | ||
// eslint-disable-next-line max-len | ||
import { Action, ComputedBoundsAction, isResponseAction, RequestAction, RequestBoundsAction, ResponseAction, SetModelAction, UpdateModelAction } from 'sprotty-protocol/lib/actions'; | ||
import { Deferred } from 'sprotty-protocol/lib/utils/async'; | ||
import { TYPES } from "../base/types"; | ||
import { SModelRootSchema } from "../base/model/smodel"; | ||
import { ViewerOptions, overrideViewerOptions } from "../base/views/viewer-options"; | ||
@@ -31,2 +30,3 @@ import { IActionDispatcher } from "../base/actions/action-dispatcher"; | ||
import defaultContainerModule from "../base/di.config"; | ||
import { SModelElement } from "sprotty-protocol"; | ||
@@ -86,3 +86,3 @@ describe('LocalModelSource', () => { | ||
const root1: SModelRootSchema = { | ||
const root1: SModelElement = { | ||
type: 'root', | ||
@@ -92,3 +92,3 @@ id: 'root' | ||
modelSource.setModel(root1); | ||
const root2: SModelRootSchema = { | ||
const root2: SModelElement = { | ||
type: 'root', | ||
@@ -119,3 +119,3 @@ id: 'root', | ||
const root1: SModelRootSchema = { | ||
const root1: SModelElement = { | ||
type: 'root', | ||
@@ -139,3 +139,3 @@ id: 'root', | ||
], { requestId: dispatcher.requests[0].requestId })); | ||
const root2: SModelRootSchema = { | ||
const root2: SModelElement = { | ||
type: 'root', | ||
@@ -265,3 +265,3 @@ id: 'root', | ||
const root1: SModelRootSchema = { | ||
const root1: SModelElement = { | ||
type: 'root', | ||
@@ -272,3 +272,3 @@ id: 'root' | ||
const root2: SModelRootSchema = { | ||
const root2: SModelElement = { | ||
type: 'root', | ||
@@ -288,3 +288,3 @@ id: 'root', | ||
const root1: SModelRootSchema = { | ||
const root1: SModelElement = { | ||
type: 'root', | ||
@@ -305,3 +305,3 @@ id: 'root', | ||
const root2: SModelRootSchema = { | ||
const root2: SModelElement = { | ||
type: 'root', | ||
@@ -308,0 +308,0 @@ id: 'root', |
@@ -17,4 +17,3 @@ /******************************************************************************** | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { almostEquals } from 'sprotty-protocol/lib/utils/geometry'; | ||
@@ -21,0 +20,0 @@ import { PointToPointLine } from "./geometry"; |
@@ -17,4 +17,3 @@ /******************************************************************************** | ||
import "mocha"; | ||
import { expect } from "chai"; | ||
import { expect, describe, it } from 'vitest'; | ||
import { FluentIterable, FluentIterableImpl, DONE_RESULT } from './iterable'; | ||
@@ -21,0 +20,0 @@ |
@@ -17,4 +17,4 @@ /******************************************************************************** | ||
import 'mocha'; | ||
import { expect } from "chai"; | ||
import 'reflect-metadata'; | ||
import { expect, describe, it } from 'vitest'; | ||
import { InstanceRegistry, ProviderRegistry } from "./registry"; | ||
@@ -21,0 +21,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
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
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
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 9 instances 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
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 9 instances in 1 package
2730043
3
44817
7
813
+ Addedinversify@~6.0.2
Updatedsprotty-protocol@^1.1.0