Add center position action.

Improve screenmanager positioning
Change several clasess to typescript
This commit is contained in:
Paulo Gustavo Veiga 2022-01-09 10:43:04 -08:00
parent 1bebfa3dff
commit cdd044c41d
23 changed files with 233 additions and 209 deletions

View File

@ -32,6 +32,7 @@
},
"private": false,
"dependencies": {
"@types/jquery": "^3.5.11",
"@wisemapping/core-js": "^0.4.0",
"@wisemapping/web2d": "^0.4.0",
"jest": "^27.4.5",

View File

@ -1 +0,0 @@
MessageBundle_*

View File

@ -54,8 +54,9 @@ import { Mindmap } from '..';
import NodeModel from './model/NodeModel';
import Topic from './Topic';
import Point from '@wisemapping/web2d';
import { DesignerOptions } from './DesignerOptions';
import { DesignerOptions } from './DesignerOptionsBuilder';
import MainTopic from './MainTopic';
import DragTopic from './DragTopic';
class Designer extends Events {
private _mindmap: Mindmap;
@ -69,7 +70,7 @@ class Designer extends Events {
private _clipboard: any[];
private _cleanScreen: any;
constructor(options: DesignerOptions, divElement) {
constructor(options: DesignerOptions, divElement:JQuery) {
$assert(options, 'options must be defined');
$assert(options.zoom, 'zoom must be defined');
$assert(options.size, 'size must be defined');
@ -166,12 +167,12 @@ class Designer extends Events {
});
// Deselect on click ...
screenManager.addEvent('click', (event) => {
screenManager.addEvent('click', (event:UIEvent) => {
me.onObjectFocusEvent(null, event);
});
// Create nodes on double click...
screenManager.addEvent('dblclick', (event) => {
screenManager.addEvent('dblclick', (event:MouseEvent) => {
if (workspace.isWorkspaceEventsEnabled()) {
const mousePos = screenManager.getWorkspaceMousePosition(event);
const centralTopic = me.getModel().getCentralTopic();
@ -181,13 +182,7 @@ class Designer extends Events {
});
}
/**
* @private
* @param {mindplot.Workspace} workspace
* @return {mindplot.DragManager} the new dragManager for the workspace with events
* registered
*/
_buildDragManager(workspace: Workspace) {
private _buildDragManager(workspace: Workspace):DragManager {
const designerModel = this.getModel();
const dragConnector = new DragConnector(designerModel, this._workspace);
const dragManager = new DragManager(workspace, this._eventBussDispatcher);
@ -198,7 +193,7 @@ class Designer extends Events {
topics.forEach((topic) => topic.setMouseEventsEnabled(false));
});
dragManager.addEvent('dragging', (event, dragTopic) => {
dragManager.addEvent('dragging', (event:MouseEvent, dragTopic:DragTopic) => {
dragTopic.updateFreeLayout(event);
if (!dragTopic.isFreeLayoutOn(event)) {
// The node is being drag. Is the connection still valid ?
@ -210,7 +205,7 @@ class Designer extends Events {
}
});
dragManager.addEvent('enddragging', (event, dragTopic) => {
dragManager.addEvent('enddragging', (event:MouseEvent, dragTopic:DragTopic) => {
topics.forEach((topic) => topic.setMouseEventsEnabled(true));
dragTopic.applyChanges(workspace);
});
@ -218,11 +213,7 @@ class Designer extends Events {
return dragManager;
}
/**
* @param {{width:Number, height:Number}} size
* sets width and height of the workspace
*/
setViewPort(size: { height: number, width: number }) {
private setViewPort(size: { height: number, width: number }):void {
this._workspace.setViewPort(size);
const model = this.getModel();
this._workspace.setZoom(model.getZoom(), true);
@ -325,10 +316,6 @@ class Designer extends Events {
});
}
/**
* Set the zoom of the map
* @param {Number} zoom number between 0.3 and 1.9
*/
setZoom(zoom: number): void {
if (zoom > 1.9 || zoom < 0.3) {
$notify($msg('ZOOM_IN_ERROR'));
@ -338,6 +325,11 @@ class Designer extends Events {
this._workspace.setZoom(zoom);
}
setZoomToFit(): void {
this.getModel().setZoom(1);
this._workspace.setZoom(1,true);
}
zoomOut(factor: number = 1.2) {
const model = this.getModel();
const scale = model.getZoom() * factor;
@ -374,11 +366,7 @@ class Designer extends Events {
}
/**
* @param {Number=} factor
* zoom in by the given factor, or 1.2, if undefined
*/
zoomIn(factor: number = 1.2) {
zoomIn(factor: number = 1.2): void {
const model = this.getModel();
const scale = model.getZoom() / factor;
@ -390,7 +378,6 @@ class Designer extends Events {
}
}
/** copy selected topics to a private clipboard */
copyToClipboard(): void {
let topics = this.getModel().filterSelectedTopics();
if (topics.length <= 0) {
@ -415,7 +402,6 @@ class Designer extends Events {
$notify($msg('SELECTION_COPIED_TO_CLIPBOARD'));
}
/** paste clipboard contents to the mindmap */
pasteClipboard(): void {
if (this._clipboard.length === 0) {
$notify($msg('CLIPBOARD_IS_EMPTY'));
@ -429,8 +415,7 @@ class Designer extends Events {
return this._model;
}
/** collapse the subtree of the selected topic */
shrinkSelectedBranch() {
shrinkSelectedBranch(): void {
const nodes = this.getModel().filterSelectedTopics();
if (nodes.length <= 0 || nodes.length !== 1) {
// If there are more than one node selected,
@ -445,7 +430,7 @@ class Designer extends Events {
}
/** create a NodeModel for the selected node's child and add it via the ActionDispatcher */
createChildForSelectedNode() {
createChildForSelectedNode():void {
const nodes = this.getModel().filterSelectedTopics();
if (nodes.length <= 0) {
// If there are more than one node selected,
@ -467,10 +452,7 @@ class Designer extends Events {
this._actionDispatcher.addTopics([childModel], [parentTopicId]);
}
/**
* @private
*/
_copyNodeProps(sourceModel: NodeModel, targetModel: NodeModel) {
private _copyNodeProps(sourceModel: NodeModel, targetModel: NodeModel) {
// I don't copy the font size if the target is the source is the central topic.
if (sourceModel.getType() !== 'CentralTopic') {
const fontSize = sourceModel.getFontSize();
@ -515,13 +497,7 @@ class Designer extends Events {
}
}
/**
* @private
* @param {Topic} topic the parent topic of the child to create the NodeModel for
* @param {Point} mousePos the mouse position
* @return {NodeModel} the node model for the new child
*/
_createChildModel(topic: Topic, mousePos: Point = null): NodeModel {
private _createChildModel(topic: Topic, mousePos: Point = null): NodeModel {
// Create a new node ...
const parentModel = topic.getModel();
const mindmap = parentModel.getMindmap();
@ -554,11 +530,7 @@ class Designer extends Events {
topic.fireEvent('mousedown', event);
}
/**
* creates a sibling or child node of the selected node, if the selected node is the
* central topic
*/
createSiblingForSelectedNode() {
createSiblingForSelectedNode():void {
const nodes = this.getModel().filterSelectedTopics();
if (nodes.length <= 0) {
// If there are no nodes selected,
@ -591,12 +563,7 @@ class Designer extends Events {
}
}
/**
* @private
* @param {mindplot.Topic} topic the topic to create the sibling to
* @return {mindplot.NodeModel} the node model of the sibling
*/
_createSiblingModel(topic: Topic) {
private _createSiblingModel(topic: Topic):NodeModel {
let result = null;
let model = null;
const parentTopic = topic.getOutgoingConnectedTopic();
@ -617,10 +584,7 @@ class Designer extends Events {
return result;
}
/**
* @param {Event} event
*/
showRelPivot(event) {
showRelPivot(event):void {
const nodes = this.getModel().filterSelectedTopics();
if (nodes.length <= 0) {
// This could not happen ...
@ -761,7 +725,7 @@ class Designer extends Events {
* deletes the relationship from the linked topics, DesignerModel, Workspace and Mindmap
* @param {mindplot.Relationship} rel the relationship to delete
*/
deleteRelationship(rel) {
deleteRelationship(rel: Relationship) {
const sourceTopic = rel.getSourceTopic();
sourceTopic.deleteRelationship(rel);

View File

@ -22,29 +22,35 @@ import Designer from './Designer';
import Menu from './widget/Menu';
import { $notifyModal } from './widget/ModalDialogNotifier';
import { $msg } from './Messages';
import { DesignerOptions } from './DesignerOptionsBuilder';
let designer = null;
export function buildDesigner(options) {
export function buildDesigner(options: DesignerOptions): Designer {
const divContainer = $(`#${options.container}`);
$assert(divContainer, 'container could not be null');
// Register load events ...
designer = new Designer(options, divContainer);
designer.addEvent('loadSuccess', () => {
// @ts-ignore
window.mindmapLoadReady = true;
console.log('Map loadded successfully');
});
const onerrorFn = (message, url, lineNo) => {
const onerrorFn = (message:string, url, lineNo) => {
// Close loading dialog ...
// @ts-ignore
if (window.waitDialog) {
// @ts-ignore
window.waitDialog.close();
// @ts-ignore
window.waitDialog = null;
}
// Open error dialog only in case of mindmap loading errors. The rest of the error are reported but not display the dialog.
// Remove this in the near future.
// @ts-ignore
if (!window.mindmapLoadReady) {
$notifyModal($msg('UNEXPECTED_ERROR_LOADING'));
}
@ -58,7 +64,7 @@ export function buildDesigner(options) {
// Register toolbar event ...
if ($('#toolbar').length) {
const menu = new Menu(designer, 'toolbar', options.mapId, '');
const menu = new Menu(designer, 'toolbar', options.mapId);
// If a node has focus, focus can be move to another node using the keys.
designer._cleanScreen = function _cleanScreen() {
@ -69,39 +75,3 @@ export function buildDesigner(options) {
return designer;
}
export function buildOptions(options) {
$assert(options.persistenceManager, 'persistence must be defined');
// Set workspace screen size as default. In this way, resize issues are solved.
const containerSize = {
height: Number.parseInt(window.screen.height, 10),
width: Number.parseInt(window.screen.width, 10),
};
const viewPort = {
height: Number.parseInt(window.innerHeight, 10),
width: Number.parseInt(window.innerWidth, 10),
};
const defaultOptions = {
readOnly: false,
zoom: 0.85,
saveOnLoad: true,
size: containerSize,
viewPort,
container: 'mindplot',
locale: 'en',
};
return { ...defaultOptions, ...options };
}
export async function loadOptions(jsonConf, options) {
const result = await $.ajax({
url: jsonConf,
dataType: 'json',
method: 'get',
});
return { ...result, ...buildOptions(options) };
}

View File

@ -16,7 +16,8 @@
* limitations under the License.
*/
import { $assert, $defined } from '@wisemapping/core-js';
import { DesignerOptions } from './DesignerOptions';
import CentralTopic from './CentralTopic';
import { DesignerOptions } from './DesignerOptionsBuilder';
import Events from './Events';
import Relationship from './Relationship';
import Topic from './Topic';
@ -34,30 +35,25 @@ class DesignerModel extends Events {
this._relationships = [];
}
/** @return {Number} zoom between 0.3 (largest text) and 1.9 */
getZoom() {
getZoom():number {
return this._zoom;
}
/** @param {Number} zoom number between 0.3 and 1.9 to set the zoom to */
setZoom(zoom: number) {
setZoom(zoom: number):void {
this._zoom = zoom;
}
/** @return {@link mindplot.Topic[]} all topics */
getTopics(): Topic[] {
return this._topics;
}
/** @return {mindplot.Relationship[]} all relationships */
getRelationships(): Relationship[] {
return this._relationships;
}
/** @return {mindplot.CentralTopic} the central topic */
getCentralTopic(): Topic {
getCentralTopic(): CentralTopic {
const topics = this.getTopics();
return topics[0];
return topics[0] as CentralTopic;
}
/** @return {mindplot.Topic[]} selected topics */
@ -71,9 +67,6 @@ class DesignerModel extends Events {
return result;
}
/**
* @return {mindplot.Relationship[]} selected relationships
*/
filterSelectedRelationships(): Relationship[] {
const result = [];
for (let i = 0; i < this._relationships.length; i++) {
@ -84,50 +77,28 @@ class DesignerModel extends Events {
return result;
}
/**
* @return {Array.<mindplot.Relationship, mindplot.Topic>} all topics and relationships
*/
getEntities(): (Relationship | Topic)[] {
let result = [].concat(this._topics);
result = result.concat(this._relationships);
return result;
}
/**
* removes occurrences of the given topic from the topic array
* @param {mindplot.Topic} topic the topic to remove
*/
removeTopic(topic) {
removeTopic(topic:Topic):void {
$assert(topic, 'topic can not be null');
this._topics = this._topics.filter((t) => t !== topic);
}
/**
* removes occurrences of the given relationship from the relationship array
* @param {mindplot.Relationship} rel the relationship to remove
*/
removeRelationship(rel) {
removeRelationship(rel:Relationship):void {
$assert(rel, 'rel can not be null');
this._relationships = this._relationships.filter((r) => r !== rel);
}
/**
* adds the given topic to the topic array
* @param {mindplot.Topic} topic the topic to add
* @throws will throw an error if topic is null or undefined
* @throws will throw an error if the topic's id is not a number
*/
addTopic(topic: Topic): void {
$assert(topic, 'topic can not be null');
$assert(typeof topic.getId() === 'number', `id is not a number:${topic.getId()}`);
this._topics.push(topic);
}
/**
* adds the given relationship to the relationship array
* @param {mindplot.Relationship} rel the relationship to add
* @throws will throw an error if rel is null or undefined
*/
addRelationship(rel: Relationship): void {
$assert(rel, 'rel can not be null');
this._relationships.push(rel);
@ -159,10 +130,6 @@ class DesignerModel extends Events {
return (topics.length > 0) ? topics[0] : null;
}
/**
* @param {String} id the id of the topic to be retrieved
* @return {mindplot.Topic} the topic with the respective id
*/
findTopicById(id: Number): Topic {
let result = null;
for (let i = 0; i < this._topics.length; i++) {

View File

@ -1,8 +0,0 @@
export type DesignerOptions = {
locale: string,
zoom: number,
size: { height: number, witdh: number },
readOnly: boolean,
viewPort: { height: number, width: number },
};

View File

@ -0,0 +1,75 @@
/*
* Copyright [2021] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { $assert } from '@wisemapping/core-js';
import PersistenceManager from './PersistenceManager';
export type DesignerOptions = {
zoom: number,
viewPort?: { height: number, width: number },
size?: { height: number, width: number },
readOnly?: boolean,
mapId?: string,
container: string,
persistenceManager?: PersistenceManager,
saveOnLoad?: boolean,
locale?: string,
};
class OptionsBuilder {
static buildOptions(options: DesignerOptions): DesignerOptions {
$assert(options.persistenceManager, 'persistence must be defined');
let containerSize = options.size;
if (options.size == null) {
// If it has not been defined, use browser size ...
containerSize = {
width: window.screen.availWidth,
height: window.screen.availHeight,
}
}
// Is offset adjustment required
const viewPort = {
height: window.innerHeight,
width: window.innerWidth,
};
const defaultOptions: DesignerOptions = {
readOnly: false,
zoom: 0.85,
saveOnLoad: true,
size: containerSize,
viewPort: viewPort,
container: 'mindplot',
locale: 'en',
};
return { ...defaultOptions, ...options };
}
static async loadOptions(jsonConf: string, options: DesignerOptions): Promise<DesignerOptions> {
const result = await $.ajax({
url: jsonConf,
dataType: 'json',
method: 'get',
});
return { ...result, ...OptionsBuilder.buildOptions(options) };
}
}
export default OptionsBuilder;

View File

@ -210,7 +210,7 @@ class DragTopic {
return this.getConnectedToTopic() != null;
}
isFreeLayoutOn() {
isFreeLayoutOn(dragTopic) {
// return this._isFreeLayoutEnabled;
// Disable free layout ...
return false;

View File

@ -19,44 +19,50 @@ import { $assert } from '@wisemapping/core-js';
import { Point } from '@wisemapping/web2d';
class ScreenManager {
constructor(divElement) {
_divContainer: JQuery;
_padding: { x: number; y: number; };
_clickEvents: ((event: UIEvent)=>void)[];
_scale: number;
constructor(divElement: JQuery) {
$assert(divElement, 'can not be null');
this._divContainer = divElement;
this._padding = { x: 0, y: 0 };
// Ignore default click event propagation. Prevent 'click' event on drag.
this._clickEvents = [];
this._divContainer.bind('click', (event) => {
this._divContainer.bind('click', (event: { stopPropagation: () => void; }) => {
event.stopPropagation();
});
this._divContainer.bind('dblclick', (event) => {
this._divContainer.bind('dblclick', (event: { stopPropagation: () => void; preventDefault: () => void; }) => {
event.stopPropagation();
event.preventDefault();
});
}
setScale(scale) {
setScale(scale: number) {
$assert(scale, 'Screen scale can not be null');
this._scale = scale;
}
addEvent(event, listener) {
if (event === 'click') this._clickEvents.push(listener);
else this._divContainer.bind(event, listener);
addEvent(eventType: string, listener:any) {
if (eventType === 'click') this._clickEvents.push(listener);
else this._divContainer.bind(eventType, listener);
}
removeEvent(event, listener) {
removeEvent(event: string, listener: any) {
if (event === 'click') {
// @ts-ignore @Todo: needs review ...
this._clickEvents.remove(listener);
} else {
this._divContainer.unbind(event, listener);
}
}
fireEvent(type, event) {
fireEvent(type: string, event: UIEvent = null) {
if (type === 'click') {
this._clickEvents.forEach((listener) => {
this._clickEvents.forEach((listener: (arg0: any, arg1: any) => void) => {
listener(type, event);
});
} else {
@ -64,7 +70,7 @@ class ScreenManager {
}
}
_getElementPosition(elem) {
_getElementPosition(elem: { getPosition: () => any; }) {
// Retrieve current element position.
const elementPosition = elem.getPosition();
let { x } = elementPosition;
@ -82,7 +88,7 @@ class ScreenManager {
return { x, y };
}
getWorkspaceIconPosition(e) {
getWorkspaceIconPosition(e: { getImage: () => any; getSize: () => any; getGroup: () => any; }) {
// Retrieve current icon position.
const image = e.getImage();
const elementPosition = image.getPosition();
@ -117,15 +123,15 @@ class ScreenManager {
return { x: x + topicPosition.x, y: y + topicPosition.y };
}
getWorkspaceMousePosition(event) {
getWorkspaceMousePosition(event: MouseEvent) {
// Retrieve current mouse position.
let x = event.clientX;
let y = event.clientY;
// FIXME: paulo: why? Subtract div position.
/* var containerPosition = this.getContainer().position();
x = x - containerPosition.x;
y = y - containerPosition.y; */
// Adjust the deviation of the container positioning ...
const containerPosition = this.getContainer().position();
x = x - containerPosition.left;
y = y - containerPosition.top;
// Scale coordinate in order to be relative to the workspace. That's coordSize/size;
x *= this._scale;
@ -143,7 +149,7 @@ class ScreenManager {
return this._divContainer;
}
setOffset(x, y) {
setOffset(x: number, y: number) {
this._padding.x = x;
this._padding.y = y;
}

View File

@ -59,7 +59,7 @@ class Workspace {
return this._isReadOnly;
}
_createWorkspace() {
private _createWorkspace() {
// Initialize workspace ...
const coordOriginX = -(this._screenWidth / 2);
const coordOriginY = -(this._screenHeight / 2);
@ -109,10 +109,18 @@ class Workspace {
return this._workspace.getCoordSize();
}
setZoom(zoom: number, center: boolean = false) {
setZoom(zoom: number, center: boolean = false): void {
this._zoom = zoom;
const workspace = this._workspace;
// Calculate the original boxview size ...
let origWidth = 0;
let origHeight = 0
if (this._viewPort) {
origWidth = this._viewPort.width;
origHeight = this._viewPort.height;
}
// Update coord scale...
const coordWidth = zoom * this._screenWidth;
const coordHeight = zoom * this._screenHeight;
@ -125,8 +133,8 @@ class Workspace {
}
// Center topic....
let coordOriginX;
let coordOriginY;
let coordOriginX: number;
let coordOriginY: number;
if (center) {
if (this._viewPort) {
@ -137,11 +145,18 @@ class Workspace {
coordOriginY = -(coordHeight / 2);
}
} else {
const coordOrigin = workspace.getCoordOrigin();
coordOriginX = coordOrigin.x / 2;
coordOriginY = coordOrigin.y / 2;
}
// Zoom keeping the center in the same place ...
// const xPaddinng = (this._viewPort.width - origWidth) / 2;
// const yPaddinng = (this._viewPort.height - origHeight) / 2;
// const coordOrigin = workspace.getCoordOrigin();
// coordOriginX = coordOrigin.x - xPaddinng;
// coordOriginY = coordOrigin.y - yPaddinng;
const coordOrigin = workspace.getCoordOrigin();
coordOriginX = coordOrigin.x;
coordOriginY = coordOrigin.y;
}
workspace.setCoordOrigin(coordOriginX, coordOriginY);
// Update screen.

View File

@ -1,7 +0,0 @@
import $ from 'jquery';
try {
$(document).trigger('loadcomplete', 'mind');
} catch (e) {
console.error(e.stack);
}

View File

@ -31,7 +31,7 @@ import AccountSettingsPanel from './AccountSettingsPanel';
import Designer from '../Designer';
class Menu extends IMenu {
constructor(designer: Designer, containerId: string, mapId: string, readOnly: boolean = false, baseUrl = '') {
constructor(designer: Designer, containerId: string, mapId: string, readOnly: boolean = false, baseUrl:string = '') {
super(designer, containerId, mapId);
const saveElem = $('#save');
@ -259,6 +259,12 @@ class Menu extends IMenu {
});
Menu._registerTooltip('zoom-minus', $msg('ZOOM_OUT'));
this._addButton('position', false, false, () => {
designer.setZoomToFit();
});
Menu._registerTooltip('position', $msg('CENTER_POSITION'));
const undoButton = this._addButton('undoEdition', false, false, () => {
designer.undo();
});

View File

@ -25,13 +25,15 @@ import {
import LoadingModal from './components/widget/LoadingModal';
import {
buildDesigner,
buildOptions,
} from './components/DesignerBuilder';
import RESTPersistenceManager from './components/RestPersistenceManager';
import PersistenceManager from './components/PersistenceManager';
import LocalStorageManager from './components/LocalStorageManager';
import DesignerOptionsBuilder from './components/DesignerOptionsBuilder';
// This hack is required to initialize Bootstrap. In future, this should be removed.
//@ts-ignore
global.jQuery = jquery;
require('@libraries/bootstrap/js/bootstrap');
@ -39,7 +41,7 @@ const loadingModal = new LoadingModal();
loadingModal.show();
// Configure designer options ...
let persistence;
let persistence:PersistenceManager;
if (!global.memoryPersistence && !global.readOnly) {
persistence = new RESTPersistenceManager({
documentUrl: '/c/restful/maps/{id}/document',
@ -55,11 +57,13 @@ if (!global.memoryPersistence && !global.readOnly) {
// Obtain map zoom from query param if it was specified...
const params = new URLSearchParams(window.location.search.substring(1));
const zoomParam = Number.parseFloat(params.get('zoom'), 10);
const options = buildOptions({
const zoomParam = Number.parseFloat(params.get('zoom'));
const options = DesignerOptionsBuilder.buildOptions(
{
persistenceManager: persistence,
readOnly: global.readOnly || false,
readOnly: Boolean(global.readOnly || false),
mapId: global.mapId,
container: 'mindplot',
zoom: zoomParam || global.userOptions.zoom,
});
@ -76,5 +80,5 @@ const mindmap = instance.load(global.mapId);
designer.loadMap(mindmap);
if (global.mindmapLocked) {
$notify(global.mindmapLockedMsg, false);
$notify(global.mindmapLockedMsg);
}

View File

@ -19,7 +19,6 @@ body {
div#mindplot {
position: relative;
top: @header-toolbar-height;
top: 0;
left: 0;
width: 100%;
height: 100%;
@ -154,6 +153,22 @@ div#bottom-logo {
height: 40px;
}
div#position {
margin-top: 5px;
}
#position-button {
cursor: pointer;
border: solid black 1px;
width: 40px;
height: 40px;
background-position: center;
background-repeat: no-repeat;
background-size: 40px 40px;
background-color: #FFF;
border-radius: 8px;
}
#zoom-button {
width: 40px;
border: 0;
@ -161,6 +176,7 @@ div#bottom-logo {
#zoom-plus,
#zoom-minus {
border: solid black 1px;
height: 40px;
width: 40px;
background-repeat: no-repeat;

View File

@ -1,10 +1,8 @@
@header-height : 0px;
@header-toolbar-height : 50px;
@header-info-height : @header-height - @header-toolbar-height;
div#header {
width: 100%;
height: @header-height;
height: 0px;
background: #202020;
z-index: 1000;
position: absolute;

View File

@ -115,6 +115,11 @@
<img src="images/minus.svg" />
</button>
</div>
<div id="position">
<button id="position-button">
<img src="images/center_focus.svg" />
</button>
</div>
</div>
<div id="bottom-logo"></div>
<div id="headerNotifier"></div>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></svg>

After

Width:  |  Height:  |  Size: 440 B

View File

@ -1,7 +1,8 @@
import '../css/editor.less';
import { buildDesigner, buildOptions } from '../../../../src/components/DesignerBuilder';
import { buildDesigner } from '../../../../src/components/DesignerBuilder';
import { PersistenceManager, LocalStorageManager } from '../../../../src';
import LoadingModal from '../../../../src/components/widget/LoadingModal';
import DesignerOptionsBuilder from '../../../../src/components/DesignerOptionsBuilder';
// Account details ...
global.accountName = 'Test User';
@ -11,11 +12,14 @@ const loadingModal = new LoadingModal();
loadingModal.show();
const p = new LocalStorageManager('samples/{id}.wxml');
const options = buildOptions({ persistenceManager: p });
const options = DesignerOptionsBuilder.buildOptions({
persistenceManager: p
});
const designer = buildDesigner(options);
designer.addEvent('loadSuccess', () => {
loadingModal.hide();
// Hack for automation testing ...
document.getElementById('mindplot').classList.add('ready');
});

View File

@ -1,10 +1,11 @@
import '../css/embedded.less';
import { buildDesigner, buildOptions } from '../../../../src/components/DesignerBuilder';
import { buildDesigner } from '../../../../src/components/DesignerBuilder';
import { PersistenceManager, LocalStorageManager } from '../../../../src';
import DesignerOptionsBuilder from '../../../../src/components/DesignerOptionsBuilder';
// Options has been defined in by a external ile ?
const p = new LocalStorageManager('samples/{id}.wxml');
const options = buildOptions({ persistenceManager: p });
const options = DesignerOptionsBuilder.buildOptions({ persistenceManager: p });
const designer = buildDesigner(options);
designer.addEvent('loadSuccess', () => {

View File

@ -1,9 +1,11 @@
import '../css/viewmode.less';
import { buildDesigner, buildOptions } from '../../../../src/components/DesignerBuilder';
import { buildDesigner } from '../../../../src/components/DesignerBuilder';
import { PersistenceManager, LocalStorageManager } from '../../../../src';
import DesignerOptionsBuilder from '../../../../src/components/DesignerOptionsBuilder';
const p = new LocalStorageManager('samples/{id}.wxml');
const options = buildOptions({ persistenceManager: p, readOnly: true, saveOnLoad: false });
const options = DesignerOptionsBuilder.buildOptions({ persistenceManager: p, readOnly: true, saveOnLoad: false });
// Obtain map id from query param
const params = new URLSearchParams(window.location.search.substring(1));

View File

@ -11,7 +11,7 @@ module.exports = {
},
entry: {
mindplot: './src/index.js',
loader: './src/indexLoader.js',
loader: './src/indexLoader.ts',
},
mode: 'production',
devtool: 'source-map',

View File

@ -78,8 +78,6 @@ class Workspace extends ElementClass {
*/
static _createDivContainer() {
const container = window.document.createElement('div');
// container.id = 'workspaceContainer';
// container.style.overflow = 'hidden';
container.style.position = 'relative';
container.style.top = '0px';
container.style.left = '0px';

View File

@ -2561,6 +2561,13 @@
jest-diff "^27.0.0"
pretty-format "^27.0.0"
"@types/jquery@^3.5.11":
version "3.5.11"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.11.tgz#fb2a255e8376779e89a10ddd04bfc1a93398f861"
integrity sha512-lYZGdfOtUa0XFjIATQgiogqeTY5PNNMOmp3Jq48ghmJALL8t/IqABRqlEwdHfuUdA8iIE1uGD1HoI4a7Tiy6OA==
dependencies:
"@types/sizzle" "*"
"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@ -2671,7 +2678,7 @@
resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz#0ecc1b9259b76598ef01942f547904ce61a6a77d"
integrity sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==
"@types/sizzle@^2.3.2":
"@types/sizzle@*", "@types/sizzle@^2.3.2":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==