UNPKG

@kieler/klighd-core

Version:

Core KLighD diagram visualization with Sprotty

495 lines 19.5 kB
"use strict"; /* * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient * * http://rtsys.informatik.uni-kiel.de/kieler * * Copyright 2021-2024 by * + Kiel University * + Department of Computer Science * + Real-Time and Embedded Systems Group * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.RenderOptionsRegistry = exports.DebugOptions = exports.AnimateGoToBookmark = exports.Shadows = exports.ShadowOption = exports.MinimumLineWidth = exports.UseMinimumLineWidth = exports.TitleScalingFactor = exports.TextSimplificationThreshold = exports.SimplifySmallText = exports.FullDetailScaleThreshold = exports.FullDetailRelativeThreshold = exports.UseSmartZoom = exports.SmartZoom = exports.Appearance = exports.ShowConstraintOption = exports.ForceLightBackground = exports.ResizeToFit = exports.PinSidebarOption = void 0; const inversify_1 = require("inversify"); const sprotty_protocol_1 = require("sprotty-protocol"); const registry_1 = require("../base/registry"); const services_1 = require("../services"); const actions_1 = require("./actions"); const option_models_1 = require("./option-models"); /** * Whether the sidebar panel is pinned or not. */ class PinSidebarOption { constructor() { this.id = PinSidebarOption.ID; this.name = PinSidebarOption.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = PinSidebarOption.DEFAULT; this.currentValue = PinSidebarOption.DEFAULT; this.debug = true; } } exports.PinSidebarOption = PinSidebarOption; PinSidebarOption.ID = 'pin-sidebar'; PinSidebarOption.NAME = 'Pin Sidebar'; PinSidebarOption.DEFAULT = true; /** * Resize the diagram to fit the viewport if it is redrawn after a model update * or a viewport resize. * This has to have the same id as the corresponding FitToScreenAction. */ class ResizeToFit { constructor() { this.id = ResizeToFit.ID; this.name = ResizeToFit.NAME; // readonly tooltip: string = ResizeToFit.TOOLTIP; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = ResizeToFit.DEFAULT; this.description = 'Always resize to fit after diagram refresh.'; this.currentValue = ResizeToFit.DEFAULT; this.debug = true; } } exports.ResizeToFit = ResizeToFit; ResizeToFit.ID = 'fit'; ResizeToFit.NAME = 'Resize To Fit on Refresh'; ResizeToFit.DEFAULT = true; /** * Uses a light background instead of an applied theme. */ class ForceLightBackground { constructor() { this.id = ForceLightBackground.ID; this.name = ForceLightBackground.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = ForceLightBackground.DEFAULT; this.renderCategory = Appearance.ID; this.description = 'Use light background regardless of the color scheme.'; this.currentValue = ForceLightBackground.DEFAULT; } } exports.ForceLightBackground = ForceLightBackground; ForceLightBackground.ID = 'force-light-background'; ForceLightBackground.NAME = 'Use Light Background'; ForceLightBackground.DEFAULT = false; class ShowConstraintOption { constructor() { this.id = ShowConstraintOption.ID; this.name = ShowConstraintOption.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = false; this.renderCategory = Appearance.ID; this.description = 'Show marker for nodes that have interactive layout constraints set.'; this.currentValue = false; } } exports.ShowConstraintOption = ShowConstraintOption; ShowConstraintOption.ID = 'show-constraints'; ShowConstraintOption.NAME = 'Show Constraint'; class Appearance { constructor() { this.id = Appearance.ID; this.name = Appearance.NAME; this.type = option_models_1.TransformationOptionType.CATEGORY; this.initialValue = true; this.description = 'Appearance Category'; this.currentValue = true; } } exports.Appearance = Appearance; Appearance.ID = 'appearance'; Appearance.NAME = 'Appearance'; /** * Smart Zoom category. */ class SmartZoom { constructor() { this.id = SmartZoom.ID; this.name = SmartZoom.NAME; this.type = option_models_1.TransformationOptionType.CATEGORY; this.initialValue = true; this.renderCategory = Appearance.ID; this.description = 'Smart Zoom Category'; this.currentValue = true; this.debug = true; } } exports.SmartZoom = SmartZoom; SmartZoom.ID = 'smart-zoom'; SmartZoom.NAME = 'Smart Zoom'; /** * Boolean option to enable and disable the smart zoom feature. * This corresponds to the automatic detail level of regions and states * as well as limiting visible elements. */ class UseSmartZoom { constructor() { this.id = UseSmartZoom.ID; this.name = UseSmartZoom.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = true; this.renderCategory = Appearance.ID; this.description = 'Enables Smart Zoom'; this.currentValue = true; } } exports.UseSmartZoom = UseSmartZoom; UseSmartZoom.ID = 'use-smart-zoom'; UseSmartZoom.NAME = 'Smart Zoom'; /** * Threshold for full detail level. * Corresponds to the regions size compared to the current viewport. */ class FullDetailRelativeThreshold { constructor() { this.id = FullDetailRelativeThreshold.ID; this.name = FullDetailRelativeThreshold.NAME; this.type = option_models_1.TransformationOptionType.RANGE; this.values = []; this.range = { first: 0.01, second: 1, }; this.stepSize = 0.01; this.initialValue = FullDetailRelativeThreshold.DEFAULT; this.renderCategory = SmartZoom.ID; this.description = 'Shows all children of an element that uses at least the amount of the canvas.' + 'A value of 0.2 means an element is shown if its parent has at least 0.2 the size (minimum of width and height) of the canvas.'; this.currentValue = 0.2; this.debug = true; } } exports.FullDetailRelativeThreshold = FullDetailRelativeThreshold; FullDetailRelativeThreshold.ID = 'full-detail-relative-threshold'; FullDetailRelativeThreshold.NAME = 'Full Detail Relative Threshold'; FullDetailRelativeThreshold.DEFAULT = 0.15; /** * Threshold for full detail level. * Corresponds to the regions scale using the current viewport. */ class FullDetailScaleThreshold { constructor() { this.id = FullDetailScaleThreshold.ID; this.name = FullDetailScaleThreshold.NAME; this.type = option_models_1.TransformationOptionType.RANGE; this.values = []; this.range = { first: 0.01, second: 1, }; this.stepSize = 0.01; this.initialValue = FullDetailScaleThreshold.DEFAULT; this.renderCategory = SmartZoom.ID; this.description = 'Show an element if it can be rendered in at least the given amount of it original size.' + 'A value of 0.25 means an element is shown if it can be drawn in a fourth of its original height or width.'; this.currentValue = 0.25; this.debug = true; } } exports.FullDetailScaleThreshold = FullDetailScaleThreshold; FullDetailScaleThreshold.ID = 'full-detail-scale-threshold'; FullDetailScaleThreshold.NAME = 'Full Detail Scale Threshold'; FullDetailScaleThreshold.DEFAULT = 0.25; /** * Boolean option toggling the use of text element replacement with rectangles. */ class SimplifySmallText { constructor() { this.id = SimplifySmallText.ID; this.name = SimplifySmallText.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = true; this.renderCategory = SmartZoom.ID; this.description = 'Whether illegible text is simplified to colored rectangles.'; this.currentValue = true; this.debug = true; } } exports.SimplifySmallText = SimplifySmallText; SimplifySmallText.ID = 'simplify-small-text'; SimplifySmallText.NAME = 'Simplify Small Text'; /** * Threshold under which text element simplification occurs in pixels. */ class TextSimplificationThreshold { constructor() { this.id = TextSimplificationThreshold.ID; this.name = TextSimplificationThreshold.NAME; this.type = option_models_1.TransformationOptionType.RANGE; this.values = []; this.range = { first: 1, second: 10, }; this.stepSize = 0.1; this.initialValue = TextSimplificationThreshold.DEFAULT; this.renderCategory = SmartZoom.ID; this.description = 'The threshold font size to simplify text.\nIf set to 3 a text which is 3 or less pixel high is simplified.'; this.currentValue = 3; this.debug = true; } } exports.TextSimplificationThreshold = TextSimplificationThreshold; TextSimplificationThreshold.ID = 'text-simplification-threshold'; TextSimplificationThreshold.NAME = 'Text Simplification Threshold'; TextSimplificationThreshold.DEFAULT = 3; /** * The factor by which titles of collapsed regions get scaled by * in relation to their size at native resolution. */ class TitleScalingFactor { constructor() { this.id = TitleScalingFactor.ID; this.name = TitleScalingFactor.NAME; this.type = option_models_1.TransformationOptionType.RANGE; this.values = []; this.range = { first: 0.5, second: 3, }; this.stepSize = 0.01; this.initialValue = TitleScalingFactor.DEFAULT; this.renderCategory = SmartZoom.ID; this.description = 'Factor to scale region titles compared to their original size.' + 'If set to 1 a region title be its original size (if the space permits) regardless of the zoom level.' + 'If it was 10 pixel high before it will always be 10 pixel high if the label can fit the region.'; this.currentValue = 1; this.debug = true; } } exports.TitleScalingFactor = TitleScalingFactor; TitleScalingFactor.ID = 'title-scaling-factor'; TitleScalingFactor.NAME = 'Title Scaling Factor'; TitleScalingFactor.DEFAULT = 1; /** * Boolean option to toggle the scaling of lines based on zoom level. */ class UseMinimumLineWidth { constructor() { this.id = UseMinimumLineWidth.ID; this.name = UseMinimumLineWidth.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = true; this.renderCategory = SmartZoom.ID; this.description = "Whether all borders and lines are at least as wide as set by the corresponding 'Minimum Line Width' option."; this.currentValue = true; this.debug = true; } } exports.UseMinimumLineWidth = UseMinimumLineWidth; UseMinimumLineWidth.ID = 'use-minimum-line-width'; UseMinimumLineWidth.NAME = 'Minimum Line Width'; /** * The size scaled lines should have as a minimum at any zoom level in pixels. */ class MinimumLineWidth { constructor() { this.id = MinimumLineWidth.ID; this.name = MinimumLineWidth.NAME; this.type = option_models_1.TransformationOptionType.RANGE; this.values = []; this.range = { first: 0.1, second: 3, }; this.stepSize = 0.01; this.initialValue = 0.5; this.renderCategory = SmartZoom.ID; this.description = 'The minium border or line width.\nIf set to 0.5 each edge or border is at least 0.5 pixel wide.'; this.currentValue = 0.5; this.debug = true; } } exports.MinimumLineWidth = MinimumLineWidth; MinimumLineWidth.ID = 'minimum-line-width'; MinimumLineWidth.NAME = 'Minimum Line Width'; MinimumLineWidth.DEFAULT = 1; var ShadowOption; (function (ShadowOption) { /** A real svg shadow. */ ShadowOption["PAPER_MODE"] = "Paper Mode"; /** The shape of the node drawn with different opacity multiple times behind the node. */ ShadowOption["KIELER_STYLE"] = "KIELER Style"; })(ShadowOption || (exports.ShadowOption = ShadowOption = {})); /** * The style shadows should be drawn in, either the paper mode shadows (nice, but slow in * performance) or in default KIELER-style (fast, not as nice looking). */ class Shadows { constructor() { this.id = Shadows.ID; this.name = Shadows.NAME; this.type = option_models_1.TransformationOptionType.CHOICE; this.initialValue = Shadows.DEFAULT; this.renderCategory = Appearance.ID; this.values = [ShadowOption.PAPER_MODE, ShadowOption.KIELER_STYLE]; this.description = 'The style shadows should be drawn in, either the paper mode shadows (nice, but slow in performance)' + 'or in default KIELER Style (fast, not as nice looking).' + 'KIELER Style draws multiple shapes in form of the node behind the node.' + 'Paper Mode uses SVG shadows.'; this.currentValue = Shadows.DEFAULT; } } exports.Shadows = Shadows; Shadows.ID = 'paper-shadows'; Shadows.NAME = 'Shadow Mode'; Shadows.DEFAULT = ShadowOption.KIELER_STYLE; /** * Whether going to a Bookmark should be animated */ class AnimateGoToBookmark { constructor() { this.id = AnimateGoToBookmark.ID; this.name = AnimateGoToBookmark.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = AnimateGoToBookmark.DEFAULT; this.currentValue = true; } } exports.AnimateGoToBookmark = AnimateGoToBookmark; AnimateGoToBookmark.ID = 'animate-go-to-bookmark'; AnimateGoToBookmark.NAME = 'Animate Go To Bookmark'; AnimateGoToBookmark.DEFAULT = true; /** * Boolean option to toggle debug options. */ class DebugOptions { constructor() { this.id = DebugOptions.ID; this.name = DebugOptions.NAME; this.type = option_models_1.TransformationOptionType.CHECK; this.initialValue = false; this.description = 'Whether debug options should be shown.'; this.currentValue = false; } } exports.DebugOptions = DebugOptions; DebugOptions.ID = 'debug-options'; DebugOptions.NAME = 'Debug Options'; /** {@link Registry} that stores and updates different render options. */ let RenderOptionsRegistry = class RenderOptionsRegistry extends registry_1.Registry { constructor() { super(); this._renderOptions = new Map(); // Add available render options to this registry // Debug this.register(DebugOptions); this.register(ResizeToFit); this.register(PinSidebarOption); this.register(AnimateGoToBookmark); // Appearance this.register(Appearance); this.register(ForceLightBackground); this.register(ShowConstraintOption); this.register(Shadows); // Smart Zoom this.register(SmartZoom); this.register(UseSmartZoom); this.register(FullDetailRelativeThreshold); this.register(FullDetailScaleThreshold); this.register(SimplifySmallText); this.register(TextSimplificationThreshold); this.register(TitleScalingFactor); this.register(UseMinimumLineWidth); this.register(MinimumLineWidth); } init() { this.storage.getItem('render').then((data) => { if (data) this.loadPersistedData(data); }); } /** * Restores options that where previously persisted in storage. Since render * options are not provided by the server, they have to be retrieved from storage. */ loadPersistedData(data) { for (const entry of Object.entries(data)) { const option = this._renderOptions.get(entry[0]); if (option) { // eslint-disable-next-line prefer-destructuring option.currentValue = entry[1]; } } this.notifyListeners(); } /** Registers a single render option. */ register(Option) { this._renderOptions.set(Option.ID, new Option()); } /** Convenience method to register all given options in order. */ registerAll(...Options) { Options.forEach((Option) => this.register(Option)); } /** Unregisters a single render option. */ unregister(Option) { return this._renderOptions.delete(Option.ID); } /** Convenience method to unregister all given options in order. */ unregisterAll(...Options) { return Options.every((Option) => this.unregister(Option)); } /** Handles the render options actions. */ // eslint-disable-next-line consistent-return handle(action) { if (actions_1.SetRenderOptionAction.isThisAction(action)) { const option = this._renderOptions.get(action.id); if (option) { option.currentValue = action.value; this.notifyListeners(); } } else if (actions_1.ResetRenderOptionsAction.isThisAction(action)) { this._renderOptions.forEach((option) => { option.currentValue = option.initialValue; }); this.notifyListeners(); } else { return sprotty_protocol_1.UpdateModelAction.create([], { animate: false, cause: action }); } } get allRenderOptions() { return Array.from(this._renderOptions.values()); } getValue(Option) { var _a; return (_a = this._renderOptions.get(Option.ID)) === null || _a === void 0 ? void 0 : _a.currentValue; } getValueOrDefault(Option) { var _a; return (_a = this.getValue(Option)) !== null && _a !== void 0 ? _a : Option.DEFAULT; } }; exports.RenderOptionsRegistry = RenderOptionsRegistry; __decorate([ (0, inversify_1.inject)(services_1.ServiceTypes.PersistenceStorage), __metadata("design:type", Object) ], RenderOptionsRegistry.prototype, "storage", void 0); __decorate([ (0, inversify_1.postConstruct)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], RenderOptionsRegistry.prototype, "init", null); exports.RenderOptionsRegistry = RenderOptionsRegistry = __decorate([ (0, inversify_1.injectable)(), __metadata("design:paramtypes", []) ], RenderOptionsRegistry); //# sourceMappingURL=render-options-registry.js.map