From cb2ca74a20aebec23c8ad36419c701da9c96655c Mon Sep 17 00:00:00 2001 From: Matias Arriola Date: Thu, 2 Dec 2021 00:41:56 +0000 Subject: [PATCH] Merged in web2d-coreJS-solutions (pull request #5) Core-js, web2d and mindplot working baseline * fix .eslintignore remove Raphael dependency * Fix to avoid crashes in _plotPrediction whitout Raphael * Fix minplot basic code inspections * Fix last inspections errors * Inital refactor copying files * Clean up. * Fix web2d cyclic dependencies remove only-warn eslint plugin set import/no-extraneous-dependencies to warn (incorrectly complaining about root package) * Fix web2d Point references (no need to assign it to core) Fix web2d imports in mindplot and update Point refs * Merge 'feature/mindplot_tests' into web2d-coreJS-solutions * mindplot fixes and add viewmode.html playground setup playground config to run the map-render examples fix mindplot components export mootools Static was not working so refactored it fix some references to _peer fix messages __bundle undefined add web2d missing export: Image downgrade cypress to avoid SIGSEGV error Approved-by: Paulo Veiga --- README.md | 10 + libraries/mootools-core-1.4.5.js | 842 +- .../underscore-min.js | 0 package.json | 3 +- packages/core-js/README.md | 2 +- packages/core-js/__tests__/core.test.js | 2 +- packages/core-js/babel.config.json | 3 +- packages/core-js/jsconfig.json | 10 + packages/core-js/lib/core.js | 13 - packages/core-js/package.json | 16 +- packages/core-js/{lib => src}/Functions.js | 32 +- packages/core-js/{lib => src}/Utils.js | 7 +- packages/core-js/src/core.js | 18 + packages/core-js/webpack.common.js | 20 +- packages/editor/package.json | 4 +- packages/mindplot/.eslintignore | 2 + packages/mindplot/.eslintrc.json | 26 +- packages/mindplot/.gitignore | 4 + packages/mindplot/README.md | 2 +- packages/mindplot/__tests__/mindplot.test.js | 6 +- packages/mindplot/babel.config.json | 3 +- packages/mindplot/cypress.json | 4 + .../cypress/integration/playground.test.js | 17 + packages/mindplot/cypress/plugins/index.js | 24 + .../playground.test.js/layout.snap.png | Bin 0 -> 75649 bytes .../playground.test.js/viewmode.snap.png | Bin 0 -> 67059 bytes packages/mindplot/cypress/support/commands.js | 29 + packages/mindplot/cypress/support/index.js | 20 + packages/mindplot/jsconfig.json | 18 + packages/mindplot/lib/components/IconGroup.js | 337 - packages/mindplot/lib/components/MainTopic.js | 170 - .../commands/AddFeatureToTopicCommand.js | 68 - .../mindplot/lib/components/commands/index.js | 21 - packages/mindplot/lib/components/index.js | 108 - .../mindplot/lib/components/layout/index.js | 27 - .../mindplot/lib/components/model/index.js | 21 - .../lib/components/persistence/index.js | 17 - .../mindplot/lib/components/util/index.js | 7 - .../mindplot/lib/components/widget/index.js | 37 - packages/mindplot/lib/mindplot.js | 56 - packages/mindplot/package.json | 25 +- .../{lib => src}/components/.gitignore | 0 .../components/ActionDispatcher.js | 41 +- .../{lib => src}/components/ActionIcon.js | 2 +- .../{lib => src}/components/CentralTopic.js | 13 +- .../{lib => src}/components/Command.js | 0 .../{lib => src}/components/ConnectionLine.js | 26 +- .../{lib => src}/components/ControlPoint.js | 65 +- .../{lib => src}/components/Designer.js | 71 +- .../components/DesignerActionRunner.js | 4 +- .../components/DesignerKeyboard.js | 19 +- .../{lib => src}/components/DesignerModel.js | 2 +- .../components/DesignerUndoManager.js | 0 .../{lib => src}/components/DragConnector.js | 0 .../{lib => src}/components/DragManager.js | 2 +- .../{lib => src}/components/DragPivot.js | 31 +- .../{lib => src}/components/DragTopic.js | 34 +- .../src/components/DragTopicConfig.js | 5 + .../{lib => src}/components/EditorOptions.js | 0 .../components/EditorProperties.js | 0 .../{lib => src}/components/Events.js | 0 .../mindplot/{lib => src}/components/Icon.js | 4 +- packages/mindplot/src/components/IconGroup.js | 346 + .../{lib => src}/components/ImageIcon.js | 4 +- .../{lib => src}/components/Keyboard.js | 0 .../{lib => src}/components/LinkIcon.js | 6 +- .../components/LocalStorageManager.js | 2 +- packages/mindplot/src/components/MainTopic.js | 162 + .../{lib => src}/components/Messages.js | 27 +- .../components/MultilineTextEditor.js | 4 +- .../{lib => src}/components/NodeGraph.js | 49 +- .../mindplot/src/components/NodeGraphUtils.js | 36 + .../{lib => src}/components/NoteIcon.js | 12 +- .../{lib => src}/components/Options.js | 0 .../components/PersistenceManager.js | 22 +- .../{lib => src}/components/Relationship.js | 58 +- .../components/RelationshipPivot.js | 20 +- .../components/RestPersistenceManager.js | 4 +- .../{lib => src}/components/ScreenManager.js | 23 +- .../components/ShrinkConnector.js | 16 +- .../components/StandaloneActionDispatcher.js | 32 +- .../{lib => src}/components/TextEditor.js | 34 +- .../components/TextEditorFactory.js | 2 +- .../mindplot/{lib => src}/components/Topic.js | 86 +- .../mindplot/src/components/TopicConfig.js | 36 + .../components/TopicEventDispatcher.js | 39 +- .../{lib => src}/components/TopicFeature.js | 18 +- .../{lib => src}/components/TopicStyle.js | 80 +- .../{lib => src}/components/Workspace.js | 8 +- .../commands/AddFeatureToTopicCommand.js | 70 + .../commands/AddRelationshipCommand.js | 2 +- .../components/commands/AddTopicCommand.js | 18 +- .../commands/ChangeFeatureToTopicCommand.js | 2 +- .../components/commands/DeleteCommand.js | 2 +- .../components/commands/DragTopicCommand.js | 6 +- .../commands/GenericFunctionCommand.js | 4 +- .../commands/MoveControlPointCommand.js | 12 +- .../commands/RemoveFeatureFromTopicCommand.js | 2 +- .../mindplot/src/components/commands/index.js | 21 + .../{lib => src}/components/footer.js | 0 .../{lib => src}/components/header.js | 0 packages/mindplot/src/components/index.js | 95 + .../components/layout/AbstractBasicSorter.js | 4 +- .../components/layout/BalancedSorter.js | 2 +- .../components/layout/ChangeEvent.js | 0 .../layout/ChildrenSorterStrategy.js | 0 .../components/layout/EventBus.js | 2 +- .../components/layout/EventBusDispatcher.js | 2 +- .../components/layout/GridSorter.js | 2 +- .../components/layout/LayoutManager.js | 15 +- .../{lib => src}/components/layout/Node.js | 0 .../components/layout/OriginalLayout.js | 6 +- .../components/layout/RootedTreeSet.js | 0 .../components/layout/SymmetricSorter.js | 2 +- .../mindplot/src/components/layout/index.js | 27 + .../bootstrap/BootstrapDialog.Request.js | 2 +- .../libraries/bootstrap/BootstrapDialog.js | 2 +- .../bootstrap/css/bootstrap-colorpicker.css | 0 .../css/bootstrap-colorpicker.min.css | 0 .../bootstrap/css/bootstrap-theme.css | 0 .../bootstrap/css/bootstrap-theme.css.map | 0 .../bootstrap/css/bootstrap-theme.min.css | 0 .../libraries/bootstrap/css/bootstrap.css | 0 .../libraries/bootstrap/css/bootstrap.css.map | 0 .../libraries/bootstrap/css/bootstrap.min.css | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../alpha-horizontal.png | Bin .../img/bootstrap-colorpicker/alpha.png | Bin .../bootstrap-colorpicker/hue-horizontal.png | Bin .../img/bootstrap-colorpicker/hue.png | Bin .../img/bootstrap-colorpicker/saturation.png | Bin .../img/glyphicons-halflings-blue.png | Bin .../bootstrap/js/bootstrap-colorpicker.js | 0 .../bootstrap/js/bootstrap-colorpicker.min.js | 0 .../libraries/bootstrap/js/bootstrap.js | 0 .../libraries/bootstrap/js/bootstrap.min.js | 0 .../libraries/hotkeys/jquery.hotkeys.js | 0 .../libraries/jquery/jquery-2.1.0.js | 0 .../libraries/jquery/jquery-2.1.0.min.js | 0 .../libraries/jquery/jquery.mousewheel.min.js | 0 .../libraries/less/less-1.4.2.min.js | 0 .../libraries/less/less-1.6.2.min.js | 14 +- .../mootools-core-1.4.5-full-nocompat-yc.js | 0 .../libraries/mootools/mootools-core-1.4.5.js | 0 .../libraries/mootools/mootools-core-1.6.0.js | 0 .../libraries/underscorejs/underscore-min.js | 13 + .../components/model/FeatureModel.js | 20 +- .../{lib => src}/components/model/IMindmap.js | 0 .../components/model/INodeModel.js | 41 +- .../components/model/IconModel.js | 2 +- .../components/model/LinkModel.js | 2 +- .../{lib => src}/components/model/Mindmap.js | 10 +- .../components/model/NodeModel.js | 4 +- .../components/model/NoteModel.js | 2 +- .../components/model/RelationshipModel.js | 20 +- .../mindplot/src/components/model/index.js | 21 + .../persistence/Beta2PelaMigrator.js | 4 +- .../components/persistence/ModelCodeName.js | 0 .../persistence/Pela2TangoMigrator.js | 4 +- .../persistence/XMLSerializerFactory.js | 12 +- .../persistence/XMLSerializer_Beta.js | 44 +- .../persistence/XMLSerializer_Pela.js | 34 +- .../persistence/XMLSerializer_Tango.js | 2 +- .../src/components/persistence/index.js | 17 + .../components/util/FadeEffect.js | 2 +- .../{lib => src}/components/util/Shape.js | 37 +- .../mindplot/src/components/util/index.js | 7 + .../components/widget/ColorPalettePanel.js | 2 +- .../components/widget/FloatingTip.js | 4 +- .../components/widget/FontFamilyPanel.js | 2 +- .../components/widget/FontSizePanel.js | 2 +- .../{lib => src}/components/widget/IMenu.js | 2 +- .../components/widget/IconPanel.js | 4 +- .../widget/KeyboardShortcutTooltip.js | 2 +- .../components/widget/LinkEditor.js | 2 +- .../components/widget/LinkIconTooltip.js | 4 +- .../components/widget/ListToolbarPanel.js | 2 +- .../{lib => src}/components/widget/Menu.js | 18 +- .../components/widget/ModalDialogNotifier.js | 0 .../components/widget/NoteEditor.js | 2 +- .../components/widget/ToolbarItem.js | 2 +- .../components/widget/ToolbarNotifier.js | 0 .../components/widget/ToolbarPaneItem.js | 4 +- .../components/widget/TopicShapePanel.js | 2 +- .../components/widget/colorPalette.css | 0 .../components/widget/colorPalette.html | 0 .../mindplot/src/components/widget/index.js | 37 + packages/mindplot/src/mindplot.js | 26 + .../test/playground/BalancedTestSuite.js | 500 - .../mindplot/test/playground/FreeTestSuite.js | 558 - .../test/playground/SymmetricTestSuite.js | 352 - .../mindplot/test/playground/TestSuite.js | 589 - .../test/playground/context-loader.js | 11 - packages/mindplot/test/playground/index.html | 34 +- .../playground/layout/BalancedTestSuite.js | 499 + .../test/playground/layout/FreeTestSuite.js | 555 + .../playground/layout/SymmetricTestSuite.js | 351 + .../test/playground/layout/TestSuite.js | 592 + .../test/playground/layout/context-loader.js | 11 + .../{layout.html => layout/index.html} | 0 .../{ => layout}/lib/raphael-min.js | 0 .../playground/layout/lib/raphael-plugins.js | 29 + .../test/playground/{ => layout}/sample.xml | 0 .../mindplot/test/playground/layout/utils.js | 59 + .../test/playground/lib/raphael-plugins.js | 29 - .../bootstrap/BootstrapDialog.Request.js | 49 + .../map-render/bootstrap/BootstrapDialog.js | 111 + .../bootstrap/css/bootstrap-colorpicker.css | 214 + .../css/bootstrap-colorpicker.min.css | 9 + .../bootstrap/css/bootstrap-theme.css | 347 + .../bootstrap/css/bootstrap-theme.css.map | 1 + .../bootstrap/css/bootstrap-theme.min.css | 7 + .../map-render/bootstrap/css/bootstrap.css | 5785 +++++ .../bootstrap/css/bootstrap.css.map | 1 + .../bootstrap/css/bootstrap.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes .../alpha-horizontal.png | Bin 0 -> 3635 bytes .../img/bootstrap-colorpicker/alpha.png | Bin 0 -> 3271 bytes .../bootstrap-colorpicker/hue-horizontal.png | Bin 0 -> 2837 bytes .../img/bootstrap-colorpicker/hue.png | Bin 0 -> 2972 bytes .../img/bootstrap-colorpicker/saturation.png | Bin 0 -> 8817 bytes .../img/glyphicons-halflings-blue.png | Bin 0 -> 4207 bytes .../bootstrap/js/bootstrap-colorpicker.js | 951 + .../bootstrap/js/bootstrap-colorpicker.min.js | 1 + .../map-render/bootstrap/js/bootstrap.js | 1951 ++ .../map-render/bootstrap/js/bootstrap.min.js | 6 + .../map-render/css/compatibility.less | 148 + .../playground/map-render/css/editor.less | 167 + .../playground/map-render/css/embedded.less | 106 + .../playground/map-render/css/header.less | 125 + .../playground/map-render/css/toolbar.less | 153 + .../map-render/css/widget/colorPalette.css | 75 + .../map-render/css/widget/colorPalette.html | 450 + .../map-render/css/widget/skin2.less | 3 + .../playground/map-render/html/container.html | 68 + .../playground/map-render/html/container.json | 16 + .../test/playground/map-render/html/drag.html | 221 + .../playground/map-render/html/editor.html | 145 + .../playground/map-render/html/embedded.html | 138 + .../playground/map-render/html/viewmode.html | 38 + .../map-render/icons/arrow_down.gif | Bin 0 -> 62 bytes .../map-render/icons/arrow_down.png | Bin 0 -> 379 bytes .../map-render/icons/arrow_left.png | Bin 0 -> 345 bytes .../map-render/icons/arrow_merge.png | Bin 0 -> 484 bytes .../map-render/icons/arrow_right.png | Bin 0 -> 409 bytes .../playground/map-render/icons/arrow_up.png | Bin 0 -> 372 bytes .../icons/arrowc_rotate_anticlockwise.png | Bin 0 -> 608 bytes .../icons/arrowc_rotate_clockwise.png | Bin 0 -> 602 bytes .../map-render/icons/arrowc_turn_left.png | Bin 0 -> 516 bytes .../map-render/icons/arrowc_turn_right.png | Bin 0 -> 489 bytes .../test/playground/map-render/icons/bomb.png | Bin 0 -> 793 bytes .../map-render/icons/bulb_light_off.png | Bin 0 -> 700 bytes .../map-render/icons/bulb_light_on.png | Bin 0 -> 782 bytes .../map-render/icons/bullet_black.png | Bin 0 -> 211 bytes .../map-render/icons/bullet_blue.png | Bin 0 -> 289 bytes .../map-render/icons/bullet_green.png | Bin 0 -> 295 bytes .../map-render/icons/bullet_orange.png | Bin 0 -> 283 bytes .../map-render/icons/bullet_pink.png | Bin 0 -> 286 bytes .../map-render/icons/bullet_purple.png | Bin 0 -> 294 bytes .../map-render/icons/bullet_red.png | Bin 0 -> 287 bytes .../playground/map-render/icons/chart_bar.png | Bin 0 -> 541 bytes .../map-render/icons/chart_curve.png | Bin 0 -> 710 bytes .../map-render/icons/chart_line.png | Bin 0 -> 526 bytes .../map-render/icons/chart_organisation.png | Bin 0 -> 444 bytes .../playground/map-render/icons/chart_pie.png | Bin 0 -> 918 bytes .../playground/map-render/icons/close.png | Bin 0 -> 3758 bytes .../map-render/icons/conn_connect.png | Bin 0 -> 748 bytes .../map-render/icons/conn_disconnect.png | Bin 0 -> 796 bytes .../map-render/icons/face_crying.png | Bin 0 -> 936 bytes .../map-render/icons/face_plain.png | Bin 0 -> 894 bytes .../playground/map-render/icons/face_sad.png | Bin 0 -> 918 bytes .../map-render/icons/face_smile-big.png | Bin 0 -> 896 bytes .../map-render/icons/face_smile.png | Bin 0 -> 919 bytes .../map-render/icons/face_surprise.png | Bin 0 -> 917 bytes .../playground/map-render/icons/face_wink.png | Bin 0 -> 914 bytes .../playground/map-render/icons/flag_blue.png | Bin 0 -> 671 bytes .../map-render/icons/flag_green.png | Bin 0 -> 672 bytes .../map-render/icons/flag_orange.png | Bin 0 -> 669 bytes .../playground/map-render/icons/flag_pink.png | Bin 0 -> 651 bytes .../map-render/icons/flag_purple.png | Bin 0 -> 656 bytes .../map-render/icons/flag_yellow.png | Bin 0 -> 671 bytes .../map-render/icons/funy_angel.png | Bin 0 -> 992 bytes .../map-render/icons/funy_devilish.png | Bin 0 -> 855 bytes .../map-render/icons/funy_glasses.png | Bin 0 -> 949 bytes .../playground/map-render/icons/funy_grin.png | Bin 0 -> 905 bytes .../playground/map-render/icons/funy_kiss.png | Bin 0 -> 919 bytes .../map-render/icons/funy_monkey.png | Bin 0 -> 784 bytes .../map-render/icons/gener_female.png | Bin 0 -> 590 bytes .../map-render/icons/gener_male.png | Bin 0 -> 629 bytes .../playground/map-render/icons/hard_cd.png | Bin 0 -> 673 bytes .../map-render/icons/hard_computer.png | Bin 0 -> 667 bytes .../map-render/icons/hard_controller.png | Bin 0 -> 666 bytes .../map-render/icons/hard_drive_cd.png | Bin 0 -> 734 bytes .../map-render/icons/hard_driver_disk.png | Bin 0 -> 620 bytes .../playground/map-render/icons/hard_ipod.png | Bin 0 -> 463 bytes .../map-render/icons/hard_keyboard.png | Bin 0 -> 570 bytes .../map-render/icons/hard_mouse.png | Bin 0 -> 634 bytes .../map-render/icons/hard_printer.png | Bin 0 -> 731 bytes .../map-render/icons/legacy/add.png | Bin 0 -> 733 bytes .../map-render/icons/legacy/arrow_down.png | Bin 0 -> 379 bytes .../map-render/icons/legacy/arrow_left.png | Bin 0 -> 345 bytes .../map-render/icons/legacy/arrow_merge.png | Bin 0 -> 484 bytes .../map-render/icons/legacy/arrow_right.png | Bin 0 -> 409 bytes .../legacy/arrow_rotate_anticlockwise.png | Bin 0 -> 608 bytes .../icons/legacy/arrow_rotate_clockwise.png | Bin 0 -> 602 bytes .../icons/legacy/arrow_turn_left.png | Bin 0 -> 516 bytes .../icons/legacy/arrow_turn_right.png | Bin 0 -> 489 bytes .../map-render/icons/legacy/arrow_up.png | Bin 0 -> 372 bytes .../map-render/icons/legacy/backColor.png | Bin 0 -> 490 bytes .../map-render/icons/legacy/balloon.png | Bin 0 -> 1464 bytes .../map-render/icons/legacy/bin.png | Bin 0 -> 476 bytes .../icons/legacy/black-keyboard.png | Bin 0 -> 9236 bytes .../map-render/icons/legacy/bold.png | Bin 0 -> 330 bytes .../map-render/icons/legacy/borderColor.png | Bin 0 -> 3368 bytes .../map-render/icons/legacy/bullet_black.png | Bin 0 -> 211 bytes .../map-render/icons/legacy/bullet_blue.png | Bin 0 -> 289 bytes .../map-render/icons/legacy/bullet_green.png | Bin 0 -> 295 bytes .../map-render/icons/legacy/bullet_orange.png | Bin 0 -> 283 bytes .../map-render/icons/legacy/bullet_pink.png | Bin 0 -> 286 bytes .../map-render/icons/legacy/bullet_purple.png | Bin 0 -> 294 bytes .../map-render/icons/legacy/bullet_red.png | Bin 0 -> 287 bytes .../map-render/icons/legacy/chart_bar.png | Bin 0 -> 541 bytes .../map-render/icons/legacy/chart_curve.png | Bin 0 -> 710 bytes .../map-render/icons/legacy/chart_line.png | Bin 0 -> 526 bytes .../icons/legacy/chart_organisation.png | Bin 0 -> 444 bytes .../map-render/icons/legacy/chart_pie.png | Bin 0 -> 918 bytes .../map-render/icons/legacy/clock.png | Bin 0 -> 882 bytes .../map-render/icons/legacy/clock_red.png | Bin 0 -> 889 bytes .../map-render/icons/legacy/close.png | Bin 0 -> 3758 bytes .../map-render/icons/legacy/coins.png | Bin 0 -> 732 bytes .../icons/legacy/collab_publish.png | Bin 0 -> 3787 bytes .../map-render/icons/legacy/collab_share.png | Bin 0 -> 3756 bytes .../map-render/icons/legacy/collab_tag.png | Bin 0 -> 3862 bytes .../map-render/icons/legacy/color_swatch.png | Bin 0 -> 3287 bytes .../map-render/icons/legacy/comment.png | Bin 0 -> 545 bytes .../map-render/icons/legacy/connect.png | Bin 0 -> 748 bytes .../map-render/icons/legacy/cross.png | Bin 0 -> 655 bytes .../map-render/icons/legacy/delNode.png | Bin 0 -> 728 bytes .../map-render/icons/legacy/delete.png | Bin 0 -> 715 bytes .../map-render/icons/legacy/disconnect.png | Bin 0 -> 796 bytes .../map-render/icons/legacy/face-angel.png | Bin 0 -> 992 bytes .../map-render/icons/legacy/face-crying.png | Bin 0 -> 936 bytes .../map-render/icons/legacy/face-devilish.png | Bin 0 -> 855 bytes .../map-render/icons/legacy/face-glasses.png | Bin 0 -> 949 bytes .../map-render/icons/legacy/face-grin.png | Bin 0 -> 905 bytes .../map-render/icons/legacy/face-kiss.png | Bin 0 -> 919 bytes .../map-render/icons/legacy/face-monkey.png | Bin 0 -> 784 bytes .../map-render/icons/legacy/face-plain.png | Bin 0 -> 894 bytes .../map-render/icons/legacy/face-sad.png | Bin 0 -> 918 bytes .../icons/legacy/face-smile-big.png | Bin 0 -> 896 bytes .../map-render/icons/legacy/face-smile.png | Bin 0 -> 919 bytes .../map-render/icons/legacy/face-surprise.png | Bin 0 -> 917 bytes .../map-render/icons/legacy/face-wink.png | Bin 0 -> 914 bytes .../map-render/icons/legacy/file_export.png | Bin 0 -> 3423 bytes .../map-render/icons/legacy/file_printer.png | Bin 0 -> 3612 bytes .../map-render/icons/legacy/file_redo.png | Bin 0 -> 3288 bytes .../map-render/icons/legacy/file_redo_dis.png | Bin 0 -> 3286 bytes .../map-render/icons/legacy/file_undo.png | Bin 0 -> 3292 bytes .../map-render/icons/legacy/file_undo_dis.png | Bin 0 -> 3296 bytes .../map-render/icons/legacy/flag_blue.png | Bin 0 -> 671 bytes .../map-render/icons/legacy/flag_green.png | Bin 0 -> 672 bytes .../map-render/icons/legacy/flag_orange.png | Bin 0 -> 669 bytes .../map-render/icons/legacy/flag_pink.png | Bin 0 -> 651 bytes .../map-render/icons/legacy/flag_purple.png | Bin 0 -> 656 bytes .../map-render/icons/legacy/flag_yellow.png | Bin 0 -> 671 bytes .../map-render/icons/legacy/font.png | Bin 0 -> 780 bytes .../map-render/icons/legacy/fontColor.png | Bin 0 -> 393 bytes .../map-render/icons/legacy/fontSize.png | Bin 0 -> 435 bytes .../map-render/icons/legacy/font_bold.png | Bin 0 -> 3650 bytes .../map-render/icons/legacy/font_color.png | Bin 0 -> 3810 bytes .../map-render/icons/legacy/font_italic.png | Bin 0 -> 3627 bytes .../map-render/icons/legacy/font_size.png | Bin 0 -> 3697 bytes .../map-render/icons/legacy/font_type.png | Bin 0 -> 3724 bytes .../map-render/icons/legacy/group.png | Bin 0 -> 616 bytes .../map-render/icons/legacy/group2.png | Bin 0 -> 894 bytes .../map-render/icons/legacy/group_go.png | Bin 0 -> 842 bytes .../map-render/icons/legacy/help.png | Bin 0 -> 786 bytes .../map-render/icons/legacy/history.png | Bin 0 -> 4080 bytes .../map-render/icons/legacy/info.png | Bin 0 -> 778 bytes .../map-render/icons/legacy/italic.png | Bin 0 -> 336 bytes .../map-render/icons/legacy/key.png | Bin 0 -> 612 bytes .../map-render/icons/legacy/lightbulb.png | Bin 0 -> 782 bytes .../map-render/icons/legacy/lightbulb_off.png | Bin 0 -> 700 bytes .../map-render/icons/legacy/links.png | Bin 0 -> 957 bytes .../map-render/icons/legacy/lock.png | Bin 0 -> 749 bytes .../map-render/icons/legacy/lock_open.png | Bin 0 -> 727 bytes .../map-render/icons/legacy/logo-big.png | Bin 0 -> 23786 bytes .../map-render/icons/legacy/logo-vsmall.png | Bin 0 -> 6970 bytes .../map-render/icons/legacy/logo-vvsmall.png | Bin 0 -> 6227 bytes .../map-render/icons/legacy/marca-vsmall.png | Bin 0 -> 6970 bytes .../map-render/icons/legacy/money.png | Bin 0 -> 738 bytes .../map-render/icons/legacy/money_dollar.png | Bin 0 -> 630 bytes .../map-render/icons/legacy/money_euro.png | Bin 0 -> 605 bytes .../map-render/icons/legacy/money_pound.png | Bin 0 -> 565 bytes .../map-render/icons/legacy/money_yen.png | Bin 0 -> 562 bytes .../map-render/icons/legacy/moor_boverlay.png | Bin 0 -> 799 bytes .../map-render/icons/legacy/moor_slider.png | Bin 0 -> 590 bytes .../map-render/icons/legacy/moor_woverlay.png | Bin 0 -> 768 bytes .../map-render/icons/legacy/move.png | Bin 0 -> 575 bytes .../map-render/icons/legacy/mymaps.png | Bin 0 -> 47252 bytes .../map-render/icons/legacy/node_add.png | Bin 0 -> 616 bytes .../map-render/icons/legacy/node_border.png | Bin 0 -> 591 bytes .../map-render/icons/legacy/node_border2.png | Bin 0 -> 633 bytes .../map-render/icons/legacy/node_elipse.png | Bin 0 -> 635 bytes .../map-render/icons/legacy/note.png | Bin 0 -> 3531 bytes .../map-render/icons/legacy/note1.png | Bin 0 -> 3551 bytes .../map-render/icons/legacy/page_delete.png | Bin 0 -> 649 bytes .../map-render/icons/legacy/page_go.png | Bin 0 -> 944 bytes .../map-render/icons/legacy/printer.png | Bin 0 -> 804 bytes .../map-render/icons/legacy/removeUser.jpeg | Bin 0 -> 415 bytes .../map-render/icons/legacy/ruby.png | Bin 0 -> 592 bytes .../map-render/icons/legacy/save.png | Bin 0 -> 3919 bytes .../map-render/icons/legacy/search.png | Bin 0 -> 2151 bytes .../map-render/icons/legacy/search2.png | Bin 0 -> 3207 bytes .../map-render/icons/legacy/search3.png | Bin 0 -> 2106 bytes .../map-render/icons/legacy/seast.png | Bin 0 -> 2838 bytes .../map-render/icons/legacy/shape-elipse.png | Bin 0 -> 963 bytes .../map-render/icons/legacy/shape-line.png | Bin 0 -> 206 bytes .../icons/legacy/shape-rectangle-rounded.png | Bin 0 -> 763 bytes .../icons/legacy/shape-rectangle.png | Bin 0 -> 643 bytes .../map-render/icons/legacy/shape.png | Bin 0 -> 445 bytes .../map-render/icons/legacy/shape_handles.png | Bin 0 -> 3604 bytes .../icons/legacy/shape_square_add.png | Bin 0 -> 539 bytes .../icons/legacy/shape_square_delete.png | Bin 0 -> 537 bytes .../icons/legacy/shape_square_edit.png | Bin 0 -> 660 bytes .../map-render/icons/legacy/signUpBodyBtn.png | Bin 0 -> 261 bytes .../map-render/icons/legacy/signUpEndBtn.png | Bin 0 -> 367 bytes .../icons/legacy/signUpStartBtn.png | Bin 0 -> 363 bytes .../map-render/icons/legacy/sne.png | Bin 0 -> 3093 bytes .../map-render/icons/legacy/snorth.png | Bin 0 -> 2829 bytes .../map-render/icons/legacy/snw.png | Bin 0 -> 3049 bytes .../map-render/icons/legacy/sse.png | Bin 0 -> 3127 bytes .../map-render/icons/legacy/ssouth.png | Bin 0 -> 2849 bytes .../map-render/icons/legacy/ssw.png | Bin 0 -> 3164 bytes .../map-render/icons/legacy/swest.png | Bin 0 -> 2840 bytes .../map-render/icons/legacy/tag_blue.png | Bin 0 -> 586 bytes .../map-render/icons/legacy/tag_blue_add.png | Bin 0 -> 824 bytes .../map-render/icons/legacy/tag_blue_add2.png | Bin 0 -> 836 bytes .../map-render/icons/legacy/tag_green.png | Bin 0 -> 613 bytes .../map-render/icons/legacy/tag_orange.png | Bin 0 -> 586 bytes .../map-render/icons/legacy/tag_pink.png | Bin 0 -> 579 bytes .../map-render/icons/legacy/tag_purple.png | Bin 0 -> 599 bytes .../map-render/icons/legacy/tag_red.png | Bin 0 -> 592 bytes .../map-render/icons/legacy/tag_yellow.png | Bin 0 -> 586 bytes .../map-render/icons/legacy/text_bold.png | Bin 0 -> 304 bytes .../map-render/icons/legacy/text_italic.png | Bin 0 -> 223 bytes .../map-render/icons/legacy/thumb_down.png | Bin 0 -> 601 bytes .../map-render/icons/legacy/thumb_up.png | Bin 0 -> 619 bytes .../map-render/icons/legacy/tick.png | Bin 0 -> 537 bytes .../map-render/icons/legacy/user_delete.png | Bin 0 -> 767 bytes .../map-render/icons/legacy/waring_icon.png | Bin 0 -> 666 bytes .../map-render/icons/legacy/world.png | Bin 0 -> 616 bytes .../map-render/icons/legacy/world2.png | Bin 0 -> 1110 bytes .../map-render/icons/legacy/world_go.png | Bin 0 -> 944 bytes .../map-render/icons/legacy/world_link.png | Bin 0 -> 957 bytes .../map-render/icons/legacy/zoom_in.png | Bin 0 -> 3636 bytes .../map-render/icons/legacy/zoom_out.png | Bin 0 -> 3637 bytes .../map-render/icons/lock_close.png | Bin 0 -> 749 bytes .../playground/map-render/icons/lock_open.png | Bin 0 -> 727 bytes .../playground/map-render/icons/mail_edit.png | Bin 0 -> 880 bytes .../map-render/icons/mail_envelop.png | Bin 0 -> 641 bytes .../playground/map-render/icons/mail_list.png | Bin 0 -> 566 bytes .../map-render/icons/mail_mailbox.png | Bin 0 -> 555 bytes .../map-render/icons/money_coins.png | Bin 0 -> 732 bytes .../map-render/icons/money_dollar.png | Bin 0 -> 630 bytes .../map-render/icons/money_euro.png | Bin 0 -> 605 bytes .../map-render/icons/money_money.png | Bin 0 -> 738 bytes .../map-render/icons/money_pound.png | Bin 0 -> 565 bytes .../map-render/icons/money_ruby.png | Bin 0 -> 592 bytes .../playground/map-render/icons/money_yen.png | Bin 0 -> 562 bytes .../playground/map-render/icons/number_1.png | Bin 0 -> 3442 bytes .../playground/map-render/icons/number_2.png | Bin 0 -> 3573 bytes .../playground/map-render/icons/number_3.png | Bin 0 -> 3667 bytes .../playground/map-render/icons/number_4.png | Bin 0 -> 3629 bytes .../playground/map-render/icons/number_5.png | Bin 0 -> 3642 bytes .../playground/map-render/icons/number_6.png | Bin 0 -> 3688 bytes .../playground/map-render/icons/number_7.png | Bin 0 -> 3530 bytes .../playground/map-render/icons/number_8.png | Bin 0 -> 3681 bytes .../playground/map-render/icons/number_9.png | Bin 0 -> 3697 bytes .../map-render/icons/object_bell.png | Bin 0 -> 789 bytes .../map-render/icons/object_cake.png | Bin 0 -> 676 bytes .../map-render/icons/object_camera.png | Bin 0 -> 665 bytes .../map-render/icons/object_clanbomber.png | Bin 0 -> 793 bytes .../map-render/icons/object_clip.png | Bin 0 -> 391 bytes .../map-render/icons/object_house.png | Bin 0 -> 806 bytes .../map-render/icons/object_key.png | Bin 0 -> 612 bytes .../map-render/icons/object_magnifier.png | Bin 0 -> 615 bytes .../map-render/icons/object_music.png | Bin 0 -> 385 bytes .../map-render/icons/object_palette.png | Bin 0 -> 856 bytes .../map-render/icons/object_pencil.png | Bin 0 -> 450 bytes .../map-render/icons/object_phone.png | Bin 0 -> 488 bytes .../map-render/icons/object_rainbow.png | Bin 0 -> 655 bytes .../map-render/icons/object_star.png | Bin 0 -> 670 bytes .../map-render/icons/object_wizard.png | Bin 0 -> 570 bytes .../playground/map-render/icons/onoff_add.png | Bin 0 -> 733 bytes .../map-render/icons/onoff_clock.png | Bin 0 -> 882 bytes .../map-render/icons/onoff_clock_red.png | Bin 0 -> 889 bytes .../map-render/icons/onoff_delete.png | Bin 0 -> 715 bytes .../map-render/icons/onoff_status_offline.png | Bin 0 -> 422 bytes .../map-render/icons/onoff_status_online.png | Bin 0 -> 722 bytes .../map-render/icons/people_female1.png | Bin 0 -> 663 bytes .../map-render/icons/people_female2.png | Bin 0 -> 722 bytes .../map-render/icons/people_group.png | Bin 0 -> 753 bytes .../map-render/icons/people_male1.png | Bin 0 -> 748 bytes .../map-render/icons/people_male2.png | Bin 0 -> 741 bytes .../map-render/icons/sign_cancel.png | Bin 0 -> 587 bytes .../map-render/icons/sign_closed.png | Bin 0 -> 715 bytes .../map-render/icons/sign_exclamation.png | Bin 0 -> 701 bytes .../playground/map-render/icons/sign_help.png | Bin 0 -> 786 bytes .../playground/map-render/icons/sign_info.png | Bin 0 -> 778 bytes .../playground/map-render/icons/sign_stop.png | Bin 0 -> 700 bytes .../map-render/icons/sign_warning.png | Bin 0 -> 666 bytes .../playground/map-render/icons/soft_bug.png | Bin 0 -> 774 bytes .../map-render/icons/soft_cursor.png | Bin 0 -> 354 bytes .../map-render/icons/soft_database.png | Bin 0 -> 390 bytes .../map-render/icons/soft_database_table.png | Bin 0 -> 726 bytes .../playground/map-render/icons/soft_feed.png | Bin 0 -> 691 bytes .../map-render/icons/soft_folder_explore.png | Bin 0 -> 679 bytes .../map-render/icons/soft_penguin.png | Bin 0 -> 696 bytes .../playground/map-render/icons/soft_rss.png | Bin 0 -> 530 bytes .../map-render/icons/soft_stuff_folder.png | Bin 0 -> 537 bytes .../map-render/icons/sport_basketball.png | Bin 0 -> 977 bytes .../map-render/icons/sport_football.png | Bin 0 -> 875 bytes .../map-render/icons/sport_golf.png | Bin 0 -> 504 bytes .../map-render/icons/sport_raquet.png | Bin 0 -> 719 bytes .../map-render/icons/sport_shuttlecock.png | Bin 0 -> 683 bytes .../map-render/icons/sport_soccer.png | Bin 0 -> 517 bytes .../map-render/icons/sport_tennis.png | Bin 0 -> 884 bytes .../playground/map-render/icons/tag_blue.png | Bin 0 -> 586 bytes .../map-render/icons/tag_blue_add.png | Bin 0 -> 824 bytes .../map-render/icons/tag_blue_add2.png | Bin 0 -> 836 bytes .../playground/map-render/icons/tag_green.png | Bin 0 -> 613 bytes .../map-render/icons/tag_orange.png | Bin 0 -> 586 bytes .../playground/map-render/icons/tag_pink.png | Bin 0 -> 579 bytes .../map-render/icons/tag_purple.png | Bin 0 -> 599 bytes .../playground/map-render/icons/tag_red.png | Bin 0 -> 592 bytes .../map-render/icons/tag_yellow.png | Bin 0 -> 586 bytes .../playground/map-render/icons/task_0.png | Bin 0 -> 3225 bytes .../playground/map-render/icons/task_100.png | Bin 0 -> 3221 bytes .../playground/map-render/icons/task_25.png | Bin 0 -> 3300 bytes .../playground/map-render/icons/task_50.png | Bin 0 -> 3297 bytes .../playground/map-render/icons/task_75.png | Bin 0 -> 3285 bytes .../map-render/icons/thumb_thumb_down.png | Bin 0 -> 601 bytes .../map-render/icons/thumb_thumb_up.png | Bin 0 -> 619 bytes .../map-render/icons/tick_cross.png | Bin 0 -> 655 bytes .../playground/map-render/icons/tick_tick.png | Bin 0 -> 537 bytes .../map-render/icons/time_calendar.png | Bin 0 -> 572 bytes .../map-render/icons/time_clock.png | Bin 0 -> 793 bytes .../map-render/icons/time_hourglass.png | Bin 0 -> 744 bytes .../map-render/icons/weather_clear-night.png | Bin 0 -> 961 bytes .../map-render/icons/weather_clear.png | Bin 0 -> 682 bytes .../icons/weather_few-clouds-night.png | Bin 0 -> 965 bytes .../map-render/icons/weather_few-clouds.png | Bin 0 -> 763 bytes .../map-render/icons/weather_overcast.png | Bin 0 -> 975 bytes .../map-render/icons/weather_severe-alert.png | Bin 0 -> 977 bytes .../icons/weather_showers-scattered.png | Bin 0 -> 1045 bytes .../map-render/icons/weather_showers.png | Bin 0 -> 959 bytes .../map-render/icons/weather_snow.png | Bin 0 -> 998 bytes .../map-render/icons/weather_storm.png | Bin 0 -> 1031 bytes .../map-render/images/ajax-loader.gif | Bin 0 -> 6820 bytes .../map-render/images/alert-sign.png | Bin 0 -> 5000 bytes .../map-render/images/btn-bg-hover.png | Bin 0 -> 571 bytes .../map-render/images/btn-bg-normal.png | Bin 0 -> 553 bytes .../map-render/images/btne-bg-hover.png | Bin 0 -> 1025 bytes .../map-render/images/btne-bg-normal.png | Bin 0 -> 1058 bytes .../map-render/images/btne-bg-selected.png | Bin 0 -> 1203 bytes .../playground/map-render/images/discard.png | Bin 0 -> 562 bytes .../map-render/images/editortoolbar.png | Bin 0 -> 2759 bytes .../playground/map-render/images/export.png | Bin 0 -> 728 bytes .../playground/map-render/images/favicon.ico | Bin 0 -> 1150 bytes .../map-render/images/font-bold.png | Bin 0 -> 666 bytes .../map-render/images/font-color.png | Bin 0 -> 986 bytes .../map-render/images/font-italic.png | Bin 0 -> 627 bytes .../map-render/images/font-size.png | Bin 0 -> 864 bytes .../map-render/images/font-type.png | Bin 0 -> 916 bytes .../playground/map-render/images/history.png | Bin 0 -> 1739 bytes .../playground/map-render/images/links.png | Bin 0 -> 2631 bytes .../map-render/images/logo-135x135.png | Bin 0 -> 11990 bytes .../map-render/images/logo-head-only.png | Bin 0 -> 5332 bytes .../map-render/images/logo-medium.png | Bin 0 -> 13338 bytes .../map-render/images/logo-small.png | Bin 0 -> 7530 bytes .../map-render/images/logo-xsmall.png | Bin 0 -> 13314 bytes .../playground/map-render/images/notes.png | Bin 0 -> 2240 bytes .../playground/map-render/images/print.png | Bin 0 -> 532 bytes .../playground/map-render/images/public.png | Bin 0 -> 1773 bytes .../playground/map-render/images/redo.png | Bin 0 -> 608 bytes .../playground/map-render/images/save.png | Bin 0 -> 730 bytes .../map-render/images/shape-circle.png | Bin 0 -> 2416 bytes .../map-render/images/shape-line.png | Bin 0 -> 1966 bytes .../images/shape-rectangle-round.png | Bin 0 -> 2303 bytes .../map-render/images/shape-rectangle.png | Bin 0 -> 2055 bytes .../playground/map-render/images/share.png | Bin 0 -> 527 bytes .../test/playground/map-render/images/tag.png | Bin 0 -> 946 bytes .../map-render/images/topic-add.png | Bin 0 -> 1037 bytes .../map-render/images/topic-border.png | Bin 0 -> 882 bytes .../map-render/images/topic-color.png | Bin 0 -> 1492 bytes .../map-render/images/topic-delete.png | Bin 0 -> 1002 bytes .../map-render/images/topic-icon.png | Bin 0 -> 916 bytes .../map-render/images/topic-link.png | Bin 0 -> 1124 bytes .../map-render/images/topic-note.png | Bin 0 -> 405 bytes .../map-render/images/topic-relation.png | Bin 0 -> 360 bytes .../map-render/images/topic-shape.png | Bin 0 -> 877 bytes .../playground/map-render/images/undo.png | Bin 0 -> 585 bytes .../playground/map-render/images/zoom-in.png | Bin 0 -> 790 bytes .../playground/map-render/images/zoom-out.png | Bin 0 -> 817 bytes .../test/playground/map-render/index.html | 23 + .../playground/map-render/js/bootstrap.js | 6 + .../test/playground/map-render/js/editor.js | 218 + .../test/playground/map-render/js/jquery.js | 1 + .../playground/map-render/samples/complex.xml | 352 + .../map-render/samples/emptyNodes.xml | 239 + .../playground/map-render/samples/huge.xml | 386 + .../playground/map-render/samples/issue.xml | 120 + .../playground/map-render/samples/sample2.xml | 29 + .../playground/map-render/samples/sample3.xml | 9 + .../playground/map-render/samples/sample4.xml | 10 + .../map-render/samples/welcome-reloaded.xml | 48 + .../playground/map-render/samples/welcome.xml | 48 + packages/mindplot/test/playground/utils.js | 59 - .../mindplot/test/unit/BalancedTestSuite.js | 464 +- .../mindplot/test/unit/DesignerTestSuite.js | 91 +- .../mindplot/test/unit/EventsTestSuite.js | 68 +- packages/mindplot/test/unit/FreeTestSuite.js | 435 +- .../mindplot/test/unit/SymmetricTestSuite.js | 138 +- packages/mindplot/test/unit/TestSuite.js | 4 +- .../mindplot/test/unit/lib/jquery-1.8.2.js | 18126 ++++++++-------- packages/mindplot/test/unit/simpleTest.js | 189 +- packages/mindplot/webpack.common.js | 52 +- packages/mindplot/webpack.dev.js | 16 +- packages/mindplot/webpack.playground.js | 46 +- packages/mindplot/webpack.prod.js | 14 +- packages/web2d/.eslintignore | 4 + packages/web2d/.eslintrc.json | 28 +- packages/web2d/.gitignore | 4 + packages/web2d/README.md | 2 +- packages/web2d/__tests__/web2d.test.js | 6 +- packages/web2d/babel.config.json | 4 +- packages/web2d/cypress.json | 4 + .../cypress/integration/playground.test.js | 12 + packages/web2d/cypress/plugins/index.js | 24 + .../playground.test.js/Arrow.snap.png | Bin 0 -> 28200 bytes .../playground.test.js/Curved Line.snap.png | Bin 0 -> 39122 bytes .../playground.test.js/Events.snap.png | Bin 0 -> 164754 bytes .../playground.test.js/Font.snap.png | Bin 0 -> 129009 bytes .../playground.test.js/Group.snap.png | Bin 0 -> 333925 bytes .../playground.test.js/Line.snap.png | Bin 0 -> 38473 bytes .../playground.test.js/Poly Line.snap.png | Bin 0 -> 28657 bytes .../playground.test.js/Prototype.snap.png | Bin 0 -> 48428 bytes .../playground.test.js/Rect.snap.png | Bin 0 -> 43939 bytes .../playground.test.js/Shapes.snap.png | Bin 0 -> 30408 bytes .../playground.test.js/Text.snap.png | Bin 0 -> 45202 bytes .../playground.test.js/Workspace.snap.png | Bin 0 -> 276269 bytes packages/web2d/cypress/support/commands.js | 29 + packages/web2d/cypress/support/index.js | 20 + packages/web2d/jsconfig.json | 13 + packages/web2d/lib/components/Issues.txt | 17 - .../components/peer/utils/TransformUtils.js | 38 - packages/web2d/lib/web2d.js | 75 - packages/web2d/package.json | 30 +- .../web2d/{lib => src}/components/Arrow.js | 6 +- .../{lib => src}/components/CurvedLine.js | 21 +- .../web2d/{lib => src}/components/Element.js | 55 +- .../web2d/{lib => src}/components/Elipse.js | 11 +- .../web2d/{lib => src}/components/Font.js | 8 +- .../web2d/{lib => src}/components/Group.js | 34 +- .../web2d/{lib => src}/components/Image.js | 4 +- .../web2d/{lib => src}/components/Line.js | 4 +- .../web2d/{lib => src}/components/Point.js | 11 +- .../web2d/{lib => src}/components/PolyLine.js | 34 +- .../web2d/{lib => src}/components/Rect.js | 11 +- .../web2d/{lib => src}/components/Text.js | 12 +- .../web2d/{lib => src}/components/Toolkit.js | 35 +- .../{lib => src}/components/Workspace.js | 28 +- .../lib => web2d/src/components}/header.js | 7 +- .../components/peer/svg/ArialFont.js | 2 +- .../components/peer/svg/ArrowPeer.js | 51 +- .../components/peer/svg/CurvedLinePeer.js | 92 +- .../components/peer/svg/ElementPeer.js | 69 +- .../components/peer/svg/ElipsePeer.js | 21 +- .../{lib => src}/components/peer/svg/Font.js | 33 +- .../components/peer/svg/GroupPeer.js | 77 +- .../components/peer/svg/ImagePeer.js | 2 +- .../components/peer/svg/LinePeer.js | 14 +- .../components/peer/svg/PolyLinePeer.js | 56 +- .../components/peer/svg/RectPeer.js | 17 +- .../components/peer/svg/TahomaFont.js | 2 +- .../components/peer/svg/TextPeer.js | 42 +- .../components/peer/svg/TimesFont.js | 4 +- .../components/peer/svg/VerdanaFont.js | 2 +- .../components/peer/svg/WorkspacePeer.js | 33 +- .../components/peer/utils/EventUtils.js | 7 +- .../components/peer/utils/PolyLineUtils.js | 30 + .../components/peer/utils/TransformUtils.js | 36 + packages/web2d/src/web2d.js | 80 + packages/web2d/test/playground/arrow.html | 4 +- .../web2d/test/playground/context-loader.js | 6 +- .../web2d/test/playground/curvedLine.html | 8 +- packages/web2d/test/playground/events.html | 2 +- packages/web2d/test/playground/index.html | 24 +- packages/web2d/test/playground/text.html | 3 +- packages/web2d/test/playground/utils.js | 119 +- packages/web2d/test/playground/workspace.html | 11 +- packages/web2d/webpack.common.js | 20 +- packages/web2d/webpack.playground.js | 107 +- packages/web2d/webpack.prod.js | 12 +- packages/webapp/.gitignore | 3 +- packages/webapp/cypress/README.md | 10 +- .../webapp/cypress/integration/maps.test.ts | 5 + packages/webapp/cypress/plugins/index.ts | 3 + .../maps.test.ts/maps-create.snap.png | Bin 0 -> 62134 bytes .../snapshots/maps.test.ts/maps.snap.png | Bin 0 -> 55703 bytes packages/webapp/cypress/support/commands.ts | 3 + packages/webapp/package.json | 12 +- packages/webcomponent/README.md | 2 +- .../__tests__/webcomponent.test.js | 2 +- packages/webcomponent/package.json | 10 +- packages/webcomponent/src/App.tsx | 2 +- webpack.common.js | 7 + yarn.lock | 2138 +- 725 files changed, 29640 insertions(+), 15221 deletions(-) create mode 100644 README.md rename {packages/mindplot/lib/components/libraries/underscorejs => libraries}/underscore-min.js (100%) create mode 100644 packages/core-js/jsconfig.json delete mode 100644 packages/core-js/lib/core.js rename packages/core-js/{lib => src}/Functions.js (56%) rename packages/core-js/{lib => src}/Utils.js (94%) create mode 100644 packages/core-js/src/core.js create mode 100644 packages/mindplot/.eslintignore create mode 100644 packages/mindplot/.gitignore create mode 100644 packages/mindplot/cypress.json create mode 100644 packages/mindplot/cypress/integration/playground.test.js create mode 100644 packages/mindplot/cypress/plugins/index.js create mode 100644 packages/mindplot/cypress/snapshots/playground.test.js/layout.snap.png create mode 100644 packages/mindplot/cypress/snapshots/playground.test.js/viewmode.snap.png create mode 100644 packages/mindplot/cypress/support/commands.js create mode 100644 packages/mindplot/cypress/support/index.js create mode 100644 packages/mindplot/jsconfig.json delete mode 100644 packages/mindplot/lib/components/IconGroup.js delete mode 100644 packages/mindplot/lib/components/MainTopic.js delete mode 100644 packages/mindplot/lib/components/commands/AddFeatureToTopicCommand.js delete mode 100644 packages/mindplot/lib/components/commands/index.js delete mode 100644 packages/mindplot/lib/components/index.js delete mode 100644 packages/mindplot/lib/components/layout/index.js delete mode 100644 packages/mindplot/lib/components/model/index.js delete mode 100644 packages/mindplot/lib/components/persistence/index.js delete mode 100644 packages/mindplot/lib/components/util/index.js delete mode 100644 packages/mindplot/lib/components/widget/index.js delete mode 100644 packages/mindplot/lib/mindplot.js rename packages/mindplot/{lib => src}/components/.gitignore (100%) rename packages/mindplot/{lib => src}/components/ActionDispatcher.js (66%) rename packages/mindplot/{lib => src}/components/ActionIcon.js (97%) rename packages/mindplot/{lib => src}/components/CentralTopic.js (85%) rename packages/mindplot/{lib => src}/components/Command.js (100%) rename packages/mindplot/{lib => src}/components/ConnectionLine.js (91%) rename packages/mindplot/{lib => src}/components/ControlPoint.js (79%) rename packages/mindplot/{lib => src}/components/Designer.js (93%) rename packages/mindplot/{lib => src}/components/DesignerActionRunner.js (93%) rename packages/mindplot/{lib => src}/components/DesignerKeyboard.js (97%) rename packages/mindplot/{lib => src}/components/DesignerModel.js (99%) rename packages/mindplot/{lib => src}/components/DesignerUndoManager.js (100%) rename packages/mindplot/{lib => src}/components/DragConnector.js (100%) rename packages/mindplot/{lib => src}/components/DragManager.js (98%) rename packages/mindplot/{lib => src}/components/DragPivot.js (89%) rename packages/mindplot/{lib => src}/components/DragTopic.js (90%) create mode 100644 packages/mindplot/src/components/DragTopicConfig.js rename packages/mindplot/{lib => src}/components/EditorOptions.js (100%) rename packages/mindplot/{lib => src}/components/EditorProperties.js (100%) rename packages/mindplot/{lib => src}/components/Events.js (100%) rename packages/mindplot/{lib => src}/components/Icon.js (95%) create mode 100644 packages/mindplot/src/components/IconGroup.js rename packages/mindplot/{lib => src}/components/ImageIcon.js (98%) rename packages/mindplot/{lib => src}/components/Keyboard.js (100%) rename packages/mindplot/{lib => src}/components/LinkIcon.js (92%) rename packages/mindplot/{lib => src}/components/LocalStorageManager.js (96%) create mode 100644 packages/mindplot/src/components/MainTopic.js rename packages/mindplot/{lib => src}/components/Messages.js (69%) rename packages/mindplot/{lib => src}/components/MultilineTextEditor.js (98%) rename packages/mindplot/{lib => src}/components/NodeGraph.js (74%) create mode 100644 packages/mindplot/src/components/NodeGraphUtils.js rename packages/mindplot/{lib => src}/components/NoteIcon.js (85%) rename packages/mindplot/{lib => src}/components/Options.js (100%) rename packages/mindplot/{lib => src}/components/PersistenceManager.js (84%) rename packages/mindplot/{lib => src}/components/Relationship.js (89%) rename packages/mindplot/{lib => src}/components/RelationshipPivot.js (90%) rename packages/mindplot/{lib => src}/components/RestPersistenceManager.js (98%) rename packages/mindplot/{lib => src}/components/ScreenManager.js (86%) rename packages/mindplot/{lib => src}/components/ShrinkConnector.js (86%) rename packages/mindplot/{lib => src}/components/StandaloneActionDispatcher.js (89%) rename packages/mindplot/{lib => src}/components/TextEditor.js (92%) rename packages/mindplot/{lib => src}/components/TextEditorFactory.js (95%) rename packages/mindplot/{lib => src}/components/Topic.js (94%) create mode 100644 packages/mindplot/src/components/TopicConfig.js rename packages/mindplot/{lib => src}/components/TopicEventDispatcher.js (78%) rename packages/mindplot/{lib => src}/components/TopicFeature.js (87%) rename packages/mindplot/{lib => src}/components/TopicStyle.js (61%) rename packages/mindplot/{lib => src}/components/Workspace.js (97%) create mode 100644 packages/mindplot/src/components/commands/AddFeatureToTopicCommand.js rename packages/mindplot/{lib => src}/components/commands/AddRelationshipCommand.js (97%) rename packages/mindplot/{lib => src}/components/commands/AddTopicCommand.js (84%) rename packages/mindplot/{lib => src}/components/commands/ChangeFeatureToTopicCommand.js (97%) rename packages/mindplot/{lib => src}/components/commands/DeleteCommand.js (99%) rename packages/mindplot/{lib => src}/components/commands/DragTopicCommand.js (94%) rename packages/mindplot/{lib => src}/components/commands/GenericFunctionCommand.js (97%) rename packages/mindplot/{lib => src}/components/commands/MoveControlPointCommand.js (96%) rename packages/mindplot/{lib => src}/components/commands/RemoveFeatureFromTopicCommand.js (97%) create mode 100644 packages/mindplot/src/components/commands/index.js rename packages/mindplot/{lib => src}/components/footer.js (100%) rename packages/mindplot/{lib => src}/components/header.js (100%) create mode 100644 packages/mindplot/src/components/index.js rename packages/mindplot/{lib => src}/components/layout/AbstractBasicSorter.js (94%) rename packages/mindplot/{lib => src}/components/layout/BalancedSorter.js (99%) rename packages/mindplot/{lib => src}/components/layout/ChangeEvent.js (100%) rename packages/mindplot/{lib => src}/components/layout/ChildrenSorterStrategy.js (100%) rename packages/mindplot/{lib => src}/components/layout/EventBus.js (96%) rename packages/mindplot/{lib => src}/components/layout/EventBusDispatcher.js (98%) rename packages/mindplot/{lib => src}/components/layout/GridSorter.js (97%) rename packages/mindplot/{lib => src}/components/layout/LayoutManager.js (95%) rename packages/mindplot/{lib => src}/components/layout/Node.js (100%) rename packages/mindplot/{lib => src}/components/layout/OriginalLayout.js (98%) rename packages/mindplot/{lib => src}/components/layout/RootedTreeSet.js (100%) rename packages/mindplot/{lib => src}/components/layout/SymmetricSorter.js (99%) create mode 100644 packages/mindplot/src/components/layout/index.js rename packages/mindplot/{lib => src}/components/libraries/bootstrap/BootstrapDialog.Request.js (95%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/BootstrapDialog.js (98%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap-colorpicker.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap-colorpicker.min.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap-theme.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap-theme.css.map (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap-theme.min.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap.css.map (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/css/bootstrap.min.css (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/bootstrap-colorpicker/hue.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/bootstrap-colorpicker/saturation.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/img/glyphicons-halflings-blue.png (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/js/bootstrap-colorpicker.js (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/js/bootstrap-colorpicker.min.js (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/js/bootstrap.js (100%) rename packages/mindplot/{lib => src}/components/libraries/bootstrap/js/bootstrap.min.js (100%) rename packages/mindplot/{lib => src}/components/libraries/hotkeys/jquery.hotkeys.js (100%) rename packages/mindplot/{lib => src}/components/libraries/jquery/jquery-2.1.0.js (100%) rename packages/mindplot/{lib => src}/components/libraries/jquery/jquery-2.1.0.min.js (100%) rename packages/mindplot/{lib => src}/components/libraries/jquery/jquery.mousewheel.min.js (100%) rename packages/mindplot/{lib => src}/components/libraries/less/less-1.4.2.min.js (100%) rename packages/mindplot/{lib => src}/components/libraries/less/less-1.6.2.min.js (99%) rename packages/mindplot/{lib => src}/components/libraries/mootools/mootools-core-1.4.5-full-nocompat-yc.js (100%) rename packages/mindplot/{lib => src}/components/libraries/mootools/mootools-core-1.4.5.js (100%) rename packages/mindplot/{lib => src}/components/libraries/mootools/mootools-core-1.6.0.js (100%) create mode 100644 packages/mindplot/src/components/libraries/underscorejs/underscore-min.js rename packages/mindplot/{lib => src}/components/model/FeatureModel.js (91%) rename packages/mindplot/{lib => src}/components/model/IMindmap.js (100%) rename packages/mindplot/{lib => src}/components/model/INodeModel.js (88%) rename packages/mindplot/{lib => src}/components/model/IconModel.js (96%) rename packages/mindplot/{lib => src}/components/model/LinkModel.js (97%) rename packages/mindplot/{lib => src}/components/model/Mindmap.js (94%) rename packages/mindplot/{lib => src}/components/model/NodeModel.js (98%) rename packages/mindplot/{lib => src}/components/model/NoteModel.js (96%) rename packages/mindplot/{lib => src}/components/model/RelationshipModel.js (92%) create mode 100644 packages/mindplot/src/components/model/index.js rename packages/mindplot/{lib => src}/components/persistence/Beta2PelaMigrator.js (93%) rename packages/mindplot/{lib => src}/components/persistence/ModelCodeName.js (100%) rename packages/mindplot/{lib => src}/components/persistence/Pela2TangoMigrator.js (95%) rename packages/mindplot/{lib => src}/components/persistence/XMLSerializerFactory.js (87%) rename packages/mindplot/{lib => src}/components/persistence/XMLSerializer_Beta.js (87%) rename packages/mindplot/{lib => src}/components/persistence/XMLSerializer_Pela.js (94%) rename packages/mindplot/{lib => src}/components/persistence/XMLSerializer_Tango.js (94%) create mode 100644 packages/mindplot/src/components/persistence/index.js rename packages/mindplot/{lib => src}/components/util/FadeEffect.js (96%) rename packages/mindplot/{lib => src}/components/util/Shape.js (80%) create mode 100644 packages/mindplot/src/components/util/index.js rename packages/mindplot/{lib => src}/components/widget/ColorPalettePanel.js (98%) rename packages/mindplot/{lib => src}/components/widget/FloatingTip.js (94%) rename packages/mindplot/{lib => src}/components/widget/FontFamilyPanel.js (95%) rename packages/mindplot/{lib => src}/components/widget/FontSizePanel.js (95%) rename packages/mindplot/{lib => src}/components/widget/IMenu.js (97%) rename packages/mindplot/{lib => src}/components/widget/IconPanel.js (94%) rename packages/mindplot/{lib => src}/components/widget/KeyboardShortcutTooltip.js (97%) rename packages/mindplot/{lib => src}/components/widget/LinkEditor.js (98%) rename packages/mindplot/{lib => src}/components/widget/LinkIconTooltip.js (95%) rename packages/mindplot/{lib => src}/components/widget/ListToolbarPanel.js (96%) rename packages/mindplot/{lib => src}/components/widget/Menu.js (96%) rename packages/mindplot/{lib => src}/components/widget/ModalDialogNotifier.js (100%) rename packages/mindplot/{lib => src}/components/widget/NoteEditor.js (96%) rename packages/mindplot/{lib => src}/components/widget/ToolbarItem.js (97%) rename packages/mindplot/{lib => src}/components/widget/ToolbarNotifier.js (100%) rename packages/mindplot/{lib => src}/components/widget/ToolbarPaneItem.js (96%) rename packages/mindplot/{lib => src}/components/widget/TopicShapePanel.js (96%) rename packages/mindplot/{lib => src}/components/widget/colorPalette.css (100%) rename packages/mindplot/{lib => src}/components/widget/colorPalette.html (100%) create mode 100644 packages/mindplot/src/components/widget/index.js create mode 100644 packages/mindplot/src/mindplot.js delete mode 100644 packages/mindplot/test/playground/BalancedTestSuite.js delete mode 100644 packages/mindplot/test/playground/FreeTestSuite.js delete mode 100644 packages/mindplot/test/playground/SymmetricTestSuite.js delete mode 100644 packages/mindplot/test/playground/TestSuite.js delete mode 100644 packages/mindplot/test/playground/context-loader.js create mode 100644 packages/mindplot/test/playground/layout/BalancedTestSuite.js create mode 100644 packages/mindplot/test/playground/layout/FreeTestSuite.js create mode 100644 packages/mindplot/test/playground/layout/SymmetricTestSuite.js create mode 100644 packages/mindplot/test/playground/layout/TestSuite.js create mode 100644 packages/mindplot/test/playground/layout/context-loader.js rename packages/mindplot/test/playground/{layout.html => layout/index.html} (100%) rename packages/mindplot/test/playground/{ => layout}/lib/raphael-min.js (100%) create mode 100644 packages/mindplot/test/playground/layout/lib/raphael-plugins.js rename packages/mindplot/test/playground/{ => layout}/sample.xml (100%) create mode 100755 packages/mindplot/test/playground/layout/utils.js delete mode 100644 packages/mindplot/test/playground/lib/raphael-plugins.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.Request.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap-colorpicker.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap-colorpicker.min.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap-theme.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap-theme.css.map create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap-theme.min.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap.css.map create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/css/bootstrap.min.css create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/bootstrap-colorpicker/alpha.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/bootstrap-colorpicker/hue.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/bootstrap-colorpicker/saturation.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/img/glyphicons-halflings-blue.png create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/js/bootstrap-colorpicker.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/js/bootstrap-colorpicker.min.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/js/bootstrap.js create mode 100644 packages/mindplot/test/playground/map-render/bootstrap/js/bootstrap.min.js create mode 100644 packages/mindplot/test/playground/map-render/css/compatibility.less create mode 100644 packages/mindplot/test/playground/map-render/css/editor.less create mode 100644 packages/mindplot/test/playground/map-render/css/embedded.less create mode 100644 packages/mindplot/test/playground/map-render/css/header.less create mode 100644 packages/mindplot/test/playground/map-render/css/toolbar.less create mode 100644 packages/mindplot/test/playground/map-render/css/widget/colorPalette.css create mode 100644 packages/mindplot/test/playground/map-render/css/widget/colorPalette.html create mode 100644 packages/mindplot/test/playground/map-render/css/widget/skin2.less create mode 100644 packages/mindplot/test/playground/map-render/html/container.html create mode 100644 packages/mindplot/test/playground/map-render/html/container.json create mode 100644 packages/mindplot/test/playground/map-render/html/drag.html create mode 100644 packages/mindplot/test/playground/map-render/html/editor.html create mode 100644 packages/mindplot/test/playground/map-render/html/embedded.html create mode 100644 packages/mindplot/test/playground/map-render/html/viewmode.html create mode 100644 packages/mindplot/test/playground/map-render/icons/arrow_down.gif create mode 100755 packages/mindplot/test/playground/map-render/icons/arrow_down.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrow_left.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrow_merge.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrow_right.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrow_up.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrowc_rotate_anticlockwise.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrowc_rotate_clockwise.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrowc_turn_left.png create mode 100755 packages/mindplot/test/playground/map-render/icons/arrowc_turn_right.png create mode 100755 packages/mindplot/test/playground/map-render/icons/bomb.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bulb_light_off.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bulb_light_on.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_black.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_blue.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_green.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_orange.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_pink.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_purple.png create mode 100644 packages/mindplot/test/playground/map-render/icons/bullet_red.png create mode 100755 packages/mindplot/test/playground/map-render/icons/chart_bar.png create mode 100755 packages/mindplot/test/playground/map-render/icons/chart_curve.png create mode 100755 packages/mindplot/test/playground/map-render/icons/chart_line.png create mode 100755 packages/mindplot/test/playground/map-render/icons/chart_organisation.png create mode 100755 packages/mindplot/test/playground/map-render/icons/chart_pie.png create mode 100644 packages/mindplot/test/playground/map-render/icons/close.png create mode 100644 packages/mindplot/test/playground/map-render/icons/conn_connect.png create mode 100644 packages/mindplot/test/playground/map-render/icons/conn_disconnect.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_crying.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_plain.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_sad.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_smile-big.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_smile.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_surprise.png create mode 100644 packages/mindplot/test/playground/map-render/icons/face_wink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_blue.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_green.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_orange.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_pink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_purple.png create mode 100755 packages/mindplot/test/playground/map-render/icons/flag_yellow.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_angel.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_devilish.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_glasses.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_grin.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_kiss.png create mode 100644 packages/mindplot/test/playground/map-render/icons/funy_monkey.png create mode 100755 packages/mindplot/test/playground/map-render/icons/gener_female.png create mode 100755 packages/mindplot/test/playground/map-render/icons/gener_male.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_cd.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_computer.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_controller.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_drive_cd.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_driver_disk.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_ipod.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_keyboard.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_mouse.png create mode 100755 packages/mindplot/test/playground/map-render/icons/hard_printer.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/add.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_down.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_left.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_merge.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_right.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_rotate_anticlockwise.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_rotate_clockwise.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_turn_left.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_turn_right.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/arrow_up.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/backColor.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/balloon.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bin.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/black-keyboard.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bold.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/borderColor.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_black.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_blue.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_green.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_orange.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_pink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_purple.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/bullet_red.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/chart_bar.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/chart_curve.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/chart_line.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/chart_organisation.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/chart_pie.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/clock.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/clock_red.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/close.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/coins.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/collab_publish.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/collab_share.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/collab_tag.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/color_swatch.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/comment.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/connect.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/cross.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/delNode.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/delete.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/disconnect.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-angel.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-crying.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-devilish.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-glasses.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-grin.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-kiss.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-monkey.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-plain.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-sad.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-smile-big.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-smile.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-surprise.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/face-wink.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_export.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_printer.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_redo.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_redo_dis.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_undo.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/file_undo_dis.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_blue.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_green.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_orange.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_pink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_purple.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/flag_yellow.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/font.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/fontColor.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/fontSize.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/font_bold.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/font_color.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/font_italic.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/font_size.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/font_type.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/group.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/group2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/group_go.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/help.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/history.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/info.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/italic.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/key.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/lightbulb.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/lightbulb_off.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/links.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/lock.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/lock_open.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/logo-big.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/logo-vsmall.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/logo-vvsmall.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/marca-vsmall.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/money.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/money_dollar.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/money_euro.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/money_pound.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/money_yen.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/moor_boverlay.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/moor_slider.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/moor_woverlay.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/move.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/mymaps.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/node_add.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/node_border.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/node_border2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/node_elipse.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/note.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/note1.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/page_delete.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/page_go.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/printer.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/removeUser.jpeg create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/ruby.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/save.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/search.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/search2.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/search3.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/seast.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/shape-elipse.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/shape-line.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/shape-rectangle-rounded.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/shape-rectangle.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/shape.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/shape_handles.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/shape_square_add.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/shape_square_delete.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/shape_square_edit.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/signUpBodyBtn.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/signUpEndBtn.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/signUpStartBtn.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/sne.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/snorth.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/snw.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/sse.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/ssouth.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/ssw.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/swest.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_blue.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_blue_add.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_blue_add2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_green.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_orange.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_pink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_purple.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_red.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tag_yellow.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/text_bold.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/text_italic.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/thumb_down.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/thumb_up.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/tick.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/user_delete.png create mode 100644 packages/mindplot/test/playground/map-render/icons/legacy/waring_icon.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/world.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/world2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/world_go.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/world_link.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/zoom_in.png create mode 100755 packages/mindplot/test/playground/map-render/icons/legacy/zoom_out.png create mode 100755 packages/mindplot/test/playground/map-render/icons/lock_close.png create mode 100755 packages/mindplot/test/playground/map-render/icons/lock_open.png create mode 100755 packages/mindplot/test/playground/map-render/icons/mail_edit.png create mode 100755 packages/mindplot/test/playground/map-render/icons/mail_envelop.png create mode 100755 packages/mindplot/test/playground/map-render/icons/mail_list.png create mode 100755 packages/mindplot/test/playground/map-render/icons/mail_mailbox.png create mode 100644 packages/mindplot/test/playground/map-render/icons/money_coins.png create mode 100755 packages/mindplot/test/playground/map-render/icons/money_dollar.png create mode 100755 packages/mindplot/test/playground/map-render/icons/money_euro.png create mode 100755 packages/mindplot/test/playground/map-render/icons/money_money.png create mode 100755 packages/mindplot/test/playground/map-render/icons/money_pound.png create mode 100644 packages/mindplot/test/playground/map-render/icons/money_ruby.png create mode 100755 packages/mindplot/test/playground/map-render/icons/money_yen.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_1.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_3.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_4.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_5.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_6.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_7.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_8.png create mode 100755 packages/mindplot/test/playground/map-render/icons/number_9.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_bell.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_cake.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_camera.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_clanbomber.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_clip.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_house.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_key.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_magnifier.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_music.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_palette.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_pencil.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_phone.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_rainbow.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_star.png create mode 100755 packages/mindplot/test/playground/map-render/icons/object_wizard.png create mode 100644 packages/mindplot/test/playground/map-render/icons/onoff_add.png create mode 100644 packages/mindplot/test/playground/map-render/icons/onoff_clock.png create mode 100644 packages/mindplot/test/playground/map-render/icons/onoff_clock_red.png create mode 100644 packages/mindplot/test/playground/map-render/icons/onoff_delete.png create mode 100755 packages/mindplot/test/playground/map-render/icons/onoff_status_offline.png create mode 100755 packages/mindplot/test/playground/map-render/icons/onoff_status_online.png create mode 100755 packages/mindplot/test/playground/map-render/icons/people_female1.png create mode 100755 packages/mindplot/test/playground/map-render/icons/people_female2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/people_group.png create mode 100755 packages/mindplot/test/playground/map-render/icons/people_male1.png create mode 100755 packages/mindplot/test/playground/map-render/icons/people_male2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_cancel.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_closed.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_exclamation.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_help.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_info.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_stop.png create mode 100755 packages/mindplot/test/playground/map-render/icons/sign_warning.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_bug.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_cursor.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_database.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_database_table.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_feed.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_folder_explore.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_penguin.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_rss.png create mode 100755 packages/mindplot/test/playground/map-render/icons/soft_stuff_folder.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_basketball.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_football.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_golf.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_raquet.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_shuttlecock.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_soccer.png create mode 100644 packages/mindplot/test/playground/map-render/icons/sport_tennis.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_blue.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_blue_add.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_blue_add2.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_green.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_orange.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_pink.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_purple.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_red.png create mode 100755 packages/mindplot/test/playground/map-render/icons/tag_yellow.png create mode 100755 packages/mindplot/test/playground/map-render/icons/task_0.png create mode 100755 packages/mindplot/test/playground/map-render/icons/task_100.png create mode 100755 packages/mindplot/test/playground/map-render/icons/task_25.png create mode 100755 packages/mindplot/test/playground/map-render/icons/task_50.png create mode 100755 packages/mindplot/test/playground/map-render/icons/task_75.png create mode 100755 packages/mindplot/test/playground/map-render/icons/thumb_thumb_down.png create mode 100755 packages/mindplot/test/playground/map-render/icons/thumb_thumb_up.png create mode 100644 packages/mindplot/test/playground/map-render/icons/tick_cross.png create mode 100644 packages/mindplot/test/playground/map-render/icons/tick_tick.png create mode 100755 packages/mindplot/test/playground/map-render/icons/time_calendar.png create mode 100755 packages/mindplot/test/playground/map-render/icons/time_clock.png create mode 100755 packages/mindplot/test/playground/map-render/icons/time_hourglass.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_clear-night.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_clear.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_few-clouds-night.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_few-clouds.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_overcast.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_severe-alert.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_showers-scattered.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_showers.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_snow.png create mode 100644 packages/mindplot/test/playground/map-render/icons/weather_storm.png create mode 100644 packages/mindplot/test/playground/map-render/images/ajax-loader.gif create mode 100644 packages/mindplot/test/playground/map-render/images/alert-sign.png create mode 100644 packages/mindplot/test/playground/map-render/images/btn-bg-hover.png create mode 100644 packages/mindplot/test/playground/map-render/images/btn-bg-normal.png create mode 100644 packages/mindplot/test/playground/map-render/images/btne-bg-hover.png create mode 100644 packages/mindplot/test/playground/map-render/images/btne-bg-normal.png create mode 100644 packages/mindplot/test/playground/map-render/images/btne-bg-selected.png create mode 100644 packages/mindplot/test/playground/map-render/images/discard.png create mode 100644 packages/mindplot/test/playground/map-render/images/editortoolbar.png create mode 100644 packages/mindplot/test/playground/map-render/images/export.png create mode 100644 packages/mindplot/test/playground/map-render/images/favicon.ico create mode 100644 packages/mindplot/test/playground/map-render/images/font-bold.png create mode 100644 packages/mindplot/test/playground/map-render/images/font-color.png create mode 100644 packages/mindplot/test/playground/map-render/images/font-italic.png create mode 100644 packages/mindplot/test/playground/map-render/images/font-size.png create mode 100644 packages/mindplot/test/playground/map-render/images/font-type.png create mode 100644 packages/mindplot/test/playground/map-render/images/history.png create mode 100644 packages/mindplot/test/playground/map-render/images/links.png create mode 100644 packages/mindplot/test/playground/map-render/images/logo-135x135.png create mode 100644 packages/mindplot/test/playground/map-render/images/logo-head-only.png create mode 100644 packages/mindplot/test/playground/map-render/images/logo-medium.png create mode 100644 packages/mindplot/test/playground/map-render/images/logo-small.png create mode 100644 packages/mindplot/test/playground/map-render/images/logo-xsmall.png create mode 100644 packages/mindplot/test/playground/map-render/images/notes.png create mode 100644 packages/mindplot/test/playground/map-render/images/print.png create mode 100644 packages/mindplot/test/playground/map-render/images/public.png create mode 100644 packages/mindplot/test/playground/map-render/images/redo.png create mode 100644 packages/mindplot/test/playground/map-render/images/save.png create mode 100644 packages/mindplot/test/playground/map-render/images/shape-circle.png create mode 100644 packages/mindplot/test/playground/map-render/images/shape-line.png create mode 100644 packages/mindplot/test/playground/map-render/images/shape-rectangle-round.png create mode 100644 packages/mindplot/test/playground/map-render/images/shape-rectangle.png create mode 100644 packages/mindplot/test/playground/map-render/images/share.png create mode 100644 packages/mindplot/test/playground/map-render/images/tag.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-add.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-border.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-color.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-delete.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-icon.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-link.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-note.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-relation.png create mode 100644 packages/mindplot/test/playground/map-render/images/topic-shape.png create mode 100644 packages/mindplot/test/playground/map-render/images/undo.png create mode 100644 packages/mindplot/test/playground/map-render/images/zoom-in.png create mode 100644 packages/mindplot/test/playground/map-render/images/zoom-out.png create mode 100644 packages/mindplot/test/playground/map-render/index.html create mode 100644 packages/mindplot/test/playground/map-render/js/bootstrap.js create mode 100644 packages/mindplot/test/playground/map-render/js/editor.js create mode 120000 packages/mindplot/test/playground/map-render/js/jquery.js create mode 100644 packages/mindplot/test/playground/map-render/samples/complex.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/emptyNodes.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/huge.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/issue.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/sample2.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/sample3.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/sample4.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/welcome-reloaded.xml create mode 100644 packages/mindplot/test/playground/map-render/samples/welcome.xml delete mode 100755 packages/mindplot/test/playground/utils.js create mode 100644 packages/web2d/.eslintignore create mode 100644 packages/web2d/cypress.json create mode 100644 packages/web2d/cypress/integration/playground.test.js create mode 100644 packages/web2d/cypress/plugins/index.js create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Arrow.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Curved Line.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Events.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Font.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Group.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Line.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Poly Line.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Prototype.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Rect.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Shapes.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Text.snap.png create mode 100644 packages/web2d/cypress/snapshots/playground.test.js/Workspace.snap.png create mode 100644 packages/web2d/cypress/support/commands.js create mode 100644 packages/web2d/cypress/support/index.js create mode 100644 packages/web2d/jsconfig.json delete mode 100644 packages/web2d/lib/components/Issues.txt delete mode 100644 packages/web2d/lib/components/peer/utils/TransformUtils.js delete mode 100644 packages/web2d/lib/web2d.js rename packages/web2d/{lib => src}/components/Arrow.js (94%) rename packages/web2d/{lib => src}/components/CurvedLine.js (84%) rename packages/web2d/{lib => src}/components/Element.js (88%) rename packages/web2d/{lib => src}/components/Elipse.js (87%) rename packages/web2d/{lib => src}/components/Font.js (86%) rename packages/web2d/{lib => src}/components/Group.js (83%) rename packages/web2d/{lib => src}/components/Image.js (92%) rename packages/web2d/{lib => src}/components/Line.js (95%) rename packages/web2d/{lib => src}/components/Point.js (86%) rename packages/web2d/{lib => src}/components/PolyLine.js (61%) rename packages/web2d/{lib => src}/components/Rect.js (89%) rename packages/web2d/{lib => src}/components/Text.js (88%) rename packages/web2d/{lib => src}/components/Toolkit.js (61%) rename packages/web2d/{lib => src}/components/Workspace.js (88%) rename packages/{core-js/lib => web2d/src/components}/header.js (91%) rename packages/web2d/{lib => src}/components/peer/svg/ArialFont.js (96%) rename packages/web2d/{lib => src}/components/peer/svg/ArrowPeer.js (62%) rename packages/web2d/{lib => src}/components/peer/svg/CurvedLinePeer.js (59%) rename packages/web2d/{lib => src}/components/peer/svg/ElementPeer.js (75%) rename packages/web2d/{lib => src}/components/peer/svg/ElipsePeer.js (80%) rename packages/web2d/{lib => src}/components/peer/svg/Font.js (67%) rename packages/web2d/{lib => src}/components/peer/svg/GroupPeer.js (61%) rename packages/web2d/{lib => src}/components/peer/svg/ImagePeer.js (96%) rename packages/web2d/{lib => src}/components/peer/svg/LinePeer.js (83%) rename packages/web2d/{lib => src}/components/peer/svg/PolyLinePeer.js (62%) rename packages/web2d/{lib => src}/components/peer/svg/RectPeer.js (80%) rename packages/web2d/{lib => src}/components/peer/svg/TahomaFont.js (96%) rename packages/web2d/{lib => src}/components/peer/svg/TextPeer.js (81%) rename packages/web2d/{lib => src}/components/peer/svg/TimesFont.js (94%) rename packages/web2d/{lib => src}/components/peer/svg/VerdanaFont.js (96%) rename packages/web2d/{lib => src}/components/peer/svg/WorkspacePeer.js (72%) rename packages/web2d/{lib => src}/components/peer/utils/EventUtils.js (88%) create mode 100644 packages/web2d/src/components/peer/utils/PolyLineUtils.js create mode 100644 packages/web2d/src/components/peer/utils/TransformUtils.js create mode 100644 packages/web2d/src/web2d.js create mode 100644 packages/webapp/cypress/snapshots/maps.test.ts/maps-create.snap.png create mode 100644 packages/webapp/cypress/snapshots/maps.test.ts/maps.snap.png create mode 100644 webpack.common.js diff --git a/README.md b/README.md new file mode 100644 index 00000000..37f36d8b --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# wisemapping-frontend + +This monorepo uses lerna and contains all the packages that compose the wisemapping frontend. + +This is a WIP migration from [legacy wisemapping](https://bitbucket.org/wisemapping/wisemapping-open-source/) into a modern web development project with multiple improvements. + +`nvm use` +`yarn install` +`yarn bootstrap` +`yarn run build` diff --git a/libraries/mootools-core-1.4.5.js b/libraries/mootools-core-1.4.5.js index 9eb4e843..32a26b11 100644 --- a/libraries/mootools-core-1.4.5.js +++ b/libraries/mootools-core-1.4.5.js @@ -16,61 +16,787 @@ ... */ -(function(){this.MooTools={version:"1.4.5",build:"ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family(); -}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments"; -}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor; - while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null; -}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this; - return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]); - }}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments; -}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w>>0; - b>>0;b>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a>>0,b=Array(d);for(var a=0;a>>0; - b-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,""); -},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); -});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase(); -});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g); - return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1); -}return(a[c]!=null)?a[c]:"";});}}); -Function.implement({bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype;g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this;if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b);},}); -Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments))); -};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h}; -}var g=function(){e(this);if(g.$prototyping){return this;}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null; - return i;}.extend(this).implement(h);g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.'); -}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments); -};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone(); - break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.'); -}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h}); - return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this; -}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping; - return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j;for(var i in h){f.call(this,i,h[i],true);}},this);}};})(); \ No newline at end of file +(function () { + this.MooTools = { version: '1.4.5', build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0' }; + var o = (this.typeOf = function (i) { + if (i == null) { + return 'null'; + } + if (i.$family != null) { + return i.$family(); + } + if (i.nodeName) { + if (i.nodeType == 1) { + return 'element'; + } + if (i.nodeType == 3) { + return /\S/.test(i.nodeValue) ? 'textnode' : 'whitespace'; + } + } else { + if (typeof i.length == 'number') { + if (i.callee) { + return 'arguments'; + } + if ('item' in i) { + return 'collection'; + } + } + } + return typeof i; + }); + var j = (this.instanceOf = function (t, i) { + if (t == null) { + return false; + } + var s = t.$constructor || t.constructor; + while (s) { + if (s === i) { + return true; + } + s = s.parent; + } + if (!t.hasOwnProperty) { + return false; + } + return t instanceof i; + }); + var f = this.Function; + var p = true; + for (var k in { toString: 1 }) { + p = null; + } + if (p) { + p = [ + 'hasOwnProperty', + 'valueOf', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'constructor', + ]; + } + f.prototype.overloadSetter = function (s) { + var i = this; + return function (u, t) { + if (u == null) { + return this; + } + if (s || typeof u != 'string') { + for (var v in u) { + i.call(this, v, u[v]); + } + if (p) { + for (var w = p.length; w--; ) { + v = p[w]; + if (u.hasOwnProperty(v)) { + i.call(this, v, u[v]); + } + } + } + } else { + i.call(this, u, t); + } + return this; + }; + }; + f.prototype.overloadGetter = function (s) { + var i = this; + return function (u) { + var v, t; + if (typeof u != 'string') { + v = u; + } else { + if (arguments.length > 1) { + v = arguments; + } else { + if (s) { + v = [u]; + } + } + } + if (v) { + t = {}; + for (var w = 0; w < v.length; w++) { + t[v[w]] = i.call(this, v[w]); + } + } else { + t = i.call(this, u); + } + return t; + }; + }; + f.prototype.extend = function (i, s) { + this[i] = s; + }.overloadSetter(); + f.prototype.implement = function (i, s) { + this.prototype[i] = s; + }.overloadSetter(); + var n = Array.prototype.slice; + f.from = function (i) { + return o(i) == 'function' + ? i + : function () { + return i; + }; + }; + Array.from = function (i) { + if (i == null) { + return []; + } + return a.isEnumerable(i) && typeof i != 'string' ? (o(i) == 'array' ? i : n.call(i)) : [i]; + }; + Number.from = function (s) { + var i = parseFloat(s); + return isFinite(i) ? i : null; + }; + String.from = function (i) { + return i + ''; + }; + f.implement({ + hide: function () { + this.$hidden = true; + return this; + }, + protect: function () { + this.$protected = true; + return this; + }, + }); + var a = (this.Type = function (u, t) { + if (u) { + var s = u.toLowerCase(); + var i = function (v) { + return o(v) == s; + }; + a['is' + u] = i; + if (t != null) { + t.prototype.$family = function () { + return s; + }.hide(); + } + } + if (t == null) { + return null; + } + t.extend(this); + t.$constructor = a; + t.prototype.$constructor = t; + return t; + }); + var e = Object.prototype.toString; + a.isEnumerable = function (i) { + return i != null && typeof i.length == 'number' && e.call(i) != '[object Function]'; + }; + var q = {}; + var r = function (i) { + var s = o(i.prototype); + return q[s] || (q[s] = []); + }; + var b = function (t, x) { + if (x && x.$hidden) { + return; + } + var s = r(this); + for (var u = 0; u < s.length; u++) { + var w = s[u]; + if (o(w) == 'type') { + b.call(w, t, x); + } else { + w.call(this, t, x); + } + } + var v = this.prototype[t]; + if (v == null || !v.$protected) { + this.prototype[t] = x; + } + if (this[t] == null && o(x) == 'function') { + m.call(this, t, function (i) { + return x.apply(i, n.call(arguments, 1)); + }); + } + }; + var m = function (i, t) { + if (t && t.$hidden) { + return; + } + var s = this[i]; + if (s == null || !s.$protected) { + this[i] = t; + } + }; + a.implement({ + implement: b.overloadSetter(), + extend: m.overloadSetter(), + alias: function (i, s) { + b.call(this, i, this.prototype[s]); + }.overloadSetter(), + mirror: function (i) { + r(this).push(i); + return this; + }, + }); + new a('Type', a); + var d = function (s, x, v) { + var u = x != Object, + B = x.prototype; + if (u) { + x = new a(s, x); + } + for (var y = 0, w = v.length; y < w; y++) { + var C = v[y], + A = x[C], + z = B[C]; + if (A) { + A.protect(); + } + if (u && z) { + x.implement(C, z.protect()); + } + } + if (u) { + var t = B.propertyIsEnumerable(v[0]); + x.forEachMethod = function (G) { + if (!t) { + for (var F = 0, D = v.length; F < D; F++) { + G.call(B, B[v[F]], v[F]); + } + } + for (var E in B) { + G.call(B, B[E], E); + } + }; + } + return d; + }; + d('String', String, [ + 'charAt', + 'charCodeAt', + 'concat', + 'indexOf', + 'lastIndexOf', + 'match', + 'quote', + 'replace', + 'search', + 'slice', + 'split', + 'substr', + 'substring', + 'trim', + 'toLowerCase', + 'toUpperCase', + ])('Array', Array, [ + 'pop', + 'push', + 'reverse', + 'shift', + 'sort', + 'splice', + 'unshift', + 'concat', + 'join', + 'slice', + 'indexOf', + 'lastIndexOf', + 'filter', + 'forEach', + 'every', + 'map', + 'some', + 'reduce', + 'reduceRight', + ])('Number', Number, ['toExponential', 'toFixed', 'toLocaleString', 'toPrecision'])( + 'Function', + f, + ['apply', 'call', 'bind'] + )('RegExp', RegExp, ['exec', 'test'])('Object', Object, [ + 'create', + 'defineProperty', + 'defineProperties', + 'keys', + 'getPrototypeOf', + 'getOwnPropertyDescriptor', + 'getOwnPropertyNames', + 'preventExtensions', + 'isExtensible', + 'seal', + 'isSealed', + 'freeze', + 'isFrozen', + ])('Date', Date, ['now']); + Object.extend = m.overloadSetter(); + Date.extend('now', function () { + return +new Date(); + }); + new a('Boolean', Boolean); + Number.prototype.$family = function () { + return isFinite(this) ? 'number' : 'null'; + }.hide(); + Number.extend('random', function (s, i) { + return Math.floor(Math.random() * (i - s + 1) + s); + }); + var g = Object.prototype.hasOwnProperty; + Object.extend('forEach', function (i, t, u) { + for (var s in i) { + if (g.call(i, s)) { + t.call(u, i[s], s, i); + } + } + }); + Object.each = Object.forEach; + Array.implement({ + forEach: function (u, v) { + for (var t = 0, s = this.length; t < s; t++) { + if (t in this) { + u.call(v, this[t], t, this); + } + } + }, + each: function (i, s) { + Array.forEach(this, i, s); + return this; + }, + }); + var l = function (i) { + switch (o(i)) { + case 'array': + return i.clone(); + case 'object': + return Object.clone(i); + default: + return i; + } + }; + Array.implement('clone', function () { + var s = this.length, + t = new Array(s); + while (s--) { + t[s] = l(this[s]); + } + return t; + }); + var h = function (s, i, t) { + switch (o(t)) { + case 'object': + if (o(s[i]) == 'object') { + Object.merge(s[i], t); + } else { + s[i] = Object.clone(t); + } + break; + case 'array': + s[i] = t.clone(); + break; + default: + s[i] = t; + } + return s; + }; + Object.extend({ + merge: function (z, u, t) { + if (o(u) == 'string') { + return h(z, u, t); + } + for (var y = 1, s = arguments.length; y < s; y++) { + var w = arguments[y]; + for (var x in w) { + h(z, x, w[x]); + } + } + return z; + }, + clone: function (i) { + var t = {}; + for (var s in i) { + t[s] = l(i[s]); + } + return t; + }, + append: function (w) { + for (var v = 1, t = arguments.length; v < t; v++) { + var s = arguments[v] || {}; + for (var u in s) { + w[u] = s[u]; + } + } + return w; + }, + }); + ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function (i) { + new a(i); + }); + var c = Date.now(); + String.extend('uniqueID', function () { + return (c++).toString(36); + }); +})(); +Array.implement({ + every: function (c, d) { + for (var b = 0, a = this.length >>> 0; b < a; b++) { + if (b in this && !c.call(d, this[b], b, this)) { + return false; + } + } + return true; + }, + filter: function (d, f) { + var c = []; + for (var e, b = 0, a = this.length >>> 0; b < a; b++) { + if (b in this) { + e = this[b]; + if (d.call(f, e, b, this)) { + c.push(e); + } + } + } + return c; + }, + indexOf: function (c, d) { + var b = this.length >>> 0; + for (var a = d < 0 ? Math.max(0, b + d) : d || 0; a < b; a++) { + if (this[a] === c) { + return a; + } + } + return -1; + }, + map: function (c, e) { + var d = this.length >>> 0, + b = Array(d); + for (var a = 0; a < d; a++) { + if (a in this) { + b[a] = c.call(e, this[a], a, this); + } + } + return b; + }, + some: function (c, d) { + for (var b = 0, a = this.length >>> 0; b < a; b++) { + if (b in this && c.call(d, this[b], b, this)) { + return true; + } + } + return false; + }, + clean: function () { + return this.filter(function (a) { + return a != null; + }); + }, + invoke: function (a) { + var b = Array.slice(arguments, 1); + return this.map(function (c) { + return c[a].apply(c, b); + }); + }, + associate: function (c) { + var d = {}, + b = Math.min(this.length, c.length); + for (var a = 0; a < b; a++) { + d[c[a]] = this[a]; + } + return d; + }, + link: function (c) { + var a = {}; + for (var e = 0, b = this.length; e < b; e++) { + for (var d in c) { + if (c[d](this[e])) { + a[d] = this[e]; + delete c[d]; + break; + } + } + } + return a; + }, + contains: function (a, b) { + return this.indexOf(a, b) != -1; + }, + append: function (a) { + this.push.apply(this, a); + return this; + }, + getLast: function () { + return this.length ? this[this.length - 1] : null; + }, + getRandom: function () { + return this.length ? this[Number.random(0, this.length - 1)] : null; + }, + include: function (a) { + if (!this.contains(a)) { + this.push(a); + } + return this; + }, + combine: function (c) { + for (var b = 0, a = c.length; b < a; b++) { + this.include(c[b]); + } + return this; + }, + erase: function (b) { + for (var a = this.length; a--; ) { + if (this[a] === b) { + this.splice(a, 1); + } + } + return this; + }, + empty: function () { + this.length = 0; + return this; + }, + flatten: function () { + var d = []; + for (var b = 0, a = this.length; b < a; b++) { + var c = typeOf(this[b]); + if (c == 'null') { + continue; + } + d = d.concat( + c == 'array' || c == 'collection' || c == 'arguments' || instanceOf(this[b], Array) + ? Array.flatten(this[b]) + : this[b] + ); + } + return d; + }, + pick: function () { + for (var b = 0, a = this.length; b < a; b++) { + if (this[b] != null) { + return this[b]; + } + } + return null; + }, + rgbToHex: function (d) { + if (this.length < 3) { + return null; + } + if (this.length == 4 && this[3] == 0 && !d) { + return 'transparent'; + } + var b = []; + for (var a = 0; a < 3; a++) { + var c = (this[a] - 0).toString(16); + b.push(c.length == 1 ? '0' + c : c); + } + return d ? b : '#' + b.join(''); + }, +}); +String.implement({ + test: function (a, b) { + return (typeOf(a) == 'regexp' ? a : new RegExp('' + a, b)).test(this); + }, + contains: function (a, b) { + return b ? (b + this + b).indexOf(b + a + b) > -1 : String(this).indexOf(a) > -1; + }, + trim: function () { + return String(this).replace(/^\s+|\s+$/g, ''); + }, + clean: function () { + return String(this).replace(/\s+/g, ' ').trim(); + }, + camelCase: function () { + return String(this).replace(/-\D/g, function (a) { + return a.charAt(1).toUpperCase(); + }); + }, + hyphenate: function () { + return String(this).replace(/[A-Z]/g, function (a) { + return '-' + a.charAt(0).toLowerCase(); + }); + }, + capitalize: function () { + return String(this).replace(/\b[a-z]/g, function (a) { + return a.toUpperCase(); + }); + }, + escapeRegExp: function () { + return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + rgbToHex: function (b) { + var a = String(this).match(/\d{1,3}/g); + return a ? a.rgbToHex(b) : null; + }, + substitute: function (a, b) { + return String(this).replace(b || /\\?\{([^{}]+)\}/g, function (d, c) { + if (d.charAt(0) == '\\') { + return d.slice(1); + } + return a[c] != null ? a[c] : ''; + }); + }, +}); +Function.implement({ + bind: function (e) { + var a = this, + b = arguments.length > 1 ? Array.slice(arguments, 1) : null, + d = function () {}; + var c = function () { + var g = e, + h = arguments.length; + if (this instanceof c) { + d.prototype = a.prototype; + g = new d(); + } + var f = + !b && !h + ? a.call(g) + : a.apply(g, b && h ? b.concat(Array.slice(arguments)) : b || arguments); + return g == e ? f : g; + }; + return c; + }, + pass: function (b, c) { + var a = this; + if (b != null) { + b = Array.from(b); + } + return function () { + return a.apply(c, b || arguments); + }; + }, + delay: function (b, c, a) { + return setTimeout(this.pass(a == null ? [] : a, c), b); + }, +}); +Number.alias('each', 'times'); +(function (b) { + var a = {}; + b.each(function (c) { + if (!Number[c]) { + a[c] = function () { + return Math[c].apply(null, [this].concat(Array.from(arguments))); + }; + } + }); + Number.implement(a); +})([ + 'abs', + 'acos', + 'asin', + 'atan', + 'atan2', + 'ceil', + 'cos', + 'exp', + 'floor', + 'log', + 'max', + 'min', + 'pow', + 'sin', + 'sqrt', + 'tan', +]); +(function () { + var a = (this.Class = new Type('Class', function (h) { + if (instanceOf(h, Function)) { + h = { initialize: h }; + } + var g = function () { + e(this); + if (g.$prototyping) { + return this; + } + this.$caller = null; + var i = this.initialize ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return i; + } + .extend(this) + .implement(h); + g.$constructor = a; + g.prototype.$constructor = g; + g.prototype.parent = c; + return g; + })); + var c = function () { + if (!this.$caller) { + throw new Error('The method "parent" cannot be called.'); + } + var g = this.$caller.$name, + h = this.$caller.$owner.parent, + i = h ? h.prototype[g] : null; + if (!i) { + throw new Error('The method "' + g + '" has no parent.'); + } + return i.apply(this, arguments); + }; + var e = function (g) { + for (var h in g) { + var j = g[h]; + switch (typeOf(j)) { + case 'object': + var i = function () {}; + i.prototype = j; + g[h] = e(new i()); + break; + case 'array': + g[h] = j.clone(); + break; + } + } + return g; + }; + var b = function (g, h, j) { + if (j.$origin) { + j = j.$origin; + } + var i = function () { + if (j.$protected && this.$caller == null) { + throw new Error('The method "' + h + '" cannot be called.'); + } + var l = this.caller, + m = this.$caller; + this.caller = m; + this.$caller = i; + var k = j.apply(this, arguments); + this.$caller = m; + this.caller = l; + return k; + }.extend({ $owner: g, $origin: j, $name: h }); + return i; + }; + var f = function (h, i, g) { + if (a.Mutators.hasOwnProperty(h)) { + i = a.Mutators[h].call(this, i); + if (i == null) { + return this; + } + } + if (typeOf(i) == 'function') { + if (i.$hidden) { + return this; + } + this.prototype[h] = g ? i : b(this, h, i); + } else { + Object.merge(this.prototype, h, i); + } + return this; + }; + var d = function (g) { + g.$prototyping = true; + var h = new g(); + delete g.$prototyping; + return h; + }; + a.implement('implement', f.overloadSetter()); + a.Mutators = { + Extends: function (g) { + this.parent = g; + this.prototype = d(g); + }, + Implements: function (g) { + Array.from(g).each(function (j) { + var h = new j(); + for (var i in h) { + f.call(this, i, h[i], true); + } + }, this); + }, + }; +})(); diff --git a/packages/mindplot/lib/components/libraries/underscorejs/underscore-min.js b/libraries/underscore-min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/underscorejs/underscore-min.js rename to libraries/underscore-min.js diff --git a/package.json b/package.json index 11d5d4d0..58facaf6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "build": "lerna run build", "clean": "lerna clean && rm -rf node_modules", "lint": "lerna run lint --stream", - "test": "lerna run test --stream" + "test": "lerna run test --stream", + "test:snapshots": "lerna run test:snapshots --stream" }, "private": true, "devDependencies": { diff --git a/packages/core-js/README.md b/packages/core-js/README.md index 194e9eba..012fbd24 100644 --- a/packages/core-js/README.md +++ b/packages/core-js/README.md @@ -11,6 +11,6 @@ To build up the package core-js and use in production, you have to use command ` To start using core-js it has to be required as a module and then intanciarce as a function ``` -const coreJs = require('core-js'); +import coreJs from 'core-js'; coreJs(); ``` diff --git a/packages/core-js/__tests__/core.test.js b/packages/core-js/__tests__/core.test.js index 9ac914ca..4f505c57 100644 --- a/packages/core-js/__tests__/core.test.js +++ b/packages/core-js/__tests__/core.test.js @@ -1,6 +1,6 @@ 'use strict'; -const coreJs = require('..'); +import coreJs from '..'; describe('core-js', () => { it('needs tests'); diff --git a/packages/core-js/babel.config.json b/packages/core-js/babel.config.json index ed1f3427..3d669db0 100644 --- a/packages/core-js/babel.config.json +++ b/packages/core-js/babel.config.json @@ -13,5 +13,6 @@ } } ] - ] + ], + "sourceType": "unambiguous" } diff --git a/packages/core-js/jsconfig.json b/packages/core-js/jsconfig.json new file mode 100644 index 00000000..d7ce2a30 --- /dev/null +++ b/packages/core-js/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "module": "commonjs", + "paths": { + "@libraries/*": ["../../libraries/*"] + } + }, + "exclude": ["node_modules"] +} diff --git a/packages/core-js/lib/core.js b/packages/core-js/lib/core.js deleted file mode 100644 index bfed9fac..00000000 --- a/packages/core-js/lib/core.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -module.exports = coreJs; // eslint-disable-line - -function coreJs() { - global.core = require('./header'); // eslint-disable-line - require('./Functions'); // eslint-disable-line - require('./Utils'); // eslint-disable-line - global.Options = require('@wisemapping/mindplot/lib/components/Options'); - global.BootstrapDialog = require('@wisemapping/mindplot/lib/components/libraries/bootstrap/BootstrapDialog'); - require('@wisemapping/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.Request'); - return global.core; // eslint-disable-line no-undef -} diff --git a/packages/core-js/package.json b/packages/core-js/package.json index a8ef5089..075415ae 100644 --- a/packages/core-js/package.json +++ b/packages/core-js/package.json @@ -1,15 +1,15 @@ { - "name": "@wismapping/core-js", + "name": "@wisemapping/core-js", "version": "0.0.1", "description": "core-js", "license": "ISC", - "main": "lib/core.js", + "main": "dist/core.js", "directories": { - "lib": "lib", + "lib": "src", "test": "__tests__" }, "files": [ - "lib" + "src" ], "publishConfig": { "registry": "https://registry.yarnpkg.com" @@ -20,7 +20,7 @@ }, "scripts": { "build": "webpack --config webpack.prod.js", - "dev": "webpack --mode development" + "dev": "webpack --mode development --config webpack.dev.js" }, "devDependencies": { "@babel/core": "^7.14.6", @@ -32,7 +32,5 @@ "webpack-cli": "^4.7.2", "webpack-merge": "^5.8.0" }, - "dependencies": { - "@wisemapping/mindplot": "^0.0.1" - } -} + "dependencies": {} +} \ No newline at end of file diff --git a/packages/core-js/lib/Functions.js b/packages/core-js/src/Functions.js similarity index 56% rename from packages/core-js/lib/Functions.js rename to packages/core-js/src/Functions.js index 3252e95e..db1c1033 100644 --- a/packages/core-js/lib/Functions.js +++ b/packages/core-js/src/Functions.js @@ -6,12 +6,11 @@ obj - object to inspect */ -global.$defined = function (obj) { - return (obj != undefined); +export const $defined = function (obj) { + return obj != undefined; }; - -global.$assert = function (assert, message) { +export const $assert = function (assert, message) { if (!$defined(assert) || !assert) { logStackTrace(); console.log(message); @@ -19,32 +18,33 @@ global.$assert = function (assert, message) { } }; -Math.sign = function (value) { - return (value >= 0) ? 1 : -1; +export const sign = function (value) { + return value >= 0 ? 1 : -1; }; -function logStackTrace(exception) { - +export function logStackTrace(exception) { if (!$defined(exception)) { try { - throw Error("Unexpected Exception"); + throw Error('Unexpected Exception'); } catch (e) { exception = e; } } - var result = ""; - if (exception.stack) { //Firefox and Chrome... + var result = ''; + if (exception.stack) { + //Firefox and Chrome... result = exception.stack; - } - else if (window.opera && exception.message) { //Opera + } else if (window.opera && exception.message) { + //Opera result = exception.message; - } else { //IE and Safari - result = exception.sourceURL + ': ' + exception.line + "\n\n"; + } else { + //IE and Safari + result = exception.sourceURL + ': ' + exception.line + '\n\n'; var currentFunction = arguments.callee.caller; while (currentFunction) { var fn = currentFunction.toString(); - result = result + "\n" + fn; + result = result + '\n' + fn; currentFunction = currentFunction.caller; } } diff --git a/packages/core-js/lib/Utils.js b/packages/core-js/src/Utils.js similarity index 94% rename from packages/core-js/lib/Utils.js rename to packages/core-js/src/Utils.js index 17071d3d..f0723ca1 100644 --- a/packages/core-js/lib/Utils.js +++ b/packages/core-js/src/Utils.js @@ -16,9 +16,7 @@ * limitations under the License. */ -core.Utils = {}; - -core.Utils.innerXML = function (node) { +export const innerXML = function (node) { // summary: // Implementation of MS's innerXML function. if ($defined(node.innerXML)) { @@ -36,7 +34,7 @@ core.Utils.innerXML = function (node) { /** * Cross-browser implementation of creating an XML document object. */ -core.Utils.createDocument = function () { +export const createDocument = function () { var doc = null; if ($defined(window.ActiveXObject)) { //http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx @@ -54,4 +52,3 @@ core.Utils.createDocument = function () { return doc; }; - diff --git a/packages/core-js/src/core.js b/packages/core-js/src/core.js new file mode 100644 index 00000000..3cce5665 --- /dev/null +++ b/packages/core-js/src/core.js @@ -0,0 +1,18 @@ +import * as Functions from './Functions'; +import * as Util from './Utils'; + +export const Function = Functions; +export const Utils = Util; + +function coreJs() { + global.core = { + Function, + Utils + }; + Math.sign = Function.sign; + global.$assert = Function.$assert; + global.$defined = Function.$defined; + return global.core; +} + +export default coreJs; diff --git a/packages/core-js/webpack.common.js b/packages/core-js/webpack.common.js index 925a2a9d..7f09214a 100644 --- a/packages/core-js/webpack.common.js +++ b/packages/core-js/webpack.common.js @@ -1,12 +1,15 @@ const path = require('path'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { - entry: './lib/core.js', + entry: './src/core.js', output: { - path: path.resolve(__dirname, 'dist'), + path: path.resolve(__dirname, 'dist'), filename: 'core.js', publicPath: '', + library: { + type: 'umd', + }, }, target: 'web', module: { @@ -14,11 +17,18 @@ module.exports = { { use: 'babel-loader', test: /.js$/, - exclude: /node_modules/, - } + exclude: [ + /node_modules/, + path.resolve(__dirname, '../../libraries/mootools-core-1.4.5'), + path.resolve(__dirname, '../../libraries/underscore-min'), + ] + }, ], }, resolve: { + alias: { + '@libraries': path.resolve(__dirname, '../../libraries/'), + }, extensions: ['.js'], }, plugins: [new CleanWebpackPlugin()], diff --git a/packages/editor/package.json b/packages/editor/package.json index 85af4c39..c45ceee1 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -25,9 +25,9 @@ }, "dependencies": { "@types/styled-components": "^5.1.4", - "@wismapping/core-js": "^0.0.1", + "@wisemapping/core-js": "^0.0.1", "react": "^17.0.1", "react-dom": "^17.0.1", "styled-components": "^5.2.1" } -} +} \ No newline at end of file diff --git a/packages/mindplot/.eslintignore b/packages/mindplot/.eslintignore new file mode 100644 index 00000000..1eae0cf6 --- /dev/null +++ b/packages/mindplot/.eslintignore @@ -0,0 +1,2 @@ +dist/ +node_modules/ diff --git a/packages/mindplot/.eslintrc.json b/packages/mindplot/.eslintrc.json index 128db24a..89fb77f1 100644 --- a/packages/mindplot/.eslintrc.json +++ b/packages/mindplot/.eslintrc.json @@ -4,10 +4,28 @@ "commonjs": true }, "extends": [ - "airbnb-base" + "airbnb-base", + "plugin:cypress/recommended" ], + "globals":{ + "Class": "readonly", + "$": "readonly", + "$assert": "readonly", + "$defined": "readonly", + "$msg": "readonly", + "$notify": "readonly", + "_": "readonly" + }, "plugins": ["only-warn"], "rules": { - "no-underscore-dangle": "off" - } -} \ No newline at end of file + "no-underscore-dangle": "off", + "import/no-extraneous-dependencies": ["error", {"devDependencies": ["!cypress/**/*.js"]}] + }, + "settings": { + "import/resolver": { + "webpack": { + "config": "./webpack.common.js" + } + } + } +} diff --git a/packages/mindplot/.gitignore b/packages/mindplot/.gitignore new file mode 100644 index 00000000..c96f2fe9 --- /dev/null +++ b/packages/mindplot/.gitignore @@ -0,0 +1,4 @@ +cypress/screenshots +cypress/videos +cypress/downloads +cypress/snapshots/*/__diff_output__ \ No newline at end of file diff --git a/packages/mindplot/README.md b/packages/mindplot/README.md index 1b7da5fc..67c00fa0 100644 --- a/packages/mindplot/README.md +++ b/packages/mindplot/README.md @@ -38,6 +38,6 @@ once this is done, it will open the explorer where you can see a menu with the t To start using mindplot it has to be required as a module and then intanciarce as a function ``` -const mindplot = require('@wisemapping/mindplot'); +import mindplot from '@wisemapping/mindplot'; mindplot(); ``` diff --git a/packages/mindplot/__tests__/mindplot.test.js b/packages/mindplot/__tests__/mindplot.test.js index 96c92eb4..58f09d89 100644 --- a/packages/mindplot/__tests__/mindplot.test.js +++ b/packages/mindplot/__tests__/mindplot.test.js @@ -1,7 +1,5 @@ -'use strict'; - -const mindplot = require('..'); +import mindplot from '..'; describe('mindplot', () => { - it('needs tests'); + it('needs tests'); }); diff --git a/packages/mindplot/babel.config.json b/packages/mindplot/babel.config.json index ed1f3427..3d669db0 100644 --- a/packages/mindplot/babel.config.json +++ b/packages/mindplot/babel.config.json @@ -13,5 +13,6 @@ } } ] - ] + ], + "sourceType": "unambiguous" } diff --git a/packages/mindplot/cypress.json b/packages/mindplot/cypress.json new file mode 100644 index 00000000..091c5f0f --- /dev/null +++ b/packages/mindplot/cypress.json @@ -0,0 +1,4 @@ +{ + "video": false, + "videoUploadOnPasses": false +} \ No newline at end of file diff --git a/packages/mindplot/cypress/integration/playground.test.js b/packages/mindplot/cypress/integration/playground.test.js new file mode 100644 index 00000000..35aad990 --- /dev/null +++ b/packages/mindplot/cypress/integration/playground.test.js @@ -0,0 +1,17 @@ +const BASE_URL = 'http://localhost:8081'; + +context('Playground', () => { + it('the playground layout page should match its snapshot', () => { + // TODO: check why this error is happening, and remove this handling + cy.on('uncaught:exception', (err) => { + expect(err.message).to.include('Prediction is incorrectly positioned'); + return false; + }); + cy.visit(`${BASE_URL}/layout.html`); + cy.matchImageSnapshot('layout'); + }); + it('the playground viewmode.html page should match its snapshot', () => { + cy.visit(`${BASE_URL}/viewmode.html`); + cy.matchImageSnapshot('viewmode'); + }); +}); diff --git a/packages/mindplot/cypress/plugins/index.js b/packages/mindplot/cypress/plugins/index.js new file mode 100644 index 00000000..8a0fa140 --- /dev/null +++ b/packages/mindplot/cypress/plugins/index.js @@ -0,0 +1,24 @@ +/// +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); + +/** + * @type {Cypress.PluginConfig} + */ +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config + addMatchImageSnapshotPlugin(on, config); +}; diff --git a/packages/mindplot/cypress/snapshots/playground.test.js/layout.snap.png b/packages/mindplot/cypress/snapshots/playground.test.js/layout.snap.png new file mode 100644 index 0000000000000000000000000000000000000000..19b29fd8d81babed4b272fc9f243f0ca6dcb803e GIT binary patch literal 75649 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"I=3Z0`+k7c#nLQ?LWlV+2cdJl+8;fv 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∓p=Ws&LvN5ffr;RG5bsdSPXBS9xcak>~t@mVw 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 V&z3*9XdFmTKpI=BD; literal 0 HcmV?d00001 diff --git a/packages/mindplot/cypress/support/commands.js b/packages/mindplot/cypress/support/commands.js new file mode 100644 index 00000000..4f9b69b0 --- /dev/null +++ b/packages/mindplot/cypress/support/commands.js @@ -0,0 +1,29 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) + +import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command'; + +addMatchImageSnapshotCommand(); diff --git a/packages/mindplot/cypress/support/index.js b/packages/mindplot/cypress/support/index.js new file mode 100644 index 00000000..37a498fb --- /dev/null +++ b/packages/mindplot/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/packages/mindplot/jsconfig.json b/packages/mindplot/jsconfig.json new file mode 100644 index 00000000..a68c753c --- /dev/null +++ b/packages/mindplot/jsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "module": "commonjs", + "paths": { + "@libraries/*": ["../../libraries/*"], + "@commands/*": ["./src/components/commands/*"], + "@layout/*": ["./src/components/layout/*"], + "@libs/*": ["./src/components/libraries/*"], + "@model/*": ["./src/components/model/*"], + "@persistence/*": ["./src/components/persistence/*"], + "@util/*": ["./src/components/util/*"], + "@widget/*": ["./src/components/widget/*"], + "@components/*": ["./src/components/*"] + } + }, + "exclude": ["node_modules"] +} diff --git a/packages/mindplot/lib/components/IconGroup.js b/packages/mindplot/lib/components/IconGroup.js deleted file mode 100644 index 61d85884..00000000 --- a/packages/mindplot/lib/components/IconGroup.js +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); -const Icon = require('./Icon'); - -const IconGroup = new Class(/** @lends IconGroup */{ - /** - * @constructs - * @param topicId - * @param iconSize - * @throws will throw an error if topicId is null or undefined - * @throws will throw an error if iconSize is null or undefined - */ - initialize(topicId, iconSize) { - $assert($defined(topicId), 'topicId can not be null'); - $assert($defined(iconSize), 'iconSize can not be null'); - - this._icons = []; - this._group = new web2d.Group({ - width: 0, - height: iconSize, - x: 0, - y: 0, - coordSizeWidth: 0, - coordSizeHeight: 100, - }); - this._removeTip = new IconGroup.RemoveTip(this._group, topicId); - this.seIconSize(iconSize, iconSize); - - this._registerListeners(); - }, - - /** */ - setPosition(x, y) { - this._group.setPosition(x, y); - }, - - /** */ - getPosition() { - return this._group.getPosition(); - }, - - /** */ - getNativeElement() { - return this._group; - }, - - /** */ - getSize() { - return this._group.getSize(); - }, - - /** */ - seIconSize(width, height) { - this._iconSize = { width, height }; - this._resize(this._icons.length); - }, - - /** - * @param icon the icon to be added to the icon group - * @param {Boolean} remove - * @throws will throw an error if icon is not defined - */ - addIcon(icon, remove) { - $defined(icon, 'icon is not defined'); - - icon.setGroup(this); - this._icons.push(icon); - - // Adjust group and position ... - this._resize(this._icons.length); - this._positionIcon(icon, this._icons.length - 1); - - const imageShape = icon.getImage(); - this._group.append(imageShape); - - // Register event for the group .. - if (remove) { - this._removeTip.decorate(this._topicId, icon); - } - }, - - _findIconFromModel(iconModel) { - let result = null; - _.each(this._icons, (icon) => { - const elModel = icon.getModel(); - if (elModel.getId() == iconModel.getId()) { - result = icon; - } - }, this); - - if (result == null) { - throw new Error(`Icon can no be found:${iconModel.getId()}, Icons:${this._icons}`); - } - - return result; - }, - - /** */ - removeIconByModel(featureModel) { - $assert(featureModel, 'featureModel can not be null'); - - const icon = this._findIconFromModel(featureModel); - this._removeIcon(icon); - }, - - _removeIcon(icon) { - $assert(icon, 'icon can not be null'); - - this._removeTip.close(0); - this._group.removeChild(icon.getImage()); - - this._icons.erase(icon); - this._resize(this._icons.length); - const me = this; - // Add all again ... - _.each(this._icons, (elem, i) => { - me._positionIcon(elem, i); - }); - }, - - /** */ - moveToFront() { - this._group.moveToFront(); - }, - - _registerListeners() { - this._group.addEvent('click', (event) => { - // Avoid node creation ... - event.stopPropagation(); - }); - - this._group.addEvent('dblclick', (event) => { - event.stopPropagation(); - }); - }, - - _resize(iconsLength) { - this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height); - - const iconSize = Icon.SIZE + (IconGroup.ICON_PADDING * 2); - this._group.setCoordSize(iconsLength * iconSize, iconSize); - }, - - _positionIcon(icon, order) { - const iconSize = Icon.SIZE + (IconGroup.ICON_PADDING * 2); - icon.getImage().setPosition(iconSize * order + IconGroup.ICON_PADDING, IconGroup.ICON_PADDING); - }, -}); - -/** - * @constant - * @type {Number} - * @default - */ -IconGroup.ICON_PADDING = 5; - -IconGroup.RemoveTip = new Class(/** @lends IconGroup.RemoveTip */{ - /** - * @classdesc inner class of IconGroup - * @constructs - * @param container - */ - initialize(container) { - $assert(container, 'group can not be null'); - this._fadeElem = container; - }, - - /** - * @param topicId - * @param icon - * @throws will throw an error if icon is null or undefined - */ - show(topicId, icon) { - $assert(icon, 'icon can not be null'); - - // Nothing to do ... - if (this._activeIcon != icon) { - // If there is an active icon, close it first ... - if (this._activeIcon) { - this.close(0); - } - - // Now, let move the position the icon... - const pos = icon.getPosition(); - - // Register events ... - const widget = this._buildWeb2d(); - widget.addEvent('click', () => { - icon.remove(); - }); - - const me = this; - - widget.addEvent('mouseover', () => { - me.show(topicId, icon); - }); - - widget.addEvent('mouseout', () => { - me.hide(); - }); - - widget.setPosition(pos.x + 80, pos.y - 50); - this._fadeElem.append(widget); - - // Setup current element ... - this._activeIcon = icon; - this._widget = widget; - } else { - clearTimeout(this._closeTimeoutId); - } - }, - - /** */ - hide() { - this.close(200); - }, - - /** - * @param delay - */ - close(delay) { - // This is not ok, trying to close the same dialog twice ? - if (this._closeTimeoutId) { - clearTimeout(this._closeTimeoutId); - } - - const me = this; - if (this._activeIcon) { - const widget = this._widget; - const close = function () { - me._activeIcon = null; - me._fadeElem.removeChild(widget); - me._widget = null; - me._closeTimeoutId = null; - }; - - if (!$defined(delay) || delay == 0) { - close(); - } else { - this._closeTimeoutId = close.delay(delay); - } - } - }, - - _buildWeb2d() { - const result = new web2d.Group({ - width: 10, - height: 10, - x: 0, - y: 0, - coordSizeWidth: 10, - coordSizeHeight: 10, - }); - - const outerRect = new web2d.Rect(0, { - x: 0, - y: 0, - width: 10, - height: 10, - stroke: '0', - fillColor: 'black', - }); - result.append(outerRect); - outerRect.setCursor('pointer'); - - const innerRect = new web2d.Rect(0, { - x: 1, - y: 1, - width: 8, - height: 8, - stroke: '1 solid white', - fillColor: 'gray', - }); - result.append(innerRect); - - const line = new web2d.Line({ stroke: '1 solid white' }); - line.setFrom(1, 1); - line.setTo(9, 9); - result.append(line); - - const line2 = new web2d.Line({ stroke: '1 solid white' }); - line2.setFrom(1, 9); - line2.setTo(9, 1); - result.append(line2); - - // Some events ... - result.addEvent('mouseover', () => { - innerRect.setFill('#CC0033'); - }); - result.addEvent('mouseout', () => { - innerRect.setFill('gray'); - }); - - result.setSize(50, 50); - return result; - }, - - /** - * @param topicId - * @param icon - */ - decorate(topicId, icon) { - const me = this; - - if (!icon.__remove) { - icon.addEvent('mouseover', () => { - me.show(topicId, icon); - }); - - icon.addEvent('mouseout', () => { - me.hide(); - }); - icon.__remove = true; - } - }, - -}); - -export default IconGroup; diff --git a/packages/mindplot/lib/components/MainTopic.js b/packages/mindplot/lib/components/MainTopic.js deleted file mode 100644 index 6eab42bf..00000000 --- a/packages/mindplot/lib/components/MainTopic.js +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const Core = require('@wismapping/core-js'); - -const core = Core(); -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); - -const Topic = require('./Topic').default; -const { TopicShape } = require('./model/INodeModel'); -const Shape = require('./util/Shape').default; - -const MainTopic = new Class(/** @lends MainTopic */ { - Extends: Topic, - /** - * @extends mindplot.Topic - * @constructs - * @param model - * @param options - */ - initialize(model, options) { - this.parent(model, options); - }, - - INNER_RECT_ATTRIBUTES: { stroke: '0.5 solid #009900' }, - - _buildDragShape() { - const innerShape = this._buildShape(this.INNER_RECT_ATTRIBUTES, this.getShapeType()); - const size = this.getSize(); - innerShape.setSize(size.width, size.height); - innerShape.setPosition(0, 0); - innerShape.setOpacity(0.5); - innerShape.setCursor('default'); - innerShape.setVisibility(true); - - const brColor = this.getBorderColor(); - innerShape.setAttribute('strokeColor', brColor); - - const bgColor = this.getBackgroundColor(); - innerShape.setAttribute('fillColor', bgColor); - - // Create group ... - const groupAttributes = { - width: 100, - height: 100, - coordSizeWidth: 100, - coordSizeHeight: 100, - }; - const group = new web2d.Group(groupAttributes); - group.append(innerShape); - - // Add Text ... - if (this.getShapeType() != TopicShape.IMAGE) { - const textShape = this._buildTextShape(true); - const text = this.getText(); - textShape.setText(text); - textShape.setOpacity(0.5); - group.append(textShape); - } - return group; - }, - - /** */ - updateTopicShape(targetTopic, workspace) { - // Change figure based on the connected topic ... - const model = this.getModel(); - let shapeType = model.getShapeType(); - if (!targetTopic.isCentralTopic()) { - if (!$defined(shapeType)) { - // Get the real shape type ... - shapeType = this.getShapeType(); - this._setShapeType(shapeType, false); - } - } - }, - - /** */ - disconnect(workspace) { - this.parent(workspace); - const size = this.getSize(); - - const model = this.getModel(); - let shapeType = model.getShapeType(); - if (!$defined(shapeType)) { - // Change figure ... - shapeType = this.getShapeType(); - this._setShapeType(TopicShape.ROUNDED_RECT, false); - } - const innerShape = this.getInnerShape(); - innerShape.setVisibility(true); - }, - - _updatePositionOnChangeSize(oldSize, newSize) { - const xOffset = Math.round((newSize.width - oldSize.width) / 2); - const pos = this.getPosition(); - if ($defined(pos)) { - if (pos.x > 0) { - pos.x += xOffset; - } else { - pos.x -= xOffset; - } - this.setPosition(pos); - } - }, - - /** */ - workoutIncomingConnectionPoint(sourcePosition) { - return Shape.workoutIncomingConnectionPoint(this, sourcePosition); - }, - - /** */ - workoutOutgoingConnectionPoint(targetPosition) { - $assert(targetPosition, 'targetPoint can not be null'); - const pos = this.getPosition(); - const isAtRight = Shape.isAtRight(targetPosition, pos); - const size = this.getSize(); - - let result; - if (this.getShapeType() == TopicShape.LINE) { - result = new core.Point(); - const groupPosition = this._elem2d.getPosition(); - const innerShareSize = this.getInnerShape().getSize(); - - if (innerShareSize) { - const magicCorrectionNumber = 0.3; - if (!isAtRight) { - result.x = groupPosition.x + innerShareSize.width - magicCorrectionNumber; - } else { - result.x = groupPosition.x + magicCorrectionNumber; - } - result.y = groupPosition.y + innerShareSize.height; - } else { - // Hack: When the size has not being defined. This is because the node has not being added. - // Try to do our best ... - if (!isAtRight) { - result.x = pos.x + size.width / 2; - } else { - result.x = pos.x - size.width / 2; - } - result.y = pos.y + size.height / 2; - } - } else { - result = Shape.calculateRectConnectionPoint( - pos, - size, - isAtRight, - true, - ); - } - return result; - }, -}); - -export default MainTopic; diff --git a/packages/mindplot/lib/components/commands/AddFeatureToTopicCommand.js b/packages/mindplot/lib/components/commands/AddFeatureToTopicCommand.js deleted file mode 100644 index 259ba865..00000000 --- a/packages/mindplot/lib/components/commands/AddFeatureToTopicCommand.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const Command = require('../Command').default; - -const AddFeatureToTopicCommand = new Class(/** @lends AddFeatureToTopicCommand */{ - Extends: Command, - /** - * @classdesc This command class handles do/undo of adding features to topics, e.g. an - * icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature} - * @constructs - * @param {String} topicId the id of the topic - * @param {String} featureType the id of the feature type to add, e.g. "icon" - * @param {Object} attributes the attribute(s) of the respective feature model - * @extends mindplot.Command - * @see mindplot.model.FeatureModel and subclasses - */ - initialize(topicId, featureType, attributes) { - $assert($defined(topicId), 'topicId can not be null'); - $assert(featureType, 'featureType can not be null'); - $assert(attributes, 'attributes can not be null'); - - this.parent(); - this._topicId = topicId; - this._featureType = featureType; - this._attributes = attributes; - this._featureModel = null; - }, - - /** - * Overrides abstract parent method - */ - execute(commandContext) { - const topic = commandContext.findTopics(this._topicId)[0]; - - // Feature must be created only one time. - if (!this._featureModel) { - const model = topic.getModel(); - this._featureModel = model.createFeature(this._featureType, this._attributes); - } - topic.addFeature(this._featureModel); - }, - - /** - * Overrides abstract parent method - * @see {@link mindplot.Command.undoExecute} - */ - undoExecute(commandContext) { - const topic = commandContext.findTopics(this._topicId)[0]; - topic.removeFeature(this._featureModel); - }, -}); - -export default AddFeatureToTopicCommand; diff --git a/packages/mindplot/lib/components/commands/index.js b/packages/mindplot/lib/components/commands/index.js deleted file mode 100644 index 9ce3d770..00000000 --- a/packages/mindplot/lib/components/commands/index.js +++ /dev/null @@ -1,21 +0,0 @@ -const addFeatureToTopicCommand = require('./AddFeatureToTopicCommand').default; -const addRelationshipCommand = require('./AddRelationshipCommand').default; -const addTopicCommand = require('./AddTopicCommand').default; -const changeFeatureToTopicCommand = require('./ChangeFeatureToTopicCommand').default; -const deleteCommand = require('./DeleteCommand').default; -const dragTopicCommand = require('./DragTopicCommand').default; -const genericFunctionCommand = require('./GenericFunctionCommand').default; -const moveControlPointCommand = require('./MoveControlPointCommand').default; -const removeFeatureFromTopicCommand = require('./RemoveFeatureFromTopicCommand').default; - -export const Commands = { - AddFeatureToTopicCommand: addFeatureToTopicCommand, - AddRelationshipCommand: addRelationshipCommand, - AddTopicCommand: addTopicCommand, - ChangeFeatureToTopicCommand: changeFeatureToTopicCommand, - DeleteCommand: deleteCommand, - DragTopicCommand: dragTopicCommand, - GenericFunctionCommand: genericFunctionCommand, - MoveControlPointCommand: moveControlPointCommand, - RemoveFeatureFromTopicCommand: removeFeatureFromTopicCommand, -}; diff --git a/packages/mindplot/lib/components/index.js b/packages/mindplot/lib/components/index.js deleted file mode 100644 index 6c12d16f..00000000 --- a/packages/mindplot/lib/components/index.js +++ /dev/null @@ -1,108 +0,0 @@ -const actionDispatcher = require('./ActionDispatcher').default; -const actionIcon = require('./ActionIcon').default; -const centralTopic = require('./CentralTopic').default; -const command = require('./Command').default; -const connectionLine = require('./ConnectionLine').default; -const controlPoint = require('./ControlPoint').default; -const designer = require('./Designer').default; -const designerActionRunner = require('./DesignerActionRunner').default; -const designerKeyboard = require('./DesignerKeyboard').default; -const designerModal = require('./DesignerModel').default; -const designerUndoManager = require('./DesignerUndoManager').default; -const dragConnector = require('./DragConnector').default; -const dragManager = require('./DragManager').default; -const dragPivot = require('./DragPivot').default; -const dragTopic = require('./DragTopic').default; -const editorOptions = require('./EditorOptions').default; -const editorProperties = require('./EditorProperties').default; -const events = require('./Events').default; -const footer = require('./footer'); -const header = require('./header'); -const icon = require('./Icon').default; -const iconGroup = require('./IconGroup').default; -const imageIcon = require('./ImageIcon').default; -const keyboard = require('./Keyboard').default; -const linkIcon = require('./LinkIcon').default; -const localSorageManager = require('./LocalStorageManager').default; -const mainTopic = require('./MainTopic').default; -const messages = require('./Messages').default; -const multilineTextEditor = require('./MultilineTextEditor').default; -const nodeGraph = require('./NodeGraph').default; -const noteIcon = require('./NoteIcon').default; -const options = require('./Options').default; - -const persistenceManager = require('./PersistenceManager').default; -const relationship = require('./Relationship').default; -const relationshipPivot = require('./RelationshipPivot').default; -const resetPersistenceManager = require('./RestPersistenceManager').default; - -const screenManager = require('./ScreenManager').default; -const shrinkConnector = require('./ShrinkConnector').default; -const standaloneActionDispatcher = require('./StandaloneActionDispatcher').default; -const textEditor = require('./TextEditor').default; - -const textEditorFactory = require('./TextEditorFactory').default; - -const topic = require('./Topic').default; -const topicEventDispatcher = require('./TopicEventDispatcher').default; -const topicFeature = require('./TopicFeature').default; -const topicStyle = require('./TopicStyle').default; -const workspace = require('./Workspace').default; - -export const Components = { - ActionDispatcher: actionDispatcher, - - ActionIcon: actionIcon, - CentralTopic: centralTopic, - Command: command, - ConnectionLine: connectionLine, - ControlPoint: controlPoint, - Designer: designer, - - DesignerActionRunner: designerActionRunner, - DesignerKeyboard: designerKeyboard, - DesignerModel: designerModal, - DesignerUndoManager: designerUndoManager, - - DragConnector: dragConnector, - DragManager: dragManager, - DragPivot: dragPivot, - DragTopic: dragTopic, - EditorOptions: editorOptions, - EditorProperties: editorProperties, - Events: events, - - footer, - header, - - Icon: icon, - IconGroup: iconGroup, - ImageIcon: imageIcon, - Keyboard: keyboard, - LinkIcon: linkIcon, - - localSorageManager, - MainTopic: mainTopic, - - Messages: messages, - MultilineTextEditor: multilineTextEditor, - NodeGraph: nodeGraph, - NoteIcon: noteIcon, - Options: options, - - PersistenceManager: persistenceManager, - Relationship: relationship, - RelationshipPivot: relationshipPivot, - RestPersistenceManager: resetPersistenceManager, - ScreenManager: screenManager, - ShrinkConnector: shrinkConnector, - StandaloneActionDispatcher: standaloneActionDispatcher, - TextEditor: textEditor, - TextEditorFactory: textEditorFactory, - - Topic: topic, - TopicEventDispatcher: topicEventDispatcher, - TopicFeature: topicFeature, - TopicStyle: topicStyle, - Workspace: workspace, -}; diff --git a/packages/mindplot/lib/components/layout/index.js b/packages/mindplot/lib/components/layout/index.js deleted file mode 100644 index c4f9dac4..00000000 --- a/packages/mindplot/lib/components/layout/index.js +++ /dev/null @@ -1,27 +0,0 @@ -const abstractBasicSorter = require('./AbstractBasicSorter').default; -const balancedSorter = require('./BalancedSorter').default; -const changeEvent = require('./ChangeEvent').default; -const childrenSorterStrategy = require('./ChildrenSorterStrategy').default; -const eventBus = require('./EventBus').default; -const eventBusDispatcher = require('./EventBusDispatcher').default; -const gridSorter = require('./GridSorter').default; -const layoutManager = require('./LayoutManager').default; -const node = require('./Node').default; -const originalLayout = require('./OriginalLayout').default; -const rootedTreeSet = require('./RootedTreeSet').default; -const symmetricSorter = require('./SymmetricSorter').default; - -export const Layout = { - AbstractBasicSorter: abstractBasicSorter, - BalancedSorter: balancedSorter, - ChangeEvent: changeEvent, - ChildrenSorterStrategy: childrenSorterStrategy, - EventBus: eventBus, - EventBusDispatcher: eventBusDispatcher, - GridSorter: gridSorter, - LayoutManager: layoutManager, - Node: node, - OriginalLayout: originalLayout, - RootedTreeSet: rootedTreeSet, - SymmetricSorter: symmetricSorter, -}; diff --git a/packages/mindplot/lib/components/model/index.js b/packages/mindplot/lib/components/model/index.js deleted file mode 100644 index 55ff4f89..00000000 --- a/packages/mindplot/lib/components/model/index.js +++ /dev/null @@ -1,21 +0,0 @@ -const featureModel = require('./FeatureModel').default; -const iconModel = require('./IconModel').default; -const iMindmap = require('./IMindmap').default; -const iNodeModel = require('./INodeModel').default; -const linkModel = require('./LinkModel').default; -const noteModel = require('./NoteModel').default; -const mindmap = require('./Mindmap').default; -const nodeModel = require('./NodeModel').default; -const relationshipModel = require('./RelationshipModel').default; - -export const Model = { - FeatureModel: featureModel, - IconModel: iconModel, - IMindmap: iMindmap, - INodeModel: iNodeModel, - LinkModel: linkModel, - NoteModel: noteModel, - Mindmap: mindmap, - NodeModel: nodeModel, - RelationshipModel: relationshipModel, -}; diff --git a/packages/mindplot/lib/components/persistence/index.js b/packages/mindplot/lib/components/persistence/index.js deleted file mode 100644 index b2525dd5..00000000 --- a/packages/mindplot/lib/components/persistence/index.js +++ /dev/null @@ -1,17 +0,0 @@ -const beta2PelaMigrator = require('./Beta2PelaMigrator').default; -const modelCodeName = require('./ModelCodeName').default; -const pela2TangoMigrator = require('./Pela2TangoMigrator').default; -const xmlSerializer_Beta = require('./XMLSerializer_Beta').default; -const xmlSerializer_Pela = require('./XMLSerializer_Pela').default; -const xmlSerializer_Tango = require('./XMLSerializer_Tango').default; -const xmlSerializerFactory = require('./XMLSerializerFactory').default; - -export const Persistence = { - Beta2PelaMigrator: beta2PelaMigrator, - ModelCodeName: modelCodeName, - Pela2TangoMigrator: pela2TangoMigrator, - XMLSerializer_Beta: xmlSerializer_Beta, - XMLSerializer_Pela: xmlSerializer_Pela, - XMLSerializer_Tango: xmlSerializer_Tango, - XMLSerializerFactory: xmlSerializerFactory, -}; diff --git a/packages/mindplot/lib/components/util/index.js b/packages/mindplot/lib/components/util/index.js deleted file mode 100644 index 527fe177..00000000 --- a/packages/mindplot/lib/components/util/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const fadeEffect = require('./FadeEffect').default; -const shape = require('./Shape').default; - -export const Utils = { - FadeEffect: fadeEffect, - Shape: shape, -}; diff --git a/packages/mindplot/lib/components/widget/index.js b/packages/mindplot/lib/components/widget/index.js deleted file mode 100644 index 1fbb5fb9..00000000 --- a/packages/mindplot/lib/components/widget/index.js +++ /dev/null @@ -1,37 +0,0 @@ -const colorPalettePanel = require('./ColorPalettePanel').default; -const floatingTip = require('./FloatingTip').default; -const fontFamilyPanel = require('./FontFamilyPanel').default; -const fontSizePanel = require('./FontSizePanel').default; -const iconPanel = require('./IconPanel').default; -const iMenu = require('./IMenu').default; -const keyboardShortcutTooltip = require('./KeyboardShortcutTooltip').default; -const linkEditor = require('./LinkEditor').default; -const linkIconTooltip = require('./LinkIconTooltip').default; -const listToolbarPanel = require('./ListToolbarPanel').default; -const menu = require('./Menu').default; -const modalDialogNotifier = require('./ModalDialogNotifier').default; -const noteEditor = require('./NoteEditor').default; -const toolbarItem = require('./ToolbarItem').default; -const toolbarNotifier = require('./ToolbarNotifier').default; -const toolbarPanelItem = require('./ToolbarPaneItem').default; -const topicShapePanel = require('./TopicShapePanel').default; - -export const Widgets = { - ColorPalettePanel: colorPalettePanel, - FloatingTip: floatingTip, - FontFamilyPanel: fontFamilyPanel, - FontSizePanel: fontSizePanel, - IconPanel: iconPanel, - IMenu: iMenu, - KeyboardShortcutTooltip: keyboardShortcutTooltip, - LinkEditor: linkEditor, - LinkIconTooltip: linkIconTooltip, - ListToolbarPanel: listToolbarPanel, - Menu: menu, - ModalDialogNotifier: modalDialogNotifier, - NoteEditor: noteEditor, - ToolbarItem: toolbarItem, - ToolbarNotifier: toolbarNotifier, - ToolbarPaneItem: toolbarPanelItem, - TopicShapePanel: topicShapePanel, -}; diff --git a/packages/mindplot/lib/mindplot.js b/packages/mindplot/lib/mindplot.js deleted file mode 100644 index bbc7aca1..00000000 --- a/packages/mindplot/lib/mindplot.js +++ /dev/null @@ -1,56 +0,0 @@ -module.exports = mindplot; //eslint-disable-line - -function mindplot() { - // Jquery for mindplot and bootstrap - global.$ = require('jquery'); - global.jQuery = require('jquery'); - - // Mootools for the classes of Mindplot - require('mootools'); - - // Underscore handling common tasks - global._ = require('underscore'); - - // Core-js packages of Wisemapping - global.core = require('@wismapping/core-js'); - - define(['raphael'], (Raphael) => { - global.Raphael = Raphael; - }); - require('../test/playground/lib/raphael-plugins'); - - // Bootsrap for styles - require('./components/libraries/bootstrap/js/bootstrap.min'); - - /* * * * * * * * - * MINDPLOT * - * * * * * * * */ - - // Commands - const { Commands } = require('./components/commands'); - - // Layout - const { Layout } = require('./components/layout'); - - // Model - - const { Model } = require('./components/model'); - - // Persistence - const { Persistence } = require('./components/persistence'); - - // Widgets - const { Widgets } = require('./components/widget'); - - // Components - const { Components } = require('./components'); - - return { - commands: Commands, - layout: Layout, - models: Model, - persistence: Persistence, - widget: Widgets, - component: Components, - }; -} diff --git a/packages/mindplot/package.json b/packages/mindplot/package.json index 6ed51f96..bdeac472 100644 --- a/packages/mindplot/package.json +++ b/packages/mindplot/package.json @@ -2,15 +2,15 @@ "name": "@wisemapping/mindplot", "version": "0.0.1", "description": "mindplot", - "homepage": "http://localhost:8080/react/packages/mindplot", + "homepage": "http://localhost:8081/react/packages/mindplot", "license": "ISC", - "main": "lib/mindplot.js", + "main": "dist/main.js", "directories": { - "lib": "lib", + "lib": "src", "test": "__tests__" }, "files": [ - "lib" + "src" ], "publishConfig": { "registry": "https://registry.yarnpkg.com" @@ -22,14 +22,18 @@ "scripts": { "build": "webpack --config webpack.prod.js", "dev": "webpack serve --config webpack.dev.js", - "playground": "webpack serve --config webpack.playground.js" + "lint": "eslint src", + "playground": "webpack serve --config webpack.playground.js", + "cy:run": "cypress run", + "cy:run:update": "cypress run --env updateSnapshots=true", + "test:snapshots": "start-server-and-test playground http-get://localhost:8081 cy:run", + "test:snapshots:update": "start-server-and-test playground http-get://localhost:8081 cy:run:update" }, "dependencies": { - "@wismapping/core-js": "^0.0.1", - "@wismapping/web2d": "^0.0.1", + "@wisemapping/core-js": "^0.0.1", + "@wisemapping/web2d": "^0.0.1", "jquery": "2.1.0", "mootools": "1.4.5", - "raphael": "^2.3.0", "underscore": "^1.13.1" }, "devDependencies": { @@ -38,15 +42,20 @@ "@babel/preset-env": "^7.14.7", "babel-loader": "^8.2.2", "clean-webpack-plugin": "^4.0.0-alpha.0", + "copy-webpack-plugin": "^10.0.0", "core-js": "^3.15.2", + "cypress": "^8.6.0", + "cypress-image-snapshot": "^4.0.1", "eslint": "^5.16.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-config-standard": "^16.0.3", "eslint-loader": "^4.0.2", + "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-import": "^2.24.2", "eslint-plugin-only-warn": "^1.0.3", "html-webpack-plugin": "^5.3.2", "nodemon": "^2.0.12", + "start-server-and-test": "^1.14.0", "webpack": "^5.44.0", "webpack-cli": "^4.7.2", "webpack-dev-server": "^3.11.2", diff --git a/packages/mindplot/lib/components/.gitignore b/packages/mindplot/src/components/.gitignore similarity index 100% rename from packages/mindplot/lib/components/.gitignore rename to packages/mindplot/src/components/.gitignore diff --git a/packages/mindplot/lib/components/ActionDispatcher.js b/packages/mindplot/src/components/ActionDispatcher.js similarity index 66% rename from packages/mindplot/lib/components/ActionDispatcher.js rename to packages/mindplot/src/components/ActionDispatcher.js index fc3fd102..447806fc 100644 --- a/packages/mindplot/lib/components/ActionDispatcher.js +++ b/packages/mindplot/src/components/ActionDispatcher.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ /* * Copyright [2015] [wisemapping] * @@ -15,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('./Events').default; +import Events from './Events'; // noinspection JSUnusedLocalSymbols const ActionDispatcher = new Class({ @@ -25,79 +26,79 @@ const ActionDispatcher = new Class({ }, addRelationship(model, mindmap) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, addTopics(models, parentTopicId) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, deleteEntities(topicsIds, relIds) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, dragTopic(topicId, position, order, parentTopic) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, moveTopic(topicId, position) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, moveControlPoint(ctrlPoint, point) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFontFamilyToTopic(topicIds, fontFamily) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFontStyleToTopic(topicsIds) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFontColorToTopic(topicsIds, color) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFontSizeToTopic(topicsIds, size) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeBackgroundColorToTopic(topicsIds, color) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeBorderColorToTopic(topicsIds, color) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeShapeTypeToTopic(topicsIds, shapeType) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFontWeightToTopic(topicsIds) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeTextToTopic(topicsIds, text) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, shrinkBranch(topicsIds, collapse) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, addFeatureToTopic(topicId, type, attributes) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, changeFeatureToTopic(topicId, featureId, attributes) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, removeFeatureFromTopic(topicId, featureId) { - throw 'method must be implemented.'; + throw new Error('method must be implemented.'); }, }); diff --git a/packages/mindplot/lib/components/ActionIcon.js b/packages/mindplot/src/components/ActionIcon.js similarity index 97% rename from packages/mindplot/lib/components/ActionIcon.js rename to packages/mindplot/src/components/ActionIcon.js index 96ed6df7..73bf33a9 100644 --- a/packages/mindplot/lib/components/ActionIcon.js +++ b/packages/mindplot/src/components/ActionIcon.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Icon = require('./Icon').default; +import Icon from './Icon'; const ActionIcon = new Class({ Extends: Icon, diff --git a/packages/mindplot/lib/components/CentralTopic.js b/packages/mindplot/src/components/CentralTopic.js similarity index 85% rename from packages/mindplot/lib/components/CentralTopic.js rename to packages/mindplot/src/components/CentralTopic.js index d94ad143..644b1a78 100644 --- a/packages/mindplot/lib/components/CentralTopic.js +++ b/packages/mindplot/src/components/CentralTopic.js @@ -15,11 +15,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); - -const core = Core(); -const Topic = require('./Topic').default; -const Shape = require('./util/Shape').default; +import web2d from '@wisemapping/web2d'; +import Topic from './Topic'; +import Shape from './util/Shape'; const CentralTopic = new Class( /** @lends CentralTopic */ { @@ -37,7 +35,8 @@ const CentralTopic = new Class( _registerEvents() { this.parent(); - // This disable the drag of the central topic. But solves the problem of deselecting the nodes when the screen is clicked. + // This disable the drag of the central topic. + // But solves the problem of deselecting the nodes when the screen is clicked. this.addEvent('mousedown', (event) => { event.stopPropagation(); }); @@ -59,7 +58,7 @@ const CentralTopic = new Class( _updatePositionOnChangeSize() { // Center main topic ... - const zeroPoint = new core.Point(0, 0); + const zeroPoint = new web2d.Point(0, 0); this.setPosition(zeroPoint); }, diff --git a/packages/mindplot/lib/components/Command.js b/packages/mindplot/src/components/Command.js similarity index 100% rename from packages/mindplot/lib/components/Command.js rename to packages/mindplot/src/components/Command.js diff --git a/packages/mindplot/lib/components/ConnectionLine.js b/packages/mindplot/src/components/ConnectionLine.js similarity index 91% rename from packages/mindplot/lib/components/ConnectionLine.js rename to packages/mindplot/src/components/ConnectionLine.js index e5a78b54..ec723775 100644 --- a/packages/mindplot/lib/components/ConnectionLine.js +++ b/packages/mindplot/src/components/ConnectionLine.js @@ -15,16 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); - -const INodeModel = require('./model/INodeModel').default; -const { TopicShape } = require('./model/INodeModel'); -const Topic = require('./Topic').default; +import INodeModel, { TopicShape } from './model/INodeModel'; +import TopicConfig from './TopicConfig'; const ConnectionLine = new Class({ initialize(sourceNode, targetNode, lineType) { @@ -58,7 +52,7 @@ const ConnectionLine = new Class({ const srcPos = sourceNode.workoutOutgoingConnectionPoint(targetNode.getPosition()); const destPos = targetNode.workoutIncomingConnectionPoint(sourceNode.getPosition()); const deltaX = (srcPos.x - destPos.x) / 3; - return [new core.Point(deltaX, 0), new core.Point(-deltaX, 0)]; + return [new web2d.Point(deltaX, 0), new web2d.Point(-deltaX, 0)]; }, _createLine(lineType, defaultStyle) { @@ -106,8 +100,8 @@ const ConnectionLine = new Class({ const targetTopic = this._targetTopic; const targetPosition = targetTopic.getPosition(); - let sPos; let - tPos; + let sPos; + let tPos; sPos = sourceTopic.workoutOutgoingConnectionPoint(targetPosition); tPos = targetTopic.workoutIncomingConnectionPoint(sourcePosition); @@ -126,10 +120,10 @@ const ConnectionLine = new Class({ _positionateConnector(targetTopic) { const targetPosition = targetTopic.getPosition(); - const offset = Topic.CONNECTOR_WIDTH / 2; + const offset = TopicConfig.CONNECTOR_WIDTH / 2; const targetTopicSize = targetTopic.getSize(); - let y; let - x; + let y; + let x; if (targetTopic.getShapeType() == TopicShape.LINE) { y = targetTopicSize.height; } else { @@ -143,7 +137,7 @@ const ConnectionLine = new Class({ x = targetTopicSize.width; connector.setPosition(x, y); } else { - x = -Topic.CONNECTOR_WIDTH; + x = -TopicConfig.CONNECTOR_WIDTH; } connector.setPosition(x, y); } diff --git a/packages/mindplot/lib/components/ControlPoint.js b/packages/mindplot/src/components/ControlPoint.js similarity index 79% rename from packages/mindplot/lib/components/ControlPoint.js rename to packages/mindplot/src/components/ControlPoint.js index f623453e..e85a5cfc 100644 --- a/packages/mindplot/lib/components/ControlPoint.js +++ b/packages/mindplot/src/components/ControlPoint.js @@ -15,15 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); - -const Shape = require('./util/Shape').default; -const ActionDispatcher = require('./ActionDispatcher').default; +import Shape from './util/Shape'; +import ActionDispatcher from './ActionDispatcher'; const ControlPoint = new Class({ initialize() { @@ -46,29 +41,31 @@ const ControlPoint = new Class({ control2.setCursor('pointer'); this._controlPointsController = [control1, control2]; - this._controlLines = [new web2d.Line({ strokeColor: '#6589de', strokeWidth: 1, opacity: 0.3 }), - new web2d.Line({ strokeColor: '#6589de', strokeWidth: 1, opacity: 0.3 })]; + this._controlLines = [ + new web2d.Line({ strokeColor: '#6589de', strokeWidth: 1, opacity: 0.3 }), + new web2d.Line({ strokeColor: '#6589de', strokeWidth: 1, opacity: 0.3 }), + ]; this._isBinded = false; const me = this; this._controlPointsController[0].addEvent('mousedown', (event) => { - (me._mouseDown)(event, ControlPoint.FROM, me); + me._mouseDown(event, ControlPoint.FROM, me); }); this._controlPointsController[0].addEvent('click', (event) => { - (me._mouseClick)(event); + me._mouseClick(event); }); this._controlPointsController[0].addEvent('dblclick', (event) => { - (me._mouseClick)(event); + me._mouseClick(event); }); this._controlPointsController[1].addEvent('mousedown', (event) => { - (me._mouseDown)(event, ControlPoint.TO, me); + me._mouseDown(event, ControlPoint.TO, me); }); this._controlPointsController[1].addEvent('click', (event) => { - (me._mouseClick)(event); + me._mouseClick(event); }); this._controlPointsController[1].addEvent('dblclick', (event) => { - (me._mouseClick)(event); + me._mouseClick(event); }); }, @@ -93,29 +90,39 @@ const ControlPoint = new Class({ _createControlPoint() { this._controls = this._line.getLine().getControlPoints(); let pos = this._line.getLine().getFrom(); - this._controlPointsController[0].setPosition(this._controls[ControlPoint.FROM].x + pos.x, this._controls[ControlPoint.FROM].y + pos.y - 3); + this._controlPointsController[0].setPosition( + this._controls[ControlPoint.FROM].x + pos.x, + this._controls[ControlPoint.FROM].y + pos.y - 3, + ); this._controlLines[0].setFrom(pos.x, pos.y); - this._controlLines[0].setTo(this._controls[ControlPoint.FROM].x + pos.x + 3, this._controls[ControlPoint.FROM].y + pos.y); + this._controlLines[0].setTo( + this._controls[ControlPoint.FROM].x + pos.x + 3, + this._controls[ControlPoint.FROM].y + pos.y, + ); pos = this._line.getLine().getTo(); this._controlLines[1].setFrom(pos.x, pos.y); - this._controlLines[1].setTo(this._controls[ControlPoint.TO].x + pos.x + 3, this._controls[ControlPoint.TO].y + pos.y); - this._controlPointsController[1].setPosition(this._controls[ControlPoint.TO].x + pos.x, this._controls[ControlPoint.TO].y + pos.y - 3); + this._controlLines[1].setTo( + this._controls[ControlPoint.TO].x + pos.x + 3, + this._controls[ControlPoint.TO].y + pos.y, + ); + this._controlPointsController[1].setPosition( + this._controls[ControlPoint.TO].x + pos.x, + this._controls[ControlPoint.TO].y + pos.y - 3, + ); }, - _removeLine() { - - }, + _removeLine() {}, _mouseDown(event, point, me) { if (!this._isBinded) { this._isBinded = true; this._mouseMoveFunction = function (event) { - (me._mouseMoveEvent)(event, point, me); + me._mouseMoveEvent(event, point, me); }; this._workspace.getScreenManager().addEvent('mousemove', this._mouseMoveFunction); this._mouseUpFunction = function (event) { - (me._mouseUp)(event, point, me); + me._mouseUp(event, point, me); }; this._workspace.getScreenManager().addEvent('mouseup', this._mouseUpFunction); } @@ -132,15 +139,15 @@ const ControlPoint = new Class({ if (point == 0) { cords = Shape.calculateRelationShipPointCoordinates(this._line.getSourceTopic(), pos); this._line.setFrom(cords.x, cords.y); - this._line.setSrcControlPoint(new core.Point(pos.x - cords.x, pos.y - cords.y)); + this._line.setSrcControlPoint(new web2d.Point(pos.x - cords.x, pos.y - cords.y)); } else { cords = Shape.calculateRelationShipPointCoordinates(this._line.getTargetTopic(), pos); this._line.setTo(cords.x, cords.y); - this._line.setDestControlPoint(new core.Point(pos.x - cords.x, pos.y - cords.y)); + this._line.setDestControlPoint(new web2d.Point(pos.x - cords.x, pos.y - cords.y)); } - this._controls[point].x = (pos.x - cords.x); - this._controls[point].y = (pos.y - cords.y); + this._controls[point].x = pos.x - cords.x; + this._controls[point].y = pos.y - cords.y; this._controlPointsController[point].setPosition(pos.x - 5, pos.y - 3); this._controlLines[point].setFrom(cords.x, cords.y); this._controlLines[point].setTo(pos.x - 2, pos.y); diff --git a/packages/mindplot/lib/components/Designer.js b/packages/mindplot/src/components/Designer.js similarity index 93% rename from packages/mindplot/lib/components/Designer.js rename to packages/mindplot/src/components/Designer.js index 1d3c0f0d..f2a46912 100644 --- a/packages/mindplot/lib/components/Designer.js +++ b/packages/mindplot/src/components/Designer.js @@ -15,34 +15,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('./Events').default; -const Messages = require('./Messages').default; +import Events from './Events'; +import Messages from './Messages'; -const { StandaloneActionDispatcher, CommandContext } = require('./StandaloneActionDispatcher'); -const ActionDispatcher = require('./ActionDispatcher').default; +import { StandaloneActionDispatcher, CommandContext } from './StandaloneActionDispatcher'; +import ActionDispatcher from './ActionDispatcher'; -const DesignerModel = require('./DesignerModel').default; -const DesignerKeyboard = require('./DesignerKeyboard').default; +import DesignerModel from './DesignerModel'; +import DesignerKeyboard from './DesignerKeyboard'; -const ScreenManager = require('./ScreenManager').default; -const Workspace = require('./Workspace').default; +import ScreenManager from './ScreenManager'; +import Workspace from './Workspace'; -const DragConnector = require('./DragConnector').default; -const DragManager = require('./DragManager').default; -const RelationshipPivot = require('./RelationshipPivot').default; -const Relationship = require('./Relationship').default; +import DragConnector from './DragConnector'; +import DragManager from './DragManager'; +import RelationshipPivot from './RelationshipPivot'; +import Relationship from './Relationship'; -const TopicEventDispatcher = require('./TopicEventDispatcher').default; -const TopicFeature = require('./TopicFeature').default; -const { TopicEvent } = require('./TopicEventDispatcher'); +import TopicEventDispatcher, { TopicEvent } from './TopicEventDispatcher'; +import TopicFeature from './TopicFeature'; -const NodeGraph = require('./NodeGraph').default; +import NodeGraphUtils from './NodeGraphUtils'; -const EventBusDispatcher = require('./layout/EventBusDispatcher').default; -const LayoutManager = require('./layout/LayoutManager').default; +import EventBus from './layout/EventBus'; +import EventBusDispatcher from './layout/EventBusDispatcher'; +import LayoutManager from './layout/LayoutManager'; -const INodeModel = require('./model/INodeModel').default; -const { TopicShape } = require('./model/INodeModel'); +import INodeModel, { TopicShape } from './model/INodeModel'; const Designer = new Class( /** @lends Designer */ { @@ -163,17 +162,14 @@ const Designer = new Class( }); // Create nodes on double click... - screenManager.addEvent( - 'dblclick', - (event) => { - if (workspace.isWorkspaceEventsEnabled()) { - const mousePos = screenManager.getWorkspaceMousePosition(event); - const centralTopic = me.getModel().getCentralTopic(); - const model = me._createChildModel(centralTopic, mousePos); - this._actionDispatcher.addTopics([model], [centralTopic.getId()]); - } - }, - ); + screenManager.addEvent('dblclick', (event) => { + if (workspace.isWorkspaceEventsEnabled()) { + const mousePos = screenManager.getWorkspaceMousePosition(event); + const centralTopic = me.getModel().getCentralTopic(); + const model = me._createChildModel(centralTopic, mousePos); + this._actionDispatcher.addTopics([model], [centralTopic.getId()]); + } + }); // Register mouse drag and drop event ... function noopHandler(evt) { @@ -242,7 +238,7 @@ const Designer = new Class( */ _buildNodeGraph(model, readOnly) { // Create node graph ... - const topic = NodeGraph.create(model, { readOnly }); + const topic = NodeGraphUtils.create(model, { readOnly }); this.getModel().addTopic(topic); const me = this; // Add Topic events ... @@ -520,7 +516,7 @@ const Designer = new Class( /** * @private * @param {mindplot.Topic} topic the parent topic of the child to create the NodeModel for - * @param {core.Point} mousePos the mouse position + * @param {web2d.Point} mousePos the mouse position * @return {mindplot.NodeModel} the node model for the new child */ _createChildModel(topic, mousePos) { @@ -803,9 +799,9 @@ const Designer = new Class( const targetTopic = dmodel.findTopicById(targetTopicId); $assert( targetTopic, - `targetTopic could not be found:${ - targetTopicId - }${dmodel.getTopics().map((e) => e.getId())}`, + `targetTopic could not be found:${targetTopicId}${dmodel + .getTopics() + .map((e) => e.getId())}`, ); // Build relationship line .... @@ -884,7 +880,8 @@ const Designer = new Class( // If there are more than one node selected, $notify($msg('ENTITIES_COULD_NOT_BE_DELETED')); return; - } if (topics.length == 1 && topics[0].isCentralTopic()) { + } + if (topics.length == 1 && topics[0].isCentralTopic()) { $notify($msg('CENTRAL_TOPIC_CAN_NOT_BE_DELETED')); return; } diff --git a/packages/mindplot/lib/components/DesignerActionRunner.js b/packages/mindplot/src/components/DesignerActionRunner.js similarity index 93% rename from packages/mindplot/lib/components/DesignerActionRunner.js rename to packages/mindplot/src/components/DesignerActionRunner.js index 777e1737..6cd3401e 100644 --- a/packages/mindplot/lib/components/DesignerActionRunner.js +++ b/packages/mindplot/src/components/DesignerActionRunner.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const DesignerUndoManager = require('./DesignerUndoManager').default; -const EventBus = require('./layout/EventBus').default; +import DesignerUndoManager from './DesignerUndoManager'; +import EventBus from './layout/EventBus'; const DesignerActionRunner = new Class({ initialize(commandContext, notifier) { diff --git a/packages/mindplot/lib/components/DesignerKeyboard.js b/packages/mindplot/src/components/DesignerKeyboard.js similarity index 97% rename from packages/mindplot/lib/components/DesignerKeyboard.js rename to packages/mindplot/src/components/DesignerKeyboard.js index c7e85a92..35816de6 100644 --- a/packages/mindplot/lib/components/DesignerKeyboard.js +++ b/packages/mindplot/src/components/DesignerKeyboard.js @@ -15,19 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Keyboard = require('./Keyboard').default; +import Keyboard from './Keyboard'; const DesignerKeyboard = new Class({ Extends: Keyboard, - Static: { - register(designer) { - this._instance = new DesignerKeyboard(designer); - }, - - getInstance() { - return this._instance; - }, - }, initialize(designer) { $assert(designer, 'designer can not be null'); @@ -430,4 +421,12 @@ DesignerKeyboard.specialKeys = { 224: 'meta', }; +DesignerKeyboard.register = function register(designer) { + this._instance = new DesignerKeyboard(designer); +}; + +DesignerKeyboard.getInstance = function getInstance() { + return this._instance; +}; + export default DesignerKeyboard; diff --git a/packages/mindplot/lib/components/DesignerModel.js b/packages/mindplot/src/components/DesignerModel.js similarity index 99% rename from packages/mindplot/lib/components/DesignerModel.js rename to packages/mindplot/src/components/DesignerModel.js index 994214a0..11289985 100644 --- a/packages/mindplot/lib/components/DesignerModel.js +++ b/packages/mindplot/src/components/DesignerModel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('./Events').default; +import Events from './Events'; const DesignerModel = new Class(/** @lends DesignerModel */{ Implements: [Events], diff --git a/packages/mindplot/lib/components/DesignerUndoManager.js b/packages/mindplot/src/components/DesignerUndoManager.js similarity index 100% rename from packages/mindplot/lib/components/DesignerUndoManager.js rename to packages/mindplot/src/components/DesignerUndoManager.js diff --git a/packages/mindplot/lib/components/DragConnector.js b/packages/mindplot/src/components/DragConnector.js similarity index 100% rename from packages/mindplot/lib/components/DragConnector.js rename to packages/mindplot/src/components/DragConnector.js diff --git a/packages/mindplot/lib/components/DragManager.js b/packages/mindplot/src/components/DragManager.js similarity index 98% rename from packages/mindplot/lib/components/DragManager.js rename to packages/mindplot/src/components/DragManager.js index 6c855ed2..9d9cbdca 100644 --- a/packages/mindplot/lib/components/DragManager.js +++ b/packages/mindplot/src/components/DragManager.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const DragTopic = require('./DragTopic').default; +import DragTopic from './DragTopic'; const DragManager = new Class({ initialize(workspace, eventDispatcher) { diff --git a/packages/mindplot/lib/components/DragPivot.js b/packages/mindplot/src/components/DragPivot.js similarity index 89% rename from packages/mindplot/lib/components/DragPivot.js rename to packages/mindplot/src/components/DragPivot.js index c689789e..5ce7ff4c 100644 --- a/packages/mindplot/lib/components/DragPivot.js +++ b/packages/mindplot/src/components/DragPivot.js @@ -15,21 +15,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); - -const DragTopic = require('./DragTopic').default; -const Shape = require('./util/Shape').default; -const INodeModel = require('./model/INodeModel').default; +import DragTopicConfig from './DragTopicConfig'; +import Shape from './util/Shape'; +import INodeModel from './model/INodeModel'; const DragPivot = new Class({ initialize() { - this._position = new core.Point(); - this._size = DragTopic.PIVOT_SIZE; + this._position = new web2d.Point(); + this._size = DragTopicConfig.PIVOT_SIZE; this._straightLine = this._buildStraightLine(); this._curvedLine = this._buildCurvedLine(); @@ -86,8 +81,8 @@ const DragPivot = new Class({ line.setFrom(pivotPoint.x, pivotPoint.y); // Update rect position - const cx = position.x - (parseInt(size.width) / 2); - const cy = position.y - (parseInt(size.height) / 2); + const cx = position.x - parseInt(size.width) / 2; + const cy = position.y - parseInt(size.height) / 2; pivotRect.setPosition(cx, cy); // Make line visible only when the position has been already changed. @@ -108,7 +103,11 @@ const DragPivot = new Class({ _buildRect() { const size = this._size; const rectAttributes = { - fillColor: '#CC0033', opacity: 0.4, width: size.width, height: size.height, strokeColor: '#FF9933', + fillColor: '#CC0033', + opacity: 0.4, + width: size.width, + height: size.height, + strokeColor: '#FF9933', }; const rect = new web2d.Rect(0, rectAttributes); rect.setVisibility(false); @@ -216,8 +215,8 @@ const DragPivot = new Class({ connectRect.setSize(width, height); const targetPosition = targetTopic.getPosition(); - const cx = Math.ceil(targetPosition.x - (width / 2)); - const cy = Math.ceil(targetPosition.y - (height / 2)); + const cx = Math.ceil(targetPosition.x - width / 2); + const cy = Math.ceil(targetPosition.y - height / 2); connectRect.setPosition(cx, cy); // Change elements position ... diff --git a/packages/mindplot/lib/components/DragTopic.js b/packages/mindplot/src/components/DragTopic.js similarity index 90% rename from packages/mindplot/lib/components/DragTopic.js rename to packages/mindplot/src/components/DragTopic.js index d876a1f0..f011df0a 100644 --- a/packages/mindplot/lib/components/DragTopic.js +++ b/packages/mindplot/src/components/DragTopic.js @@ -15,12 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); - -const ActionDispatcher = require('./ActionDispatcher').default; -const DragPivot = require('./DragPivot').default; +import ActionDispatcher from './ActionDispatcher'; +import DragPivot from './DragPivot'; const DragTopic = new Class({ initialize(dragShape, draggedNode, layoutManger) { @@ -32,7 +30,7 @@ const DragTopic = new Class({ this._order = null; this._draggedNode = draggedNode; this._layoutManager = layoutManger; - this._position = new core.Point(); + this._position = new web2d.Point(); this._isInWorkspace = false; this._isFreeLayoutEnabled = false; }, @@ -47,7 +45,12 @@ const DragTopic = new Class({ if (this.isFreeLayoutOn() && this.isConnected()) { const { _layoutManager } = this; const par = this.getConnectedToTopic(); - position = _layoutManager.predict(par.getId(), this._draggedNode.getId(), position, true).position; + position = _layoutManager.predict( + par.getId(), + this._draggedNode.getId(), + position, + true, + ).position; } this._position.setValue(position.x, position.y); @@ -56,13 +59,17 @@ const DragTopic = new Class({ const draggedNode = this._draggedNode; const size = draggedNode.getSize(); const cx = position.x - (position.x > 0 ? 0 : size.width); - const cy = Math.ceil(position.y - (size.height / 2)); + const cy = Math.ceil(position.y - size.height / 2); this._elem2d.setPosition(cx, cy); // In case is not free, pivot must be draw ... if (this.isConnected() && !this.isFreeLayoutOn()) { const parent = this.getConnectedToTopic(); - const predict = this._layoutManager.predict(parent.getId(), this._draggedNode.getId(), this.getPosition()); + const predict = this._layoutManager.predict( + parent.getId(), + this._draggedNode.getId(), + this.getPosition(), + ); if (this._order != predict.order) { const dragPivot = this._getDragPivot(); const pivotPosition = predict.position; @@ -105,7 +112,11 @@ const DragTopic = new Class({ $assert(parent, 'Parent connection node can not be null.'); // Where it should be connected ? - const predict = designer._eventBussDispatcher._layoutManager.predict(parent.getId(), this._draggedNode.getId(), this.getPosition()); + const predict = designer._eventBussDispatcher._layoutManager.predict( + parent.getId(), + this._draggedNode.getId(), + this.getPosition(), + ); // Connect pivot ... const dragPivot = this._getDragPivot(); @@ -197,11 +208,8 @@ const DragTopic = new Class({ // Disable free layout ... return false; }, - }); -DragTopic.PIVOT_SIZE = { width: 50, height: 6 }; - DragTopic.init = function (workspace) { $assert(workspace, 'workspace can not be null'); const pivot = DragTopic.__getDragPivot(); diff --git a/packages/mindplot/src/components/DragTopicConfig.js b/packages/mindplot/src/components/DragTopicConfig.js new file mode 100644 index 00000000..ef339928 --- /dev/null +++ b/packages/mindplot/src/components/DragTopicConfig.js @@ -0,0 +1,5 @@ +export const PIVOT_SIZE = { width: 50, height: 6 }; + +export default { + PIVOT_SIZE, +}; diff --git a/packages/mindplot/lib/components/EditorOptions.js b/packages/mindplot/src/components/EditorOptions.js similarity index 100% rename from packages/mindplot/lib/components/EditorOptions.js rename to packages/mindplot/src/components/EditorOptions.js diff --git a/packages/mindplot/lib/components/EditorProperties.js b/packages/mindplot/src/components/EditorProperties.js similarity index 100% rename from packages/mindplot/lib/components/EditorProperties.js rename to packages/mindplot/src/components/EditorProperties.js diff --git a/packages/mindplot/lib/components/Events.js b/packages/mindplot/src/components/Events.js similarity index 100% rename from packages/mindplot/lib/components/Events.js rename to packages/mindplot/src/components/Events.js diff --git a/packages/mindplot/lib/components/Icon.js b/packages/mindplot/src/components/Icon.js similarity index 95% rename from packages/mindplot/lib/components/Icon.js rename to packages/mindplot/src/components/Icon.js index b983227a..db2e9164 100644 --- a/packages/mindplot/lib/components/Icon.js +++ b/packages/mindplot/src/components/Icon.js @@ -15,9 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); +import web2d from '@wisemapping/web2d'; const Icon = new Class({ initialize(url) { diff --git a/packages/mindplot/src/components/IconGroup.js b/packages/mindplot/src/components/IconGroup.js new file mode 100644 index 00000000..48b0477e --- /dev/null +++ b/packages/mindplot/src/components/IconGroup.js @@ -0,0 +1,346 @@ +/* + * Copyright [2015] [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 web2d from '@wisemapping/web2d'; + +import Icon from './Icon'; + +const IconGroup = new Class( + /** @lends IconGroup */ { + /** + * @constructs + * @param topicId + * @param iconSize + * @throws will throw an error if topicId is null or undefined + * @throws will throw an error if iconSize is null or undefined + */ + initialize(topicId, iconSize) { + $assert($defined(topicId), 'topicId can not be null'); + $assert($defined(iconSize), 'iconSize can not be null'); + + this._icons = []; + this._group = new web2d.Group({ + width: 0, + height: iconSize, + x: 0, + y: 0, + coordSizeWidth: 0, + coordSizeHeight: 100, + }); + this._removeTip = new IconGroup.RemoveTip(this._group, topicId); + this.seIconSize(iconSize, iconSize); + + this._registerListeners(); + }, + + /** */ + setPosition(x, y) { + this._group.setPosition(x, y); + }, + + /** */ + getPosition() { + return this._group.getPosition(); + }, + + /** */ + getNativeElement() { + return this._group; + }, + + /** */ + getSize() { + return this._group.getSize(); + }, + + /** */ + seIconSize(width, height) { + this._iconSize = { width, height }; + this._resize(this._icons.length); + }, + + /** + * @param icon the icon to be added to the icon group + * @param {Boolean} remove + * @throws will throw an error if icon is not defined + */ + addIcon(icon, remove) { + $defined(icon, 'icon is not defined'); + + icon.setGroup(this); + this._icons.push(icon); + + // Adjust group and position ... + this._resize(this._icons.length); + this._positionIcon(icon, this._icons.length - 1); + + const imageShape = icon.getImage(); + this._group.append(imageShape); + + // Register event for the group .. + if (remove) { + this._removeTip.decorate(this._topicId, icon); + } + }, + + _findIconFromModel(iconModel) { + let result = null; + _.each( + this._icons, + (icon) => { + const elModel = icon.getModel(); + if (elModel.getId() == iconModel.getId()) { + result = icon; + } + }, + this, + ); + + if (result == null) { + throw new Error(`Icon can no be found:${iconModel.getId()}, Icons:${this._icons}`); + } + + return result; + }, + + /** */ + removeIconByModel(featureModel) { + $assert(featureModel, 'featureModel can not be null'); + + const icon = this._findIconFromModel(featureModel); + this._removeIcon(icon); + }, + + _removeIcon(icon) { + $assert(icon, 'icon can not be null'); + + this._removeTip.close(0); + this._group.removeChild(icon.getImage()); + + this._icons.erase(icon); + this._resize(this._icons.length); + const me = this; + // Add all again ... + _.each(this._icons, (elem, i) => { + me._positionIcon(elem, i); + }); + }, + + /** */ + moveToFront() { + this._group.moveToFront(); + }, + + _registerListeners() { + this._group.addEvent('click', (event) => { + // Avoid node creation ... + event.stopPropagation(); + }); + + this._group.addEvent('dblclick', (event) => { + event.stopPropagation(); + }); + }, + + _resize(iconsLength) { + this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height); + + const iconSize = Icon.SIZE + IconGroup.ICON_PADDING * 2; + this._group.setCoordSize(iconsLength * iconSize, iconSize); + }, + + _positionIcon(icon, order) { + const iconSize = Icon.SIZE + IconGroup.ICON_PADDING * 2; + icon.getImage().setPosition( + iconSize * order + IconGroup.ICON_PADDING, + IconGroup.ICON_PADDING, + ); + }, + }, +); + +/** + * @constant + * @type {Number} + * @default + */ +IconGroup.ICON_PADDING = 5; + +IconGroup.RemoveTip = new Class( + /** @lends IconGroup.RemoveTip */ { + /** + * @classdesc inner class of IconGroup + * @constructs + * @param container + */ + initialize(container) { + $assert(container, 'group can not be null'); + this._fadeElem = container; + }, + + /** + * @param topicId + * @param icon + * @throws will throw an error if icon is null or undefined + */ + show(topicId, icon) { + $assert(icon, 'icon can not be null'); + + // Nothing to do ... + if (this._activeIcon != icon) { + // If there is an active icon, close it first ... + if (this._activeIcon) { + this.close(0); + } + + // Now, let move the position the icon... + const pos = icon.getPosition(); + + // Register events ... + const widget = this._buildWeb2d(); + widget.addEvent('click', () => { + icon.remove(); + }); + + const me = this; + + widget.addEvent('mouseover', () => { + me.show(topicId, icon); + }); + + widget.addEvent('mouseout', () => { + me.hide(); + }); + + widget.setPosition(pos.x + 80, pos.y - 50); + this._fadeElem.append(widget); + + // Setup current element ... + this._activeIcon = icon; + this._widget = widget; + } else { + clearTimeout(this._closeTimeoutId); + } + }, + + /** */ + hide() { + this.close(200); + }, + + /** + * @param delay + */ + close(delay) { + // This is not ok, trying to close the same dialog twice ? + if (this._closeTimeoutId) { + clearTimeout(this._closeTimeoutId); + } + + const me = this; + if (this._activeIcon) { + const widget = this._widget; + const close = function () { + me._activeIcon = null; + me._fadeElem.removeChild(widget); + me._widget = null; + me._closeTimeoutId = null; + }; + + if (!$defined(delay) || delay == 0) { + close(); + } else { + this._closeTimeoutId = close.delay(delay); + } + } + }, + + _buildWeb2d() { + const result = new web2d.Group({ + width: 10, + height: 10, + x: 0, + y: 0, + coordSizeWidth: 10, + coordSizeHeight: 10, + }); + + const outerRect = new web2d.Rect(0, { + x: 0, + y: 0, + width: 10, + height: 10, + stroke: '0', + fillColor: 'black', + }); + result.append(outerRect); + outerRect.setCursor('pointer'); + + const innerRect = new web2d.Rect(0, { + x: 1, + y: 1, + width: 8, + height: 8, + stroke: '1 solid white', + fillColor: 'gray', + }); + result.append(innerRect); + + const line = new web2d.Line({ stroke: '1 solid white' }); + line.setFrom(1, 1); + line.setTo(9, 9); + result.append(line); + + const line2 = new web2d.Line({ stroke: '1 solid white' }); + line2.setFrom(1, 9); + line2.setTo(9, 1); + result.append(line2); + + // Some events ... + result.addEvent('mouseover', () => { + innerRect.setFill('#CC0033'); + }); + result.addEvent('mouseout', () => { + innerRect.setFill('gray'); + }); + + result.setSize(50, 50); + return result; + }, + + /** + * @param topicId + * @param icon + */ + decorate(topicId, icon) { + const me = this; + + if (!icon.__remove) { + icon.addEvent('mouseover', () => { + me.show(topicId, icon); + }); + + icon.addEvent('mouseout', () => { + me.hide(); + }); + icon.__remove = true; + } + }, + }, +); + +export default IconGroup; diff --git a/packages/mindplot/lib/components/ImageIcon.js b/packages/mindplot/src/components/ImageIcon.js similarity index 98% rename from packages/mindplot/lib/components/ImageIcon.js rename to packages/mindplot/src/components/ImageIcon.js index 3d0f0f59..e3498476 100644 --- a/packages/mindplot/lib/components/ImageIcon.js +++ b/packages/mindplot/src/components/ImageIcon.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Icon = require('./Icon').default; -const ActionDispatcher = require('./ActionDispatcher').default; +import Icon from './Icon'; +import ActionDispatcher from './ActionDispatcher'; const ImageIcon = new Class({ Extends: Icon, diff --git a/packages/mindplot/lib/components/Keyboard.js b/packages/mindplot/src/components/Keyboard.js similarity index 100% rename from packages/mindplot/lib/components/Keyboard.js rename to packages/mindplot/src/components/Keyboard.js diff --git a/packages/mindplot/lib/components/LinkIcon.js b/packages/mindplot/src/components/LinkIcon.js similarity index 92% rename from packages/mindplot/lib/components/LinkIcon.js rename to packages/mindplot/src/components/LinkIcon.js index 491597a0..ad484edf 100644 --- a/packages/mindplot/lib/components/LinkIcon.js +++ b/packages/mindplot/src/components/LinkIcon.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Icon = require('./Icon').default; -const LinkIconTooltip = require('./widget/LinkIconTooltip').default; +import Icon from './Icon'; +import LinkIconTooltip from './widget/LinkIconTooltip'; const LinkIcon = new Class({ @@ -56,7 +56,7 @@ const LinkIcon = new Class({ }); } - $(this.getImage()._peer._native).mouseenter(() => { + $(this.getImage().peer._native).mouseenter(() => { me._tip.show(); }); }, diff --git a/packages/mindplot/lib/components/LocalStorageManager.js b/packages/mindplot/src/components/LocalStorageManager.js similarity index 96% rename from packages/mindplot/lib/components/LocalStorageManager.js rename to packages/mindplot/src/components/LocalStorageManager.js index ed2358d1..e4aafe8b 100644 --- a/packages/mindplot/lib/components/LocalStorageManager.js +++ b/packages/mindplot/src/components/LocalStorageManager.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const PersistenceManager = require('./PersistenceManager').default; +import PersistenceManager from './PersistenceManager'; const LocalStorageManager = new Class({ Extends: PersistenceManager, diff --git a/packages/mindplot/src/components/MainTopic.js b/packages/mindplot/src/components/MainTopic.js new file mode 100644 index 00000000..9f2da86c --- /dev/null +++ b/packages/mindplot/src/components/MainTopic.js @@ -0,0 +1,162 @@ +/* + * Copyright [2015] [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 web2d from '@wisemapping/web2d'; + +import Topic from './Topic'; +import { TopicShape } from './model/INodeModel'; +import Shape from './util/Shape'; + +const MainTopic = new Class( + /** @lends MainTopic */ { + Extends: Topic, + /** + * @extends mindplot.Topic + * @constructs + * @param model + * @param options + */ + initialize(model, options) { + this.parent(model, options); + }, + + INNER_RECT_ATTRIBUTES: { stroke: '0.5 solid #009900' }, + + _buildDragShape() { + const innerShape = this._buildShape(this.INNER_RECT_ATTRIBUTES, this.getShapeType()); + const size = this.getSize(); + innerShape.setSize(size.width, size.height); + innerShape.setPosition(0, 0); + innerShape.setOpacity(0.5); + innerShape.setCursor('default'); + innerShape.setVisibility(true); + + const brColor = this.getBorderColor(); + innerShape.setAttribute('strokeColor', brColor); + + const bgColor = this.getBackgroundColor(); + innerShape.setAttribute('fillColor', bgColor); + + // Create group ... + const groupAttributes = { + width: 100, + height: 100, + coordSizeWidth: 100, + coordSizeHeight: 100, + }; + const group = new web2d.Group(groupAttributes); + group.append(innerShape); + + // Add Text ... + if (this.getShapeType() !== TopicShape.IMAGE) { + const textShape = this._buildTextShape(true); + const text = this.getText(); + textShape.setText(text); + textShape.setOpacity(0.5); + group.append(textShape); + } + return group; + }, + + /** */ + updateTopicShape(targetTopic, workspace) { + // Change figure based on the connected topic ... + const model = this.getModel(); + let shapeType = model.getShapeType(); + if (!targetTopic.isCentralTopic()) { + if (!$defined(shapeType)) { + // Get the real shape type ... + shapeType = this.getShapeType(); + this._setShapeType(shapeType, false); + } + } + }, + + /** */ + disconnect(workspace) { + this.parent(workspace); + const size = this.getSize(); + + const model = this.getModel(); + let shapeType = model.getShapeType(); + if (!$defined(shapeType)) { + // Change figure ... + shapeType = this.getShapeType(); + this._setShapeType(TopicShape.ROUNDED_RECT, false); + } + const innerShape = this.getInnerShape(); + innerShape.setVisibility(true); + }, + + _updatePositionOnChangeSize(oldSize, newSize) { + const xOffset = Math.round((newSize.width - oldSize.width) / 2); + const pos = this.getPosition(); + if ($defined(pos)) { + if (pos.x > 0) { + pos.x += xOffset; + } else { + pos.x -= xOffset; + } + this.setPosition(pos); + } + }, + + /** */ + workoutIncomingConnectionPoint(sourcePosition) { + return Shape.workoutIncomingConnectionPoint(this, sourcePosition); + }, + + /** */ + workoutOutgoingConnectionPoint(targetPosition) { + $assert(targetPosition, 'targetPoint can not be null'); + const pos = this.getPosition(); + const isAtRight = Shape.isAtRight(targetPosition, pos); + const size = this.getSize(); + + let result; + if (this.getShapeType() === TopicShape.LINE) { + result = new web2d.Point(); + const groupPosition = this._elem2d.getPosition(); + const innerShareSize = this.getInnerShape().getSize(); + + if (innerShareSize) { + const magicCorrectionNumber = 0.3; + if (!isAtRight) { + result.x = groupPosition.x + innerShareSize.width - magicCorrectionNumber; + } else { + result.x = groupPosition.x + magicCorrectionNumber; + } + result.y = groupPosition.y + innerShareSize.height; + } else { + // Hack: When the size has not being defined. This is because the node has not being added. + // Try to do our best ... + if (!isAtRight) { + result.x = pos.x + size.width / 2; + } else { + result.x = pos.x - size.width / 2; + } + result.y = pos.y + size.height / 2; + } + } else { + result = Shape.calculateRectConnectionPoint(pos, size, isAtRight, true); + } + return result; + }, + }, +); + +export default MainTopic; diff --git a/packages/mindplot/lib/components/Messages.js b/packages/mindplot/src/components/Messages.js similarity index 69% rename from packages/mindplot/lib/components/Messages.js rename to packages/mindplot/src/components/Messages.js index 49cf03e4..2d9c162f 100644 --- a/packages/mindplot/lib/components/Messages.js +++ b/packages/mindplot/src/components/Messages.js @@ -17,25 +17,24 @@ */ const Messages = new Class({ - Static: { - init(locale) { - locale = $defined(locale) ? locale : 'en'; - let bundle = Messages.BUNDLES[locale]; - if (bundle == null && locale.indexOf('_') != -1) { - // Try to locate without the specialization ... - locale = locale.substring(0, locale.indexOf('_')); - bundle = Messages.BUNDLES[locale]; - } - Messages.__bundle = bundle; - }, - }, + }); -global.$msg = function (key) { +Messages.init = (locale) => { + locale = $defined(locale) ? locale : 'en'; + let bundle = Messages.BUNDLES[locale]; + if (bundle == null && locale.indexOf('_') !== -1) { + // Try to locate without the specialization ... + locale = locale.substring(0, locale.indexOf('_')); + bundle = Messages.BUNDLES[locale]; + } + Messages.__bundle = bundle || {}; +}; + +global.$msg = function $msg(key) { if (!Messages.__bundle) { Messages.init('en'); } - const msg = Messages.__bundle[key]; return msg || key; }; diff --git a/packages/mindplot/lib/components/MultilineTextEditor.js b/packages/mindplot/src/components/MultilineTextEditor.js similarity index 98% rename from packages/mindplot/lib/components/MultilineTextEditor.js rename to packages/mindplot/src/components/MultilineTextEditor.js index c6a4fabc..080a597c 100644 --- a/packages/mindplot/lib/components/MultilineTextEditor.js +++ b/packages/mindplot/src/components/MultilineTextEditor.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('./Events').default; -const ActionDispatcher = require('./ActionDispatcher').default; +import Events from './Events'; +import ActionDispatcher from './ActionDispatcher'; const MultilineTextEditor = new Class({ Extends: Events, diff --git a/packages/mindplot/lib/components/NodeGraph.js b/packages/mindplot/src/components/NodeGraph.js similarity index 74% rename from packages/mindplot/lib/components/NodeGraph.js rename to packages/mindplot/src/components/NodeGraph.js index 8e047cc2..003b9d69 100644 --- a/packages/mindplot/lib/components/NodeGraph.js +++ b/packages/mindplot/src/components/NodeGraph.js @@ -15,9 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Topic = require('./Topic').default; -const DragTopic = require('./DragTopic').default; -const INodeModel = require('./model/INodeModel').default; +import TopicConfig from './TopicConfig'; +import DragTopic from './DragTopic'; const NodeGraph = new Class( /** @lends NodeGraph */ { @@ -72,7 +71,7 @@ const NodeGraph = new Class( /** @abstract */ setPosition(point, fireEvent) { - throw 'Unsupported operation'; + throw new Error('Unsupported operation'); }, /** */ @@ -110,8 +109,8 @@ const NodeGraph = new Class( /** @param {Object} size */ setSize(size) { - this._size.width = parseInt(size.width); - this._size.height = parseInt(size.height); + this._size.width = parseInt(size.width, 10); + this._size.height = parseInt(size.height, 10); }, /** @@ -138,14 +137,14 @@ const NodeGraph = new Class( /** */ setOnFocus(focus) { - if (this._onFocus != focus) { + if (this._onFocus !== focus) { this._onFocus = focus; const outerShape = this.getOuterShape(); if (focus) { - outerShape.setFill(Topic.OUTER_SHAPE_ATTRIBUTES_FOCUS.fillColor); + outerShape.setFill(TopicConfig.OUTER_SHAPE_ATTRIBUTES_FOCUS.fillColor); outerShape.setOpacity(1); } else { - outerShape.setFill(Topic.OUTER_SHAPE_ATTRIBUTES.fillColor); + outerShape.setFill(TopicConfig.OUTER_SHAPE_ATTRIBUTES.fillColor); outerShape.setOpacity(0); } this.setCursor('move'); @@ -187,36 +186,4 @@ const NodeGraph = new Class( }, ); -/** - * creates a new topic from the given node model - * @memberof mindplot.Nodegraph - * @param {mindplot.model.NodeModel} nodeModel - * @param {Object} options - * @throws will throw an error if nodeModel is null or undefined - * @throws will throw an error if the nodeModel's type is null or undefined - * @throws will throw an error if the node type cannot be recognized as either central or main - * topic type - * @return {mindplot.CentralTopic|mindplot.MainTopic} the new topic - */ -NodeGraph.create = function (nodeModel, options) { - const CentralTopic = require('./CentralTopic').default; - const MainTopic = require('./MainTopic').default; - - $assert(nodeModel, 'Model can not be null'); - - const type = nodeModel.getType(); - $assert(type, 'Node model type can not be null'); - - let result; - if (type == INodeModel.CENTRAL_TOPIC_TYPE) { - result = new CentralTopic(nodeModel, options); - } else if (type == INodeModel.MAIN_TOPIC_TYPE) { - result = new MainTopic(nodeModel, options); - } else { - $assert(false, `unsupported node type:${type}`); - } - - return result; -}; - export default NodeGraph; diff --git a/packages/mindplot/src/components/NodeGraphUtils.js b/packages/mindplot/src/components/NodeGraphUtils.js new file mode 100644 index 00000000..3b466eb3 --- /dev/null +++ b/packages/mindplot/src/components/NodeGraphUtils.js @@ -0,0 +1,36 @@ +import CentralTopic from './CentralTopic'; +import MainTopic from './MainTopic'; +import INodeModel from './model/INodeModel'; + +/** + * creates a new topic from the given node model + * @memberof mindplot.Nodegraph + * @param {mindplot.model.NodeModel} nodeModel + * @param {Object} options + * @throws will throw an error if nodeModel is null or undefined + * @throws will throw an error if the nodeModel's type is null or undefined + * @throws will throw an error if the node type cannot be recognized as either central or main + * topic type + * @return {mindplot.CentralTopic|mindplot.MainTopic} the new topic + */ +export const create = (nodeModel, options) => { + $assert(nodeModel, 'Model can not be null'); + + const type = nodeModel.getType(); + $assert(type, 'Node model type can not be null'); + + let result; + if (type === INodeModel.CENTRAL_TOPIC_TYPE) { + result = new CentralTopic(nodeModel, options); + } else if (type === INodeModel.MAIN_TOPIC_TYPE) { + result = new MainTopic(nodeModel, options); + } else { + $assert(false, `unsupported node type:${type}`); + } + + return result; +}; + +export default { + create, +}; diff --git a/packages/mindplot/lib/components/NoteIcon.js b/packages/mindplot/src/components/NoteIcon.js similarity index 85% rename from packages/mindplot/lib/components/NoteIcon.js rename to packages/mindplot/src/components/NoteIcon.js index a1a4f1da..2a42ea62 100644 --- a/packages/mindplot/lib/components/NoteIcon.js +++ b/packages/mindplot/src/components/NoteIcon.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Icon = require('./Icon').default; -const FloatingTip = require('./widget/FloatingTip').default; +import Icon from './Icon'; +import FloatingTip from './widget/FloatingTip'; const NoteIcon = new Class({ Extends: Icon, @@ -42,7 +42,7 @@ const NoteIcon = new Class({ event.stopPropagation(); }); } - this._tip = new FloatingTip($(me.getImage()._peer._native), { + this._tip = new FloatingTip($(me.getImage().peer._native), { title: $msg('NOTE'), container: 'body', // Content can also be a function of the target element! @@ -56,13 +56,13 @@ const NoteIcon = new Class({ }, _buildTooltipContent() { - if ($('body').find('#textPopoverNote').length == 1) { - var text = $('body').find('#textPopoverNote'); + if ($('body').find('#textPopoverNote').length === 1) { + const text = $('body').find('#textPopoverNote'); text.text(this._linksModel.getText()); } else { const result = $('
').css({ padding: '5px' }); - var text = $('
').text(this._linksModel.getText()) + const text = $('
').text(this._linksModel.getText()) .css({ 'white-space': 'pre-wrap', 'word-wrap': 'break-word', diff --git a/packages/mindplot/lib/components/Options.js b/packages/mindplot/src/components/Options.js similarity index 100% rename from packages/mindplot/lib/components/Options.js rename to packages/mindplot/src/components/Options.js diff --git a/packages/mindplot/lib/components/PersistenceManager.js b/packages/mindplot/src/components/PersistenceManager.js similarity index 84% rename from packages/mindplot/lib/components/PersistenceManager.js rename to packages/mindplot/src/components/PersistenceManager.js index b3e3ceba..59c63683 100644 --- a/packages/mindplot/lib/components/PersistenceManager.js +++ b/packages/mindplot/src/components/PersistenceManager.js @@ -15,22 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import Core from '@wisemapping/core-js'; +import XMLSerializerFactory from './persistence/XMLSerializerFactory'; const core = Core(); -const XMLSerializerFactory = require('./persistence/XMLSerializerFactory'); const PersistenceManager = new Class({ - Static: { - loadFromDom(mapId, mapDom) { - $assert(mapId, 'mapId can not be null'); - $assert(mapDom, 'mapDom can not be null'); - - const serializer = XMLSerializerFactory.getSerializerFromDocument(mapDom); - return serializer.loadFromDom(mapDom, mapId); - }, - }, - initialize() {}, save(mindmap, editorProperties, saveHistory, events, sync) { @@ -84,4 +74,12 @@ PersistenceManager.getInstance = function () { return PersistenceManager._instance; }; +PersistenceManager.loadFromDom = function loadFromDom(mapId, mapDom) { + $assert(mapId, 'mapId can not be null'); + $assert(mapDom, 'mapDom can not be null'); + + const serializer = XMLSerializerFactory.getSerializerFromDocument(mapDom); + return serializer.loadFromDom(mapDom, mapId); +}; + export default PersistenceManager; diff --git a/packages/mindplot/lib/components/Relationship.js b/packages/mindplot/src/components/Relationship.js similarity index 89% rename from packages/mindplot/lib/components/Relationship.js rename to packages/mindplot/src/components/Relationship.js index a587fe03..d0d233b7 100644 --- a/packages/mindplot/lib/components/Relationship.js +++ b/packages/mindplot/src/components/Relationship.js @@ -15,29 +15,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); +import ConnectionLine from './ConnectionLine'; +import ControlPoint from './ControlPoint'; -const web2D = require('@wismapping/web2d'); +import INodeModel from './model/INodeModel'; -const web2d = web2D(); - -const ConnectionLine = require('./ConnectionLine').default; -const ControlPoint = require('./ControlPoint').default; - -const INodeModel = require('./model/INodeModel').default; - -const Shape = require('./util/Shape').default; +import Shape from './util/Shape'; const Relationship = new Class({ Extends: ConnectionLine, - Static: { - getStrokeColor() { - return '#9b74e6'; - }, - type: 'Relationship', - }, + initialize(sourceNode, targetNode, model) { $assert(sourceNode, 'sourceNode can not be null'); $assert(targetNode, 'targetNode can not be null'); @@ -98,29 +87,32 @@ const Relationship = new Class({ const targetTopic = this._targetTopic; let targetPosition = targetTopic.getPosition(); - if (targetTopic.getType() == INodeModel.CENTRAL_TOPIC_TYPE) { + if (targetTopic.getType() === INodeModel.CENTRAL_TOPIC_TYPE) { targetPosition = Shape.workoutIncomingConnectionPoint(targetTopic, sourcePosition); } - let sPos; let - tPos; + let sPos; + let tPos; this._line2d.setStroke(2); const ctrlPoints = this._line2d.getControlPoints(); if (!this._line2d.isDestControlPointCustom() && !this._line2d.isSrcControlPointCustom()) { - const defaultPoints = Shape.calculateDefaultControlPoints(sourcePosition, targetPosition); + const defaultPoints = Shape.calculateDefaultControlPoints( + sourcePosition, + targetPosition, + ); ctrlPoints[0].x = defaultPoints[0].x; ctrlPoints[0].y = defaultPoints[0].y; ctrlPoints[1].x = defaultPoints[1].x; ctrlPoints[1].y = defaultPoints[1].y; } - const spoint = new core.Point(); - spoint.x = parseInt(ctrlPoints[0].x) + parseInt(sourcePosition.x); - spoint.y = parseInt(ctrlPoints[0].y) + parseInt(sourcePosition.y); + const spoint = new web2d.Point(); + spoint.x = parseInt(ctrlPoints[0].x, 10) + parseInt(sourcePosition.x, 10); + spoint.y = parseInt(ctrlPoints[0].y, 10) + parseInt(sourcePosition.y, 10); - const tpoint = new core.Point(); - tpoint.x = parseInt(ctrlPoints[1].x) + parseInt(targetPosition.x); - tpoint.y = parseInt(ctrlPoints[1].y) + parseInt(targetPosition.y); + const tpoint = new web2d.Point(); + tpoint.x = parseInt(ctrlPoints[1].x, 10) + parseInt(targetPosition.x, 10); + tpoint.y = parseInt(ctrlPoints[1].y, 10) + parseInt(targetPosition.y, 10); sPos = Shape.calculateRelationShipPointCoordinates(sourceTopic, spoint); tPos = Shape.calculateRelationShipPointCoordinates(targetTopic, tpoint); @@ -155,7 +147,7 @@ const Relationship = new Class({ this._endArrow.moveToBack(); } - if (this._line2d.getType() == 'CurvedLine') { + if (this._line2d.getType() === 'CurvedLine') { const controlPoints = this._line2d.getControlPoints(); this._startArrow.setControlPoint(controlPoints[0]); if (this._endArrow) { @@ -211,7 +203,7 @@ const Relationship = new Class({ setOnFocus(focus) { // Change focus shape - if (this.isOnFocus() != focus) { + if (this.isOnFocus() !== focus) { if (focus) { this._refreshShape(); this._controlPointsController.setLine(this); @@ -240,7 +232,7 @@ const Relationship = new Class({ addEvent(type, listener) { // Translate to web 2d events ... - if (type == 'onfocus') { + if (type === 'onfocus') { type = 'mousedown'; } @@ -334,4 +326,10 @@ const Relationship = new Class({ }, }); +Relationship.getStrokeColor = function getStrokeColor() { + return '#9b74e6'; +}; + +Relationship.type = 'Relationship'; + export default Relationship; diff --git a/packages/mindplot/lib/components/RelationshipPivot.js b/packages/mindplot/src/components/RelationshipPivot.js similarity index 90% rename from packages/mindplot/lib/components/RelationshipPivot.js rename to packages/mindplot/src/components/RelationshipPivot.js index b597e93e..375b310f 100644 --- a/packages/mindplot/lib/components/RelationshipPivot.js +++ b/packages/mindplot/src/components/RelationshipPivot.js @@ -15,14 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; -const core = Core(); -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); -const INodeModel = require('./model/INodeModel').default; -const Shape = require('./util/Shape').default; +import INodeModel from './model/INodeModel'; +import Shape from './util/Shape'; const RelationshipPivot = new Class({ initialize(workspace, designer) { @@ -134,14 +130,14 @@ const RelationshipPivot = new Class({ _calculateFromPosition(toPosition) { // Calculate origin position ... let sourcePosition = this._sourceTopic.getPosition(); - if (this._sourceTopic.getType() == INodeModel.CENTRAL_TOPIC_TYPE) { + if (this._sourceTopic.getType() === INodeModel.CENTRAL_TOPIC_TYPE) { sourcePosition = Shape.workoutIncomingConnectionPoint(this._sourceTopic, toPosition); } const controlPoint = Shape.calculateDefaultControlPoints(sourcePosition, toPosition); - const spoint = new core.Point(); - spoint.x = parseInt(controlPoint[0].x) + parseInt(sourcePosition.x); - spoint.y = parseInt(controlPoint[0].y) + parseInt(sourcePosition.y); + const spoint = new web2d.Point(); + spoint.x = parseInt(controlPoint[0].x, 10) + parseInt(sourcePosition.x, 10); + spoint.y = parseInt(controlPoint[0].y, 10) + parseInt(sourcePosition.y, 10); return Shape.calculateRelationShipPointCoordinates(this._sourceTopic, spoint); }, @@ -150,7 +146,7 @@ const RelationshipPivot = new Class({ const mindmap = this._designer.getMindmap(); // Avoid circular connections ... - if (targetTopic.getId() != sourceTopic.getId()) { + if (targetTopic.getId() !== sourceTopic.getId()) { const relModel = mindmap.createRelationship(targetTopic.getId(), sourceTopic.getId()); this._designer._actionDispatcher.addRelationship(relModel); } diff --git a/packages/mindplot/lib/components/RestPersistenceManager.js b/packages/mindplot/src/components/RestPersistenceManager.js similarity index 98% rename from packages/mindplot/lib/components/RestPersistenceManager.js rename to packages/mindplot/src/components/RestPersistenceManager.js index d5795c83..e3a8cfda 100644 --- a/packages/mindplot/lib/components/RestPersistenceManager.js +++ b/packages/mindplot/src/components/RestPersistenceManager.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const PersistenceManager = require('./PersistenceManager').default; +import PersistenceManager from './PersistenceManager'; const RESTPersistenceManager = new Class({ Extends: PersistenceManager, @@ -81,7 +81,7 @@ const RESTPersistenceManager = new Class({ let userMsg = { severity: 'SEVERE', message: $msg('SAVE_COULD_NOT_BE_COMPLETED') }; const contentType = xhr.getResponseHeader('Content-Type'); - if (contentType != null && contentType.indexOf('application/json') != -1) { + if (contentType != null && contentType.indexOf('application/json') !== -1) { let serverMsg = null; try { serverMsg = $.parseJSON(responseText); diff --git a/packages/mindplot/lib/components/ScreenManager.js b/packages/mindplot/src/components/ScreenManager.js similarity index 86% rename from packages/mindplot/lib/components/ScreenManager.js rename to packages/mindplot/src/components/ScreenManager.js index 83c47b2f..36d8e227 100644 --- a/packages/mindplot/lib/components/ScreenManager.js +++ b/packages/mindplot/src/components/ScreenManager.js @@ -15,9 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); - -const core = Core(); +import web2d from '@wisemapping/web2d'; const ScreenManager = new Class({ initialize(divElement) { @@ -43,12 +41,12 @@ const ScreenManager = new Class({ }, addEvent(event, listener) { - if (event == 'click') this._clickEvents.push(listener); + if (event === 'click') this._clickEvents.push(listener); else this._divContainer.bind(event, listener); }, removeEvent(event, listener) { - if (event == 'click') { + if (event === 'click') { this._clickEvents.remove(listener); } else { this._divContainer.unbind(event, listener); @@ -56,7 +54,7 @@ const ScreenManager = new Class({ }, fireEvent(type, event) { - if (type == 'click') { + if (type === 'click') { _.each(this._clickEvents, (listener) => { listener(type, event); }); @@ -96,10 +94,13 @@ const ScreenManager = new Class({ const groupSize = group.getSize(); const coordSize = group.getCoordSize(); - const scale = { x: coordSize.width / parseInt(groupSize.width), y: coordSize.height / parseInt(groupSize.height) }; + const scale = { + x: coordSize.width / parseInt(groupSize.width, 10), + y: coordSize.height / parseInt(groupSize.height, 10), + }; - let x = (elementPosition.x - coordOrigin.x - (parseInt(imageSize.width) / 2)) / scale.x; - let y = (elementPosition.y - coordOrigin.y - (parseInt(imageSize.height) / 2)) / scale.y; + let x = (elementPosition.x - coordOrigin.x - parseInt(imageSize.width, 10) / 2) / scale.x; + let y = (elementPosition.y - coordOrigin.y - parseInt(imageSize.height, 10) / 2) / scale.y; // Retrieve iconGroup Position const groupPosition = iconGroup.getPosition(); @@ -109,7 +110,7 @@ const ScreenManager = new Class({ // Retrieve topic Position const topic = iconGroup.getTopic(); const topicPosition = this._getElementPosition(topic); - topicPosition.x -= (parseInt(topic.getSize().width) / 2); + topicPosition.x -= parseInt(topic.getSize().width, 10) / 2; // Remove decimal part.. return { x: x + topicPosition.x, y: y + topicPosition.y }; @@ -134,7 +135,7 @@ const ScreenManager = new Class({ y += this._padding.y; // Remove decimal part.. - return new core.Point(x, y); + return new web2d.Point(x, y); }, getContainer() { diff --git a/packages/mindplot/lib/components/ShrinkConnector.js b/packages/mindplot/src/components/ShrinkConnector.js similarity index 86% rename from packages/mindplot/lib/components/ShrinkConnector.js rename to packages/mindplot/src/components/ShrinkConnector.js index ea02d655..b93f5ef4 100644 --- a/packages/mindplot/lib/components/ShrinkConnector.js +++ b/packages/mindplot/src/components/ShrinkConnector.js @@ -15,20 +15,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const web2D = require('@wismapping/web2d'); +import web2d from '@wisemapping/web2d'; -const web2d = web2D(); - -const Topic = require('./Topic').default; -const ActionDispatcher = require('./ActionDispatcher').default; +import TopicConfig from './TopicConfig'; +import ActionDispatcher from './ActionDispatcher'; const ShirinkConnector = new Class({ initialize(topic) { - const ellipse = new web2D.Elipse(Topic.prototype.INNER_RECT_ATTRIBUTES); + const ellipse = new web2d.Elipse(TopicConfig.INNER_RECT_ATTRIBUTES); this._ellipse = ellipse; ellipse.setFill('rgb(62,118,179)'); - ellipse.setSize(Topic.CONNECTOR_WIDTH, Topic.CONNECTOR_WIDTH); + ellipse.setSize(TopicConfig.CONNECTOR_WIDTH, TopicConfig.CONNECTOR_WIDTH); ellipse.addEvent('click', (event) => { const model = topic.getModel(); const collapse = !model.areChildrenShrunken(); @@ -50,11 +48,11 @@ const ShirinkConnector = new Class({ event.stopPropagation(); }); - ellipse.addEvent('mouseover', (event) => { + ellipse.addEvent('mouseover', () => { ellipse.setFill('rgb(153, 0, 255)'); }); const me = this; - ellipse.addEvent('mouseout', (event) => { + ellipse.addEvent('mouseout', () => { const color = topic.getBackgroundColor(); me.setFill(color); }); diff --git a/packages/mindplot/lib/components/StandaloneActionDispatcher.js b/packages/mindplot/src/components/StandaloneActionDispatcher.js similarity index 89% rename from packages/mindplot/lib/components/StandaloneActionDispatcher.js rename to packages/mindplot/src/components/StandaloneActionDispatcher.js index 0442fa3d..53cefe27 100644 --- a/packages/mindplot/lib/components/StandaloneActionDispatcher.js +++ b/packages/mindplot/src/components/StandaloneActionDispatcher.js @@ -15,18 +15,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ActionDispatcher = require('./ActionDispatcher').default; -const DesignerActionRunner = require('./DesignerActionRunner').default; -const AddTopicCommand = require('./commands/AddTopicCommand').default; -const AddRelationshipCommand = require('./commands/AddRelationshipCommand').default; -const AddFeatureToTopicCommand = require('./commands/AddFeatureToTopicCommand').default; -const DeleteCommand = require('./commands/DeleteCommand').default; -const RemoveFeatureFromTopicCommand = require('./commands/RemoveFeatureFromTopicCommand').default; -const DragTopicCommand = require('./commands/DragTopicCommand').default; -const GenericFunctionCommand = require('./commands/GenericFunctionCommand').default; -const MoveControlPointCommand = require('./commands/MoveControlPointCommand').default; -const ChangeFeatureToTopicCommand = require('./commands/ChangeFeatureToTopicCommand').default; -const NodeModel = require('./model/NodeModel').default; +import ActionDispatcher from './ActionDispatcher'; +import DesignerActionRunner from './DesignerActionRunner'; +import AddTopicCommand from './commands/AddTopicCommand'; +import AddRelationshipCommand from './commands/AddRelationshipCommand'; +import AddFeatureToTopicCommand from './commands/AddFeatureToTopicCommand'; +import DeleteCommand from './commands/DeleteCommand'; +import RemoveFeatureFromTopicCommand from './commands/RemoveFeatureFromTopicCommand'; +import DragTopicCommand from './commands/DragTopicCommand'; +import GenericFunctionCommand from './commands/GenericFunctionCommand'; +import MoveControlPointCommand from './commands/MoveControlPointCommand'; +import ChangeFeatureToTopicCommand from './commands/ChangeFeatureToTopicCommand'; +import NodeModel from './model/NodeModel'; const StandaloneActionDispatcher = new Class( /** @lends StandaloneActionDispatcher */ { @@ -93,7 +93,7 @@ const StandaloneActionDispatcher = new Class( changeFontStyleToTopic(topicsIds) { const commandFunc = function (topic) { const result = topic.getFontStyle(); - const style = result == 'italic' ? 'normal' : 'italic'; + const style = result === 'italic' ? 'normal' : 'italic'; topic.setFontStyle(style, true); return result; }; @@ -219,7 +219,7 @@ const StandaloneActionDispatcher = new Class( const commandFunc = function (topic) { const result = topic.getFontWeight(); - const weight = result == 'bold' ? 'normal' : 'bold'; + const weight = result === 'bold' ? 'normal' : 'bold'; topic.setFontWeight(weight, true); topic._adjustShapes(); @@ -289,10 +289,10 @@ const CommandContext = new Class( const designerTopics = this._designer.getModel().getTopics(); const result = designerTopics.filter((topic) => topicsIds.contains(topic.getId())); - if (result.length != topicsIds.length) { + if (result.length !== topicsIds.length) { const ids = designerTopics.map((topic) => topic.getId()); $assert( - result.length == topicsIds.length, + result.length === topicsIds.length, `Could not find topic. Result:${ result }, Filter Criteria:${ diff --git a/packages/mindplot/lib/components/TextEditor.js b/packages/mindplot/src/components/TextEditor.js similarity index 92% rename from packages/mindplot/lib/components/TextEditor.js rename to packages/mindplot/src/components/TextEditor.js index 29864daf..2b54422d 100644 --- a/packages/mindplot/lib/components/TextEditor.js +++ b/packages/mindplot/src/components/TextEditor.js @@ -12,11 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const web2D = require('@wismapping/web2d'); +import web2d from '@wisemapping/web2d'; -const web2d = web2D(); - -const ActionDispatcher = require('./ActionDispatcher').default; +import ActionDispatcher from './ActionDispatcher'; // FIXME: Not used! const TextEditor = new Class({ @@ -42,12 +40,11 @@ const TextEditor = new Class({ }); inputContainer.inject(result); - const inputText = new Element('input', - { - type: 'text', - tabindex: '-1', - value: '', - }); + const inputText = new Element('input', { + type: 'text', + tabindex: '-1', + value: '', + }); inputText.setStyles({ border: 'none', background: 'transparent', @@ -82,8 +79,9 @@ const TextEditor = new Class({ default: spanElem.innerHTML = inputElem.value; var size = inputElem.value.length + 1; + inputElem.size = size; - if (spanElem.offsetWidth > (parseInt(divElem.style.width) - 100)) { + if (spanElem.offsetWidth > parseInt(divElem.style.width, 10) - 100) { divElem.style.width = `${spanElem.offsetWidth + 100}px`; } break; @@ -104,11 +102,11 @@ const TextEditor = new Class({ }, isVisible() { - return $defined(this._containerElem) && this._containerElem.getStyle('display') == 'block'; + return $defined(this._containerElem) && this._containerElem.getStyle('display') === 'block'; }, _updateModel() { - if (this._topic.getText() != this._getText()) { + if (this._topic.getText() !== this._getText()) { const text = this._getText(); const topicId = this._topic.getId(); @@ -196,7 +194,9 @@ const TextEditor = new Class({ _setText(text) { const inputField = this._getTextareaElem(); inputField.size = text.length + 1; - this._containerElem.style.width = `${inputField.size * parseInt(inputField.style.fontSize) + 100}px`; + this._containerElem.style.width = `${ + inputField.size * parseInt(inputField.style.fontSize, 10) + 100 + }px`; const spanField = this._getSpanElem(); spanField.innerHTML = text; inputField.value = text; @@ -216,7 +216,7 @@ const TextEditor = new Class({ _setEditorSize(width, height) { const textShape = this._topic.getTextShape(); - const scale = web2d.utils.TransformUtil.workoutScale(textShape._peer); + const scale = web2d.utils.TransformUtil.workoutScale(textShape.peer); this._size = { width: width * scale.width, height: height * scale.height }; this._containerElem.style.width = `${this._size.width * 2}px`; this._containerElem.style.height = `${this._size.height}px`; @@ -224,8 +224,8 @@ const TextEditor = new Class({ _positionCursor(inputElem, selectText) { // Select text if it's required ... - if (inputElem.createTextRange) // ie - { + if (inputElem.createTextRange) { + // ie const range = inputElem.createTextRange(); const pos = inputElem.value.length; if (!selectText) { diff --git a/packages/mindplot/lib/components/TextEditorFactory.js b/packages/mindplot/src/components/TextEditorFactory.js similarity index 95% rename from packages/mindplot/lib/components/TextEditorFactory.js rename to packages/mindplot/src/components/TextEditorFactory.js index a2016404..ff9ed8fa 100644 --- a/packages/mindplot/lib/components/TextEditorFactory.js +++ b/packages/mindplot/src/components/TextEditorFactory.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const TextEditor = require('./TextEditor').default; +import TextEditor from './TextEditor'; const TextEditorFactory = {}; diff --git a/packages/mindplot/lib/components/Topic.js b/packages/mindplot/src/components/Topic.js similarity index 94% rename from packages/mindplot/lib/components/Topic.js rename to packages/mindplot/src/components/Topic.js index 5bd9922e..252d38d0 100644 --- a/packages/mindplot/lib/components/Topic.js +++ b/packages/mindplot/src/components/Topic.js @@ -15,23 +15,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const web2D = require('@wismapping/web2d'); +import web2d from '@wisemapping/web2d'; -const web2d = web2D(); -const NodeGraph = require('./NodeGraph').default; -const { TopicShape } = require('./model/INodeModel'); -const TopicStyle = require('./TopicStyle').default; -const TopicFeature = require('./TopicFeature').default; -const ConnectionLine = require('./ConnectionLine').default; -const IconGroup = require('./IconGroup').default; -const FadeEffect = require('./util/FadeEffect').default; -const EventBus = require('./layout/EventBus').default; -const ShirinkConnector = require('./ShrinkConnector').default; -const NoteEditor = require('./widget/NoteEditor').default; -const ActionDispatcher = require('./ActionDispatcher').default; -const LinkEditor = require('./widget/LinkEditor').default; -const TopicEventDispatcher = require('./TopicEventDispatcher').default; -const INodeModel = require('./model/INodeModel').default; +import NodeGraph from './NodeGraph'; +import TopicConfig from './TopicConfig'; +import TopicStyle from './TopicStyle'; +import TopicFeature from './TopicFeature'; +import ConnectionLine from './ConnectionLine'; +import IconGroup from './IconGroup'; +import FadeEffect from './util/FadeEffect'; +import EventBus from './layout/EventBus'; +import ShirinkConnector from './ShrinkConnector'; +import NoteEditor from './widget/NoteEditor'; +import ActionDispatcher from './ActionDispatcher'; +import LinkEditor from './widget/LinkEditor'; +import TopicEventDispatcher, { TopicEvent } from './TopicEventDispatcher'; +import INodeModel, { TopicShape } from './model/INodeModel'; const Topic = new Class( /** @lends Topic */ { @@ -151,7 +150,7 @@ const Topic = new Class( if (!$defined(this._innerShape)) { // Create inner box. this._innerShape = this._buildShape( - Topic.INNER_RECT_ATTRIBUTES, + TopicConfig.INNER_RECT_ATTRIBUTES, this.getShapeType(), ); @@ -178,9 +177,9 @@ const Topic = new Class( $assert(shapeType, 'shapeType can not be null'); let result; - if (shapeType == TopicShape.RECTANGLE) { + if (shapeType === TopicShape.RECTANGLE) { result = new web2d.Rect(0, attributes); - } else if (shapeType == TopicShape.IMAGE) { + } else if (shapeType === TopicShape.IMAGE) { const model = this.getModel(); const url = model.getImageUrl(); const size = model.getImageSize(); @@ -194,11 +193,11 @@ const Topic = new Class( }; result.setPosition = function () {}; - } else if (shapeType == TopicShape.ELLIPSE) { + } else if (shapeType === TopicShape.ELLIPSE) { result = new web2d.Rect(0.9, attributes); - } else if (shapeType == TopicShape.ROUNDED_RECT) { + } else if (shapeType === TopicShape.ROUNDED_RECT) { result = new web2d.Rect(0.3, attributes); - } else if (shapeType == TopicShape.LINE) { + } else if (shapeType === TopicShape.LINE) { result = new web2d.Line({ strokeColor: '#495879', strokeWidth: 1 }); result.setSize = function (width, height) { this.size = { width, height }; @@ -241,7 +240,10 @@ const Topic = new Class( /** @return outer shape */ getOuterShape() { if (!$defined(this._outerShape)) { - const rect = this._buildShape(Topic.OUTER_SHAPE_ATTRIBUTES, TopicShape.ROUNDED_RECT); + const rect = this._buildShape( + TopicConfig.OUTER_SHAPE_ATTRIBUTES, + TopicShape.ROUNDED_RECT, + ); rect.setPosition(-2, -3); rect.setOpacity(0); this._outerShape = rect; @@ -293,7 +295,7 @@ const Topic = new Class( const icon = TopicFeature.createIcon(this, featureModel, this.isReadOnly()); result.addIcon( icon, - featureModel.getType() == TopicFeature.Icon.id && !this.isReadOnly(), + featureModel.getType() === TopicFeature.Icon.id && !this.isReadOnly(), ); } @@ -316,7 +318,7 @@ const Topic = new Class( const result = TopicFeature.createIcon(this, featureModel, this.isReadOnly()); iconGroup.addIcon( result, - featureModel.getType() == TopicFeature.Icon.id && !this.isReadOnly(), + featureModel.getType() === TopicFeature.Icon.id && !this.isReadOnly(), ); this._adjustShapes(); @@ -506,7 +508,7 @@ const Topic = new Class( /** */ setText(text) { // Avoid empty nodes ... - if (!text || $.trim(text).length == 0) { + if (!text || $.trim(text).length === 0) { text = null; } @@ -606,7 +608,7 @@ const Topic = new Class( // Update figure size ... const model = this.getModel(); - if (model.getFeatures().length != 0) { + if (model.getFeatures().length !== 0) { this.getOrBuildIconGroup(); } @@ -1334,34 +1336,4 @@ const Topic = new Class( }, ); -/** - * @constant - * @type {Number} - * @default - */ -Topic.CONNECTOR_WIDTH = 6; -/** - * @constant - * @type {Object} - * @default - */ -Topic.OUTER_SHAPE_ATTRIBUTES = { - fillColor: 'rgb(252,235,192)', - stroke: '1 dot rgb(241,163,39)', - x: 0, - y: 0, -}; -/** - * @constant - * @type {Object} - * @default - */ -Topic.OUTER_SHAPE_ATTRIBUTES_FOCUS = { fillColor: 'rgb(244,184,45)', x: 0, y: 0 }; -/** - * @constant - * @type {Object} - * @default - * */ -Topic.INNER_RECT_ATTRIBUTES = { stroke: '2 solid' }; - export default Topic; diff --git a/packages/mindplot/src/components/TopicConfig.js b/packages/mindplot/src/components/TopicConfig.js new file mode 100644 index 00000000..731511d2 --- /dev/null +++ b/packages/mindplot/src/components/TopicConfig.js @@ -0,0 +1,36 @@ +/** + * @constant + * @type {Number} + * @default + */ +export const CONNECTOR_WIDTH = 6; +/** + * @constant + * @type {Object} + * @default + */ +export const OUTER_SHAPE_ATTRIBUTES = { + fillColor: 'rgb(252,235,192)', + stroke: '1 dot rgb(241,163,39)', + x: 0, + y: 0, +}; +/** + * @constant + * @type {Object} + * @default + */ +export const OUTER_SHAPE_ATTRIBUTES_FOCUS = { fillColor: 'rgb(244,184,45)', x: 0, y: 0 }; +/** + * @constant + * @type {Object} + * @default + * */ +export const INNER_RECT_ATTRIBUTES = { stroke: '2 solid' }; + +export default { + CONNECTOR_WIDTH, + OUTER_SHAPE_ATTRIBUTES, + OUTER_SHAPE_ATTRIBUTES_FOCUS, + INNER_RECT_ATTRIBUTES, +}; diff --git a/packages/mindplot/lib/components/TopicEventDispatcher.js b/packages/mindplot/src/components/TopicEventDispatcher.js similarity index 78% rename from packages/mindplot/lib/components/TopicEventDispatcher.js rename to packages/mindplot/src/components/TopicEventDispatcher.js index e82bccf5..a31273b1 100644 --- a/packages/mindplot/lib/components/TopicEventDispatcher.js +++ b/packages/mindplot/src/components/TopicEventDispatcher.js @@ -15,23 +15,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('./Events').default; -const MultilineTextEditor = require('./MultilineTextEditor').default; -const { TopicShape } = require('./model/INodeModel'); +import Events from './Events'; +import MultilineTextEditor from './MultilineTextEditor'; +import { TopicShape } from './model/INodeModel'; + +const TopicEvent = { + EDIT: 'editnode', + CLICK: 'clicknode', +}; const TopicEventDispatcher = new Class({ Extends: Events, - Static: { - _instance: null, - - configure(readOnly) { - this._instance = new TopicEventDispatcher(readOnly); - }, - - getInstance() { - return this._instance; - }, - }, initialize(readOnly) { this._readOnly = readOnly; @@ -61,9 +55,9 @@ const TopicEventDispatcher = new Class({ // Open the new editor ... const model = topic.getModel(); if ( - model.getShapeType() != TopicShape.IMAGE + model.getShapeType() !== TopicShape.IMAGE && !this._readOnly - && eventType == TopicEvent.EDIT + && eventType === TopicEvent.EDIT ) { this._multilineEditor.show(topic, options ? options.text : null); this._activeEditor = this._multilineEditor; @@ -77,10 +71,15 @@ const TopicEventDispatcher = new Class({ }, }); -const TopicEvent = { - EDIT: 'editnode', - CLICK: 'clicknode', +TopicEventDispatcher._instance = null; + +TopicEventDispatcher.configure = function configure(readOnly) { + this._instance = new TopicEventDispatcher(readOnly); +}; + +TopicEventDispatcher.getInstance = function getInstance() { + return this._instance; }; export { TopicEvent }; -export default TopicEvent; +export default TopicEventDispatcher; diff --git a/packages/mindplot/lib/components/TopicFeature.js b/packages/mindplot/src/components/TopicFeature.js similarity index 87% rename from packages/mindplot/lib/components/TopicFeature.js rename to packages/mindplot/src/components/TopicFeature.js index 1312349c..758173a1 100644 --- a/packages/mindplot/lib/components/TopicFeature.js +++ b/packages/mindplot/src/components/TopicFeature.js @@ -17,12 +17,12 @@ */ /** */ -const IconModel = require('./model/IconModel').default; -const ImageIcon = require('./ImageIcon').default; -const LinkModel = require('./model/LinkModel').default; -const LinkIcon = require('./LinkIcon').default; -const NoteModel = require('./model/NoteModel').default; -const NoteIcon = require('./NoteIcon').default; +import IconModel from './model/IconModel'; +import ImageIcon from './ImageIcon'; +import LinkModel from './model/LinkModel'; +import LinkIcon from './LinkIcon'; +import NoteModel from './model/NoteModel'; +import NoteIcon from './NoteIcon'; const TopicFeature = { /** the icon object */ @@ -51,7 +51,7 @@ const TopicFeature = { * @return {Boolean} returns true if the given id is contained in the metadata array */ isSupported(id) { - return TopicFeature._featuresMetadataById.some((elem) => elem.id == id); + return TopicFeature._featuresMetadataById.some((elem) => elem.id === id); }, /** @@ -66,7 +66,7 @@ const TopicFeature = { $assert(type, 'type can not be null'); $assert(attributes, 'attributes can not be null'); - const { model } = TopicFeature._featuresMetadataById.filter((elem) => elem.id == type)[0]; + const { model } = TopicFeature._featuresMetadataById.filter((elem) => elem.id === type)[0]; return new model(attributes); }, @@ -82,7 +82,7 @@ const TopicFeature = { $assert(topic, 'topic can not be null'); $assert(model, 'model can not be null'); - const { icon } = TopicFeature._featuresMetadataById.filter((elem) => elem.id == model.getType())[0]; + const { icon } = TopicFeature._featuresMetadataById.filter((elem) => elem.id === model.getType())[0]; return new icon(topic, model, readOnly); }, }; diff --git a/packages/mindplot/lib/components/TopicStyle.js b/packages/mindplot/src/components/TopicStyle.js similarity index 61% rename from packages/mindplot/lib/components/TopicStyle.js rename to packages/mindplot/src/components/TopicStyle.js index 9e34da5c..7db56086 100644 --- a/packages/mindplot/lib/components/TopicStyle.js +++ b/packages/mindplot/src/components/TopicStyle.js @@ -15,57 +15,55 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const { TopicShape } = require('./model/INodeModel'); +import { TopicShape } from './model/INodeModel'; -const TopicStyle = new Class({ - Static: { - _getStyles(topic) { - $assert(topic, 'topic can not be null'); +const TopicStyle = new Class({}); - let result; - if (topic.isCentralTopic()) { - result = TopicStyle.STYLES.CENTRAL_TOPIC; +TopicStyle._getStyles = function _getStyles(topic) { + $assert(topic, 'topic can not be null'); + + let result; + if (topic.isCentralTopic()) { + result = TopicStyle.STYLES.CENTRAL_TOPIC; + } else { + const targetTopic = topic.getOutgoingConnectedTopic(); + if ($defined(targetTopic)) { + if (targetTopic.isCentralTopic()) { + result = TopicStyle.STYLES.MAIN_TOPIC; } else { - const targetTopic = topic.getOutgoingConnectedTopic(); - if ($defined(targetTopic)) { - if (targetTopic.isCentralTopic()) { - result = TopicStyle.STYLES.MAIN_TOPIC; - } else { - result = TopicStyle.STYLES.SUB_TOPIC; - } - } else { - result = TopicStyle.STYLES.ISOLATED_TOPIC; - } + result = TopicStyle.STYLES.SUB_TOPIC; } - return result; - }, + } else { + result = TopicStyle.STYLES.ISOLATED_TOPIC; + } + } + return result; +}; - defaultText(topic) { - const { msgKey } = this._getStyles(topic); - return $msg(msgKey); - }, +TopicStyle.defaultText = function defaultText(topic) { + const { msgKey } = this._getStyles(topic); + return $msg(msgKey); +}; - defaultFontStyle(topic) { - return this._getStyles(topic).fontStyle; - }, +TopicStyle.defaultFontStyle = function defaultFontStyle(topic) { + return this._getStyles(topic).fontStyle; +}; - defaultBackgroundColor(topic) { - return this._getStyles(topic).backgroundColor; - }, +TopicStyle.defaultBackgroundColor = function defaultBackgroundColor(topic) { + return this._getStyles(topic).backgroundColor; +}; - defaultBorderColor(topic) { - return this._getStyles(topic).borderColor; - }, +TopicStyle.defaultBorderColor = function defaultBorderColor(topic) { + return this._getStyles(topic).borderColor; +}; - getInnerPadding(topic) { - return this._getStyles(topic).innerPadding; - }, +TopicStyle.getInnerPadding = function getInnerPadding(topic) { + return this._getStyles(topic).innerPadding; +}; - defaultShapeType(topic) { - return this._getStyles(topic).shapeType; - }, - }, -}); +TopicStyle.defaultShapeType = function defaultShapeType(topic) { + return this._getStyles(topic).shapeType; +}; TopicStyle.STYLES = { CENTRAL_TOPIC: { diff --git a/packages/mindplot/lib/components/Workspace.js b/packages/mindplot/src/components/Workspace.js similarity index 97% rename from packages/mindplot/lib/components/Workspace.js rename to packages/mindplot/src/components/Workspace.js index a975525f..80c3be05 100644 --- a/packages/mindplot/lib/components/Workspace.js +++ b/packages/mindplot/src/components/Workspace.js @@ -15,9 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const web2D = require('@wismapping/web2d'); - -const web2d = web2D(); +import web2d from '@wisemapping/web2d'; const Workspace = new Class({ initialize(screenManager, zoom) { @@ -29,8 +27,8 @@ const Workspace = new Class({ this._screenManager = screenManager; const divContainer = screenManager.getContainer(); - this._screenWidth = parseInt(divContainer.css('width')); - this._screenHeight = parseInt(divContainer.css('height')); + this._screenWidth = parseInt(divContainer.css('width'), 10); + this._screenHeight = parseInt(divContainer.css('height'), 10); // Initialize web2d workspace. const workspace = this._createWorkspace(); diff --git a/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.js b/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.js new file mode 100644 index 00000000..b013ffe9 --- /dev/null +++ b/packages/mindplot/src/components/commands/AddFeatureToTopicCommand.js @@ -0,0 +1,70 @@ +/* + * Copyright [2015] [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 Command from '../Command'; + +const AddFeatureToTopicCommand = new Class( + /** @lends AddFeatureToTopicCommand */ { + Extends: Command, + /* + * @classdesc This command class handles do/undo of adding features to topics, e.g. an + * icon or a note. For a reference of existing features, refer to {@link mindplot.TopicFeature} + * @constructs + * @param {String} topicId the id of the topic + * @param {String} featureType the id of the feature type to add, e.g. "icon" + * @param {Object} attributes the attribute(s) of the respective feature model + * @extends mindplot.Command + * @see mindplot.model.FeatureModel and subclasses + */ + initialize(topicId, featureType, attributes) { + $assert($defined(topicId), 'topicId can not be null'); + $assert(featureType, 'featureType can not be null'); + $assert(attributes, 'attributes can not be null'); + + this.parent(); + this._topicId = topicId; + this._featureType = featureType; + this._attributes = attributes; + this._featureModel = null; + }, + + /** + * Overrides abstract parent method + */ + execute(commandContext) { + const topic = commandContext.findTopics(this._topicId)[0]; + + // Feature must be created only one time. + if (!this._featureModel) { + const model = topic.getModel(); + this._featureModel = model.createFeature(this._featureType, this._attributes); + } + topic.addFeature(this._featureModel); + }, + + /** + * Overrides abstract parent method + * @see {@link mindplot.Command.undoExecute} + */ + undoExecute(commandContext) { + const topic = commandContext.findTopics(this._topicId)[0]; + topic.removeFeature(this._featureModel); + }, + }, +); + +export default AddFeatureToTopicCommand; diff --git a/packages/mindplot/lib/components/commands/AddRelationshipCommand.js b/packages/mindplot/src/components/commands/AddRelationshipCommand.js similarity index 97% rename from packages/mindplot/lib/components/commands/AddRelationshipCommand.js rename to packages/mindplot/src/components/commands/AddRelationshipCommand.js index 88180472..cbad2d3e 100644 --- a/packages/mindplot/lib/components/commands/AddRelationshipCommand.js +++ b/packages/mindplot/src/components/commands/AddRelationshipCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const AddRelationshipCommand = new Class(/** @lends AddRelationshipCommand */{ Extends: Command, diff --git a/packages/mindplot/lib/components/commands/AddTopicCommand.js b/packages/mindplot/src/components/commands/AddTopicCommand.js similarity index 84% rename from packages/mindplot/lib/components/commands/AddTopicCommand.js rename to packages/mindplot/src/components/commands/AddTopicCommand.js index 76fde1f5..471d60aa 100644 --- a/packages/mindplot/lib/components/commands/AddTopicCommand.js +++ b/packages/mindplot/src/components/commands/AddTopicCommand.js @@ -15,20 +15,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const AddTopicCommand = new Class( /** @lends AddTopicCommand */ { Extends: Command, /** - * @classdesc This command class handles do/undo of adding one or multiple topics to - * the mindmap. - * @constructs - * @param {Array} models one or multiple models - * @param {Array} parentTopicsId ids of the parent topics to add the children to, or null - * when attaching a dragged node or a node/branch from clipboard - * @extends mindplot.Command - */ + * @classdesc This command class handles do/undo of adding one or multiple topics to + * the mindmap. + * @constructs + * @param {Array} models one or multiple models + * @param {Array} parentTopicsId ids of the parent topics to add the children to, or null + * when attaching a dragged node or a node/branch from clipboard + * @extends mindplot.Command + */ initialize(models, parentTopicsId) { $assert(models, 'models can not be null'); $assert( diff --git a/packages/mindplot/lib/components/commands/ChangeFeatureToTopicCommand.js b/packages/mindplot/src/components/commands/ChangeFeatureToTopicCommand.js similarity index 97% rename from packages/mindplot/lib/components/commands/ChangeFeatureToTopicCommand.js rename to packages/mindplot/src/components/commands/ChangeFeatureToTopicCommand.js index a5dc5625..3babdd1a 100644 --- a/packages/mindplot/lib/components/commands/ChangeFeatureToTopicCommand.js +++ b/packages/mindplot/src/components/commands/ChangeFeatureToTopicCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const ChangeFeatureToTopicCommand = new Class(/** @lends ChangeFeatureToTopicCommand */{ Extends: Command, diff --git a/packages/mindplot/lib/components/commands/DeleteCommand.js b/packages/mindplot/src/components/commands/DeleteCommand.js similarity index 99% rename from packages/mindplot/lib/components/commands/DeleteCommand.js rename to packages/mindplot/src/components/commands/DeleteCommand.js index 00d54c4b..39ab3c10 100644 --- a/packages/mindplot/lib/components/commands/DeleteCommand.js +++ b/packages/mindplot/src/components/commands/DeleteCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const DeleteCommand = new Class(/** @lends mindplot.commands.DeleteCommand */{ Extends: Command, diff --git a/packages/mindplot/lib/components/commands/DragTopicCommand.js b/packages/mindplot/src/components/commands/DragTopicCommand.js similarity index 94% rename from packages/mindplot/lib/components/commands/DragTopicCommand.js rename to packages/mindplot/src/components/commands/DragTopicCommand.js index b0c5135f..1536109b 100644 --- a/packages/mindplot/lib/components/commands/DragTopicCommand.js +++ b/packages/mindplot/src/components/commands/DragTopicCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const DragTopicCommand = new Class(/** @lends DragTopicCommand */{ Extends: Command, @@ -54,7 +54,7 @@ const DragTopicCommand = new Class(/** @lends DragTopicCommand */{ const origPosition = topic.getPosition(); // Disconnect topic .. - if ($defined(origParentTopic) && origParentTopic != this._parentId) { + if ($defined(origParentTopic) && origParentTopic !== this._parentId) { commandContext.disconnect(topic); } @@ -68,7 +68,7 @@ const DragTopicCommand = new Class(/** @lends DragTopicCommand */{ } // Finally, connect topic ... - if (origParentTopic != this._parentId) { + if (origParentTopic !== this._parentId) { if ($defined(this._parentId)) { const parentTopic = commandContext.findTopics(this._parentId)[0]; commandContext.connect(topic, parentTopic); diff --git a/packages/mindplot/lib/components/commands/GenericFunctionCommand.js b/packages/mindplot/src/components/commands/GenericFunctionCommand.js similarity index 97% rename from packages/mindplot/lib/components/commands/GenericFunctionCommand.js rename to packages/mindplot/src/components/commands/GenericFunctionCommand.js index 731f27de..193c7254 100644 --- a/packages/mindplot/lib/components/commands/GenericFunctionCommand.js +++ b/packages/mindplot/src/components/commands/GenericFunctionCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const GenericFunctionCommand = new Class(/** @lends GenericFunctionCommand */{ Extends: Command, @@ -87,7 +87,7 @@ const GenericFunctionCommand = new Class(/** @lends GenericFunctionCommand */{ this.applied = false; this._oldValues = []; } else { - throw 'undo can not be applied.'; + throw new Error('undo can not be applied.'); } }, }); diff --git a/packages/mindplot/lib/components/commands/MoveControlPointCommand.js b/packages/mindplot/src/components/commands/MoveControlPointCommand.js similarity index 96% rename from packages/mindplot/lib/components/commands/MoveControlPointCommand.js rename to packages/mindplot/src/components/commands/MoveControlPointCommand.js index fdfa9e74..c6fc7232 100644 --- a/packages/mindplot/lib/components/commands/MoveControlPointCommand.js +++ b/packages/mindplot/src/components/commands/MoveControlPointCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const MoveControlPointCommand = new Class( /** @lends MoveControlPointCommand */ { @@ -50,6 +50,8 @@ const MoveControlPointCommand = new Class( this._wasCustom = this._line.getLine().isDestControlPointCustom(); this._endPoint = this._line.getLine().getTo().clone(); break; + default: + break; } this._point = point; }, @@ -57,7 +59,7 @@ const MoveControlPointCommand = new Class( /** * Overrides abstract parent method */ - execute(commandContext) { + execute() { const model = this._line.getModel(); switch (this._point) { case 0: @@ -73,6 +75,8 @@ const MoveControlPointCommand = new Class( this._line.setIsDestControlPointCustom(true); this._line.setDestControlPoint(this._controlPoint.clone()); break; + default: + break; } if (this._line.isOnFocus()) { this._line._refreshShape(); @@ -85,7 +89,7 @@ const MoveControlPointCommand = new Class( * Overrides abstract parent method * @see {@link mindplot.Command.undoExecute} */ - undoExecute(commandContext) { + undoExecute() { const line = this._line; const model = line.getModel(); switch (this._point) { @@ -105,6 +109,8 @@ const MoveControlPointCommand = new Class( line.setIsDestControlPointCustom(this._wasCustom); } break; + default: + break; } this._line.getLine().updateLine(this._point); if (this._line.isOnFocus()) { diff --git a/packages/mindplot/lib/components/commands/RemoveFeatureFromTopicCommand.js b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.js similarity index 97% rename from packages/mindplot/lib/components/commands/RemoveFeatureFromTopicCommand.js rename to packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.js index cfd725d1..7e0aa2f7 100644 --- a/packages/mindplot/lib/components/commands/RemoveFeatureFromTopicCommand.js +++ b/packages/mindplot/src/components/commands/RemoveFeatureFromTopicCommand.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Command = require('../Command').default; +import Command from '../Command'; const RemoveFeatureFromTopicCommand = new Class(/** @lends RemoveFeatureFromTopicCommand */{ Extends: Command, diff --git a/packages/mindplot/src/components/commands/index.js b/packages/mindplot/src/components/commands/index.js new file mode 100644 index 00000000..20c113d5 --- /dev/null +++ b/packages/mindplot/src/components/commands/index.js @@ -0,0 +1,21 @@ +import addFeatureToTopicCommand from './AddFeatureToTopicCommand'; +import addRelationshipCommand from './AddRelationshipCommand'; +import addTopicCommand from './AddTopicCommand'; +import changeFeatureToTopicCommand from './ChangeFeatureToTopicCommand'; +import deleteCommand from './DeleteCommand'; +import dragTopicCommand from './DragTopicCommand'; +import genericFunctionCommand from './GenericFunctionCommand'; +import moveControlPointCommand from './MoveControlPointCommand'; +import removeFeatureFromTopicCommand from './RemoveFeatureFromTopicCommand'; + +export default { + AddFeatureToTopicCommand: addFeatureToTopicCommand, + AddRelationshipCommand: addRelationshipCommand, + AddTopicCommand: addTopicCommand, + ChangeFeatureToTopicCommand: changeFeatureToTopicCommand, + DeleteCommand: deleteCommand, + DragTopicCommand: dragTopicCommand, + GenericFunctionCommand: genericFunctionCommand, + MoveControlPointCommand: moveControlPointCommand, + RemoveFeatureFromTopicCommand: removeFeatureFromTopicCommand, +}; diff --git a/packages/mindplot/lib/components/footer.js b/packages/mindplot/src/components/footer.js similarity index 100% rename from packages/mindplot/lib/components/footer.js rename to packages/mindplot/src/components/footer.js diff --git a/packages/mindplot/lib/components/header.js b/packages/mindplot/src/components/header.js similarity index 100% rename from packages/mindplot/lib/components/header.js rename to packages/mindplot/src/components/header.js diff --git a/packages/mindplot/src/components/index.js b/packages/mindplot/src/components/index.js new file mode 100644 index 00000000..b6b417ed --- /dev/null +++ b/packages/mindplot/src/components/index.js @@ -0,0 +1,95 @@ +import actionDispatcher from './ActionDispatcher'; +import actionIcon from './ActionIcon'; +import centralTopic from './CentralTopic'; +import command from './Command'; +import connectionLine from './ConnectionLine'; +import controlPoint from './ControlPoint'; +import designer from './Designer'; +import designerActionRunner from './DesignerActionRunner'; +import designerKeyboard from './DesignerKeyboard'; +import designerModal from './DesignerModel'; +import designerUndoManager from './DesignerUndoManager'; +import dragConnector from './DragConnector'; +import dragManager from './DragManager'; +import dragPivot from './DragPivot'; +import dragTopic from './DragTopic'; +import editorOptions from './EditorOptions'; +import editorProperties from './EditorProperties'; +import events from './Events'; +import footer from './footer'; +import header from './header'; +import icon from './Icon'; +import iconGroup from './IconGroup'; +import imageIcon from './ImageIcon'; +import keyboard from './Keyboard'; +import linkIcon from './LinkIcon'; +import localSorageManager from './LocalStorageManager'; +import mainTopic from './MainTopic'; +import messages from './Messages'; +import multilineTextEditor from './MultilineTextEditor'; +import nodeGraph from './NodeGraph'; +import noteIcon from './NoteIcon'; +import options from './Options'; +import persistenceManager from './PersistenceManager'; +import relationship from './Relationship'; +import relationshipPivot from './RelationshipPivot'; +import resetPersistenceManager from './RestPersistenceManager'; +import screenManager from './ScreenManager'; +import shrinkConnector from './ShrinkConnector'; +import standaloneActionDispatcher from './StandaloneActionDispatcher'; +import textEditor from './TextEditor'; +import textEditorFactory from './TextEditorFactory'; +import topic from './Topic'; +import topicEventDispatcher from './TopicEventDispatcher'; +import topicFeature from './TopicFeature'; +import topicStyle from './TopicStyle'; +import workspace from './Workspace'; + +export default { + ActionDispatcher: actionDispatcher, + ActionIcon: actionIcon, + CentralTopic: centralTopic, + Command: command, + ConnectionLine: connectionLine, + ControlPoint: controlPoint, + Designer: designer, + DesignerActionRunner: designerActionRunner, + DesignerKeyboard: designerKeyboard, + DesignerModel: designerModal, + DesignerUndoManager: designerUndoManager, + DragConnector: dragConnector, + DragManager: dragManager, + DragPivot: dragPivot, + DragTopic: dragTopic, + EditorOptions: editorOptions, + EditorProperties: editorProperties, + Events: events, + Footer: footer, + Header: header, + Icon: icon, + IconGroup: iconGroup, + ImageIcon: imageIcon, + Keyboard: keyboard, + LinkIcon: linkIcon, + LocalStorageManager: localSorageManager, + MainTopic: mainTopic, + Messages: messages, + MultilineTextEditor: multilineTextEditor, + NodeGraph: nodeGraph, + NoteIcon: noteIcon, + Options: options, + PersistenceManager: persistenceManager, + Relationship: relationship, + RelationshipPivot: relationshipPivot, + RestPersistenceManager: resetPersistenceManager, + ScreenManager: screenManager, + ShrinkConnector: shrinkConnector, + StandaloneActionDispatcher: standaloneActionDispatcher, + TextEditor: textEditor, + TextEditorFactory: textEditorFactory, + Topic: topic, + TopicEventDispatcher: topicEventDispatcher, + TopicFeature: topicFeature, + TopicStyle: topicStyle, + Workspace: workspace, +}; diff --git a/packages/mindplot/lib/components/layout/AbstractBasicSorter.js b/packages/mindplot/src/components/layout/AbstractBasicSorter.js similarity index 94% rename from packages/mindplot/lib/components/layout/AbstractBasicSorter.js rename to packages/mindplot/src/components/layout/AbstractBasicSorter.js index 0c95b6a7..505363c7 100644 --- a/packages/mindplot/lib/components/layout/AbstractBasicSorter.js +++ b/packages/mindplot/src/components/layout/AbstractBasicSorter.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ChildrenSorterStrategy = require('./ChildrenSorterStrategy').default; +import ChildrenSorterStrategy from './ChildrenSorterStrategy'; /** * @class @@ -45,7 +45,7 @@ const AbstractBasicSorter = new Class( let result; const children = treeSet.getChildren(node); - if (children.length == 0 || node.areChildrenShrunken()) { + if (children.length === 0 || node.areChildrenShrunken()) { result = height; } else { let childrenHeight = 0; diff --git a/packages/mindplot/lib/components/layout/BalancedSorter.js b/packages/mindplot/src/components/layout/BalancedSorter.js similarity index 99% rename from packages/mindplot/lib/components/layout/BalancedSorter.js rename to packages/mindplot/src/components/layout/BalancedSorter.js index 0f67c9e5..867915bd 100644 --- a/packages/mindplot/lib/components/layout/BalancedSorter.js +++ b/packages/mindplot/src/components/layout/BalancedSorter.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const AbstractBasicSorter = require('./AbstractBasicSorter').default; +import AbstractBasicSorter from './AbstractBasicSorter'; const BalancedSorter = new Class( /** @lends BalancedSorter */ { diff --git a/packages/mindplot/lib/components/layout/ChangeEvent.js b/packages/mindplot/src/components/layout/ChangeEvent.js similarity index 100% rename from packages/mindplot/lib/components/layout/ChangeEvent.js rename to packages/mindplot/src/components/layout/ChangeEvent.js diff --git a/packages/mindplot/lib/components/layout/ChildrenSorterStrategy.js b/packages/mindplot/src/components/layout/ChildrenSorterStrategy.js similarity index 100% rename from packages/mindplot/lib/components/layout/ChildrenSorterStrategy.js rename to packages/mindplot/src/components/layout/ChildrenSorterStrategy.js diff --git a/packages/mindplot/lib/components/layout/EventBus.js b/packages/mindplot/src/components/layout/EventBus.js similarity index 96% rename from packages/mindplot/lib/components/layout/EventBus.js rename to packages/mindplot/src/components/layout/EventBus.js index d4e473d1..17a890b9 100644 --- a/packages/mindplot/lib/components/layout/EventBus.js +++ b/packages/mindplot/src/components/layout/EventBus.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('../Events').default; +import Events from '../Events'; const EventBus = new Class(/** @lends EventBus */{ Implements: Events, diff --git a/packages/mindplot/lib/components/layout/EventBusDispatcher.js b/packages/mindplot/src/components/layout/EventBusDispatcher.js similarity index 98% rename from packages/mindplot/lib/components/layout/EventBusDispatcher.js rename to packages/mindplot/src/components/layout/EventBusDispatcher.js index b2e9cb15..e634e1d3 100644 --- a/packages/mindplot/lib/components/layout/EventBusDispatcher.js +++ b/packages/mindplot/src/components/layout/EventBusDispatcher.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const EventBus = require('./EventBus').default; +import EventBus from './EventBus'; const EventBusDispatcher = new Class(/** @lends EventBusDispatcher */{ /** diff --git a/packages/mindplot/lib/components/layout/GridSorter.js b/packages/mindplot/src/components/layout/GridSorter.js similarity index 97% rename from packages/mindplot/lib/components/layout/GridSorter.js rename to packages/mindplot/src/components/layout/GridSorter.js index c3f6bd86..6c9e962e 100644 --- a/packages/mindplot/lib/components/layout/GridSorter.js +++ b/packages/mindplot/src/components/layout/GridSorter.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const AbstractBasicSorter = require('./AbstractBasicSorter').default; +import AbstractBasicSorter from './AbstractBasicSorter'; /** * @class diff --git a/packages/mindplot/lib/components/layout/LayoutManager.js b/packages/mindplot/src/components/layout/LayoutManager.js similarity index 95% rename from packages/mindplot/lib/components/layout/LayoutManager.js rename to packages/mindplot/src/components/layout/LayoutManager.js index b925fa61..240d7566 100644 --- a/packages/mindplot/lib/components/layout/LayoutManager.js +++ b/packages/mindplot/src/components/layout/LayoutManager.js @@ -15,10 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('../Events').default; -const RootedTreeSet = require('./RootedTreeSet').default; -const OriginalLayout = require('./OriginalLayout').default; -const ChangeEvent = require('./ChangeEvent').default; +import Events from '../Events'; +import RootedTreeSet from './RootedTreeSet'; +import OriginalLayout from './OriginalLayout'; +import ChangeEvent from './ChangeEvent'; const LayoutManager = new Class( /** @lends LayoutManager */ { @@ -202,10 +202,15 @@ const LayoutManager = new Class( * @return canvas */ plot(containerId, size) { + // this method is only used from tests that include Raphael + if (!global.Raphael) { + console.warn('Raphael.js not found, exiting plot()'); + return null; + } $assert(containerId, 'containerId cannot be null'); size = size || { width: 200, height: 200 }; const squaresize = 10; - const canvas = Raphael(containerId, size.width, size.height); + const canvas = global.Raphael(containerId, size.width, size.height); canvas.drawGrid( 0, 0, diff --git a/packages/mindplot/lib/components/layout/Node.js b/packages/mindplot/src/components/layout/Node.js similarity index 100% rename from packages/mindplot/lib/components/layout/Node.js rename to packages/mindplot/src/components/layout/Node.js diff --git a/packages/mindplot/lib/components/layout/OriginalLayout.js b/packages/mindplot/src/components/layout/OriginalLayout.js similarity index 98% rename from packages/mindplot/lib/components/layout/OriginalLayout.js rename to packages/mindplot/src/components/layout/OriginalLayout.js index 7a338189..ee62054d 100644 --- a/packages/mindplot/lib/components/layout/OriginalLayout.js +++ b/packages/mindplot/src/components/layout/OriginalLayout.js @@ -16,9 +16,9 @@ * limitations under the License. */ -const Node = require('./Node').default; -const SymmetricSorter = require('./SymmetricSorter').default; -const BalancedSorter = require('./BalancedSorter').default; +import Node from './Node'; +import SymmetricSorter from './SymmetricSorter'; +import BalancedSorter from './BalancedSorter'; const OriginalLayout = new Class( /** @lends OriginalLayout */ { diff --git a/packages/mindplot/lib/components/layout/RootedTreeSet.js b/packages/mindplot/src/components/layout/RootedTreeSet.js similarity index 100% rename from packages/mindplot/lib/components/layout/RootedTreeSet.js rename to packages/mindplot/src/components/layout/RootedTreeSet.js diff --git a/packages/mindplot/lib/components/layout/SymmetricSorter.js b/packages/mindplot/src/components/layout/SymmetricSorter.js similarity index 99% rename from packages/mindplot/lib/components/layout/SymmetricSorter.js rename to packages/mindplot/src/components/layout/SymmetricSorter.js index 9bb46ba3..590b2c2d 100644 --- a/packages/mindplot/lib/components/layout/SymmetricSorter.js +++ b/packages/mindplot/src/components/layout/SymmetricSorter.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const AbstractBasicSorter = require('./AbstractBasicSorter').default; +import AbstractBasicSorter from './AbstractBasicSorter'; const SymmetricSorter = new Class( /** @lends SymmetricSorter */ { diff --git a/packages/mindplot/src/components/layout/index.js b/packages/mindplot/src/components/layout/index.js new file mode 100644 index 00000000..3071d189 --- /dev/null +++ b/packages/mindplot/src/components/layout/index.js @@ -0,0 +1,27 @@ +import abstractBasicSorter from './AbstractBasicSorter'; +import balancedSorter from './BalancedSorter'; +import changeEvent from './ChangeEvent'; +import childrenSorterStrategy from './ChildrenSorterStrategy'; +import eventBus from './EventBus'; +import eventBusDispatcher from './EventBusDispatcher'; +import gridSorter from './GridSorter'; +import layoutManager from './LayoutManager'; +import node from './Node'; +import originalLayout from './OriginalLayout'; +import rootedTreeSet from './RootedTreeSet'; +import symmetricSorter from './SymmetricSorter'; + +export default { + AbstractBasicSorter: abstractBasicSorter, + BalancedSorter: balancedSorter, + ChangeEvent: changeEvent, + ChildrenSorterStrategy: childrenSorterStrategy, + EventBus: eventBus, + EventBusDispatcher: eventBusDispatcher, + GridSorter: gridSorter, + LayoutManager: layoutManager, + Node: node, + OriginalLayout: originalLayout, + RootedTreeSet: rootedTreeSet, + SymmetricSorter: symmetricSorter, +}; diff --git a/packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.Request.js b/packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.Request.js similarity index 95% rename from packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.Request.js rename to packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.Request.js index 01920850..2f92cf29 100644 --- a/packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.Request.js +++ b/packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.Request.js @@ -1,4 +1,4 @@ -const BootstrapDialog = require('./BootstrapDialog').default; +import BootstrapDialog from './BootstrapDialog'; BootstrapDialog.Request = new Class({ diff --git a/packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.js b/packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.js similarity index 98% rename from packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.js rename to packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.js index 5aa9a24a..9098942c 100644 --- a/packages/mindplot/lib/components/libraries/bootstrap/BootstrapDialog.js +++ b/packages/mindplot/src/components/libraries/bootstrap/BootstrapDialog.js @@ -1,4 +1,4 @@ -const Options = require('../../Options').default; +import Options from '../../Options'; const BootstrapDialog = new Class({ Implements: Options, diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-colorpicker.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-colorpicker.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-colorpicker.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-colorpicker.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-colorpicker.min.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-colorpicker.min.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-colorpicker.min.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-colorpicker.min.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.css.map b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.css.map similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.css.map rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.css.map diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.min.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.min.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap-theme.min.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap-theme.min.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.css.map b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.css.map similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.css.map rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.css.map diff --git a/packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.min.css b/packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.min.css similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/css/bootstrap.min.css rename to packages/mindplot/src/components/libraries/bootstrap/css/bootstrap.min.css diff --git a/packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.eot b/packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.eot rename to packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.svg b/packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.svg rename to packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.ttf b/packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.woff b/packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.woff rename to packages/mindplot/src/components/libraries/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png b/packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png rename to packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha-horizontal.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha.png b/packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha.png rename to packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/alpha.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png b/packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png rename to packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/hue-horizontal.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/hue.png b/packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/hue.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/hue.png rename to packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/hue.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/saturation.png b/packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/saturation.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/bootstrap-colorpicker/saturation.png rename to packages/mindplot/src/components/libraries/bootstrap/img/bootstrap-colorpicker/saturation.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/img/glyphicons-halflings-blue.png b/packages/mindplot/src/components/libraries/bootstrap/img/glyphicons-halflings-blue.png similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/img/glyphicons-halflings-blue.png rename to packages/mindplot/src/components/libraries/bootstrap/img/glyphicons-halflings-blue.png diff --git a/packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap-colorpicker.js b/packages/mindplot/src/components/libraries/bootstrap/js/bootstrap-colorpicker.js similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap-colorpicker.js rename to packages/mindplot/src/components/libraries/bootstrap/js/bootstrap-colorpicker.js diff --git a/packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap-colorpicker.min.js b/packages/mindplot/src/components/libraries/bootstrap/js/bootstrap-colorpicker.min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap-colorpicker.min.js rename to packages/mindplot/src/components/libraries/bootstrap/js/bootstrap-colorpicker.min.js diff --git a/packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap.js b/packages/mindplot/src/components/libraries/bootstrap/js/bootstrap.js similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap.js rename to packages/mindplot/src/components/libraries/bootstrap/js/bootstrap.js diff --git a/packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap.min.js b/packages/mindplot/src/components/libraries/bootstrap/js/bootstrap.min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/bootstrap/js/bootstrap.min.js rename to packages/mindplot/src/components/libraries/bootstrap/js/bootstrap.min.js diff --git a/packages/mindplot/lib/components/libraries/hotkeys/jquery.hotkeys.js b/packages/mindplot/src/components/libraries/hotkeys/jquery.hotkeys.js similarity index 100% rename from packages/mindplot/lib/components/libraries/hotkeys/jquery.hotkeys.js rename to packages/mindplot/src/components/libraries/hotkeys/jquery.hotkeys.js diff --git a/packages/mindplot/lib/components/libraries/jquery/jquery-2.1.0.js b/packages/mindplot/src/components/libraries/jquery/jquery-2.1.0.js similarity index 100% rename from packages/mindplot/lib/components/libraries/jquery/jquery-2.1.0.js rename to packages/mindplot/src/components/libraries/jquery/jquery-2.1.0.js diff --git a/packages/mindplot/lib/components/libraries/jquery/jquery-2.1.0.min.js b/packages/mindplot/src/components/libraries/jquery/jquery-2.1.0.min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/jquery/jquery-2.1.0.min.js rename to packages/mindplot/src/components/libraries/jquery/jquery-2.1.0.min.js diff --git a/packages/mindplot/lib/components/libraries/jquery/jquery.mousewheel.min.js b/packages/mindplot/src/components/libraries/jquery/jquery.mousewheel.min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/jquery/jquery.mousewheel.min.js rename to packages/mindplot/src/components/libraries/jquery/jquery.mousewheel.min.js diff --git a/packages/mindplot/lib/components/libraries/less/less-1.4.2.min.js b/packages/mindplot/src/components/libraries/less/less-1.4.2.min.js similarity index 100% rename from packages/mindplot/lib/components/libraries/less/less-1.4.2.min.js rename to packages/mindplot/src/components/libraries/less/less-1.4.2.min.js diff --git a/packages/mindplot/lib/components/libraries/less/less-1.6.2.min.js b/packages/mindplot/src/components/libraries/less/less-1.6.2.min.js similarity index 99% rename from packages/mindplot/lib/components/libraries/less/less-1.6.2.min.js rename to packages/mindplot/src/components/libraries/less/less-1.6.2.min.js index 57b3a78b..7c11e839 100644 --- a/packages/mindplot/lib/components/libraries/less/less-1.6.2.min.js +++ b/packages/mindplot/src/components/libraries/less/less-1.6.2.min.js @@ -291,13 +291,13 @@ }; } for (g = 0; g < q.length; g++) { if (l = q[g].group, l === t || l === m) { - try { d = q[g].mixin, d instanceof a.mixin.Definition || (d = new a.mixin.Definition('', [], d.rules, null, !1), d.originalRuleset = c[g].originalRuleset || c[g]), Array.prototype.push.apply(o, d.eval(b, e, this.important).rules); } catch (w) { - throw { - message: w.message, index: this.index, filename: this.currentFileInfo.filename, stack: w.stack, - }; - } -} -} if (p) { if (!this.currentFileInfo || !this.currentFileInfo.reference) for (f = 0; f < o.length; f++)k = o[f], k.markReferenced && k.markReferenced(); return o; } + try { d = q[g].mixin, d instanceof a.mixin.Definition || (d = new a.mixin.Definition('', [], d.rules, null, !1), d.originalRuleset = c[g].originalRuleset || c[g]), Array.prototype.push.apply(o, d.eval(b, e, this.important).rules); } catch (w) { + throw { + message: w.message, index: this.index, filename: this.currentFileInfo.filename, stack: w.stack, + }; + } + } + } if (p) { if (!this.currentFileInfo || !this.currentFileInfo.reference) for (f = 0; f < o.length; f++)k = o[f], k.markReferenced && k.markReferenced(); return o; } } } throw j ? { type: 'Runtime', message: `No matching definition was found for \`${this.format(e)}\``, index: this.index, filename: this.currentFileInfo.filename, diff --git a/packages/mindplot/lib/components/libraries/mootools/mootools-core-1.4.5-full-nocompat-yc.js b/packages/mindplot/src/components/libraries/mootools/mootools-core-1.4.5-full-nocompat-yc.js similarity index 100% rename from packages/mindplot/lib/components/libraries/mootools/mootools-core-1.4.5-full-nocompat-yc.js rename to packages/mindplot/src/components/libraries/mootools/mootools-core-1.4.5-full-nocompat-yc.js diff --git a/packages/mindplot/lib/components/libraries/mootools/mootools-core-1.4.5.js b/packages/mindplot/src/components/libraries/mootools/mootools-core-1.4.5.js similarity index 100% rename from packages/mindplot/lib/components/libraries/mootools/mootools-core-1.4.5.js rename to packages/mindplot/src/components/libraries/mootools/mootools-core-1.4.5.js diff --git a/packages/mindplot/lib/components/libraries/mootools/mootools-core-1.6.0.js b/packages/mindplot/src/components/libraries/mootools/mootools-core-1.6.0.js similarity index 100% rename from packages/mindplot/lib/components/libraries/mootools/mootools-core-1.6.0.js rename to packages/mindplot/src/components/libraries/mootools/mootools-core-1.6.0.js diff --git a/packages/mindplot/src/components/libraries/underscorejs/underscore-min.js b/packages/mindplot/src/components/libraries/underscorejs/underscore-min.js new file mode 100644 index 00000000..90b5ebfd --- /dev/null +++ b/packages/mindplot/src/components/libraries/underscorejs/underscore-min.js @@ -0,0 +1,13 @@ +// Underscore.js 1.6.0 +// http://underscorejs.org +// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. +(function () { + const n = this; const t = n._; const r = {}; const e = Array.prototype; const u = Object.prototype; const i = Function.prototype; const a = e.push; const o = e.slice; const c = e.concat; const l = u.toString; const f = u.hasOwnProperty; const s = e.forEach; const p = e.map; const h = e.reduce; const v = e.reduceRight; const g = e.filter; const d = e.every; const m = e.some; const y = e.indexOf; const b = e.lastIndexOf; const x = Array.isArray; const w = Object.keys; const _ = i.bind; var j = function (n) { return n instanceof j ? n : this instanceof j ? void (this._wrapped = n) : new j(n); }; typeof exports !== 'undefined' ? (typeof module !== 'undefined' && module.exports && (exports = module.exports = j), exports._ = j) : n._ = j, j.VERSION = '1.6.0'; const A = j.each = j.forEach = function (n, t, e) { if (n == null) return n; if (s && n.forEach === s)n.forEach(t, e); else if (n.length === +n.length) { for (var u = 0, i = n.length; i > u; u++) if (t.call(e, n[u], u, n) === r) return; } else for (var a = j.keys(n), u = 0, i = a.length; i > u; u++) if (t.call(e, n[a[u]], a[u], n) === r) return; return n; }; j.map = j.collect = function (n, t, r) { const e = []; return n == null ? e : p && n.map === p ? n.map(t, r) : (A(n, (n, u, i) => { e.push(t.call(r, n, u, i)); }), e); }; const O = 'Reduce of empty array with no initial value'; j.reduce = j.foldl = j.inject = function (n, t, r, e) { let u = arguments.length > 2; if (n == null && (n = []), h && n.reduce === h) return e && (t = j.bind(t, e)), u ? n.reduce(t, r) : n.reduce(t); if (A(n, (n, i, a) => { u ? r = t.call(e, r, n, i, a) : (r = n, u = !0); }), !u) throw new TypeError(O); return r; }, j.reduceRight = j.foldr = function (n, t, r, e) { let u = arguments.length > 2; if (n == null && (n = []), v && n.reduceRight === v) return e && (t = j.bind(t, e)), u ? n.reduceRight(t, r) : n.reduceRight(t); let i = n.length; if (i !== +i) { var a = j.keys(n); i = a.length; } if (A(n, (o, c, l) => { c = a ? a[--i] : --i, u ? r = t.call(e, r, n[c], c, l) : (r = n[c], u = !0); }), !u) throw new TypeError(O); return r; }, j.find = j.detect = function (n, t, r) { let e; return k(n, (n, u, i) => (t.call(r, n, u, i) ? (e = n, !0) : void 0)), e; }, j.filter = j.select = function (n, t, r) { const e = []; return n == null ? e : g && n.filter === g ? n.filter(t, r) : (A(n, (n, u, i) => { t.call(r, n, u, i) && e.push(n); }), e); }, j.reject = function (n, t, r) { return j.filter(n, (n, e, u) => !t.call(r, n, e, u), r); }, j.every = j.all = function (n, t, e) { t || (t = j.identity); let u = !0; return n == null ? u : d && n.every === d ? n.every(t, e) : (A(n, (n, i, a) => ((u = u && t.call(e, n, i, a)) ? void 0 : r)), !!u); }; var k = j.some = j.any = function (n, t, e) { t || (t = j.identity); let u = !1; return n == null ? u : m && n.some === m ? n.some(t, e) : (A(n, (n, i, a) => (u || (u = t.call(e, n, i, a)) ? r : void 0)), !!u); }; j.contains = j.include = function (n, t) { return n == null ? !1 : y && n.indexOf === y ? n.indexOf(t) != -1 : k(n, (n) => n === t); }, j.invoke = function (n, t) { const r = o.call(arguments, 2); const e = j.isFunction(t); return j.map(n, (n) => (e ? t : n[t]).apply(n, r)); }, j.pluck = function (n, t) { return j.map(n, j.property(t)); }, j.where = function (n, t) { return j.filter(n, j.matches(t)); }, j.findWhere = function (n, t) { return j.find(n, j.matches(t)); }, j.max = function (n, t, r) { if (!t && j.isArray(n) && n[0] === +n[0] && n.length < 65535) return Math.max.apply(Math, n); let e = -1 / 0; let u = -1 / 0; return A(n, (n, i, a) => { const o = t ? t.call(r, n, i, a) : n; o > u && (e = n, u = o); }), e; }, j.min = function (n, t, r) { if (!t && j.isArray(n) && n[0] === +n[0] && n.length < 65535) return Math.min.apply(Math, n); let e = 1 / 0; let u = 1 / 0; return A(n, (n, i, a) => { const o = t ? t.call(r, n, i, a) : n; u > o && (e = n, u = o); }), e; }, j.shuffle = function (n) { let t; let r = 0; const e = []; return A(n, (n) => { t = j.random(r++), e[r - 1] = e[t], e[t] = n; }), e; }, j.sample = function (n, t, r) { return t == null || r ? (n.length !== +n.length && (n = j.values(n)), n[j.random(n.length - 1)]) : j.shuffle(n).slice(0, Math.max(0, t)); }; const E = function (n) { return n == null ? j.identity : j.isFunction(n) ? n : j.property(n); }; j.sortBy = function (n, t, r) { return t = E(t), j.pluck(j.map(n, (n, e, u) => ({ value: n, index: e, criteria: t.call(r, n, e, u) })).sort((n, t) => { const r = n.criteria; const e = t.criteria; if (r !== e) { if (r > e || r === void 0) return 1; if (e > r || e === void 0) return -1; } return n.index - t.index; }), 'value'); }; const F = function (n) { return function (t, r, e) { const u = {}; return r = E(r), A(t, (i, a) => { const o = r.call(e, i, a, t); n(u, o, i); }), u; }; }; j.groupBy = F((n, t, r) => { j.has(n, t) ? n[t].push(r) : n[t] = [r]; }), j.indexBy = F((n, t, r) => { n[t] = r; }), j.countBy = F((n, t) => { j.has(n, t) ? n[t]++ : n[t] = 1; }), j.sortedIndex = function (n, t, r, e) { r = E(r); for (var u = r.call(e, t), i = 0, a = n.length; a > i;) { const o = i + a >>> 1; r.call(e, n[o]) < u ? i = o + 1 : a = o; } return i; }, j.toArray = function (n) { return n ? j.isArray(n) ? o.call(n) : n.length === +n.length ? j.map(n, j.identity) : j.values(n) : []; }, j.size = function (n) { return n == null ? 0 : n.length === +n.length ? n.length : j.keys(n).length; }, j.first = j.head = j.take = function (n, t, r) { return n == null ? void 0 : t == null || r ? n[0] : t < 0 ? [] : o.call(n, 0, t); }, j.initial = function (n, t, r) { return o.call(n, 0, n.length - (t == null || r ? 1 : t)); }, j.last = function (n, t, r) { return n == null ? void 0 : t == null || r ? n[n.length - 1] : o.call(n, Math.max(n.length - t, 0)); }, j.rest = j.tail = j.drop = function (n, t, r) { return o.call(n, t == null || r ? 1 : t); }, j.compact = function (n) { return j.filter(n, j.identity); }; var M = function (n, t, r) { return t && j.every(n, j.isArray) ? c.apply(r, n) : (A(n, (n) => { j.isArray(n) || j.isArguments(n) ? t ? a.apply(r, n) : M(n, t, r) : r.push(n); }), r); }; j.flatten = function (n, t) { return M(n, t, []); }, j.without = function (n) { return j.difference(n, o.call(arguments, 1)); }, j.partition = function (n, t) { const r = []; const e = []; return A(n, (n) => { (t(n) ? r : e).push(n); }), [r, e]; }, j.uniq = j.unique = function (n, t, r, e) { j.isFunction(t) && (e = r, r = t, t = !1); const u = r ? j.map(n, r, e) : n; const i = []; const a = []; return A(u, (r, e) => { (t ? e && a[a.length - 1] === r : j.contains(a, r)) || (a.push(r), i.push(n[e])); }), i; }, j.union = function () { return j.uniq(j.flatten(arguments, !0)); }, j.intersection = function (n) { const t = o.call(arguments, 1); return j.filter(j.uniq(n), (n) => j.every(t, (t) => j.contains(t, n))); }, j.difference = function (n) { const t = c.apply(e, o.call(arguments, 1)); return j.filter(n, (n) => !j.contains(t, n)); }, j.zip = function () { for (var n = j.max(j.pluck(arguments, 'length').concat(0)), t = new Array(n), r = 0; n > r; r++)t[r] = j.pluck(arguments, `${r}`); return t; }, j.object = function (n, t) { if (n == null) return {}; for (var r = {}, e = 0, u = n.length; u > e; e++)t ? r[n[e]] = t[e] : r[n[e][0]] = n[e][1]; return r; }, j.indexOf = function (n, t, r) { if (n == null) return -1; let e = 0; const u = n.length; if (r) { if (typeof r !== 'number') return e = j.sortedIndex(n, t), n[e] === t ? e : -1; e = r < 0 ? Math.max(0, u + r) : r; } if (y && n.indexOf === y) return n.indexOf(t, r); for (;u > e; e++) if (n[e] === t) return e; return -1; }, j.lastIndexOf = function (n, t, r) { if (n == null) return -1; const e = r != null; if (b && n.lastIndexOf === b) return e ? n.lastIndexOf(t, r) : n.lastIndexOf(t); for (let u = e ? r : n.length; u--;) if (n[u] === t) return u; return -1; }, j.range = function (n, t, r) { arguments.length <= 1 && (t = n || 0, n = 0), r = arguments[2] || 1; for (var e = Math.max(Math.ceil((t - n) / r), 0), u = 0, i = new Array(e); e > u;)i[u++] = n, n += r; return i; }; const R = function () {}; j.bind = function (n, t) { let r; let e; if (_ && n.bind === _) return _.apply(n, o.call(arguments, 1)); if (!j.isFunction(n)) throw new TypeError(); return r = o.call(arguments, 2), e = function () { if (!(this instanceof e)) return n.apply(t, r.concat(o.call(arguments))); R.prototype = n.prototype; const u = new R(); R.prototype = null; const i = n.apply(u, r.concat(o.call(arguments))); return Object(i) === i ? i : u; }; }, j.partial = function (n) { const t = o.call(arguments, 1); return function () { for (var r = 0, e = t.slice(), u = 0, i = e.length; i > u; u++)e[u] === j && (e[u] = arguments[r++]); for (;r < arguments.length;)e.push(arguments[r++]); return n.apply(this, e); }; }, j.bindAll = function (n) { const t = o.call(arguments, 1); if (t.length === 0) throw new Error('bindAll must be passed function names'); return A(t, (t) => { n[t] = j.bind(n[t], n); }), n; }, j.memoize = function (n, t) { const r = {}; return t || (t = j.identity), function () { const e = t.apply(this, arguments); return j.has(r, e) ? r[e] : r[e] = n.apply(this, arguments); }; }, j.delay = function (n, t) { const r = o.call(arguments, 2); return setTimeout(() => n.apply(null, r), t); }, j.defer = function (n) { return j.delay.apply(j, [n, 1].concat(o.call(arguments, 1))); }, j.throttle = function (n, t, r) { let e; let u; let i; let a = null; let o = 0; r || (r = {}); const c = function () { o = r.leading === !1 ? 0 : j.now(), a = null, i = n.apply(e, u), e = u = null; }; return function () { const l = j.now(); o || r.leading !== !1 || (o = l); const f = t - (l - o); return e = this, u = arguments, f <= 0 ? (clearTimeout(a), a = null, o = l, i = n.apply(e, u), e = u = null) : a || r.trailing === !1 || (a = setTimeout(c, f)), i; }; }, j.debounce = function (n, t, r) { let e; let u; let i; let a; let o; var c = function () { const l = j.now() - a; t > l ? e = setTimeout(c, t - l) : (e = null, r || (o = n.apply(i, u), i = u = null)); }; return function () { i = this, u = arguments, a = j.now(); const l = r && !e; return e || (e = setTimeout(c, t)), l && (o = n.apply(i, u), i = u = null), o; }; }, j.once = function (n) { let t; let r = !1; return function () { return r ? t : (r = !0, t = n.apply(this, arguments), n = null, t); }; }, j.wrap = function (n, t) { return j.partial(t, n); }, j.compose = function () { const n = arguments; return function () { for (var t = arguments, r = n.length - 1; r >= 0; r--)t = [n[r].apply(this, t)]; return t[0]; }; }, j.after = function (n, t) { return function () { return --n < 1 ? t.apply(this, arguments) : void 0; }; }, j.keys = function (n) { if (!j.isObject(n)) return []; if (w) return w(n); const t = []; for (const r in n)j.has(n, r) && t.push(r); return t; }, j.values = function (n) { for (var t = j.keys(n), r = t.length, e = new Array(r), u = 0; r > u; u++)e[u] = n[t[u]]; return e; }, j.pairs = function (n) { for (var t = j.keys(n), r = t.length, e = new Array(r), u = 0; r > u; u++)e[u] = [t[u], n[t[u]]]; return e; }, j.invert = function (n) { for (var t = {}, r = j.keys(n), e = 0, u = r.length; u > e; e++)t[n[r[e]]] = r[e]; return t; }, j.functions = j.methods = function (n) { const t = []; for (const r in n)j.isFunction(n[r]) && t.push(r); return t.sort(); }, j.extend = function (n) { return A(o.call(arguments, 1), (t) => { if (t) for (const r in t)n[r] = t[r]; }), n; }, j.pick = function (n) { const t = {}; const r = c.apply(e, o.call(arguments, 1)); return A(r, (r) => { r in n && (t[r] = n[r]); }), t; }, j.omit = function (n) { const t = {}; const r = c.apply(e, o.call(arguments, 1)); for (const u in n)j.contains(r, u) || (t[u] = n[u]); return t; }, j.defaults = function (n) { return A(o.call(arguments, 1), (t) => { if (t) for (const r in t)n[r] === void 0 && (n[r] = t[r]); }), n; }, j.clone = function (n) { return j.isObject(n) ? j.isArray(n) ? n.slice() : j.extend({}, n) : n; }, j.tap = function (n, t) { return t(n), n; }; var S = function (n, t, r, e) { if (n === t) return n !== 0 || 1 / n == 1 / t; if (n == null || t == null) return n === t; n instanceof j && (n = n._wrapped), t instanceof j && (t = t._wrapped); const u = l.call(n); if (u != l.call(t)) return !1; switch (u) { case '[object String]': return n == String(t); case '[object Number]': return n != +n ? t != +t : n == 0 ? 1 / n == 1 / t : n == +t; case '[object Date]': case '[object Boolean]': return +n == +t; case '[object RegExp]': return n.source == t.source && n.global == t.global && n.multiline == t.multiline && n.ignoreCase == t.ignoreCase; } if (typeof n !== 'object' || typeof t !== 'object') return !1; for (let i = r.length; i--;) if (r[i] == n) return e[i] == t; const a = n.constructor; const o = t.constructor; if (a !== o && !(j.isFunction(a) && a instanceof a && j.isFunction(o) && o instanceof o) && 'constructor' in n && 'constructor' in t) return !1; r.push(n), e.push(t); let c = 0; let f = !0; if (u == '[object Array]') { if (c = n.length, f = c == t.length) for (;c-- && (f = S(n[c], t[c], r, e));); } else { for (var s in n) if (j.has(n, s) && (c++, !(f = j.has(t, s) && S(n[s], t[s], r, e)))) break; if (f) { for (s in t) if (j.has(t, s) && !c--) break; f = !c; } } return r.pop(), e.pop(), f; }; j.isEqual = function (n, t) { return S(n, t, [], []); }, j.isEmpty = function (n) { if (n == null) return !0; if (j.isArray(n) || j.isString(n)) return n.length === 0; for (const t in n) if (j.has(n, t)) return !1; return !0; }, j.isElement = function (n) { return !(!n || n.nodeType !== 1); }, j.isArray = x || function (n) { return l.call(n) == '[object Array]'; }, j.isObject = function (n) { return n === Object(n); }, A(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], (n) => { j[`is${n}`] = function (t) { return l.call(t) == `[object ${n}]`; }; }), j.isArguments(arguments) || (j.isArguments = function (n) { return !(!n || !j.has(n, 'callee')); }), typeof /./ !== 'function' && (j.isFunction = function (n) { return typeof n === 'function'; }), j.isFinite = function (n) { return isFinite(n) && !isNaN(parseFloat(n)); }, j.isNaN = function (n) { return j.isNumber(n) && n != +n; }, j.isBoolean = function (n) { return n === !0 || n === !1 || l.call(n) == '[object Boolean]'; }, j.isNull = function (n) { return n === null; }, j.isUndefined = function (n) { return n === void 0; }, j.has = function (n, t) { return f.call(n, t); }, j.noConflict = function () { return n._ = t, this; }, j.identity = function (n) { return n; }, j.constant = function (n) { return function () { return n; }; }, j.property = function (n) { return function (t) { return t[n]; }; }, j.matches = function (n) { return function (t) { if (t === n) return !0; for (const r in n) if (n[r] !== t[r]) return !1; return !0; }; }, j.times = function (n, t, r) { for (var e = Array(Math.max(0, n)), u = 0; n > u; u++)e[u] = t.call(r, u); return e; }, j.random = function (n, t) { return t == null && (t = n, n = 0), n + Math.floor(Math.random() * (t - n + 1)); }, j.now = Date.now || function () { return (new Date()).getTime(); }; const T = { + escape: { + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', + }, + }; T.unescape = j.invert(T.escape); const I = { escape: new RegExp(`[${j.keys(T.escape).join('')}]`, 'g'), unescape: new RegExp(`(${j.keys(T.unescape).join('|')})`, 'g') }; j.each(['escape', 'unescape'], (n) => { j[n] = function (t) { return t == null ? '' : (`${t}`).replace(I[n], (t) => T[n][t]); }; }), j.result = function (n, t) { if (n == null) return void 0; const r = n[t]; return j.isFunction(r) ? r.call(n) : r; }, j.mixin = function (n) { A(j.functions(n), (t) => { const r = j[t] = n[t]; j.prototype[t] = function () { const n = [this._wrapped]; return a.apply(n, arguments), z.call(this, r.apply(j, n)); }; }); }; let N = 0; j.uniqueId = function (n) { const t = `${++N}`; return n ? n + t : t; }, j.templateSettings = { evaluate: /<%([\s\S]+?)%>/g, interpolate: /<%=([\s\S]+?)%>/g, escape: /<%-([\s\S]+?)%>/g }; const q = /(.)^/; const B = { + "'": "'", '\\': '\\', '\r': 'r', '\n': 'n', ' ': 't', '\u2028': 'u2028', '\u2029': 'u2029', + }; const D = /\\|'|\r|\n|\t|\u2028|\u2029/g; j.template = function (n, t, r) { let e; r = j.defaults({}, r, j.templateSettings); const u = new RegExp(`${[(r.escape || q).source, (r.interpolate || q).source, (r.evaluate || q).source].join('|')}|$`, 'g'); let i = 0; let a = "__p+='"; n.replace(u, (t, r, e, u, o) => (a += n.slice(i, o).replace(D, (n) => `\\${B[n]}`), r && (a += `'+\n((__t=(${r}))==null?'':_.escape(__t))+\n'`), e && (a += `'+\n((__t=(${e}))==null?'':__t)+\n'`), u && (a += `';\n${u}\n__p+='`), i = o + t.length, t)), a += "';\n", r.variable || (a = `with(obj||{}){\n${a}}\n`), a = `${"var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n"}${a}return __p;\n`; try { e = new Function(r.variable || 'obj', '_', a); } catch (o) { throw o.source = a, o; } if (t) return e(t, j); const c = function (n) { return e.call(this, n, j); }; return c.source = `function(${r.variable || 'obj'}){\n${a}}`, c; }, j.chain = function (n) { return j(n).chain(); }; var z = function (n) { return this._chain ? j(n).chain() : n; }; j.mixin(j), A(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (n) => { const t = e[n]; j.prototype[n] = function () { const r = this._wrapped; return t.apply(r, arguments), n != 'shift' && n != 'splice' || r.length !== 0 || delete r[0], z.call(this, r); }; }), A(['concat', 'join', 'slice'], (n) => { const t = e[n]; j.prototype[n] = function () { return z.call(this, t.apply(this._wrapped, arguments)); }; }), j.extend(j.prototype, { chain() { return this._chain = !0, this; }, value() { return this._wrapped; } }), typeof define === 'function' && define.amd && define('underscore', [], () => j); +}).call(this); diff --git a/packages/mindplot/lib/components/model/FeatureModel.js b/packages/mindplot/src/components/model/FeatureModel.js similarity index 91% rename from packages/mindplot/lib/components/model/FeatureModel.js rename to packages/mindplot/src/components/model/FeatureModel.js index 6ba78c88..ac93b60c 100644 --- a/packages/mindplot/lib/components/model/FeatureModel.js +++ b/packages/mindplot/src/components/model/FeatureModel.js @@ -17,17 +17,6 @@ */ const FeatureModel = new Class(/** @lends FeatureModel */{ - Static: { - _nextUUID() { - if (!$defined(FeatureModel._uuid)) { - FeatureModel._uuid = 0; - } - - FeatureModel._uuid += 1; - return FeatureModel._uuid; - }, - }, - /** * @constructs * @param type @@ -88,4 +77,13 @@ const FeatureModel = new Class(/** @lends FeatureModel */{ }, }); +FeatureModel._nextUUID = function _nextUUID() { + if (!$defined(FeatureModel._uuid)) { + FeatureModel._uuid = 0; + } + + FeatureModel._uuid += 1; + return FeatureModel._uuid; +}; + export default FeatureModel; diff --git a/packages/mindplot/lib/components/model/IMindmap.js b/packages/mindplot/src/components/model/IMindmap.js similarity index 100% rename from packages/mindplot/lib/components/model/IMindmap.js rename to packages/mindplot/src/components/model/IMindmap.js diff --git a/packages/mindplot/lib/components/model/INodeModel.js b/packages/mindplot/src/components/model/INodeModel.js similarity index 88% rename from packages/mindplot/lib/components/model/INodeModel.js rename to packages/mindplot/src/components/model/INodeModel.js index f94c555e..c8ac8556 100644 --- a/packages/mindplot/lib/components/model/INodeModel.js +++ b/packages/mindplot/src/components/model/INodeModel.js @@ -1,3 +1,11 @@ +/* eslint-disable no-shadow */ +/* eslint-disable no-throw-literal */ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-eval */ +/* eslint-disable radix */ +/* eslint-disable no-restricted-globals */ +/* eslint-disable no-param-reassign */ +/* eslint-disable no-underscore-dangle */ /* * Copyright [2015] [wisemapping] * @@ -15,6 +23,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import coreJs from '@wisemapping/core-js'; +import _ from '../../../../../libraries/underscore-min'; + +const core = coreJs(); const INodeModel = new Class( /** @lends INodeModel */ { @@ -23,7 +35,7 @@ const INodeModel = new Class( * @param mindmap */ initialize(mindmap) { - $assert(mindmap && mindmap.getBranches, 'mindmap can not be null'); + core.Function.$assert(mindmap && mindmap.getBranches, 'mindmap can not be null'); this._mindmap = mindmap; }, @@ -34,10 +46,10 @@ const INodeModel = new Class( /** */ setId(id) { - if ($defined(id) && id > INodeModel._uuid) { + if (core.Function.$defined(id) && id > INodeModel._uuid) { INodeModel._uuid = id; } - if (!$defined(id)) { + if (!core.Function.$defined(id)) { id = INodeModel._nextUUID(); } @@ -66,8 +78,8 @@ const INodeModel = new Class( /** */ setPosition(x, y) { - $assert(!isNaN(parseInt(x)), `x position is not valid:${x}`); - $assert(!isNaN(parseInt(y)), `y position is not valid:${y}`); + core.Function.$assert(!isNaN(parseInt(x)), `x position is not valid:${x}`); + core.Function.$assert(!isNaN(parseInt(y)), `y position is not valid:${y}`); this.putProperty('position', `{x:${parseInt(x)},y:${parseInt(y)}}`); }, @@ -142,7 +154,7 @@ const INodeModel = new Class( /** */ setOrder(value) { - $assert( + core.Function.$assert( (typeof value === 'number' && isFinite(value)) || value == null, 'Order must be null or a number', ); @@ -227,7 +239,7 @@ const INodeModel = new Class( /** */ areChildrenShrunken() { const result = this.getProperty('shrunken'); - return $defined(result) ? result : false; + return core.Function.$defined(result) ? result : false; }, /** @@ -262,7 +274,7 @@ const INodeModel = new Class( * @see mindplot.model.IMindmap.connect */ connectTo(parent) { - $assert(parent, 'parent can not be null'); + core.Function.$assert(parent, 'parent can not be null'); const mindmap = this.getMindmap(); mindmap.connect(parent, this); }, @@ -302,7 +314,7 @@ const INodeModel = new Class( // console.log("Before:" + mindmap.inspect()); const parent = this.getParent(); - if ($defined(parent)) { + if (core.Function.$defined(parent)) { parent.removeChild(this); } else { // If it has not parent, it must be an isolate topic ... @@ -344,12 +356,7 @@ const INodeModel = new Class( /** */ inspect() { - let result = `{ type: ${ - this.getType() - } , id: ${ - this.getId() - } , text: ${ - this.getText()}`; + let result = `{ type: ${this.getType()} , id: ${this.getId()} , text: ${this.getText()}`; const children = this.getChildren(); if (children.length > 0) { @@ -410,8 +417,8 @@ INodeModel.MAIN_TOPIC_TO_MAIN_TOPIC_DISTANCE = 220; /** * @todo: This method must be implemented. (unascribed) */ -INodeModel._nextUUID = function () { - if (!$defined(INodeModel._uuid)) { +INodeModel._nextUUID = () => { + if (!core.Function.$defined(INodeModel._uuid)) { INodeModel._uuid = 0; } diff --git a/packages/mindplot/lib/components/model/IconModel.js b/packages/mindplot/src/components/model/IconModel.js similarity index 96% rename from packages/mindplot/lib/components/model/IconModel.js rename to packages/mindplot/src/components/model/IconModel.js index bdc9723d..279be526 100644 --- a/packages/mindplot/lib/components/model/IconModel.js +++ b/packages/mindplot/src/components/model/IconModel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const FeatureModel = require('./FeatureModel').default; +import FeatureModel from './FeatureModel'; const IconModel = new Class(/** @lends IconModel */{ Extends: FeatureModel, diff --git a/packages/mindplot/lib/components/model/LinkModel.js b/packages/mindplot/src/components/model/LinkModel.js similarity index 97% rename from packages/mindplot/lib/components/model/LinkModel.js rename to packages/mindplot/src/components/model/LinkModel.js index 84ba3df5..588e20b0 100644 --- a/packages/mindplot/lib/components/model/LinkModel.js +++ b/packages/mindplot/src/components/model/LinkModel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const FeatureModel = require('./FeatureModel').default; +import FeatureModel from './FeatureModel'; const LinkModel = new Class(/** @lends LinkModel */{ Extends: FeatureModel, diff --git a/packages/mindplot/lib/components/model/Mindmap.js b/packages/mindplot/src/components/model/Mindmap.js similarity index 94% rename from packages/mindplot/lib/components/model/Mindmap.js rename to packages/mindplot/src/components/model/Mindmap.js index 0e47f556..fe4074b2 100644 --- a/packages/mindplot/lib/components/model/Mindmap.js +++ b/packages/mindplot/src/components/model/Mindmap.js @@ -15,11 +15,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const IMindmap = require('./IMindmap').default; -const INodeModel = require('./INodeModel').default; -const NodeModel = require('./NodeModel').default; -const RelationshipModel = require('./RelationshipModel').default; -const ModelCodeName = require('../persistence/ModelCodeName').default; +import IMindmap from './IMindmap'; +import INodeModel from './INodeModel'; +import NodeModel from './NodeModel'; +import RelationshipModel from './RelationshipModel'; +import ModelCodeName from '../persistence/ModelCodeName'; const Mindmap = new Class(/** @lends Mindmap */{ Extends: IMindmap, diff --git a/packages/mindplot/lib/components/model/NodeModel.js b/packages/mindplot/src/components/model/NodeModel.js similarity index 98% rename from packages/mindplot/lib/components/model/NodeModel.js rename to packages/mindplot/src/components/model/NodeModel.js index 2e913d49..6933ea22 100644 --- a/packages/mindplot/lib/components/model/NodeModel.js +++ b/packages/mindplot/src/components/model/NodeModel.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const INodeModel = require('./INodeModel').default; -const TopicFeature = require('../TopicFeature').default; +import INodeModel from './INodeModel'; +import TopicFeature from '../TopicFeature'; const NodeModel = new Class(/** @lends NodeModel */{ Extends: INodeModel, diff --git a/packages/mindplot/lib/components/model/NoteModel.js b/packages/mindplot/src/components/model/NoteModel.js similarity index 96% rename from packages/mindplot/lib/components/model/NoteModel.js rename to packages/mindplot/src/components/model/NoteModel.js index eb7858e0..eb0751ff 100644 --- a/packages/mindplot/lib/components/model/NoteModel.js +++ b/packages/mindplot/src/components/model/NoteModel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const FeatureModel = require('./FeatureModel').default; +import FeatureModel from './FeatureModel'; const NoteModel = new Class(/** @lends NoteModel */{ Extends: FeatureModel, diff --git a/packages/mindplot/lib/components/model/RelationshipModel.js b/packages/mindplot/src/components/model/RelationshipModel.js similarity index 92% rename from packages/mindplot/lib/components/model/RelationshipModel.js rename to packages/mindplot/src/components/model/RelationshipModel.js index d6580ce3..5d6b44e2 100644 --- a/packages/mindplot/lib/components/model/RelationshipModel.js +++ b/packages/mindplot/src/components/model/RelationshipModel.js @@ -15,20 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ConnectionLine = require('../ConnectionLine').default; +import ConnectionLine from '../ConnectionLine'; const RelationshipModel = new Class( /** @lends RelationshipModel */ { - Static: { - _nextUUID() { - if (!$defined(RelationshipModel._uuid)) { - RelationshipModel._uuid = 0; - } - RelationshipModel._uuid += 1; - return RelationshipModel._uuid; - }, - }, - /** * @constructs * @param sourceTopicId @@ -145,4 +135,12 @@ const RelationshipModel = new Class( }, ); +RelationshipModel._nextUUID = function _nextUUID() { + if (!$defined(RelationshipModel._uuid)) { + RelationshipModel._uuid = 0; + } + RelationshipModel._uuid += 1; + return RelationshipModel._uuid; +}; + export default RelationshipModel; diff --git a/packages/mindplot/src/components/model/index.js b/packages/mindplot/src/components/model/index.js new file mode 100644 index 00000000..76dca648 --- /dev/null +++ b/packages/mindplot/src/components/model/index.js @@ -0,0 +1,21 @@ +import featureModel from './FeatureModel'; +import iconModel from './IconModel'; +import iMindmap from './IMindmap'; +import iNodeModel from './INodeModel'; +import linkModel from './LinkModel'; +import noteModel from './NoteModel'; +import mindmap from './Mindmap'; +import nodeModel from './NodeModel'; +import relationshipModel from './RelationshipModel'; + +export default { + FeatureModel: featureModel, + IconModel: iconModel, + IMindmap: iMindmap, + INodeModel: iNodeModel, + LinkModel: linkModel, + NoteModel: noteModel, + Mindmap: mindmap, + NodeModel: nodeModel, + RelationshipModel: relationshipModel, +}; diff --git a/packages/mindplot/lib/components/persistence/Beta2PelaMigrator.js b/packages/mindplot/src/components/persistence/Beta2PelaMigrator.js similarity index 93% rename from packages/mindplot/lib/components/persistence/Beta2PelaMigrator.js rename to packages/mindplot/src/components/persistence/Beta2PelaMigrator.js index 4c30b672..db6fe335 100644 --- a/packages/mindplot/lib/components/persistence/Beta2PelaMigrator.js +++ b/packages/mindplot/src/components/persistence/Beta2PelaMigrator.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ModelCodeName = require('./ModelCodeName').default; -const XMLSerializer_Pela = require('./XMLSerializer_Pela').default; +import ModelCodeName from './ModelCodeName'; +import XMLSerializer_Pela from './XMLSerializer_Pela'; const Beta2PelaMigrator = new Class({ initialize(betaSerializer) { diff --git a/packages/mindplot/lib/components/persistence/ModelCodeName.js b/packages/mindplot/src/components/persistence/ModelCodeName.js similarity index 100% rename from packages/mindplot/lib/components/persistence/ModelCodeName.js rename to packages/mindplot/src/components/persistence/ModelCodeName.js diff --git a/packages/mindplot/lib/components/persistence/Pela2TangoMigrator.js b/packages/mindplot/src/components/persistence/Pela2TangoMigrator.js similarity index 95% rename from packages/mindplot/lib/components/persistence/Pela2TangoMigrator.js rename to packages/mindplot/src/components/persistence/Pela2TangoMigrator.js index 341e6fb7..0240c7f1 100644 --- a/packages/mindplot/lib/components/persistence/Pela2TangoMigrator.js +++ b/packages/mindplot/src/components/persistence/Pela2TangoMigrator.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const XMLSerializer_Tango = require('./XMLSerializer_Tango').default; -const ModelCodeName = require('./ModelCodeName').default; +import XMLSerializer_Tango from './XMLSerializer_Tango'; +import ModelCodeName from './ModelCodeName'; const Pela2TangoMigrator = new Class({ initialize(pelaSerializer) { diff --git a/packages/mindplot/lib/components/persistence/XMLSerializerFactory.js b/packages/mindplot/src/components/persistence/XMLSerializerFactory.js similarity index 87% rename from packages/mindplot/lib/components/persistence/XMLSerializerFactory.js rename to packages/mindplot/src/components/persistence/XMLSerializerFactory.js index c7918015..d35c706c 100644 --- a/packages/mindplot/lib/components/persistence/XMLSerializerFactory.js +++ b/packages/mindplot/src/components/persistence/XMLSerializerFactory.js @@ -15,12 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ModelCodeName = require('./ModelCodeName').default; -const Beta2PelaMigrator = require('./Beta2PelaMigrator').default; -const Pela2TangoMigrator = require('./Pela2TangoMigrator').default; -const XMLSerializer_Beta = require('./XMLSerializer_Beta').default; -const XMLSerializer_Pela = require('./XMLSerializer_Pela').default; -const XMLSerializer_Tango = require('./XMLSerializer_Tango').default; +import ModelCodeName from './ModelCodeName'; +import Beta2PelaMigrator from './Beta2PelaMigrator'; +import Pela2TangoMigrator from './Pela2TangoMigrator'; +import XMLSerializer_Beta from './XMLSerializer_Beta'; +import XMLSerializer_Pela from './XMLSerializer_Pela'; +import XMLSerializer_Tango from './XMLSerializer_Tango'; /** * @class mindplot.persistence.XMLSerializerFactory diff --git a/packages/mindplot/lib/components/persistence/XMLSerializer_Beta.js b/packages/mindplot/src/components/persistence/XMLSerializer_Beta.js similarity index 87% rename from packages/mindplot/lib/components/persistence/XMLSerializer_Beta.js rename to packages/mindplot/src/components/persistence/XMLSerializer_Beta.js index 7f6f0539..95366151 100644 --- a/packages/mindplot/lib/components/persistence/XMLSerializer_Beta.js +++ b/packages/mindplot/src/components/persistence/XMLSerializer_Beta.js @@ -14,16 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import Core from '@wisemapping/core-js'; +import ModelCodeName from './ModelCodeName'; +import Mindmap from '../model/Mindmap'; +import INodeModel from '../model/INodeModel'; +import TopicFeature from '../TopicFeature'; const core = Core(); -const ModelCodeName = require('./ModelCodeName').default; -const Mindmap = require('../model/Mindmap').default; -const INodeModel = require('../model/INodeModel').default; -const TopicFeature = require('../TopicFeature').default; const XMLSerializer_Beta = new Class({ - toXML(mindmap) { $assert(mindmap, 'Can not save a null mindmap'); @@ -97,8 +96,13 @@ const XMLSerializer_Beta = new Class({ const fontStyle = topic.getFontStyle(); font += `${fontStyle || ''};`; - if ($defined(fontFamily) || $defined(fontSize) || $defined(fontColor) - || $defined(fontWeight) || $defined(fontStyle)) { + if ( + $defined(fontFamily) + || $defined(fontSize) + || $defined(fontColor) + || $defined(fontWeight) + || $defined(fontStyle) + ) { parentTopic.setAttribute('fontStyle', font); } @@ -171,10 +175,18 @@ const XMLSerializer_Beta = new Class({ // Is a valid object ? const { documentElement } = dom; - $assert(documentElement.nodeName != 'parsererror', `Error while parsing: '${documentElement.childNodes[0].nodeValue}`); + $assert( + documentElement.nodeName != 'parsererror', + `Error while parsing: '${documentElement.childNodes[0].nodeValue}`, + ); // Is a wisemap?. - $assert(documentElement.tagName == XMLSerializer_Beta.MAP_ROOT_NODE, `This seem not to be a map document. Root Tag: '${documentElement.tagName},',HTML:${dom.innerHTML},XML:${core.Utils.innerXML(dom)}`); + $assert( + documentElement.tagName == XMLSerializer_Beta.MAP_ROOT_NODE, + `This seem not to be a map document. Root Tag: '${documentElement.tagName},',HTML:${ + dom.innerHTML + },XML:${core.Utils.innerXML(dom)}`, + ); // Start the loading process ... let version = documentElement.getAttribute('version'); @@ -194,7 +206,9 @@ const XMLSerializer_Beta = new Class({ }, _deserializeNode(domElem, mindmap) { - const type = (domElem.getAttribute('central') != null) ? INodeModel.CENTRAL_TOPIC_TYPE : INodeModel.MAIN_TOPIC_TYPE; + const type = domElem.getAttribute('central') != null + ? INodeModel.CENTRAL_TOPIC_TYPE + : INodeModel.MAIN_TOPIC_TYPE; const topic = mindmap.createNode(type); // Load attributes... @@ -264,7 +278,13 @@ const XMLSerializer_Beta = new Class({ for (let i = 0; i < children.length; i++) { const child = children[i]; if (child.nodeType == 1) { - $assert(child.tagName == 'topic' || child.tagName == 'icon' || child.tagName == 'link' || child.tagName == 'note', `Illegal node type:${child.tagName}`); + $assert( + child.tagName == 'topic' + || child.tagName == 'icon' + || child.tagName == 'link' + || child.tagName == 'note', + `Illegal node type:${child.tagName}`, + ); if (child.tagName == 'topic') { const childTopic = this._deserializeNode(child, mindmap); childTopic.connectTo(topic); diff --git a/packages/mindplot/lib/components/persistence/XMLSerializer_Pela.js b/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js similarity index 94% rename from packages/mindplot/lib/components/persistence/XMLSerializer_Pela.js rename to packages/mindplot/src/components/persistence/XMLSerializer_Pela.js index 8893547b..b263c5cf 100644 --- a/packages/mindplot/lib/components/persistence/XMLSerializer_Pela.js +++ b/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js @@ -15,14 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import Core from '@wisemapping/core-js'; +import web2d from '@wisemapping/web2d'; +import Mindmap from '../model/Mindmap'; +import INodeModel, { TopicShape } from '../model/INodeModel'; +import TopicFeature from '../TopicFeature'; +import ConnectionLine from '../ConnectionLine'; const core = Core(); -const Mindmap = require('../model/Mindmap').default; -const INodeModel = require('../model/INodeModel').default; -const { TopicShape } = require('../model/INodeModel'); -const TopicFeature = require('../TopicFeature').default; -const ConnectionLine = require('../ConnectionLine').default; /** * @class @@ -90,7 +90,7 @@ const XMLSerializer_Pela = new Class( parentTopic.setAttribute('position', `${pos.x},${pos.y}`); const order = topic.getOrder(); - if (typeof order === 'number' && isFinite(order)) parentTopic.setAttribute('order', order); + if (typeof order === 'number' && isFinite(order)) { parentTopic.setAttribute('order', order); } } const text = topic.getText(); @@ -105,19 +105,14 @@ const XMLSerializer_Pela = new Class( if (shape == TopicShape.IMAGE) { parentTopic.setAttribute( 'image', - `${topic.getImageSize().width - },${ + `${topic.getImageSize().width},${ topic.getImageSize().height - }:${ - topic.getImageUrl()}`, + }:${topic.getImageUrl()}`, ); } } - if ( - topic.areChildrenShrunken() - && topic.getType() != INodeModel.CENTRAL_TOPIC_TYPE - ) { + if (topic.areChildrenShrunken() && topic.getType() != INodeModel.CENTRAL_TOPIC_TYPE) { parentTopic.setAttribute('shrink', 'true'); } @@ -216,10 +211,7 @@ const XMLSerializer_Pela = new Class( const lineType = relationship.getLineType(); result.setAttribute('lineType', lineType); - if ( - lineType == ConnectionLine.CURVED - || lineType == ConnectionLine.SIMPLE_CURVED - ) { + if (lineType == ConnectionLine.CURVED || lineType == ConnectionLine.SIMPLE_CURVED) { if ($defined(relationship.getSrcCtrlPoint())) { const srcPoint = relationship.getSrcCtrlPoint(); result.setAttribute( @@ -475,10 +467,10 @@ const XMLSerializer_Pela = new Class( const model = mindmap.createRelationship(srcId, destId); model.setLineType(lineType); if ($defined(srcCtrlPoint) && srcCtrlPoint != '') { - model.setSrcCtrlPoint(core.Point.fromString(srcCtrlPoint)); + model.setSrcCtrlPoint(web2d.Point.fromString(srcCtrlPoint)); } if ($defined(destCtrlPoint) && destCtrlPoint != '') { - model.setDestCtrlPoint(core.Point.fromString(destCtrlPoint)); + model.setDestCtrlPoint(web2d.Point.fromString(destCtrlPoint)); } model.setEndArrow('false'); model.setStartArrow('true'); diff --git a/packages/mindplot/lib/components/persistence/XMLSerializer_Tango.js b/packages/mindplot/src/components/persistence/XMLSerializer_Tango.js similarity index 94% rename from packages/mindplot/lib/components/persistence/XMLSerializer_Tango.js rename to packages/mindplot/src/components/persistence/XMLSerializer_Tango.js index ac7e29c5..543b9cf6 100644 --- a/packages/mindplot/lib/components/persistence/XMLSerializer_Tango.js +++ b/packages/mindplot/src/components/persistence/XMLSerializer_Tango.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const XMLSerializer_Pela = require('./XMLSerializer_Pela').default; +import XMLSerializer_Pela from './XMLSerializer_Pela'; /** * This serializer works exactly the same way as for the former version Pela diff --git a/packages/mindplot/src/components/persistence/index.js b/packages/mindplot/src/components/persistence/index.js new file mode 100644 index 00000000..2c75d466 --- /dev/null +++ b/packages/mindplot/src/components/persistence/index.js @@ -0,0 +1,17 @@ +import beta2PelaMigrator from './Beta2PelaMigrator'; +import modelCodeName from './ModelCodeName'; +import pela2TangoMigrator from './Pela2TangoMigrator'; +import xmlSerializerBeta from './XMLSerializer_Beta'; +import xmlSerializerPela from './XMLSerializer_Pela'; +import xmlSerializerTango from './XMLSerializer_Tango'; +import xmlSerializerFactory from './XMLSerializerFactory'; + +export default { + Beta2PelaMigrator: beta2PelaMigrator, + ModelCodeName: modelCodeName, + Pela2TangoMigrator: pela2TangoMigrator, + XMLSerializer_Beta: xmlSerializerBeta, + XMLSerializer_Pela: xmlSerializerPela, + XMLSerializer_Tango: xmlSerializerTango, + XMLSerializerFactory: xmlSerializerFactory, +}; diff --git a/packages/mindplot/lib/components/util/FadeEffect.js b/packages/mindplot/src/components/util/FadeEffect.js similarity index 96% rename from packages/mindplot/lib/components/util/FadeEffect.js rename to packages/mindplot/src/components/util/FadeEffect.js index 395faaac..dcab59ee 100644 --- a/packages/mindplot/lib/components/util/FadeEffect.js +++ b/packages/mindplot/src/components/util/FadeEffect.js @@ -17,7 +17,7 @@ */ // FIXME: this Class should be reimplemented -const Events = require('../Events').default; +import Events from '../Events'; const FadeEffect = new Class(/** @lends FadeEffect */{ Extends: Events, diff --git a/packages/mindplot/lib/components/util/Shape.js b/packages/mindplot/src/components/util/Shape.js similarity index 80% rename from packages/mindplot/lib/components/util/Shape.js rename to packages/mindplot/src/components/util/Shape.js index b9353522..0aa4f3e4 100644 --- a/packages/mindplot/lib/components/util/Shape.js +++ b/packages/mindplot/src/components/util/Shape.js @@ -15,25 +15,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Core = require('@wismapping/core-js'); +import web2d from '@wisemapping/web2d'; +import coreJs from '@wisemapping/core-js'; +import { TopicShape } from '../model/INodeModel'; +import TopicConfig from '../TopicConfig'; -const core = Core(); -const { TopicShape } = require('../model/INodeModel'); +const core = coreJs(); const Shape = { isAtRight(sourcePoint, targetPoint) { - $assert(sourcePoint, 'Source can not be null'); - $assert(targetPoint, 'Target can not be null'); + core.Function.$assert(sourcePoint, 'Source can not be null'); + core.Function.$assert(targetPoint, 'Target can not be null'); return sourcePoint.x < targetPoint.x; }, calculateRectConnectionPoint(rectCenterPoint, rectSize, isAtRight) { - $assert(rectCenterPoint, 'rectCenterPoint can not be null'); - $assert(rectSize, 'rectSize can not be null'); - $assert($defined(isAtRight), 'isRight can not be null'); + core.Function.$assert(rectCenterPoint, 'rectCenterPoint can not be null'); + core.Function.$assert(rectSize, 'rectSize can not be null'); + core.Function.$assert(core.Function.$defined(isAtRight), 'isRight can not be null'); // Node is placed at the right ? - const result = new core.Point(); + const result = new web2d.Point(); // This is used fix a minor difference ...z const correctionHardcode = 2; @@ -55,13 +57,12 @@ const Shape = { calculateRelationShipPointCoordinates(topic, controlPoint) { const size = topic.getSize(); const position = topic.getPosition(); - let m; const yGap = position.y - controlPoint.y; const xGap = position.x - controlPoint.x; const disable = Math.abs(yGap) < 5 || Math.abs(xGap) < 5 || Math.abs(yGap - xGap) < 5; - let y; let - x; + let y; + let x; const gap = 5; if (controlPoint.y > position.y + size.height / 2) { y = position.y + size.height / 2 + gap; @@ -87,7 +88,7 @@ const Shape = { y = !disable ? position.y - (yGap / xGap) * (position.x - x) : position.y; } - return new core.Point(x, y); + return new web2d.Point(x, y); }, calculateDefaultControlPoints(srcPos, tarPos) { @@ -108,24 +109,24 @@ const Shape = { const y2 = m * (x2 - tarPos.x) + tarPos.y; return [ - new core.Point(-srcPos.x + x1, -srcPos.y + y1), - new core.Point(-tarPos.x + x2, -tarPos.y + y2), + new web2d.Point(-srcPos.x + x1, -srcPos.y + y1), + new web2d.Point(-tarPos.x + x2, -tarPos.y + y2), ]; }, workoutIncomingConnectionPoint(targetNode, sourcePosition) { - $assert(sourcePosition, 'sourcePoint can not be null'); + core.Function.$assert(sourcePosition, 'sourcePoint can not be null'); const pos = targetNode.getPosition(); const size = targetNode.getSize(); const isAtRight = Shape.isAtRight(sourcePosition, pos); const result = Shape.calculateRectConnectionPoint(pos, size, isAtRight); - if (targetNode.getShapeType() == TopicShape.LINE) { + if (targetNode.getShapeType() === TopicShape.LINE) { result.y += targetNode.getSize().height / 2; } // Move a little the position... - const offset = Topic.CONNECTOR_WIDTH / 2; + const offset = TopicConfig.CONNECTOR_WIDTH / 2; if (!isAtRight) { result.x += offset; } else { diff --git a/packages/mindplot/src/components/util/index.js b/packages/mindplot/src/components/util/index.js new file mode 100644 index 00000000..0dedb597 --- /dev/null +++ b/packages/mindplot/src/components/util/index.js @@ -0,0 +1,7 @@ +import fadeEffect from './FadeEffect'; +import shape from './Shape'; + +export default { + FadeEffect: fadeEffect, + Shape: shape, +}; diff --git a/packages/mindplot/lib/components/widget/ColorPalettePanel.js b/packages/mindplot/src/components/widget/ColorPalettePanel.js similarity index 98% rename from packages/mindplot/lib/components/widget/ColorPalettePanel.js rename to packages/mindplot/src/components/widget/ColorPalettePanel.js index 90806f54..f928a654 100644 --- a/packages/mindplot/lib/components/widget/ColorPalettePanel.js +++ b/packages/mindplot/src/components/widget/ColorPalettePanel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ToolbarPaneItem = require('./ToolbarPaneItem').default; +import ToolbarPaneItem from './ToolbarPaneItem'; const ColorPalettePanel = new Class({ Extends: ToolbarPaneItem, diff --git a/packages/mindplot/lib/components/widget/FloatingTip.js b/packages/mindplot/src/components/widget/FloatingTip.js similarity index 94% rename from packages/mindplot/lib/components/widget/FloatingTip.js rename to packages/mindplot/src/components/widget/FloatingTip.js index 58584ad5..af6ed756 100644 --- a/packages/mindplot/lib/components/widget/FloatingTip.js +++ b/packages/mindplot/src/components/widget/FloatingTip.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Options = require('../Options').default; -const Events = require('../Events').default; +import Options from '../Options'; +import Events from '../Events'; const FloatingTip = new Class({ Implements: [Options, Events], diff --git a/packages/mindplot/lib/components/widget/FontFamilyPanel.js b/packages/mindplot/src/components/widget/FontFamilyPanel.js similarity index 95% rename from packages/mindplot/lib/components/widget/FontFamilyPanel.js rename to packages/mindplot/src/components/widget/FontFamilyPanel.js index 80581898..4696dafc 100644 --- a/packages/mindplot/lib/components/widget/FontFamilyPanel.js +++ b/packages/mindplot/src/components/widget/FontFamilyPanel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ListToolbarPanel = require('./ListToolbarPanel').default; +import ListToolbarPanel from './ListToolbarPanel'; const FontFamilyPanel = new Class({ Extends: ListToolbarPanel, diff --git a/packages/mindplot/lib/components/widget/FontSizePanel.js b/packages/mindplot/src/components/widget/FontSizePanel.js similarity index 95% rename from packages/mindplot/lib/components/widget/FontSizePanel.js rename to packages/mindplot/src/components/widget/FontSizePanel.js index 2307b1b6..1ee6dd02 100644 --- a/packages/mindplot/lib/components/widget/FontSizePanel.js +++ b/packages/mindplot/src/components/widget/FontSizePanel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ListToolbarPanel = require('./ListToolbarPanel').default; +import ListToolbarPanel from './ListToolbarPanel'; const FontSizePanel = new Class({ Extends: ListToolbarPanel, diff --git a/packages/mindplot/lib/components/widget/IMenu.js b/packages/mindplot/src/components/widget/IMenu.js similarity index 97% rename from packages/mindplot/lib/components/widget/IMenu.js rename to packages/mindplot/src/components/widget/IMenu.js index e530c28a..d592baba 100644 --- a/packages/mindplot/lib/components/widget/IMenu.js +++ b/packages/mindplot/src/components/widget/IMenu.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const PersistenceManager = require('../PersistenceManager').default; +import PersistenceManager from '../PersistenceManager'; const IMenu = new Class({ diff --git a/packages/mindplot/lib/components/widget/IconPanel.js b/packages/mindplot/src/components/widget/IconPanel.js similarity index 94% rename from packages/mindplot/lib/components/widget/IconPanel.js rename to packages/mindplot/src/components/widget/IconPanel.js index 9282a883..0586a723 100644 --- a/packages/mindplot/lib/components/widget/IconPanel.js +++ b/packages/mindplot/src/components/widget/IconPanel.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ToolbarPaneItem = require('./ToolbarPaneItem').default; -const ImageIcon = require('../ImageIcon').default; +import ToolbarPaneItem from './ToolbarPaneItem'; +import ImageIcon from '../ImageIcon'; const IconPanel = new Class({ Extends: ToolbarPaneItem, diff --git a/packages/mindplot/lib/components/widget/KeyboardShortcutTooltip.js b/packages/mindplot/src/components/widget/KeyboardShortcutTooltip.js similarity index 97% rename from packages/mindplot/lib/components/widget/KeyboardShortcutTooltip.js rename to packages/mindplot/src/components/widget/KeyboardShortcutTooltip.js index e14fc13d..03cfd3cf 100644 --- a/packages/mindplot/lib/components/widget/KeyboardShortcutTooltip.js +++ b/packages/mindplot/src/components/widget/KeyboardShortcutTooltip.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const FloatingTip = require('./FloatingTip').default; +import FloatingTip from './FloatingTip'; const KeyboardShortcutTooltip = new Class({ Extends: FloatingTip, diff --git a/packages/mindplot/lib/components/widget/LinkEditor.js b/packages/mindplot/src/components/widget/LinkEditor.js similarity index 98% rename from packages/mindplot/lib/components/widget/LinkEditor.js rename to packages/mindplot/src/components/widget/LinkEditor.js index 99bea08d..0459787e 100644 --- a/packages/mindplot/lib/components/widget/LinkEditor.js +++ b/packages/mindplot/src/components/widget/LinkEditor.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const BootstrapDialog = require('../libraries/bootstrap/BootstrapDialog').default; +import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; const LinkEditor = new Class(/** @lends LinkEditor */{ Extends: BootstrapDialog, diff --git a/packages/mindplot/lib/components/widget/LinkIconTooltip.js b/packages/mindplot/src/components/widget/LinkIconTooltip.js similarity index 95% rename from packages/mindplot/lib/components/widget/LinkIconTooltip.js rename to packages/mindplot/src/components/widget/LinkIconTooltip.js index d8527c8e..f8314da7 100644 --- a/packages/mindplot/lib/components/widget/LinkIconTooltip.js +++ b/packages/mindplot/src/components/widget/LinkIconTooltip.js @@ -15,14 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const FloatingTip = require('./FloatingTip').default; +import FloatingTip from './FloatingTip'; const LinkIconTooltip = new Class({ Extends: FloatingTip, initialize(linkIcon) { $assert(linkIcon, 'linkIcon can not be null'); - const nativeElement = $(linkIcon.getImage()._peer._native); + const nativeElement = $(linkIcon.getImage().peer._native); this.parent(nativeElement, { // Content can also be a function of the target element! content: this._buildContent(linkIcon), diff --git a/packages/mindplot/lib/components/widget/ListToolbarPanel.js b/packages/mindplot/src/components/widget/ListToolbarPanel.js similarity index 96% rename from packages/mindplot/lib/components/widget/ListToolbarPanel.js rename to packages/mindplot/src/components/widget/ListToolbarPanel.js index acbcc11b..31714d72 100644 --- a/packages/mindplot/lib/components/widget/ListToolbarPanel.js +++ b/packages/mindplot/src/components/widget/ListToolbarPanel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ToolbarPaneItem = require('./ToolbarPaneItem').default; +import ToolbarPaneItem from './ToolbarPaneItem'; const ListToolbarPanel = new Class({ Extends: ToolbarPaneItem, diff --git a/packages/mindplot/lib/components/widget/Menu.js b/packages/mindplot/src/components/widget/Menu.js similarity index 96% rename from packages/mindplot/lib/components/widget/Menu.js rename to packages/mindplot/src/components/widget/Menu.js index 5e628fa3..84d7a341 100644 --- a/packages/mindplot/lib/components/widget/Menu.js +++ b/packages/mindplot/src/components/widget/Menu.js @@ -15,15 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const BootstrapDialog = require('../libraries/bootstrap/BootstrapDialog').default; -const IMenu = require('./IMenu').default; -const FontFamilyPanel = require('./FontFamilyPanel').default; -const FontSizePanel = require('./FontSizePanel').default; -const TopicShapePanel = require('./TopicShapePanel').default; -const IconPanel = require('./IconPanel').default; -const ColorPalettePanel = require('./ColorPalettePanel').default; -const ToolbarItem = require('./ToolbarItem').default; -const KeyboardShortcutTooltip = require('./KeyboardShortcutTooltip').default; +import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; +import IMenu from './IMenu'; +import FontFamilyPanel from './FontFamilyPanel'; +import FontSizePanel from './FontSizePanel'; +import TopicShapePanel from './TopicShapePanel'; +import IconPanel from './IconPanel'; +import ColorPalettePanel from './ColorPalettePanel'; +import ToolbarItem from './ToolbarItem'; +import KeyboardShortcutTooltip from './KeyboardShortcutTooltip'; const Menu = new Class({ Extends: IMenu, diff --git a/packages/mindplot/lib/components/widget/ModalDialogNotifier.js b/packages/mindplot/src/components/widget/ModalDialogNotifier.js similarity index 100% rename from packages/mindplot/lib/components/widget/ModalDialogNotifier.js rename to packages/mindplot/src/components/widget/ModalDialogNotifier.js diff --git a/packages/mindplot/lib/components/widget/NoteEditor.js b/packages/mindplot/src/components/widget/NoteEditor.js similarity index 96% rename from packages/mindplot/lib/components/widget/NoteEditor.js rename to packages/mindplot/src/components/widget/NoteEditor.js index 2575a43b..f9230591 100644 --- a/packages/mindplot/lib/components/widget/NoteEditor.js +++ b/packages/mindplot/src/components/widget/NoteEditor.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const BootstrapDialog = require('../libraries/bootstrap/BootstrapDialog').default; +import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; const NoteEditor = new Class({ Extends: BootstrapDialog, diff --git a/packages/mindplot/lib/components/widget/ToolbarItem.js b/packages/mindplot/src/components/widget/ToolbarItem.js similarity index 97% rename from packages/mindplot/lib/components/widget/ToolbarItem.js rename to packages/mindplot/src/components/widget/ToolbarItem.js index 8f741e22..72cb40b9 100644 --- a/packages/mindplot/lib/components/widget/ToolbarItem.js +++ b/packages/mindplot/src/components/widget/ToolbarItem.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const Events = require('../Events').default; +import Events from '../Events'; const ToolbarItem = new Class({ Implements: Events, // FIXME: should be extends? diff --git a/packages/mindplot/lib/components/widget/ToolbarNotifier.js b/packages/mindplot/src/components/widget/ToolbarNotifier.js similarity index 100% rename from packages/mindplot/lib/components/widget/ToolbarNotifier.js rename to packages/mindplot/src/components/widget/ToolbarNotifier.js diff --git a/packages/mindplot/lib/components/widget/ToolbarPaneItem.js b/packages/mindplot/src/components/widget/ToolbarPaneItem.js similarity index 96% rename from packages/mindplot/lib/components/widget/ToolbarPaneItem.js rename to packages/mindplot/src/components/widget/ToolbarPaneItem.js index dddb7f04..10a03cec 100644 --- a/packages/mindplot/lib/components/widget/ToolbarPaneItem.js +++ b/packages/mindplot/src/components/widget/ToolbarPaneItem.js @@ -15,8 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ToolbarItem = require('./ToolbarItem').default; -const FloatingTip = require('./FloatingTip').default; +import ToolbarItem from './ToolbarItem'; +import FloatingTip from './FloatingTip'; const ToolbarPaneItem = new Class({ Extends: ToolbarItem, diff --git a/packages/mindplot/lib/components/widget/TopicShapePanel.js b/packages/mindplot/src/components/widget/TopicShapePanel.js similarity index 96% rename from packages/mindplot/lib/components/widget/TopicShapePanel.js rename to packages/mindplot/src/components/widget/TopicShapePanel.js index 23d5cc15..a706fbd2 100644 --- a/packages/mindplot/lib/components/widget/TopicShapePanel.js +++ b/packages/mindplot/src/components/widget/TopicShapePanel.js @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const ListToolbarPanel = require('./ListToolbarPanel').default; +import ListToolbarPanel from './ListToolbarPanel'; const TopicShapePanel = new Class({ Extends: ListToolbarPanel, diff --git a/packages/mindplot/lib/components/widget/colorPalette.css b/packages/mindplot/src/components/widget/colorPalette.css similarity index 100% rename from packages/mindplot/lib/components/widget/colorPalette.css rename to packages/mindplot/src/components/widget/colorPalette.css diff --git a/packages/mindplot/lib/components/widget/colorPalette.html b/packages/mindplot/src/components/widget/colorPalette.html similarity index 100% rename from packages/mindplot/lib/components/widget/colorPalette.html rename to packages/mindplot/src/components/widget/colorPalette.html diff --git a/packages/mindplot/src/components/widget/index.js b/packages/mindplot/src/components/widget/index.js new file mode 100644 index 00000000..f498c470 --- /dev/null +++ b/packages/mindplot/src/components/widget/index.js @@ -0,0 +1,37 @@ +import colorPalettePanel from './ColorPalettePanel'; +import floatingTip from './FloatingTip'; +import fontFamilyPanel from './FontFamilyPanel'; +import fontSizePanel from './FontSizePanel'; +import iconPanel from './IconPanel'; +import iMenu from './IMenu'; +import keyboardShortcutTooltip from './KeyboardShortcutTooltip'; +import linkEditor from './LinkEditor'; +import linkIconTooltip from './LinkIconTooltip'; +import listToolbarPanel from './ListToolbarPanel'; +import menu from './Menu'; +import modalDialogNotifier from './ModalDialogNotifier'; +import noteEditor from './NoteEditor'; +import toolbarItem from './ToolbarItem'; +import toolbarNotifier from './ToolbarNotifier'; +import toolbarPanelItem from './ToolbarPaneItem'; +import topicShapePanel from './TopicShapePanel'; + +export default { + ColorPalettePanel: colorPalettePanel, + FloatingTip: floatingTip, + FontFamilyPanel: fontFamilyPanel, + FontSizePanel: fontSizePanel, + IconPanel: iconPanel, + IMenu: iMenu, + KeyboardShortcutTooltip: keyboardShortcutTooltip, + LinkEditor: linkEditor, + LinkIconTooltip: linkIconTooltip, + ListToolbarPanel: listToolbarPanel, + Menu: menu, + ModalDialogNotifier: modalDialogNotifier, + NoteEditor: noteEditor, + ToolbarItem: toolbarItem, + ToolbarNotifier: toolbarNotifier, + ToolbarPaneItem: toolbarPanelItem, + TopicShapePanel: topicShapePanel, +}; diff --git a/packages/mindplot/src/mindplot.js b/packages/mindplot/src/mindplot.js new file mode 100644 index 00000000..69ede71a --- /dev/null +++ b/packages/mindplot/src/mindplot.js @@ -0,0 +1,26 @@ +import '@libraries/mootools-core-1.4.5'; +import $ from '@libraries/jquery-2.1.0'; +import _ from '@libraries/underscore-min'; + +import coreJs from '@wisemapping/core-js'; + +import commands from '@commands'; +import layout from '@layout'; +import models from '@model'; +import persistence from '@persistence'; +import widget from '@widget'; +import component from '@components'; + +global.$ = $; +global.JQuery = $; +global._ = _; +global.core = coreJs(); + +export default { + commands, + layout, + models, + persistence, + widget, + ...component, +}; diff --git a/packages/mindplot/test/playground/BalancedTestSuite.js b/packages/mindplot/test/playground/BalancedTestSuite.js deleted file mode 100644 index 6ee10063..00000000 --- a/packages/mindplot/test/playground/BalancedTestSuite.js +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const TestSuite = require('./TestSuite').default; - -const Mindplot = require('../../lib/mindplot'); -const mindplot = Mindplot(); - -const BalancedTestSuite = new Class({ - Extends: TestSuite, - - initialize: function () { - $('#balancedTest').css('display', 'block'); - - this.testBalanced(); - this.testBalancedPredict(); - this.testBalancedNodeDragPredict(); - }, - - testBalanced: function () { - console.log('testBalanced:'); - var position = { x: 0, y: 0 }; - var plotsize = { width: 1000, height: 200 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 1, 0); - manager.layout(); - manager.plot('testBalanced1', plotsize); - - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 2, 1); - manager.layout(); - manager.plot('testBalanced2', plotsize); - - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 3, 2); - manager.layout(); - manager.plot('testBalanced3', plotsize); - - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 4, 3); - manager.layout(); - manager.plot('testBalanced4', plotsize); - - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 5, 4); - manager.layout(); - manager.plot('testBalanced5', plotsize); - - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 6, 5); - manager.layout(); - manager.plot('testBalanced6', plotsize); - - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.connectNode(3, 7, 0); - manager.connectNode(7, 8, 0); - manager.connectNode(7, 9, 1); - manager.layout(); - manager.plot('testBalanced7', plotsize); - - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - manager.addNode(12, TestSuite.NODE_SIZE, position); - manager.connectNode(6, 10, 0); - manager.connectNode(10, 11, 0); - manager.connectNode(10, 12, 1); - manager.layout(); - manager.plot('testBalanced8', plotsize); - - manager.addNode(13, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 13, 4); - manager.layout(); - manager.plot('testBalanced9', { width: 1000, height: 400 }); - - // Check orders have shifted accordingly - $assert(manager.find(5).getOrder() == 6, 'Node 5 should have order 6'); - - manager.addNode(14, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 14, 5); - manager.layout(); - manager.plot('testBalanced10', { width: 1000, height: 400 }); - - // Check orders have shifted accordingly - $assert(manager.find(6).getOrder() == 7, 'Node 6 should have order 7'); - - manager.addNode(15, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 15, 4); - manager.layout(); - manager.plot('testBalanced11', { width: 1000, height: 400 }); - - // Check orders have shifted accordingly - $assert(manager.find(13).getOrder() == 6, 'Node 13 should have order 6'); - $assert(manager.find(5).getOrder() == 8, 'Node 5 should have order 8'); - - manager.addNode(16, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 16, 25); - manager.layout(); - manager.plot('testBalanced12', { width: 1000, height: 400 }); - - // Check orders have shifted accordingly - $assert(manager.find(16).getOrder() == 9, 'Node 16 should have order 9'); - - manager.addNode(17, TestSuite.NODE_SIZE, position); - manager.addNode(18, TestSuite.NODE_SIZE, position); - manager.addNode(19, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 17, 11); - manager.connectNode(0, 18, 13); - manager.connectNode(0, 19, 10); - manager.layout(); - manager.plot('testBalanced13', { width: 1000, height: 400 }); - - // Check that everything is ok - $assert( - manager.find(1).getPosition().x > manager.find(0).getPosition().x, - 'even order nodes must be at right of central topic' - ); - $assert( - manager.find(3).getPosition().x > manager.find(0).getPosition().x, - 'even order nodes must be at right of central topic' - ); - $assert( - manager.find(5).getPosition().x > manager.find(0).getPosition().x, - 'even order nodes must be at right of central topic' - ); - $assert( - manager.find(2).getPosition().x < manager.find(0).getPosition().x, - 'odd order nodes must be at right of central topic' - ); - $assert( - manager.find(4).getPosition().x < manager.find(0).getPosition().x, - 'odd order nodes must be at right of central topic' - ); - $assert( - manager.find(6).getPosition().x < manager.find(0).getPosition().x, - 'odd order nodes must be at right of central topic' - ); - $assert( - manager.find(7).getPosition().x > manager.find(3).getPosition().x, - 'children of 1st level even order nodes must be to the right' - ); - $assert( - manager.find(8).getPosition().x > manager.find(7).getPosition().x, - 'children of 1st level even order nodes must be to the right' - ); - $assert( - manager.find(9).getPosition().x > manager.find(7).getPosition().x, - 'children of 1st level even order nodes must be to the right' - ); - $assert( - manager.find(10).getPosition().x < manager.find(6).getPosition().x, - 'children of 1st level odd order nodes must be to the left' - ); - $assert( - manager.find(11).getPosition().x < manager.find(10).getPosition().x, - 'children of 1st level odd order nodes must be to the left' - ); - $assert( - manager.find(12).getPosition().x < manager.find(10).getPosition().x, - 'children of 1st level odd order nodes must be to the left' - ); - - console.log('OK!\n\n'); - }, - - testBalancedPredict: function () { - console.log('testBalancedPredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(0, 4, 3); - manager.connectNode(0, 5, 4); - manager.connectNode(4, 7, 0); - manager.connectNode(4, 8, 1); - manager.connectNode(8, 9, 0); - manager.connectNode(3, 10, 0); - manager.connectNode(3, 11, 1); - - manager.layout(); - - // Graph 1 - var graph1 = manager.plot('testBalancedPredict1', { width: 1000, height: 400 }); - - console.log('\tAdded as child of node 0 and dropped at (165, -70):'); - var prediction1a = manager.predict(0, null, { x: 165, y: -70 }); - this._plotPrediction(graph1, prediction1a); - $assert( - prediction1a.position.y < manager.find(1).getPosition().y && - prediction1a.position.x == manager.find(1).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1a.order == 0, 'Prediction order should be 0'); - - console.log('\tAdded as child of node 0 and dropped at (165, -10):'); - var prediction1b = manager.predict(0, null, { x: 165, y: -10 }); - this._plotPrediction(graph1, prediction1b); - $assert( - prediction1b.position.y > manager.find(1).getPosition().y && - prediction1b.position.y < manager.find(3).getPosition().y && - prediction1b.position.x == manager.find(1).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1b.order == 2, 'Prediction order should be 2'); - - console.log('\tAdded as child of node 0 and dropped at (145, 15):'); - var prediction1c = manager.predict(0, null, { x: 145, y: 15 }); - this._plotPrediction(graph1, prediction1c); - $assert( - prediction1c.position.y > manager.find(3).getPosition().y && - prediction1c.position.y < manager.find(5).getPosition().y && - prediction1c.position.x == manager.find(3).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1c.order == 4, 'Prediction order should be 4'); - - console.log('\tAdded as child of node 0 and dropped at (145, 70):'); - var prediction1d = manager.predict(0, null, { x: 145, y: 70 }); - this._plotPrediction(graph1, prediction1d); - $assert( - prediction1d.position.y > manager.find(5).getPosition().y && - prediction1d.position.x == manager.find(5).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1d.order == 6, 'Prediction order should be 6'); - - // Graph 2 - var graph2 = manager.plot('testBalancedPredict2', { width: 1000, height: 400 }); - - console.log('\tAdded as child of node 0 and dropped at (-145, -50):'); - var prediction2a = manager.predict(0, null, { x: -145, y: -50 }); - this._plotPrediction(graph2, prediction2a); - $assert( - prediction2a.position.y < manager.find(2).getPosition().y && - prediction2a.position.x == manager.find(2).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2a.order == 1, 'Prediction order should be 1'); - - console.log('\tAdded as child of node 0 and dropped at (-145, -10):'); - var prediction2b = manager.predict(0, null, { x: -145, y: -10 }); - this._plotPrediction(graph2, prediction2b); - $assert( - prediction2b.position.y > manager.find(2).getPosition().y && - prediction2b.position.y < manager.find(4).getPosition().y && - prediction2b.position.x == manager.find(2).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2b.order == 3, 'Prediction order should be 3'); - - console.log('\tAdded as child of node 0 and dropped at (-145, 40):'); - var prediction2c = manager.predict(0, null, { x: -145, y: 400 }); - this._plotPrediction(graph2, prediction2c); - $assert( - prediction2c.position.y > manager.find(4).getPosition().y && - prediction2c.position.x == manager.find(4).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2c.order == 5, 'Prediction order should be 5'); - - // Graph 3 - console.log('\tPredict nodes added with no position:'); - var graph3 = manager.plot('testBalancedPredict3', { width: 1000, height: 400 }); - var prediction3 = manager.predict(0, null, null); - this._plotPrediction(graph3, prediction3); - $assert( - prediction3.position.y > manager.find(4).getPosition().y && - prediction3.position.x == manager.find(4).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction3.order == 5, 'Prediction order should be 5'); - - console.log('\tPredict nodes added with no position:'); - manager.addNode(6, TestSuite.NODE_SIZE, prediction3.position); - manager.connectNode(0, 6, prediction3.order); - manager.layout(); - var graph4 = manager.plot('testBalancedPredict4', { width: 1000, height: 400 }); - var prediction4 = manager.predict(0, null, null); - this._plotPrediction(graph4, prediction4); - $assert( - prediction4.position.y > manager.find(5).getPosition().y && - prediction4.position.x == manager.find(5).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction4.order == 6, 'Prediction order should be 6'); - - console.log('\tPredict nodes added only a root node:'); - manager.removeNode(1).removeNode(2).removeNode(3).removeNode(4).removeNode(5); - manager.layout(); - var graph5 = manager.plot('testBalancedPredict5', { width: 1000, height: 400 }); - var prediction5a = manager.predict(0, null, null); - var prediction5b = manager.predict(0, null, { x: 40, y: 100 }); - this._plotPrediction(graph5, prediction5a); - this._plotPrediction(graph5, prediction5b); - $assert( - prediction5a.position.x > manager.find(0).getPosition().x && - prediction5a.position.y == manager.find(0).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction5a.order == 0, 'Prediction order should be 0'); - $assert( - prediction5a.position.x == prediction5b.position.x && - prediction5a.position.y == prediction5b.position.y, - 'Both predictions should be the same' - ); - $assert(prediction5a.order == prediction5b.order, 'Both predictions should be the same'); - - console.log('OK!\n\n'); - }, - - testBalancedNodeDragPredict: function () { - console.log('testBalancedNodeDragPredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Graph 1 - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.layout(); - var graph1 = manager.plot('testBalancedNodeDragPredict1', { width: 800, height: 400 }); - - var prediction1a = manager.predict(0, 1, { x: 50, y: 50 }); - this._plotPrediction(graph1, prediction1a); - $assert( - prediction1a.position.x == manager.find(1).getPosition().x && - prediction1a.position.y == manager.find(1).getPosition().y, - 'Prediction position should be the same as node 1' - ); - $assert( - prediction1a.order == manager.find(1).getOrder(), - 'Prediction order should be the same as node 1' - ); - - var prediction1b = manager.predict(0, 1, { x: 50, y: -50 }); - this._plotPrediction(graph1, prediction1b); - $assert( - prediction1b.position.x == manager.find(1).getPosition().x && - prediction1b.position.y == manager.find(1).getPosition().y, - 'Prediction position should be the same as node 1' - ); - $assert( - prediction1b.order == manager.find(1).getOrder(), - 'Prediction order should be the same as node 1' - ); - - var prediction1c = manager.predict(0, 1, { x: -50, y: 50 }); - this._plotPrediction(graph1, prediction1c); - $assert( - prediction1c.position.x < manager.find(0).getPosition().x && - prediction1c.position.y == manager.find(0).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1c.order == 1, 'Prediction order should be the same as node 1'); - - var prediction1d = manager.predict(0, 1, { x: -50, y: -50 }); - this._plotPrediction(graph1, prediction1d); - $assert( - prediction1d.position.x < manager.find(0).getPosition().x && - prediction1d.position.y == manager.find(0).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1d.order == 1, 'Prediction order should be the same as node 1'); - - // Graph 2 - manager.disconnectNode(1); - manager.connectNode(0, 1, 1); - manager.layout(); - var graph2 = manager.plot('testBalancedNodeDragPredict2', { width: 800, height: 400 }); - - var prediction2a = manager.predict(0, 1, { x: 50, y: 50 }); - this._plotPrediction(graph2, prediction2a); - $assert( - prediction2a.position.x > manager.find(0).getPosition().x && - prediction2a.position.y == manager.find(0).getPosition().y, - 'Prediction is positioned incorrectly' - ); - $assert(prediction2a.order == 0, 'Prediction order should be 0'); - - var prediction2b = manager.predict(0, 1, { x: 50, y: -50 }); - this._plotPrediction(graph2, prediction2b); - $assert( - prediction2b.position.x > manager.find(0).getPosition().x && - prediction2b.position.y == manager.find(0).getPosition().y, - 'Prediction is positioned incorrectly' - ); - $assert(prediction2b.order == 0, 'Prediction order should be 0'); - - var prediction2c = manager.predict(0, 1, { x: -50, y: 50 }); - this._plotPrediction(graph2, prediction2c); - $assert( - prediction2c.position.x == manager.find(1).getPosition().x && - prediction2c.position.y == manager.find(1).getPosition().y, - 'Prediction position should be the same as node 1' - ); - $assert( - prediction2c.order == manager.find(1).getOrder(), - 'Prediction order should be the same as node 1' - ); - - var prediction2d = manager.predict(0, 1, { x: -50, y: -50 }); - this._plotPrediction(graph2, prediction2d); - $assert( - prediction2d.position.x == manager.find(1).getPosition().x && - prediction2d.position.y == manager.find(1).getPosition().y, - 'Prediction position should be the same as node 1' - ); - $assert( - prediction2d.order == manager.find(1).getOrder(), - 'Prediction order should be the same as node 1' - ); - - // Graph 3 - manager.disconnectNode(1); - manager.connectNode(0, 1, 0); - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); - manager.layout(); - var graph3 = manager.plot('testBalancedNodeDragPredict3', { width: 800, height: 400 }); - - var prediction3a = manager.predict(0, 1, { x: 50, y: 50 }); - this._plotPrediction(graph3, prediction3a); - $assert( - prediction3a.position.x == manager.find(2).getPosition().x && - prediction3a.position.y > manager.find(2).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction3a.order == 4, 'Prediction order should be 4'); - - var prediction3b = manager.predict(0, 1, { x: 50, y: -50 }); - this._plotPrediction(graph3, prediction3b); - $assert( - prediction3b.position.x == manager.find(1).getPosition().x && - prediction3b.position.y == manager.find(1).getPosition().y && - prediction3b.order == manager.find(1).getOrder(), - 'Prediction should be the exact same as dragged node' - ); - - var prediction3c = manager.predict(0, 1, { x: -50, y: 50 }); - this._plotPrediction(graph3, prediction3c); - $assert( - prediction3c.position.x < manager.find(0).getPosition().x && - prediction3c.position.y == manager.find(0).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction3c.order == 1, 'Prediction order should be 1'); - - var prediction3d = manager.predict(0, 1, { x: -50, y: -50 }); - this._plotPrediction(graph3, prediction3d); - $assert( - prediction3d.position.x < manager.find(0).getPosition().x && - prediction3d.position.y == manager.find(0).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction3d.order == 1, 'Prediction order should be 1'); - - var prediction3e = manager.predict(0, 1, { x: 50, y: 0 }); - this._plotPrediction(graph3, prediction3e); - $assert( - prediction3e.position.x == manager.find(1).getPosition().x && - prediction3e.position.y == manager.find(1).getPosition().y, - 'Prediction position should be the same as node 1' - ); - $assert( - prediction3e.order == manager.find(1).getOrder(), - 'Prediction order should be the same as node 1' - ); - - console.log('OK!\n\n'); - }, -}); - -export default BalancedTestSuite; diff --git a/packages/mindplot/test/playground/FreeTestSuite.js b/packages/mindplot/test/playground/FreeTestSuite.js deleted file mode 100644 index 25ba6484..00000000 --- a/packages/mindplot/test/playground/FreeTestSuite.js +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const TestSuite = require('./TestSuite').default; -const Mindplot = require('../../lib/mindplot'); -const mindplot = Mindplot(); - -const FreeTestSuite = new Class({ - Extends: TestSuite, - - initialize: function () { - $('#freeTest').css('display', 'block'); - - this.testFreePosition(); - this.testFreePredict(); - this.testReconnectFreeNode(); - this.testSiblingOverlapping(); - this.testRootNodeChildrenPositioning(); - this.testBalancedFreePredict(); - this.testFreeReorder(); - this.testFreeOverlap(); - }, - - testFreePosition: function () { - console.log('testFreePosition:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - manager.addNode(12, TestSuite.NODE_SIZE, position); - manager.addNode(13, TestSuite.NODE_SIZE, position); - manager.addNode(14, TestSuite.NODE_SIZE, position); - manager.addNode(15, TestSuite.NODE_SIZE, position); - manager.addNode(16, TestSuite.NODE_SIZE, position); - manager.addNode(17, TestSuite.NODE_SIZE, position); - manager.addNode(18, TestSuite.NODE_SIZE, position); - manager.addNode(19, TestSuite.NODE_SIZE, position); - manager.addNode(20, TestSuite.NODE_SIZE, position); - manager.addNode(21, TestSuite.NODE_SIZE, position); - manager.addNode(22, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0).connectNode(0, 2, 1).connectNode(0, 3, 2).connectNode(0, 4, 3); - manager.connectNode(4, 21, 0).connectNode(4, 22, 0); - manager.connectNode(1, 5, 0); - manager.connectNode(5, 6, 0).connectNode(6, 8, 0).connectNode(8, 9, 0); - manager.connectNode(5, 7, 1).connectNode(7, 10, 0); - manager - .connectNode(3, 11, 0) - .connectNode(11, 14, 0) - .connectNode(14, 18, 0) - .connectNode(14, 19, 1) - .connectNode(14, 20, 2); - manager - .connectNode(3, 12, 1) - .connectNode(12, 15, 0) - .connectNode(12, 16, 1) - .connectNode(12, 17, 2); - manager.connectNode(3, 13, 2); - - manager.layout(); - manager.plot('testFreePosition1', { width: 1400, height: 600 }); - - console.log('\tmove node 12 to (300,30):'); - manager.moveNode(12, { x: 300, y: 30 }); - manager.layout(true); - manager.plot('testFreePosition2', { width: 1400, height: 600 }); - this._assertFreePosition(manager, 12, { x: 300, y: 30 }); - - console.log('\tmove node 13 to (340,180):'); - var node13Pos = { x: 340, y: 180 }; - manager.moveNode(13, node13Pos); - manager.layout(true); - manager.plot('testFreePosition3', { width: 1400, height: 600 }); - this._assertFreePosition(manager, 13, node13Pos); - - console.log('\tmove node 11 to (250,-50):'); - manager.moveNode(11, { x: 250, y: -50 }); - manager.layout(true); - manager.plot('testFreePosition4', { width: 1400, height: 600 }); - this._assertFreePosition(manager, 11, { x: 250, y: -50 }); - $assert( - manager.find(13).getPosition().x == node13Pos.x && - manager.find(13).getPosition().y == node13Pos.y, - "Node 13 shouldn't have moved" - ); - - console.log('\tmove node 7 to (350,-190):'); - manager.moveNode(7, { x: 350, y: -190 }); - manager.layout(true); - manager.plot('testFreePosition5', { width: 1400, height: 600 }); - this._assertFreePosition(manager, 7, { x: 350, y: -190 }); - - console.log('\tadd node 23 to 12:'); - manager.addNode(23, TestSuite.NODE_SIZE, position); - manager.connectNode(12, 23, 3); - manager.layout(true); - manager.plot('testFreePosition6', { width: 1400, height: 600 }); - this._assertFreePosition(manager, null, null); - - console.log('\tmove node 4 to (-300, 190):'); - manager.moveNode(4, { x: -300, y: 190 }); - manager.layout(true); - manager.plot('testFreePosition7', { width: 1400, height: 600 }); - this._assertFreePosition(manager, 4, { x: -300, y: 190 }); - - console.log('\tadd node 24 to 3:'); - manager.addNode(24, TestSuite.NODE_SIZE, position); - manager.connectNode(3, 24, 3); - manager.layout(true); - manager.plot('testFreePosition8', { width: 1400, height: 600 }); - this._assertFreePosition(manager, null, null); - - console.log('\tadd node 25 to 17:'); - manager.addNode(25, TestSuite.NODE_SIZE, position); - manager.connectNode(17, 25, 0); - manager.layout(true); - manager.plot('testFreePosition9', { width: 1400, height: 600 }); - this._assertFreePosition(manager, null, null); - - console.log('OK!\n\n'); - }, - - testFreePredict: function () { - console.log('testFreePredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(3, 4, 0); - manager.connectNode(3, 5, 1); - manager.connectNode(3, 6, 2); - manager.connectNode(5, 7, 0); - manager.connectNode(5, 8, 1); - manager.connectNode(5, 11, 2); - manager.connectNode(2, 9, 0); - manager.connectNode(2, 10, 1); - - manager.layout(); - var graph = manager.plot('testFreePredict1', { width: 1000, height: 400 }); - - var pos1 = { x: 370, y: 80 }; - var predict1 = manager.predict(5, 11, pos1, true); - this._plotPrediction(graph, predict1); - $assert( - predict1.position.x == pos1.x && predict1.position.y == pos1.y, - 'free predict should return the same position' - ); - - var pos2 = { x: -200, y: 80 }; - var predict2 = manager.predict(0, 2, pos2, true); - this._plotPrediction(graph, predict2); - $assert( - predict2.position.x == pos2.x && predict2.position.y == pos2.y, - 'free predict should return the same position' - ); - - var pos3 = { x: 200, y: 30 }; - var node5 = manager.find(5); - var predict3 = manager.predict(3, 5, pos3, true); - this._plotPrediction(graph, predict3); - $assert( - predict3.position.x == node5.getPosition().x && predict3.position.y == pos3.y, - 'free predict should return the x-coordinate of the node' - ); - - var pos4 = { x: -100, y: 45 }; - var node10 = manager.find(10); - var predict4 = manager.predict(2, 10, pos4, true); - this._plotPrediction(graph, predict4); - $assert( - predict4.position.x == node10.getPosition().x && predict4.position.y == pos4.y, - 'free predict should return the x-coordinate of the node' - ); - - console.log('OK!\n\n'); - }, - - testReconnectFreeNode: function () { - console.log('testReconnectFreeNode:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(3, 4, 0); - manager.connectNode(3, 5, 1); - manager.connectNode(3, 6, 2); - manager.connectNode(5, 7, 0); - manager.connectNode(5, 8, 1); - manager.connectNode(5, 11, 2); - manager.connectNode(2, 9, 0); - manager.connectNode(2, 10, 1); - - manager.layout(); - manager.plot('testReconnectFreeNode1', { width: 1000, height: 400 }); - - console.log('\tmove node 5'); - manager.moveNode(5, { x: 250, y: 30 }); - manager.layout(); - manager.plot('testReconnectFreeNode2', { width: 1000, height: 400 }); - this._assertFreePosition(manager, 5, { x: 250, y: 30 }); - - console.log('\treconnect node 5 to node 2'); - manager.disconnectNode(5); - manager.connectNode(2, 5, 2); - manager.layout(); - manager.plot('testReconnectFreeNode3', { width: 1000, height: 400 }); - $assert( - manager.find(5).getPosition().y > manager.find(10).getPosition().y && - manager.find(5).getPosition().x == manager.find(10).getPosition().x, - 'Node 5 is incorrectly positioned' - ); - $assert(manager.find(5).getOrder() == 2, 'Node 5 should have order 2'); - - console.log('\tmove node 8'); - manager.moveNode(8, { x: -370, y: 60 }); - manager.layout(); - manager.plot('testReconnectFreeNode4', { width: 1000, height: 400 }); - this._assertFreePosition(manager, 8, { x: -370, y: 60 }); - - console.log('\treconnect node 5 to node 10'); - manager.disconnectNode(5); - manager.connectNode(10, 5, 0); - manager.layout(); - manager.plot('testReconnectFreeNode5', { width: 1000, height: 400 }); - $assert( - manager.find(5).getPosition().y == manager.find(10).getPosition().y && - manager.find(5).getPosition().x < manager.find(10).getPosition().x, - 'Node 5 is incorrectly positioned' - ); - $assert(manager.find(5).getOrder() == 0, 'Node 5 should have order 0'); - - console.log('reconnect node 5 to node 3'); - manager.disconnectNode(5); - manager.connectNode(3, 5, 2); - manager.layout(); - manager.plot('testReconnectFreeNode6', { width: 1000, height: 400 }); - $assert( - manager.find(5).getPosition().y > manager.find(6).getPosition().y && - manager.find(5).getPosition().x == manager.find(6).getPosition().x, - 'Node 5 is incorrectly positioned' - ); - $assert(manager.find(5).getOrder() == 2, 'Node 5 should have order 2'); - - console.log('\tmove node 8'); - manager.moveNode(8, { x: 370, y: 30 }); - manager.layout(); - manager.plot('testReconnectFreeNode7', { width: 1000, height: 400 }); - this._assertFreePosition(manager, 8, { x: 370, y: 30 }); - - console.log('OK!\n\n'); - }, - - testSiblingOverlapping: function () { - console.log('testSiblingOverlapping:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(1, 3, 1); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 2); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 3); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 4); - manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(1, 7, 5); - manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(1, 8, 6); - manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(0, 9, 4); - manager.layout(); - manager.plot('testSiblingOverlapping1', { width: 800, height: 600 }); - - console.log('\tmove node 2'); - manager.moveNode(2, { x: 250, y: -30 }); - manager.layout(); - manager.plot('testSiblingOverlapping2', { width: 800, height: 600 }); - this._assertFreePosition(manager, 2, { x: 250, y: -30 }); - - console.log('\tmove node 7'); - manager.moveNode(7, { x: 250, y: 100 }); - manager.layout(); - manager.plot('testSiblingOverlapping3', { width: 800, height: 600 }); - this._assertFreePosition(manager, 7, { x: 250, y: 100 }); - - console.log('OK!\n\n'); - }, - - testRootNodeChildrenPositioning: function () { - console.log('testRootNodeChildrenPositioning:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 1); - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 2); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(0, 4, 3); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(0, 5, 4); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(0, 6, 5); - manager.layout(); - manager.plot('testRootNodeChildrenPositioning1', { width: 800, height: 600 }); - - console.log('\tmove node 1'); - manager.moveNode(1, { x: 150, y: 0 }); - manager.layout(); - manager.plot('testRootNodeChildrenPositioning2', { width: 800, height: 600 }); - this._assertFreePosition(manager, 1, { x: 150, y: 0 }); - - console.log('\tmove node 4'); - manager.moveNode(4, { x: -140, y: 30 }); - manager.layout(); - manager.plot('testRootNodeChildrenPositioning3', { width: 800, height: 600 }); - this._assertFreePosition(manager, 4, { x: -140, y: 30 }); - - console.log('\tmove node 2'); - manager.moveNode(2, { x: -150, y: -50 }); - manager.layout(); - manager.plot('testRootNodeChildrenPositioning4', { width: 800, height: 600 }); - this._assertFreePosition(manager, 2, { x: -150, y: -50 }); - - //TODO(gb): fix this. It's not working - // console.log("\tmove node 6"); - // manager.moveNode(6, {x:-150, y:-50}); - // manager.layout(); - // manager.plot("testRootNodeChildrenPositioning5", {width:800, height:600}); - // this._assertFreePosition(manager, 6, {x:-150, y:-50}); - - console.log('OK!\n\n'); - }, - - testBalancedFreePredict: function () { - console.log('testBalancedFreePredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.layout(); - var graph1 = manager.plot('testBalancedFreePredict1', { width: 800, height: 400 }); - - var predict1 = manager.predict(0, 1, { x: 70, y: 0 }, true); - this._plotPrediction(graph1, predict1); - $assert( - predict1.position.x == manager.find(1).getPosition().x, - 'Prediction x pos should be the same as node 1' - ); - - console.log('OK!\n\n'); - }, - - testFreeReorder: function () { - console.log('testFreeReorder:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 0); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 1); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 2); - - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); - manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(2, 7, 0); - manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(2, 8, 1); - manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(2, 9, 2); - manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(2, 10, 3); - - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 4); - manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(3, 11, 0); - manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(3, 12, 1); - manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(3, 13, 2); - manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(3, 14, 3); - manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(3, 15, 4); - manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(3, 16, 5); - - manager.layout(); - manager.moveNode(14, { x: 270, y: -160 }); - manager.layout(); - manager.plot('testFreeReorder1', { width: 800, height: 1200 }); - $assert( - manager.find(14).getPosition().y > manager.find(10).getPosition().y, - 'Node 14 should be below branch 2' - ); - - console.log('OK!\n\n'); - }, - - testFreeOverlap: function () { - console.log('testFreeOverlap:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 0); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 1); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 2); - - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); - manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(2, 7, 0); - manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(2, 8, 1); - manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(2, 9, 2); - manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(2, 10, 3); - - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 4); - manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(3, 11, 0); - manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(3, 12, 1); - manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(3, 13, 2); - manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(3, 14, 3); - manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(3, 15, 4); - manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(3, 16, 5); - - manager.layout(); - manager.plot('testFreeOverlap1', { width: 800, height: 1200 }); - - manager.moveNode(14, { x: 270, y: 7 }); - manager.layout(); - manager.plot('testFreeOverlap2', { width: 800, height: 1200 }); - $assert( - manager.find(2).getPosition().y > manager.find(1).getPosition().y, - 'Branches 1 and 2 are overlapping' - ); - - console.log('OK!\n\n'); - }, - - _assertFreePosition: function (manager, id, position) { - if (id != null && position.x != null && position.y != null) { - var node = manager.find(id); - $assert( - node.getPosition().x == position.x && node.getPosition().y == position.y, - 'Freely moved node ' + - id + - ' is not left at free position (' + - position.x + - ',' + - position.y + - '). ' + - 'Actual position: (' + - node.getPosition().x + - ',' + - node.getPosition().y + - ')' - ); - } - - var treeSet = manager._treeSet; - _.each( - treeSet._rootNodes, - function (rootNode) { - var heightById = rootNode.getSorter().computeChildrenIdByHeights(treeSet, rootNode); - this._assertBranchCollision(treeSet, rootNode, heightById); - }, - this - ); - }, - - _assertBranchCollision: function (treeSet, node, heightById) { - var children = treeSet.getChildren(node); - var childOfRootNode = treeSet._rootNodes.contains(node); - - _.each( - children, - function (child) { - var height = heightById[child.getId()]; - var siblings = treeSet.getSiblings(child); - if (childOfRootNode) { - siblings = siblings.filter(function (sibling) { - return child.getOrder() % 2 == sibling.getOrder() % 2; - }); - } - _.each( - siblings, - function (sibling) { - this._branchesOverlap(child, sibling, heightById); - }, - this - ); - }, - this - ); - - _.each( - children, - function (child) { - this._assertBranchCollision(treeSet, child, heightById); - }, - this - ); - }, - - _branchesOverlap: function (branchA, branchB, heightById) { - var topA = branchA.getPosition().y - heightById[branchA.getId()] / 2; - var bottomA = branchA.getPosition().y + heightById[branchA.getId()] / 2; - var topB = branchB.getPosition().y - heightById[branchB.getId()] / 2; - var bottomB = branchB.getPosition().y + heightById[branchB.getId()] / 2; - - $assert( - topA >= bottomB || bottomA <= topB, - 'Branches ' + branchA.getId() + ' and ' + branchB.getId() + ' overlap' - ); - }, -}); - -export default FreeTestSuite; diff --git a/packages/mindplot/test/playground/SymmetricTestSuite.js b/packages/mindplot/test/playground/SymmetricTestSuite.js deleted file mode 100644 index a505ce6b..00000000 --- a/packages/mindplot/test/playground/SymmetricTestSuite.js +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const TestSuite = require('./TestSuite').default; -const Mindplot = require('../../lib/mindplot'); -const mindplot = Mindplot(); - -const SymmetricTestSuite = new Class({ - Extends: TestSuite, - - initialize: function () { - $('#symmetricTest').css('display', 'block'); - - this.testSymmetry(); - this.testSymmetricPredict(); - this.testSymmetricDragPredict(); - }, - - testSymmetry: function () { - console.log('testSymmetry:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - manager.addNode(12, TestSuite.NODE_SIZE, position); - manager.addNode(13, TestSuite.NODE_SIZE, position); - manager.addNode(14, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 14, 0); - manager.connectNode(14, 13, 0); - manager.connectNode(13, 1, 0); - manager.connectNode(13, 2, 1); - manager.connectNode(13, 3, 2); - manager.connectNode(13, 4, 3); - manager.connectNode(13, 5, 4); - manager.connectNode(1, 6, 0); - manager.connectNode(1, 7, 1); - manager.connectNode(7, 8, 0); - manager.connectNode(8, 9, 0); - manager.connectNode(5, 10, 0); - manager.connectNode(6, 11, 0); - manager.connectNode(6, 12, 1); - - manager.layout(); - manager.plot('testSymmetry', { width: 1600, height: 400 }); - - // All nodes should be positioned symmetrically with respect to their common ancestors - $assert( - manager.find(14).getPosition().y == manager.find(13).getPosition().y, - 'Symmetry is not respected' - ); - $assert( - manager.find(5).getPosition().y == manager.find(10).getPosition().y, - 'Symmetry is not respected' - ); - $assert( - manager.find(11).getPosition().y - manager.find(6).getPosition().y == - -(manager.find(12).getPosition().y - manager.find(6).getPosition().y), - 'Symmetry is not respected' - ); - $assert( - manager.find(8).getPosition().y - manager.find(1).getPosition().y == - -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), - 'Symmetry is not respected' - ); - $assert( - manager.find(9).getPosition().y - manager.find(1).getPosition().y == - -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), - 'Symmetry is not respected' - ); - - console.log('OK!\n\n'); - }, - - testSymmetricPredict: function () { - console.log('testSymmetricPredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(3, 4, 0); - manager.connectNode(3, 5, 1); - manager.connectNode(3, 6, 2); - manager.connectNode(5, 7, 0); - manager.connectNode(5, 8, 1); - manager.connectNode(5, 11, 2); - manager.connectNode(2, 9, 0); - manager.connectNode(2, 10, 1); - - manager.layout(); - - // Graph - var graph1 = manager.plot('testSymmetricPredict1', { width: 1000, height: 400 }); - - console.log('\tAdded as child of node 9 and dropped at (-280, 45):'); - var prediction1a = manager.predict(9, null, { x: -280, y: 45 }); - this._plotPrediction(graph1, prediction1a); - $assert( - prediction1a.position.x < manager.find(9).getPosition().x && - prediction1a.position.y == manager.find(9).getPosition().y, - 'Prediction incorrectly positioned' - ); - $assert(prediction1a.order == 0, 'Prediction order should be 0'); - - console.log('\tAdded as child of node 1 and dropped at (155, -90):'); - var prediction1b = manager.predict(1, null, { x: -155, y: -90 }); - this._plotPrediction(graph1, prediction1b); - $assert( - prediction1b.position.x > manager.find(1).getPosition().x && - prediction1b.position.y == manager.find(1).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1b.order == 0, 'Prediction order should be 0'); - - // Graph 2 - var graph2 = manager.plot('testSymmetricPredict2', { width: 1000, height: 400 }); - - console.log('\tAdded as child of node 5 and dropped at (380, -30):'); - var prediction2d = manager.predict(5, null, { x: 380, y: -30 }); - this._plotPrediction(graph2, prediction2d); - - // Prediction calculator error - $assert( - prediction2d.position.y < manager.find(7).getPosition().y && - prediction2d.position.x == manager.find(7).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2d.order == 0, 'Prediction order should be 0'); - - console.log('\tAdded as child of node 5 and dropped at (375, 15):'); - var prediction2a = manager.predict(5, null, { x: 375, y: 15 }); - this._plotPrediction(graph2, prediction2a); - - $assert( - prediction2a.position.y > manager.find(7).getPosition().y && - prediction2a.position.y < manager.find(8).getPosition().y && - prediction2a.position.x == manager.find(7).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2a.order == 1, 'Prediction order should be 1'); - - console.log('\tAdded as child of node 5 and dropped at (375, 45):'); - var prediction2b = manager.predict(5, null, { x: 375, y: 45 }); - this._plotPrediction(graph2, prediction2b); - $assert( - prediction2b.position.y > manager.find(8).getPosition().y && - prediction2b.position.y < manager.find(11).getPosition().y && - prediction2b.position.x == manager.find(7).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2b.order == 2, 'Prediction order should be 2'); - - console.log('\tAdded as child of node 5 and dropped at (375, 45):'); - var prediction2c = manager.predict(5, null, { x: 375, y: 65 }); - this._plotPrediction(graph2, prediction2c); - $assert( - prediction2c.position.y > manager.find(11).getPosition().y && - prediction2c.position.x == manager.find(11).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction2c.order == 3, 'Prediction order should be 3'); - - // Graph 3 - var graph3 = manager.plot('testSymmetricPredict3', { width: 1000, height: 400 }); - - console.log('\tAdded as child of node 3 and dropped at (280, 45):'); - var prediction3a = manager.predict(3, null, { x: 280, y: 45 }); - this._plotPrediction(graph3, prediction3a); - $assert( - prediction3a.position.y > manager.find(5).getPosition().y && - prediction3a.position.y < manager.find(6).getPosition().y && - prediction3a.position.x == manager.find(5).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction3a.order == 2, 'Prediction order should be 2'); - - console.log('\tAdded as child of node 3 and dropped at (255, 110):'); - var prediction3b = manager.predict(3, null, { x: 255, y: 110 }); - this._plotPrediction(graph3, prediction3b); - $assert( - prediction3b.position.y > manager.find(6).getPosition().y && - prediction3b.position.x == manager.find(6).getPosition().x, - 'Prediction incorrectly positioned' - ); - $assert(prediction3b.order == 3, 'Prediction order should be 3'); - - // Graph 4 - console.log('\tAdded as child of node 2 and dropped at (-260, 0):'); - var graph4 = manager.plot('testSymmetricPredict4', { width: 1000, height: 400 }); - var prediction4 = manager.predict(2, null, { x: -260, y: 0 }); - this._plotPrediction(graph4, prediction4); - $assert( - prediction4.position.y > manager.find(9).getPosition().y && - prediction4.position.y < manager.find(10).getPosition().y && - prediction4.position.x == manager.find(9).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction4.order == 1, 'Prediction order should be 1'); - - // Graph 5 - console.log('\tPredict nodes added with no position:'); - var graph5 = manager.plot('testSymmetricPredict5', { width: 1000, height: 400 }); - var prediction5a = manager.predict(1, null, null); - this._plotPrediction(graph5, prediction5a); - $assert( - prediction5a.position.y == manager.find(1).getPosition().y && - prediction5a.position.x > manager.find(1).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction5a.order == 0, 'Prediction order should be 0'); - - var prediction5b = manager.predict(2, null, null); - this._plotPrediction(graph5, prediction5b); - $assert( - prediction5b.position.y > manager.find(10).getPosition().y && - prediction5b.position.x < manager.find(2).getPosition().x && - prediction5b.position.x == manager.find(10).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction5b.order == 2, 'Prediction order should be 2'); - - var prediction5c = manager.predict(3, null, null); - this._plotPrediction(graph5, prediction5c); - $assert( - prediction5c.position.y > manager.find(6).getPosition().y && - prediction5c.position.x > manager.find(3).getPosition().x && - prediction5c.position.x == manager.find(6).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction5c.order == 3, 'Prediction order should be 3'); - - var prediction5d = manager.predict(10, null, null); - this._plotPrediction(graph5, prediction5d); - $assert( - prediction5d.position.y == manager.find(10).getPosition().y && - prediction5d.position.x < manager.find(10).getPosition().x, - 'Prediction is incorrectly positioned' - ); - $assert(prediction5d.order == 0, 'Prediction order should be 0'); - - console.log('OK!\n\n'); - }, - - testSymmetricDragPredict: function () { - console.log('testSymmetricDragPredict:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 1); - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); - manager.layout(); - - // Graph 1 - var graph1 = manager.plot('testSymmetricDragPredict1', { width: 1000, height: 400 }); - - var prediction1a = manager.predict(1, 2, { x: -250, y: -20 }); - this._plotPrediction(graph1, prediction1a); - $assert( - prediction1a.position.x == manager.find(2).getPosition().x && - prediction1a.position.y == manager.find(2).getPosition().y, - 'Prediction position should be the same as node 2' - ); - $assert( - prediction1a.order == manager.find(2).getOrder(), - 'Predicition order should be the same as node 2' - ); - - var prediction1b = manager.predict(1, 2, { x: -250, y: 20 }); - this._plotPrediction(graph1, prediction1b); - $assert( - prediction1b.position.x == manager.find(2).getPosition().x && - prediction1b.position.y == manager.find(2).getPosition().y, - 'Prediction position should be the same as node 2' - ); - $assert( - prediction1b.order == manager.find(2).getOrder(), - 'Predicition order should be the same as node 2' - ); - - var prediction1c = manager.predict(0, 2, { x: -100, y: -20 }); - this._plotPrediction(graph1, prediction1c); - $assert( - prediction1c.position.x == manager.find(1).getPosition().x && - prediction1c.position.y < manager.find(1).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1c.order == 1, 'Prediction order should be 1'); - - var prediction1d = manager.predict(0, 2, { x: -100, y: 20 }); - this._plotPrediction(graph1, prediction1d); - $assert( - prediction1d.position.x == manager.find(1).getPosition().x && - prediction1d.position.y > manager.find(1).getPosition().y, - 'Prediction is incorrectly positioned' - ); - $assert(prediction1d.order == 3, 'Prediction order should be 3'); - - var prediction1e = manager.predict(1, 2, { x: -250, y: 0 }); - this._plotPrediction(graph1, prediction1e); - $assert( - prediction1e.position.x == manager.find(2).getPosition().x && - prediction1e.position.y == manager.find(2).getPosition().y, - 'Prediction position should be the same as node 2' - ); - $assert( - prediction1e.order == manager.find(2).getOrder(), - 'Predicition order should be the same as node 2' - ); - - console.log('OK!\n\n'); - }, -}); - -export default SymmetricTestSuite; diff --git a/packages/mindplot/test/playground/TestSuite.js b/packages/mindplot/test/playground/TestSuite.js deleted file mode 100644 index 963af45b..00000000 --- a/packages/mindplot/test/playground/TestSuite.js +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright [2015] [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. - */ -const Mindplot = require('../../lib/mindplot'); -const mindplot = Mindplot(); - -const TestSuite = new Class({ - Extends: mindplot.layout.ChildrenSorterStrategy, - - initialize: function () { - $('#basicTest').css('display', 'block'); - // this.testAligned(); - this.testBaselineAligned1(); - this.testBaselineAligned2(); - this.testEvents(); - this.testEventsComplex(); - this.testDisconnect(); - this.testReconnect(); - this.testRemoveNode(); - this.testSize(); - this.testReconnectSingleNode(); - }, - - testAligned: function () { - console.log('testAligned:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(2, 3, 0); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(3, 4, 0); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(0, 5, 2); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(0, 6, 4); - manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(0, 7, 6); - - manager.layout(); - manager.plot('testAligned', { width: 1200, height: 200 }); - - // Child nodes should be vertically aligned - $assert( - manager.find(1).getPosition().y == manager.find(2).getPosition().y, - 'Child nodes are not vertically aligned' - ); - $assert( - manager.find(1).getPosition().y == manager.find(3).getPosition().y, - 'Child nodes are not vertically aligned' - ); - $assert( - manager.find(1).getPosition().y == manager.find(4).getPosition().y, - 'Child nodes are not vertically aligned' - ); - - // Siblings should be horizontally aligned - $assert( - manager.find(1).getPosition().x == manager.find(5).getPosition().x, - 'Sibling nodes are not horizontally aligned' - ); - $assert( - manager.find(1).getPosition().x == manager.find(6).getPosition().x, - 'Sibling nodes are not horizontally aligned' - ); - $assert( - manager.find(1).getPosition().x == manager.find(7).getPosition().x, - 'Sibling nodes are not horizontally aligned' - ); - - console.log('OK!\n\n'); - }, - - testBaselineAligned1: function () { - console.log('testBaselineAligned1:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(1, 3, 0); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(3, 5, 0); - manager.addNode(6, { width: 140, height: 130 }, position).connectNode(3, 6, 1); - manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(6, 7, 0); - manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(7, 8, 0); - manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(7, 9, 1); - manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(7, 10, 2); - manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(7, 11, 3); - manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(7, 12, 4); - manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(7, 13, 5); - manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(7, 14, 6); - manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(7, 15, 7); - manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(7, 16, 8); - manager.addNode(17, TestSuite.NODE_SIZE, position).connectNode(7, 17, 9); - manager.addNode(29, TestSuite.NODE_SIZE, position).connectNode(6, 29, 1); - manager.addNode(30, TestSuite.NODE_SIZE, position).connectNode(6, 30, 2); - manager.addNode(31, { width: 100, height: 50 }, position).connectNode(6, 31, 3); - - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 1); - manager.addNode(18, { width: 80, height: 70 }, position).connectNode(4, 18, 0); - manager.addNode(19, TestSuite.NODE_SIZE, position).connectNode(18, 19, 0); - manager.addNode(20, TestSuite.NODE_SIZE, position).connectNode(19, 20, 0); - manager.addNode(21, TestSuite.NODE_SIZE, position).connectNode(20, 21, 0); - - manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 1); - manager.addNode(22, TestSuite.NODE_SIZE, position).connectNode(2, 22, 0); - manager.addNode(24, TestSuite.NODE_SIZE, position).connectNode(22, 24, 0); - - manager.addNode(23, { width: 80, height: 50 }, position).connectNode(2, 23, 1); - manager.addNode(25, { width: 80, height: 40 }, position).connectNode(23, 25, 0); - manager.addNode(26, { width: 80, height: 80 }, position).connectNode(25, 26, 0); - manager.addNode(27, TestSuite.NODE_SIZE, position).connectNode(26, 27, 0); - manager.addNode(28, { width: 80, height: 80 }, position).connectNode(27, 28, 0); - - // manager.layout(); - // manager.plot("testBaselineAligned1", {width:1600,height:800}); - - console.log('OK!\n\n'); - }, - - testBaselineAligned2: function () { - console.log('testBaselineAligned2:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); - manager.addNode(2, { width: 130, height: 200 }, position).connectNode(1, 2, 0); - manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(2, 3, 0); - manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(2, 4, 1); - manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(2, 5, 2); - manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(2, 6, 3); - - manager.layout(); - manager.plot('testBaselineAligned2', { width: 1600, height: 800 }); - - console.log('OK!\n\n'); - }, - - testEvents: function () { - console.log('testEvents:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, { x: 0, y: 60 }); - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(1, 3, 0); - - var events = []; - manager.addEvent('change', function (event) { - console.log( - '\tUpdated nodes: {id:' + - event.getId() + - ', order: ' + - event.getOrder() + - ',position: {' + - event.getPosition().x + - ',' + - event.getPosition().y + - '}' - ); - events.push(event); - }); - manager.layout(true); - manager.plot('testEvents1', { width: 800, height: 200 }); - - console.log('\t--- Layout without changes should not affect the tree ---'); - events.empty(); - manager.layout(true); - manager.plot('testEvents2', { width: 800, height: 200 }); - - // Check no events where fired - $assert(events.length == 0, 'Unnecessary tree updated.'); - - console.log('OK!\n\n'); - }, - - testEventsComplex: function () { - console.log('testEventsComplex:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, { x: 0, y: 60 }); - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(3, 4, 0); - manager.connectNode(3, 5, 1); - - var events = []; - manager.addEvent('change', function (event) { - console.log( - '\tUpdated nodes: {id:' + - event.getId() + - ', order: ' + - event.getOrder() + - ',position: {' + - event.getPosition().x + - ',' + - event.getPosition().y + - '}' - ); - events.push(event); - }); - - manager.layout(true); - manager.plot('testEventsComplex1', { width: 800, height: 200 }); - - console.log('\t--- Connect a new node ---'); - - events.empty(); - manager.connectNode(3, 6, 2); - manager.layout(true); - manager.plot('testEventsComplex2', { width: 800, height: 200 }); - - // Check only 4 nodes were repositioned - - console.log(events.length); - - $assert(events.length == 4, 'Only 4 nodes should be repositioned.'); - - console.log('OK!\n\n'); - }, - - testDisconnect: function () { - console.log('testDisconnect:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 1, 0); - manager.connectNode(1, 2, 0); - manager.connectNode(1, 3, 1); - manager.connectNode(1, 4, 2); - manager.connectNode(4, 5, 0); - manager.connectNode(5, 6, 0); - manager.connectNode(5, 7, 1); - - var events = []; - manager.addEvent('change', function (event) { - var pos = event.getPosition(); - var posStr = pos ? ',position: {' + pos.x + ',' + pos.y : ''; - var node = manager.find(event.getId()); - console.log( - '\tUpdated nodes: {id:' + - event.getId() + - ', order: ' + - event.getOrder() + - posStr + - '}' - ); - events.push(event); - }); - manager.layout(true); - manager.plot('testDisconnect1', { width: 1200, height: 400 }); - - console.log('--- Disconnect node 2 ---'); - events.empty(); - manager.disconnectNode(2); - manager.layout(true); - manager.plot('testDisconnect2', { width: 1200, height: 400 }); - - // Check that orders have been shifted accordingly - $assert(manager.find(2).getOrder() == 0, 'Node 2 should have order 0'); - $assert(manager.find(3).getOrder() == 0, 'Node 3 should now have order 0'); - $assert(manager.find(4).getOrder() == 1, 'Node 4 should have order 1'); - - console.log('--- Disconnect node 4 ---'); - manager.disconnectNode(4); - manager.layout(true); - manager.plot('testDisconnect3', { width: 1200, height: 400 }); - - // Check that nodes 1 and 3 are now vertically aligned - $assert( - manager.find(1).getPosition().y == manager.find(3).getPosition().y, - 'Nodes 1 and 3 should now be vertically aligned' - ); - - console.log('OK!\n\n'); - }, - - testReconnect: function () { - console.log('testReconnect:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - manager.addNode(12, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(0, 4, 3); - manager.connectNode(0, 5, 4); - manager.connectNode(1, 6, 0); - manager.connectNode(1, 7, 1); - manager.connectNode(7, 8, 0); - manager.connectNode(8, 9, 0); - manager.connectNode(5, 10, 0); - manager.connectNode(6, 11, 0); - manager.connectNode(6, 12, 1); - - manager.layout(); - manager.plot('testReconnect1', { width: 1200, height: 400 }); - - // Reconnect node 6 to node 4 - console.log('\tReconnect node 6 to node 4'); - manager.disconnectNode(6); - manager.connectNode(4, 6, 0); - manager.layout(); - manager.plot('testReconnect2', { width: 1200, height: 400 }); - - // Check nodes are left aligned correctly - $assert( - manager.find(1).getPosition().y == manager.find(7).getPosition().y, - 'Nodes 1 and 7 should be vertically aligned' - ); - $assert( - manager.find(4).getPosition().y == manager.find(6).getPosition().y, - 'Nodes 4 and 6 should be vertically aligned' - ); - $assert( - manager.find(4).getPosition().x > manager.find(6).getPosition().x, - 'Node 6 and their children should be to the left of node 4' - ); - $assert( - manager.find(6).getPosition().x > manager.find(11).getPosition().x && - manager.find(11).getPosition().x == manager.find(12).getPosition().x, - 'Nodes 11 and 12 should be to the left of node 6 and horizontally aligned' - ); - - console.log('OK!\n\n'); - }, - - testRemoveNode: function () { - console.log('testRemoveNode:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, TestSuite.NODE_SIZE, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(6, TestSuite.NODE_SIZE, position); - manager.addNode(7, TestSuite.NODE_SIZE, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(0, 5, 1); - manager.connectNode(0, 6, 2); - manager.connectNode(0, 7, 3); - manager.connectNode(0, 8, 4); - manager.connectNode(0, 9, 5); - manager.connectNode(1, 2, 0); - manager.connectNode(1, 3, 1); - manager.connectNode(3, 4, 0); - - var events = []; - manager.addEvent('change', function (event) { - var pos = event.getPosition(); - var posStr = pos ? ',position: {' + pos.x + ',' + event.getPosition().y : ''; - events.push(event); - }); - manager.layout(true); - manager.plot('testRemoveNode1', { width: 1000, height: 200 }); - - console.log('\t--- Remove node 3 ---'); - manager.removeNode(3); - manager.layout(true); - manager.plot('testRemoveNode2', { width: 1000, height: 200 }); - - // Check nodes are correctly aligned and node 6 is aligned with the root node - $assert( - manager.find(1).getPosition().y == manager.find(2).getPosition().y, - 'Nodes 1 and 2 should be vertically algined' - ); - $assert( - manager.find(6).getPosition().y == manager.find(0).getPosition().y, - 'Node 6 should be aligned to the root node' - ); - - console.log('\t--- Remove node 6 ---'); - manager.removeNode(6); - manager.layout(true); - manager.plot('testRemoveNode3', { width: 1000, height: 200 }); - - // Check orders were shifted accordingly - $assert(manager.find(8).getOrder() == 2, 'Node 8 should have order 2'); - - console.log('\t--- Remove node 5 ---'); - manager.removeNode(5); - manager.layout(true); - manager.plot('testRemoveNode4', { width: 1000, height: 200 }); - - // Check orders were shifted accordingly - $assert(manager.find(7).getOrder() == 1, 'Node 7 should have order 1'); - $assert(manager.find(9).getOrder() == 3, 'Node 9 should have order 3'); - - console.log('OK!\n\n'); - }, - - testSize: function () { - console.log('testSize:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - manager.addNode(1, { width: 60, height: 60 }, position); - manager.addNode(2, TestSuite.NODE_SIZE, position); - manager.addNode(3, { width: 260, height: 30 }, position); - manager.addNode(4, TestSuite.NODE_SIZE, position); - manager.addNode(5, TestSuite.NODE_SIZE, position); - manager.addNode(7, { width: 80, height: 80 }, position); - manager.addNode(8, TestSuite.NODE_SIZE, position); - manager.addNode(9, { width: 30, height: 30 }, position); - manager.addNode(10, TestSuite.NODE_SIZE, position); - manager.addNode(11, TestSuite.NODE_SIZE, position); - manager.addNode(12, { width: 100, height: 70 }, position); - manager.addNode(13, TestSuite.NODE_SIZE, position); - manager.addNode(14, TestSuite.NODE_SIZE, position); - manager.addNode(15, TestSuite.NODE_SIZE, position); - manager.addNode(16, TestSuite.NODE_SIZE, position); - manager.addNode(17, TestSuite.NODE_SIZE, position); - - manager.connectNode(0, 1, 0); - manager.connectNode(1, 16, 0); - manager.connectNode(0, 2, 1); - manager.connectNode(0, 3, 2); - manager.connectNode(0, 4, 3); - manager.connectNode(0, 5, 4); - manager.connectNode(4, 7, 0); - manager.connectNode(7, 15, 0); - manager.connectNode(7, 17, 1); - manager.connectNode(4, 8, 1); - manager.connectNode(8, 9, 0); - manager.connectNode(3, 10, 0); - manager.connectNode(3, 11, 1); - manager.connectNode(9, 12, 0); - manager.connectNode(9, 13, 1); - manager.connectNode(13, 14, 0); - - manager.layout(); - manager.plot('testSize1', { width: 1400, height: 400 }); - - // Check that all enlarged nodes shift children accordingly - $assert( - manager.find(10).getPosition().x > manager.find(3).getPosition().x && - manager.find(10).getPosition().x == manager.find(11).getPosition().x, - 'Nodes 10 and 11 should be horizontally algined and to the right of enlarged node 3' - ); - var xPosNode7 = manager.find(7).getPosition().x; - var xPosNode8 = manager.find(8).getPosition().x; - - manager.updateNodeSize(4, { width: 100, height: 30 }); - manager.layout(); - manager.plot('testSize2', { width: 1400, height: 400 }); - - // Check that all enlarged nodes shift children accordingly - $assert( - manager.find(2).getPosition().x - manager.find(4).getPosition().x == 10, - 'Node 4 should have been shifted by 10' - ); - $assert( - xPosNode7 - manager.find(7).getPosition().x == 20, - 'Node 7 should have been shifted by 20' - ); - $assert( - xPosNode8 - manager.find(8).getPosition().x == 20, - 'Node 8 should have been shifted by 20' - ); - - var graph2 = manager.plot('testSize3', { width: 1400, height: 400 }); - this._plotPrediction(graph2, manager.predict(0, null, { x: -145, y: 400 })); - this._plotPrediction(graph2, manager.predict(9, null, { x: -330, y: 70 })); - this._plotPrediction(graph2, manager.predict(9, null, { x: -330, y: 120 })); - this._plotPrediction(graph2, manager.predict(0, null, { x: 15, y: 20 })); - //TODO(gb): make asserts - - var graph3 = manager.plot('testSize4', { width: 1400, height: 400 }); - this._plotPrediction(graph3, manager.predict(0, null, null)); - this._plotPrediction(graph3, manager.predict(9, null, null)); - this._plotPrediction(graph3, manager.predict(3, null, null)); - this._plotPrediction(graph3, manager.predict(1, null, null)); - //TODO(gb): make asserts - - var yPosNode2 = manager.find(2).getPosition().y; - manager.updateNodeSize(7, { width: 80, height: 120 }); - manager.layout(); - manager.plot('testSize5', { width: 1400, height: 400 }); - - // Check that all enlarged nodes shift children accordingly - $assert( - yPosNode2 - manager.find(2).getPosition().y == 20, - 'Node 2 should have been shifted by 20' - ); - - console.log('OK!\n\n'); - }, - - testReconnectSingleNode: function () { - console.log('testReconnectSingleNode:'); - var position = { x: 0, y: 0 }; - var manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); - - // Prepare a sample graph ... - manager.addNode(1, TestSuite.NODE_SIZE, position); - manager.connectNode(0, 1, 0); - manager.layout(); - var graph = manager.plot('testReconnectSingleNode1', { width: 1000, height: 400 }); - var prediction = manager.predict(0, null, { x: -50, y: 0 }); - this._plotPrediction(graph, prediction); - - // Check prediction is to the left of the root node - $assert( - prediction.position.x < manager.find(0).getPosition().x, - 'Prediction should be to the left of the root node' - ); - $assert(prediction.order == 1, 'Prediction should have order 1'); - - manager.disconnectNode(1); - manager.connectNode(0, 1, 1); - manager.layout(); - manager.plot('testReconnectSingleNode2', { width: 1000, height: 400 }); - - // Check reconnected node is to the left of the root node - $assert( - manager.find(1).getPosition().x < manager.find(0).getPosition().x, - 'Node 1 should now be to the left of the root node' - ); - $assert(manager.find(1).getOrder() == 1, 'Node 1 should now have order 0'); - }, - - _plotPrediction: function (canvas, prediction) { - var position = prediction.position; - var order = prediction.order; - console.log( - '\t\tprediction {order:' + - order + - ', position: (' + - position.x + - ',' + - position.y + - ')}' - ); - var cx = position.x + canvas.width / 2 - TestSuite.NODE_SIZE.width / 2; - var cy = position.y + canvas.height / 2 - TestSuite.NODE_SIZE.height / 2; - canvas.rect(cx, cy, TestSuite.NODE_SIZE.width, TestSuite.NODE_SIZE.height); - }, -}); - -(TestSuite.NODE_SIZE = { width: 80, height: 30 }), - (TestSuite.ROOT_NODE_SIZE = { width: 120, height: 40 }); - -export default TestSuite; diff --git a/packages/mindplot/test/playground/context-loader.js b/packages/mindplot/test/playground/context-loader.js deleted file mode 100644 index dadf1a1c..00000000 --- a/packages/mindplot/test/playground/context-loader.js +++ /dev/null @@ -1,11 +0,0 @@ -const TestSuite = require('./TestSuite').default; -const BalancedTestSuite = require('./BalancedTestSuite').default; -const SymmetricTestSuite = require('./SymmetricTestSuite').default; -const FreeTestSuite = require('./FreeTestSuite').default; - -window.addEventListener('DOMContentLoaded', function () { - var basicTest = new TestSuite(); - var balancedTest = new BalancedTestSuite(); - var symmetricTest = new SymmetricTestSuite(); - var freeTest = new FreeTestSuite(); -}); diff --git a/packages/mindplot/test/playground/index.html b/packages/mindplot/test/playground/index.html index ec4feeba..b039afec 100644 --- a/packages/mindplot/test/playground/index.html +++ b/packages/mindplot/test/playground/index.html @@ -1,16 +1,22 @@ - - - - Document - - -
-

Mindplot Playground

- -
- - + + + + + Mindplot Playground + + + +
+

Mindplot Playground

+ +
+ + + \ No newline at end of file diff --git a/packages/mindplot/test/playground/layout/BalancedTestSuite.js b/packages/mindplot/test/playground/layout/BalancedTestSuite.js new file mode 100644 index 00000000..1f50a718 --- /dev/null +++ b/packages/mindplot/test/playground/layout/BalancedTestSuite.js @@ -0,0 +1,499 @@ +/* + * Copyright [2015] [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 TestSuite from './TestSuite'; +import mindplot from '../../../src/mindplot'; + +const BalancedTestSuite = new Class({ + Extends: TestSuite, + + initialize() { + $('#balancedTest').css('display', 'block'); + + this.testBalanced(); + this.testBalancedPredict(); + this.testBalancedNodeDragPredict(); + }, + + testBalanced() { + console.log('testBalanced:'); + const position = { x: 0, y: 0 }; + const plotsize = { width: 1000, height: 200 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 1, 0); + manager.layout(); + manager.plot('testBalanced1', plotsize); + + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 2, 1); + manager.layout(); + manager.plot('testBalanced2', plotsize); + + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 3, 2); + manager.layout(); + manager.plot('testBalanced3', plotsize); + + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 4, 3); + manager.layout(); + manager.plot('testBalanced4', plotsize); + + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 5, 4); + manager.layout(); + manager.plot('testBalanced5', plotsize); + + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 6, 5); + manager.layout(); + manager.plot('testBalanced6', plotsize); + + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.connectNode(3, 7, 0); + manager.connectNode(7, 8, 0); + manager.connectNode(7, 9, 1); + manager.layout(); + manager.plot('testBalanced7', plotsize); + + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + manager.addNode(12, TestSuite.NODE_SIZE, position); + manager.connectNode(6, 10, 0); + manager.connectNode(10, 11, 0); + manager.connectNode(10, 12, 1); + manager.layout(); + manager.plot('testBalanced8', plotsize); + + manager.addNode(13, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 13, 4); + manager.layout(); + manager.plot('testBalanced9', { width: 1000, height: 400 }); + + // Check orders have shifted accordingly + $assert(manager.find(5).getOrder() == 6, 'Node 5 should have order 6'); + + manager.addNode(14, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 14, 5); + manager.layout(); + manager.plot('testBalanced10', { width: 1000, height: 400 }); + + // Check orders have shifted accordingly + $assert(manager.find(6).getOrder() == 7, 'Node 6 should have order 7'); + + manager.addNode(15, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 15, 4); + manager.layout(); + manager.plot('testBalanced11', { width: 1000, height: 400 }); + + // Check orders have shifted accordingly + $assert(manager.find(13).getOrder() == 6, 'Node 13 should have order 6'); + $assert(manager.find(5).getOrder() == 8, 'Node 5 should have order 8'); + + manager.addNode(16, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 16, 25); + manager.layout(); + manager.plot('testBalanced12', { width: 1000, height: 400 }); + + // Check orders have shifted accordingly + $assert(manager.find(16).getOrder() == 9, 'Node 16 should have order 9'); + + manager.addNode(17, TestSuite.NODE_SIZE, position); + manager.addNode(18, TestSuite.NODE_SIZE, position); + manager.addNode(19, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 17, 11); + manager.connectNode(0, 18, 13); + manager.connectNode(0, 19, 10); + manager.layout(); + manager.plot('testBalanced13', { width: 1000, height: 400 }); + + // Check that everything is ok + $assert( + manager.find(1).getPosition().x > manager.find(0).getPosition().x, + 'even order nodes must be at right of central topic', + ); + $assert( + manager.find(3).getPosition().x > manager.find(0).getPosition().x, + 'even order nodes must be at right of central topic', + ); + $assert( + manager.find(5).getPosition().x > manager.find(0).getPosition().x, + 'even order nodes must be at right of central topic', + ); + $assert( + manager.find(2).getPosition().x < manager.find(0).getPosition().x, + 'odd order nodes must be at right of central topic', + ); + $assert( + manager.find(4).getPosition().x < manager.find(0).getPosition().x, + 'odd order nodes must be at right of central topic', + ); + $assert( + manager.find(6).getPosition().x < manager.find(0).getPosition().x, + 'odd order nodes must be at right of central topic', + ); + $assert( + manager.find(7).getPosition().x > manager.find(3).getPosition().x, + 'children of 1st level even order nodes must be to the right', + ); + $assert( + manager.find(8).getPosition().x > manager.find(7).getPosition().x, + 'children of 1st level even order nodes must be to the right', + ); + $assert( + manager.find(9).getPosition().x > manager.find(7).getPosition().x, + 'children of 1st level even order nodes must be to the right', + ); + $assert( + manager.find(10).getPosition().x < manager.find(6).getPosition().x, + 'children of 1st level odd order nodes must be to the left', + ); + $assert( + manager.find(11).getPosition().x < manager.find(10).getPosition().x, + 'children of 1st level odd order nodes must be to the left', + ); + $assert( + manager.find(12).getPosition().x < manager.find(10).getPosition().x, + 'children of 1st level odd order nodes must be to the left', + ); + + console.log('OK!\n\n'); + }, + + testBalancedPredict() { + console.log('testBalancedPredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(0, 4, 3); + manager.connectNode(0, 5, 4); + manager.connectNode(4, 7, 0); + manager.connectNode(4, 8, 1); + manager.connectNode(8, 9, 0); + manager.connectNode(3, 10, 0); + manager.connectNode(3, 11, 1); + + manager.layout(); + + // Graph 1 + const graph1 = manager.plot('testBalancedPredict1', { width: 1000, height: 400 }); + + console.log('\tAdded as child of node 0 and dropped at (165, -70):'); + const prediction1a = manager.predict(0, null, { x: 165, y: -70 }); + this._plotPrediction(graph1, prediction1a); + $assert( + prediction1a.position.y < manager.find(1).getPosition().y + && prediction1a.position.x == manager.find(1).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1a.order == 0, 'Prediction order should be 0'); + + console.log('\tAdded as child of node 0 and dropped at (165, -10):'); + const prediction1b = manager.predict(0, null, { x: 165, y: -10 }); + this._plotPrediction(graph1, prediction1b); + $assert( + prediction1b.position.y > manager.find(1).getPosition().y + && prediction1b.position.y < manager.find(3).getPosition().y + && prediction1b.position.x == manager.find(1).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1b.order == 2, 'Prediction order should be 2'); + + console.log('\tAdded as child of node 0 and dropped at (145, 15):'); + const prediction1c = manager.predict(0, null, { x: 145, y: 15 }); + this._plotPrediction(graph1, prediction1c); + $assert( + prediction1c.position.y > manager.find(3).getPosition().y + && prediction1c.position.y < manager.find(5).getPosition().y + && prediction1c.position.x == manager.find(3).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1c.order == 4, 'Prediction order should be 4'); + + console.log('\tAdded as child of node 0 and dropped at (145, 70):'); + const prediction1d = manager.predict(0, null, { x: 145, y: 70 }); + this._plotPrediction(graph1, prediction1d); + $assert( + prediction1d.position.y > manager.find(5).getPosition().y + && prediction1d.position.x == manager.find(5).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1d.order == 6, 'Prediction order should be 6'); + + // Graph 2 + const graph2 = manager.plot('testBalancedPredict2', { width: 1000, height: 400 }); + + console.log('\tAdded as child of node 0 and dropped at (-145, -50):'); + const prediction2a = manager.predict(0, null, { x: -145, y: -50 }); + this._plotPrediction(graph2, prediction2a); + $assert( + prediction2a.position.y < manager.find(2).getPosition().y + && prediction2a.position.x == manager.find(2).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2a.order == 1, 'Prediction order should be 1'); + + console.log('\tAdded as child of node 0 and dropped at (-145, -10):'); + const prediction2b = manager.predict(0, null, { x: -145, y: -10 }); + this._plotPrediction(graph2, prediction2b); + $assert( + prediction2b.position.y > manager.find(2).getPosition().y + && prediction2b.position.y < manager.find(4).getPosition().y + && prediction2b.position.x == manager.find(2).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2b.order == 3, 'Prediction order should be 3'); + + console.log('\tAdded as child of node 0 and dropped at (-145, 40):'); + const prediction2c = manager.predict(0, null, { x: -145, y: 400 }); + this._plotPrediction(graph2, prediction2c); + $assert( + prediction2c.position.y > manager.find(4).getPosition().y + && prediction2c.position.x == manager.find(4).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2c.order == 5, 'Prediction order should be 5'); + + // Graph 3 + console.log('\tPredict nodes added with no position:'); + const graph3 = manager.plot('testBalancedPredict3', { width: 1000, height: 400 }); + const prediction3 = manager.predict(0, null, null); + this._plotPrediction(graph3, prediction3); + $assert( + prediction3.position.y > manager.find(4).getPosition().y + && prediction3.position.x == manager.find(4).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction3.order == 5, 'Prediction order should be 5'); + + console.log('\tPredict nodes added with no position:'); + manager.addNode(6, TestSuite.NODE_SIZE, prediction3.position); + manager.connectNode(0, 6, prediction3.order); + manager.layout(); + const graph4 = manager.plot('testBalancedPredict4', { width: 1000, height: 400 }); + const prediction4 = manager.predict(0, null, null); + this._plotPrediction(graph4, prediction4); + $assert( + prediction4.position.y > manager.find(5).getPosition().y + && prediction4.position.x == manager.find(5).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction4.order == 6, 'Prediction order should be 6'); + + console.log('\tPredict nodes added only a root node:'); + manager.removeNode(1).removeNode(2).removeNode(3).removeNode(4) + .removeNode(5); + manager.layout(); + const graph5 = manager.plot('testBalancedPredict5', { width: 1000, height: 400 }); + const prediction5a = manager.predict(0, null, null); + const prediction5b = manager.predict(0, null, { x: 40, y: 100 }); + this._plotPrediction(graph5, prediction5a); + this._plotPrediction(graph5, prediction5b); + $assert( + prediction5a.position.x > manager.find(0).getPosition().x + && prediction5a.position.y == manager.find(0).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction5a.order == 0, 'Prediction order should be 0'); + $assert( + prediction5a.position.x == prediction5b.position.x + && prediction5a.position.y == prediction5b.position.y, + 'Both predictions should be the same', + ); + $assert(prediction5a.order == prediction5b.order, 'Both predictions should be the same'); + + console.log('OK!\n\n'); + }, + + testBalancedNodeDragPredict() { + console.log('testBalancedNodeDragPredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Graph 1 + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.layout(); + const graph1 = manager.plot('testBalancedNodeDragPredict1', { width: 800, height: 400 }); + + const prediction1a = manager.predict(0, 1, { x: 50, y: 50 }); + this._plotPrediction(graph1, prediction1a); + $assert( + prediction1a.position.x == manager.find(1).getPosition().x + && prediction1a.position.y == manager.find(1).getPosition().y, + 'Prediction position should be the same as node 1', + ); + $assert( + prediction1a.order == manager.find(1).getOrder(), + 'Prediction order should be the same as node 1', + ); + + const prediction1b = manager.predict(0, 1, { x: 50, y: -50 }); + this._plotPrediction(graph1, prediction1b); + $assert( + prediction1b.position.x == manager.find(1).getPosition().x + && prediction1b.position.y == manager.find(1).getPosition().y, + 'Prediction position should be the same as node 1', + ); + $assert( + prediction1b.order == manager.find(1).getOrder(), + 'Prediction order should be the same as node 1', + ); + + const prediction1c = manager.predict(0, 1, { x: -50, y: 50 }); + this._plotPrediction(graph1, prediction1c); + $assert( + prediction1c.position.x < manager.find(0).getPosition().x + && prediction1c.position.y == manager.find(0).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1c.order == 1, 'Prediction order should be the same as node 1'); + + const prediction1d = manager.predict(0, 1, { x: -50, y: -50 }); + this._plotPrediction(graph1, prediction1d); + $assert( + prediction1d.position.x < manager.find(0).getPosition().x + && prediction1d.position.y == manager.find(0).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1d.order == 1, 'Prediction order should be the same as node 1'); + + // Graph 2 + manager.disconnectNode(1); + manager.connectNode(0, 1, 1); + manager.layout(); + const graph2 = manager.plot('testBalancedNodeDragPredict2', { width: 800, height: 400 }); + + const prediction2a = manager.predict(0, 1, { x: 50, y: 50 }); + this._plotPrediction(graph2, prediction2a); + $assert( + prediction2a.position.x > manager.find(0).getPosition().x + && prediction2a.position.y == manager.find(0).getPosition().y, + 'Prediction is positioned incorrectly', + ); + $assert(prediction2a.order == 0, 'Prediction order should be 0'); + + const prediction2b = manager.predict(0, 1, { x: 50, y: -50 }); + this._plotPrediction(graph2, prediction2b); + $assert( + prediction2b.position.x > manager.find(0).getPosition().x + && prediction2b.position.y == manager.find(0).getPosition().y, + 'Prediction is positioned incorrectly', + ); + $assert(prediction2b.order == 0, 'Prediction order should be 0'); + + const prediction2c = manager.predict(0, 1, { x: -50, y: 50 }); + this._plotPrediction(graph2, prediction2c); + $assert( + prediction2c.position.x == manager.find(1).getPosition().x + && prediction2c.position.y == manager.find(1).getPosition().y, + 'Prediction position should be the same as node 1', + ); + $assert( + prediction2c.order == manager.find(1).getOrder(), + 'Prediction order should be the same as node 1', + ); + + const prediction2d = manager.predict(0, 1, { x: -50, y: -50 }); + this._plotPrediction(graph2, prediction2d); + $assert( + prediction2d.position.x == manager.find(1).getPosition().x + && prediction2d.position.y == manager.find(1).getPosition().y, + 'Prediction position should be the same as node 1', + ); + $assert( + prediction2d.order == manager.find(1).getOrder(), + 'Prediction order should be the same as node 1', + ); + + // Graph 3 + manager.disconnectNode(1); + manager.connectNode(0, 1, 0); + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); + manager.layout(); + const graph3 = manager.plot('testBalancedNodeDragPredict3', { width: 800, height: 400 }); + + const prediction3a = manager.predict(0, 1, { x: 50, y: 50 }); + this._plotPrediction(graph3, prediction3a); + $assert( + prediction3a.position.x == manager.find(2).getPosition().x + && prediction3a.position.y > manager.find(2).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction3a.order == 4, 'Prediction order should be 4'); + + const prediction3b = manager.predict(0, 1, { x: 50, y: -50 }); + this._plotPrediction(graph3, prediction3b); + $assert( + prediction3b.position.x == manager.find(1).getPosition().x + && prediction3b.position.y == manager.find(1).getPosition().y + && prediction3b.order == manager.find(1).getOrder(), + 'Prediction should be the exact same as dragged node', + ); + + const prediction3c = manager.predict(0, 1, { x: -50, y: 50 }); + this._plotPrediction(graph3, prediction3c); + $assert( + prediction3c.position.x < manager.find(0).getPosition().x + && prediction3c.position.y == manager.find(0).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction3c.order == 1, 'Prediction order should be 1'); + + const prediction3d = manager.predict(0, 1, { x: -50, y: -50 }); + this._plotPrediction(graph3, prediction3d); + $assert( + prediction3d.position.x < manager.find(0).getPosition().x + && prediction3d.position.y == manager.find(0).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction3d.order == 1, 'Prediction order should be 1'); + + const prediction3e = manager.predict(0, 1, { x: 50, y: 0 }); + this._plotPrediction(graph3, prediction3e); + $assert( + prediction3e.position.x == manager.find(1).getPosition().x + && prediction3e.position.y == manager.find(1).getPosition().y, + 'Prediction position should be the same as node 1', + ); + $assert( + prediction3e.order == manager.find(1).getOrder(), + 'Prediction order should be the same as node 1', + ); + + console.log('OK!\n\n'); + }, +}); + +export default BalancedTestSuite; diff --git a/packages/mindplot/test/playground/layout/FreeTestSuite.js b/packages/mindplot/test/playground/layout/FreeTestSuite.js new file mode 100644 index 00000000..78403d9e --- /dev/null +++ b/packages/mindplot/test/playground/layout/FreeTestSuite.js @@ -0,0 +1,555 @@ +/* + * Copyright [2015] [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 TestSuite from './TestSuite'; +import mindplot from '../../../src/mindplot'; + +const FreeTestSuite = new Class({ + Extends: TestSuite, + + initialize() { + $('#freeTest').css('display', 'block'); + + this.testFreePosition(); + this.testFreePredict(); + this.testReconnectFreeNode(); + this.testSiblingOverlapping(); + this.testRootNodeChildrenPositioning(); + this.testBalancedFreePredict(); + this.testFreeReorder(); + this.testFreeOverlap(); + }, + + testFreePosition() { + console.log('testFreePosition:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + manager.addNode(12, TestSuite.NODE_SIZE, position); + manager.addNode(13, TestSuite.NODE_SIZE, position); + manager.addNode(14, TestSuite.NODE_SIZE, position); + manager.addNode(15, TestSuite.NODE_SIZE, position); + manager.addNode(16, TestSuite.NODE_SIZE, position); + manager.addNode(17, TestSuite.NODE_SIZE, position); + manager.addNode(18, TestSuite.NODE_SIZE, position); + manager.addNode(19, TestSuite.NODE_SIZE, position); + manager.addNode(20, TestSuite.NODE_SIZE, position); + manager.addNode(21, TestSuite.NODE_SIZE, position); + manager.addNode(22, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0).connectNode(0, 2, 1).connectNode(0, 3, 2).connectNode(0, 4, 3); + manager.connectNode(4, 21, 0).connectNode(4, 22, 0); + manager.connectNode(1, 5, 0); + manager.connectNode(5, 6, 0).connectNode(6, 8, 0).connectNode(8, 9, 0); + manager.connectNode(5, 7, 1).connectNode(7, 10, 0); + manager + .connectNode(3, 11, 0) + .connectNode(11, 14, 0) + .connectNode(14, 18, 0) + .connectNode(14, 19, 1) + .connectNode(14, 20, 2); + manager + .connectNode(3, 12, 1) + .connectNode(12, 15, 0) + .connectNode(12, 16, 1) + .connectNode(12, 17, 2); + manager.connectNode(3, 13, 2); + + manager.layout(); + manager.plot('testFreePosition1', { width: 1400, height: 600 }); + + console.log('\tmove node 12 to (300,30):'); + manager.moveNode(12, { x: 300, y: 30 }); + manager.layout(true); + manager.plot('testFreePosition2', { width: 1400, height: 600 }); + this._assertFreePosition(manager, 12, { x: 300, y: 30 }); + + console.log('\tmove node 13 to (340,180):'); + const node13Pos = { x: 340, y: 180 }; + manager.moveNode(13, node13Pos); + manager.layout(true); + manager.plot('testFreePosition3', { width: 1400, height: 600 }); + this._assertFreePosition(manager, 13, node13Pos); + + console.log('\tmove node 11 to (250,-50):'); + manager.moveNode(11, { x: 250, y: -50 }); + manager.layout(true); + manager.plot('testFreePosition4', { width: 1400, height: 600 }); + this._assertFreePosition(manager, 11, { x: 250, y: -50 }); + $assert( + manager.find(13).getPosition().x == node13Pos.x + && manager.find(13).getPosition().y == node13Pos.y, + "Node 13 shouldn't have moved", + ); + + console.log('\tmove node 7 to (350,-190):'); + manager.moveNode(7, { x: 350, y: -190 }); + manager.layout(true); + manager.plot('testFreePosition5', { width: 1400, height: 600 }); + this._assertFreePosition(manager, 7, { x: 350, y: -190 }); + + console.log('\tadd node 23 to 12:'); + manager.addNode(23, TestSuite.NODE_SIZE, position); + manager.connectNode(12, 23, 3); + manager.layout(true); + manager.plot('testFreePosition6', { width: 1400, height: 600 }); + this._assertFreePosition(manager, null, null); + + console.log('\tmove node 4 to (-300, 190):'); + manager.moveNode(4, { x: -300, y: 190 }); + manager.layout(true); + manager.plot('testFreePosition7', { width: 1400, height: 600 }); + this._assertFreePosition(manager, 4, { x: -300, y: 190 }); + + console.log('\tadd node 24 to 3:'); + manager.addNode(24, TestSuite.NODE_SIZE, position); + manager.connectNode(3, 24, 3); + manager.layout(true); + manager.plot('testFreePosition8', { width: 1400, height: 600 }); + this._assertFreePosition(manager, null, null); + + console.log('\tadd node 25 to 17:'); + manager.addNode(25, TestSuite.NODE_SIZE, position); + manager.connectNode(17, 25, 0); + manager.layout(true); + manager.plot('testFreePosition9', { width: 1400, height: 600 }); + this._assertFreePosition(manager, null, null); + + console.log('OK!\n\n'); + }, + + testFreePredict() { + console.log('testFreePredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(3, 4, 0); + manager.connectNode(3, 5, 1); + manager.connectNode(3, 6, 2); + manager.connectNode(5, 7, 0); + manager.connectNode(5, 8, 1); + manager.connectNode(5, 11, 2); + manager.connectNode(2, 9, 0); + manager.connectNode(2, 10, 1); + + manager.layout(); + const graph = manager.plot('testFreePredict1', { width: 1000, height: 400 }); + + const pos1 = { x: 370, y: 80 }; + const predict1 = manager.predict(5, 11, pos1, true); + this._plotPrediction(graph, predict1); + $assert( + predict1.position.x == pos1.x && predict1.position.y == pos1.y, + 'free predict should return the same position', + ); + + const pos2 = { x: -200, y: 80 }; + const predict2 = manager.predict(0, 2, pos2, true); + this._plotPrediction(graph, predict2); + $assert( + predict2.position.x == pos2.x && predict2.position.y == pos2.y, + 'free predict should return the same position', + ); + + const pos3 = { x: 200, y: 30 }; + const node5 = manager.find(5); + const predict3 = manager.predict(3, 5, pos3, true); + this._plotPrediction(graph, predict3); + $assert( + predict3.position.x == node5.getPosition().x && predict3.position.y == pos3.y, + 'free predict should return the x-coordinate of the node', + ); + + const pos4 = { x: -100, y: 45 }; + const node10 = manager.find(10); + const predict4 = manager.predict(2, 10, pos4, true); + this._plotPrediction(graph, predict4); + $assert( + predict4.position.x == node10.getPosition().x && predict4.position.y == pos4.y, + 'free predict should return the x-coordinate of the node', + ); + + console.log('OK!\n\n'); + }, + + testReconnectFreeNode() { + console.log('testReconnectFreeNode:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(3, 4, 0); + manager.connectNode(3, 5, 1); + manager.connectNode(3, 6, 2); + manager.connectNode(5, 7, 0); + manager.connectNode(5, 8, 1); + manager.connectNode(5, 11, 2); + manager.connectNode(2, 9, 0); + manager.connectNode(2, 10, 1); + + manager.layout(); + manager.plot('testReconnectFreeNode1', { width: 1000, height: 400 }); + + console.log('\tmove node 5'); + manager.moveNode(5, { x: 250, y: 30 }); + manager.layout(); + manager.plot('testReconnectFreeNode2', { width: 1000, height: 400 }); + this._assertFreePosition(manager, 5, { x: 250, y: 30 }); + + console.log('\treconnect node 5 to node 2'); + manager.disconnectNode(5); + manager.connectNode(2, 5, 2); + manager.layout(); + manager.plot('testReconnectFreeNode3', { width: 1000, height: 400 }); + $assert( + manager.find(5).getPosition().y > manager.find(10).getPosition().y + && manager.find(5).getPosition().x == manager.find(10).getPosition().x, + 'Node 5 is incorrectly positioned', + ); + $assert(manager.find(5).getOrder() == 2, 'Node 5 should have order 2'); + + console.log('\tmove node 8'); + manager.moveNode(8, { x: -370, y: 60 }); + manager.layout(); + manager.plot('testReconnectFreeNode4', { width: 1000, height: 400 }); + this._assertFreePosition(manager, 8, { x: -370, y: 60 }); + + console.log('\treconnect node 5 to node 10'); + manager.disconnectNode(5); + manager.connectNode(10, 5, 0); + manager.layout(); + manager.plot('testReconnectFreeNode5', { width: 1000, height: 400 }); + $assert( + manager.find(5).getPosition().y == manager.find(10).getPosition().y + && manager.find(5).getPosition().x < manager.find(10).getPosition().x, + 'Node 5 is incorrectly positioned', + ); + $assert(manager.find(5).getOrder() == 0, 'Node 5 should have order 0'); + + console.log('reconnect node 5 to node 3'); + manager.disconnectNode(5); + manager.connectNode(3, 5, 2); + manager.layout(); + manager.plot('testReconnectFreeNode6', { width: 1000, height: 400 }); + $assert( + manager.find(5).getPosition().y > manager.find(6).getPosition().y + && manager.find(5).getPosition().x == manager.find(6).getPosition().x, + 'Node 5 is incorrectly positioned', + ); + $assert(manager.find(5).getOrder() == 2, 'Node 5 should have order 2'); + + console.log('\tmove node 8'); + manager.moveNode(8, { x: 370, y: 30 }); + manager.layout(); + manager.plot('testReconnectFreeNode7', { width: 1000, height: 400 }); + this._assertFreePosition(manager, 8, { x: 370, y: 30 }); + + console.log('OK!\n\n'); + }, + + testSiblingOverlapping() { + console.log('testSiblingOverlapping:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(1, 3, 1); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 2); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 3); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 4); + manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(1, 7, 5); + manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(1, 8, 6); + manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(0, 9, 4); + manager.layout(); + manager.plot('testSiblingOverlapping1', { width: 800, height: 600 }); + + console.log('\tmove node 2'); + manager.moveNode(2, { x: 250, y: -30 }); + manager.layout(); + manager.plot('testSiblingOverlapping2', { width: 800, height: 600 }); + this._assertFreePosition(manager, 2, { x: 250, y: -30 }); + + console.log('\tmove node 7'); + manager.moveNode(7, { x: 250, y: 100 }); + manager.layout(); + manager.plot('testSiblingOverlapping3', { width: 800, height: 600 }); + this._assertFreePosition(manager, 7, { x: 250, y: 100 }); + + console.log('OK!\n\n'); + }, + + testRootNodeChildrenPositioning() { + console.log('testRootNodeChildrenPositioning:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 1); + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 2); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(0, 4, 3); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(0, 5, 4); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(0, 6, 5); + manager.layout(); + manager.plot('testRootNodeChildrenPositioning1', { width: 800, height: 600 }); + + console.log('\tmove node 1'); + manager.moveNode(1, { x: 150, y: 0 }); + manager.layout(); + manager.plot('testRootNodeChildrenPositioning2', { width: 800, height: 600 }); + this._assertFreePosition(manager, 1, { x: 150, y: 0 }); + + console.log('\tmove node 4'); + manager.moveNode(4, { x: -140, y: 30 }); + manager.layout(); + manager.plot('testRootNodeChildrenPositioning3', { width: 800, height: 600 }); + this._assertFreePosition(manager, 4, { x: -140, y: 30 }); + + console.log('\tmove node 2'); + manager.moveNode(2, { x: -150, y: -50 }); + manager.layout(); + manager.plot('testRootNodeChildrenPositioning4', { width: 800, height: 600 }); + this._assertFreePosition(manager, 2, { x: -150, y: -50 }); + + // TODO(gb): fix this. It's not working + // console.log("\tmove node 6"); + // manager.moveNode(6, {x:-150, y:-50}); + // manager.layout(); + // manager.plot("testRootNodeChildrenPositioning5", {width:800, height:600}); + // this._assertFreePosition(manager, 6, {x:-150, y:-50}); + + console.log('OK!\n\n'); + }, + + testBalancedFreePredict() { + console.log('testBalancedFreePredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.layout(); + const graph1 = manager.plot('testBalancedFreePredict1', { width: 800, height: 400 }); + + const predict1 = manager.predict(0, 1, { x: 70, y: 0 }, true); + this._plotPrediction(graph1, predict1); + $assert( + predict1.position.x == manager.find(1).getPosition().x, + 'Prediction x pos should be the same as node 1', + ); + + console.log('OK!\n\n'); + }, + + testFreeReorder() { + console.log('testFreeReorder:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 0); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 1); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 2); + + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); + manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(2, 7, 0); + manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(2, 8, 1); + manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(2, 9, 2); + manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(2, 10, 3); + + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 4); + manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(3, 11, 0); + manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(3, 12, 1); + manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(3, 13, 2); + manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(3, 14, 3); + manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(3, 15, 4); + manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(3, 16, 5); + + manager.layout(); + manager.moveNode(14, { x: 270, y: -160 }); + manager.layout(); + manager.plot('testFreeReorder1', { width: 800, height: 1200 }); + $assert( + manager.find(14).getPosition().y > manager.find(10).getPosition().y, + 'Node 14 should be below branch 2', + ); + + console.log('OK!\n\n'); + }, + + testFreeOverlap() { + console.log('testFreeOverlap:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 0); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(1, 5, 1); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(1, 6, 2); + + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 2); + manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(2, 7, 0); + manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(2, 8, 1); + manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(2, 9, 2); + manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(2, 10, 3); + + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(0, 3, 4); + manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(3, 11, 0); + manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(3, 12, 1); + manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(3, 13, 2); + manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(3, 14, 3); + manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(3, 15, 4); + manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(3, 16, 5); + + manager.layout(); + manager.plot('testFreeOverlap1', { width: 800, height: 1200 }); + + manager.moveNode(14, { x: 270, y: 7 }); + manager.layout(); + manager.plot('testFreeOverlap2', { width: 800, height: 1200 }); + $assert( + manager.find(2).getPosition().y > manager.find(1).getPosition().y, + 'Branches 1 and 2 are overlapping', + ); + + console.log('OK!\n\n'); + }, + + _assertFreePosition(manager, id, position) { + if (id != null && position.x != null && position.y != null) { + const node = manager.find(id); + $assert( + node.getPosition().x == position.x && node.getPosition().y == position.y, + `Freely moved node ${ + id + } is not left at free position (${ + position.x + },${ + position.y + }). ` + + `Actual position: (${ + node.getPosition().x + },${ + node.getPosition().y + })`, + ); + } + + const treeSet = manager._treeSet; + _.each( + treeSet._rootNodes, + function (rootNode) { + const heightById = rootNode.getSorter().computeChildrenIdByHeights(treeSet, rootNode); + this._assertBranchCollision(treeSet, rootNode, heightById); + }, + this, + ); + }, + + _assertBranchCollision(treeSet, node, heightById) { + const children = treeSet.getChildren(node); + const childOfRootNode = treeSet._rootNodes.contains(node); + + _.each( + children, + function (child) { + const height = heightById[child.getId()]; + let siblings = treeSet.getSiblings(child); + if (childOfRootNode) { + siblings = siblings.filter((sibling) => child.getOrder() % 2 == sibling.getOrder() % 2); + } + _.each( + siblings, + function (sibling) { + this._branchesOverlap(child, sibling, heightById); + }, + this, + ); + }, + this, + ); + + _.each( + children, + function (child) { + this._assertBranchCollision(treeSet, child, heightById); + }, + this, + ); + }, + + _branchesOverlap(branchA, branchB, heightById) { + const topA = branchA.getPosition().y - heightById[branchA.getId()] / 2; + const bottomA = branchA.getPosition().y + heightById[branchA.getId()] / 2; + const topB = branchB.getPosition().y - heightById[branchB.getId()] / 2; + const bottomB = branchB.getPosition().y + heightById[branchB.getId()] / 2; + + $assert( + topA >= bottomB || bottomA <= topB, + `Branches ${branchA.getId()} and ${branchB.getId()} overlap`, + ); + }, +}); + +export default FreeTestSuite; diff --git a/packages/mindplot/test/playground/layout/SymmetricTestSuite.js b/packages/mindplot/test/playground/layout/SymmetricTestSuite.js new file mode 100644 index 00000000..f71414f4 --- /dev/null +++ b/packages/mindplot/test/playground/layout/SymmetricTestSuite.js @@ -0,0 +1,351 @@ +/* + * Copyright [2015] [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 TestSuite from './TestSuite'; +import mindplot from '../../../src/mindplot'; + +const SymmetricTestSuite = new Class({ + Extends: TestSuite, + + initialize() { + $('#symmetricTest').css('display', 'block'); + + this.testSymmetry(); + this.testSymmetricPredict(); + this.testSymmetricDragPredict(); + }, + + testSymmetry() { + console.log('testSymmetry:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + manager.addNode(12, TestSuite.NODE_SIZE, position); + manager.addNode(13, TestSuite.NODE_SIZE, position); + manager.addNode(14, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 14, 0); + manager.connectNode(14, 13, 0); + manager.connectNode(13, 1, 0); + manager.connectNode(13, 2, 1); + manager.connectNode(13, 3, 2); + manager.connectNode(13, 4, 3); + manager.connectNode(13, 5, 4); + manager.connectNode(1, 6, 0); + manager.connectNode(1, 7, 1); + manager.connectNode(7, 8, 0); + manager.connectNode(8, 9, 0); + manager.connectNode(5, 10, 0); + manager.connectNode(6, 11, 0); + manager.connectNode(6, 12, 1); + + manager.layout(); + manager.plot('testSymmetry', { width: 1600, height: 400 }); + + // All nodes should be positioned symmetrically with respect to their common ancestors + $assert( + manager.find(14).getPosition().y == manager.find(13).getPosition().y, + 'Symmetry is not respected', + ); + $assert( + manager.find(5).getPosition().y == manager.find(10).getPosition().y, + 'Symmetry is not respected', + ); + $assert( + manager.find(11).getPosition().y - manager.find(6).getPosition().y + == -(manager.find(12).getPosition().y - manager.find(6).getPosition().y), + 'Symmetry is not respected', + ); + $assert( + manager.find(8).getPosition().y - manager.find(1).getPosition().y + == -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), + 'Symmetry is not respected', + ); + $assert( + manager.find(9).getPosition().y - manager.find(1).getPosition().y + == -(manager.find(11).getPosition().y - manager.find(1).getPosition().y), + 'Symmetry is not respected', + ); + + console.log('OK!\n\n'); + }, + + testSymmetricPredict() { + console.log('testSymmetricPredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(3, 4, 0); + manager.connectNode(3, 5, 1); + manager.connectNode(3, 6, 2); + manager.connectNode(5, 7, 0); + manager.connectNode(5, 8, 1); + manager.connectNode(5, 11, 2); + manager.connectNode(2, 9, 0); + manager.connectNode(2, 10, 1); + + manager.layout(); + + // Graph + const graph1 = manager.plot('testSymmetricPredict1', { width: 1000, height: 400 }); + + console.log('\tAdded as child of node 9 and dropped at (-280, 45):'); + const prediction1a = manager.predict(9, null, { x: -280, y: 45 }); + this._plotPrediction(graph1, prediction1a); + $assert( + prediction1a.position.x < manager.find(9).getPosition().x + && prediction1a.position.y == manager.find(9).getPosition().y, + 'Prediction incorrectly positioned', + ); + $assert(prediction1a.order == 0, 'Prediction order should be 0'); + + console.log('\tAdded as child of node 1 and dropped at (155, -90):'); + const prediction1b = manager.predict(1, null, { x: -155, y: -90 }); + this._plotPrediction(graph1, prediction1b); + $assert( + prediction1b.position.x > manager.find(1).getPosition().x + && prediction1b.position.y == manager.find(1).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1b.order == 0, 'Prediction order should be 0'); + + // Graph 2 + const graph2 = manager.plot('testSymmetricPredict2', { width: 1000, height: 400 }); + + console.log('\tAdded as child of node 5 and dropped at (380, -30):'); + const prediction2d = manager.predict(5, null, { x: 380, y: -30 }); + this._plotPrediction(graph2, prediction2d); + + // Prediction calculator error + $assert( + prediction2d.position.y < manager.find(7).getPosition().y + && prediction2d.position.x == manager.find(7).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2d.order == 0, 'Prediction order should be 0'); + + console.log('\tAdded as child of node 5 and dropped at (375, 15):'); + const prediction2a = manager.predict(5, null, { x: 375, y: 15 }); + this._plotPrediction(graph2, prediction2a); + + $assert( + prediction2a.position.y > manager.find(7).getPosition().y + && prediction2a.position.y < manager.find(8).getPosition().y + && prediction2a.position.x == manager.find(7).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2a.order == 1, 'Prediction order should be 1'); + + console.log('\tAdded as child of node 5 and dropped at (375, 45):'); + const prediction2b = manager.predict(5, null, { x: 375, y: 45 }); + this._plotPrediction(graph2, prediction2b); + $assert( + prediction2b.position.y > manager.find(8).getPosition().y + && prediction2b.position.y < manager.find(11).getPosition().y + && prediction2b.position.x == manager.find(7).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2b.order == 2, 'Prediction order should be 2'); + + console.log('\tAdded as child of node 5 and dropped at (375, 45):'); + const prediction2c = manager.predict(5, null, { x: 375, y: 65 }); + this._plotPrediction(graph2, prediction2c); + $assert( + prediction2c.position.y > manager.find(11).getPosition().y + && prediction2c.position.x == manager.find(11).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction2c.order == 3, 'Prediction order should be 3'); + + // Graph 3 + const graph3 = manager.plot('testSymmetricPredict3', { width: 1000, height: 400 }); + + console.log('\tAdded as child of node 3 and dropped at (280, 45):'); + const prediction3a = manager.predict(3, null, { x: 280, y: 45 }); + this._plotPrediction(graph3, prediction3a); + $assert( + prediction3a.position.y > manager.find(5).getPosition().y + && prediction3a.position.y < manager.find(6).getPosition().y + && prediction3a.position.x == manager.find(5).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction3a.order == 2, 'Prediction order should be 2'); + + console.log('\tAdded as child of node 3 and dropped at (255, 110):'); + const prediction3b = manager.predict(3, null, { x: 255, y: 110 }); + this._plotPrediction(graph3, prediction3b); + $assert( + prediction3b.position.y > manager.find(6).getPosition().y + && prediction3b.position.x == manager.find(6).getPosition().x, + 'Prediction incorrectly positioned', + ); + $assert(prediction3b.order == 3, 'Prediction order should be 3'); + + // Graph 4 + console.log('\tAdded as child of node 2 and dropped at (-260, 0):'); + const graph4 = manager.plot('testSymmetricPredict4', { width: 1000, height: 400 }); + const prediction4 = manager.predict(2, null, { x: -260, y: 0 }); + this._plotPrediction(graph4, prediction4); + $assert( + prediction4.position.y > manager.find(9).getPosition().y + && prediction4.position.y < manager.find(10).getPosition().y + && prediction4.position.x == manager.find(9).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction4.order == 1, 'Prediction order should be 1'); + + // Graph 5 + console.log('\tPredict nodes added with no position:'); + const graph5 = manager.plot('testSymmetricPredict5', { width: 1000, height: 400 }); + const prediction5a = manager.predict(1, null, null); + this._plotPrediction(graph5, prediction5a); + $assert( + prediction5a.position.y == manager.find(1).getPosition().y + && prediction5a.position.x > manager.find(1).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction5a.order == 0, 'Prediction order should be 0'); + + const prediction5b = manager.predict(2, null, null); + this._plotPrediction(graph5, prediction5b); + $assert( + prediction5b.position.y > manager.find(10).getPosition().y + && prediction5b.position.x < manager.find(2).getPosition().x + && prediction5b.position.x == manager.find(10).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction5b.order == 2, 'Prediction order should be 2'); + + const prediction5c = manager.predict(3, null, null); + this._plotPrediction(graph5, prediction5c); + $assert( + prediction5c.position.y > manager.find(6).getPosition().y + && prediction5c.position.x > manager.find(3).getPosition().x + && prediction5c.position.x == manager.find(6).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction5c.order == 3, 'Prediction order should be 3'); + + const prediction5d = manager.predict(10, null, null); + this._plotPrediction(graph5, prediction5d); + $assert( + prediction5d.position.y == manager.find(10).getPosition().y + && prediction5d.position.x < manager.find(10).getPosition().x, + 'Prediction is incorrectly positioned', + ); + $assert(prediction5d.order == 0, 'Prediction order should be 0'); + + console.log('OK!\n\n'); + }, + + testSymmetricDragPredict() { + console.log('testSymmetricDragPredict:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 1); + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); + manager.layout(); + + // Graph 1 + const graph1 = manager.plot('testSymmetricDragPredict1', { width: 1000, height: 400 }); + + const prediction1a = manager.predict(1, 2, { x: -250, y: -20 }); + this._plotPrediction(graph1, prediction1a); + $assert( + prediction1a.position.x == manager.find(2).getPosition().x + && prediction1a.position.y == manager.find(2).getPosition().y, + 'Prediction position should be the same as node 2', + ); + $assert( + prediction1a.order == manager.find(2).getOrder(), + 'Predicition order should be the same as node 2', + ); + + const prediction1b = manager.predict(1, 2, { x: -250, y: 20 }); + this._plotPrediction(graph1, prediction1b); + $assert( + prediction1b.position.x == manager.find(2).getPosition().x + && prediction1b.position.y == manager.find(2).getPosition().y, + 'Prediction position should be the same as node 2', + ); + $assert( + prediction1b.order == manager.find(2).getOrder(), + 'Predicition order should be the same as node 2', + ); + + const prediction1c = manager.predict(0, 2, { x: -100, y: -20 }); + this._plotPrediction(graph1, prediction1c); + $assert( + prediction1c.position.x == manager.find(1).getPosition().x + && prediction1c.position.y < manager.find(1).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1c.order == 1, 'Prediction order should be 1'); + + const prediction1d = manager.predict(0, 2, { x: -100, y: 20 }); + this._plotPrediction(graph1, prediction1d); + $assert( + prediction1d.position.x == manager.find(1).getPosition().x + && prediction1d.position.y > manager.find(1).getPosition().y, + 'Prediction is incorrectly positioned', + ); + $assert(prediction1d.order == 3, 'Prediction order should be 3'); + + const prediction1e = manager.predict(1, 2, { x: -250, y: 0 }); + this._plotPrediction(graph1, prediction1e); + $assert( + prediction1e.position.x == manager.find(2).getPosition().x + && prediction1e.position.y == manager.find(2).getPosition().y, + 'Prediction position should be the same as node 2', + ); + $assert( + prediction1e.order == manager.find(2).getOrder(), + 'Predicition order should be the same as node 2', + ); + + console.log('OK!\n\n'); + }, +}); + +export default SymmetricTestSuite; diff --git a/packages/mindplot/test/playground/layout/TestSuite.js b/packages/mindplot/test/playground/layout/TestSuite.js new file mode 100644 index 00000000..79b9c104 --- /dev/null +++ b/packages/mindplot/test/playground/layout/TestSuite.js @@ -0,0 +1,592 @@ +/* + * Copyright [2015] [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 mindplot from '../../../src/mindplot'; + +const TestSuite = new Class({ + Extends: mindplot.layout.ChildrenSorterStrategy, + + initialize() { + $('#basicTest').css('display', 'block'); + // this.testAligned(); + this.testBaselineAligned1(); + this.testBaselineAligned2(); + this.testEvents(); + this.testEventsComplex(); + this.testDisconnect(); + this.testReconnect(); + this.testRemoveNode(); + this.testSize(); + this.testReconnectSingleNode(); + }, + + testAligned() { + console.log('testAligned:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(1, 2, 0); + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(2, 3, 0); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(3, 4, 0); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(0, 5, 2); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(0, 6, 4); + manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(0, 7, 6); + + manager.layout(); + manager.plot('testAligned', { width: 1200, height: 200 }); + + // Child nodes should be vertically aligned + $assert( + manager.find(1).getPosition().y == manager.find(2).getPosition().y, + 'Child nodes are not vertically aligned', + ); + $assert( + manager.find(1).getPosition().y == manager.find(3).getPosition().y, + 'Child nodes are not vertically aligned', + ); + $assert( + manager.find(1).getPosition().y == manager.find(4).getPosition().y, + 'Child nodes are not vertically aligned', + ); + + // Siblings should be horizontally aligned + $assert( + manager.find(1).getPosition().x == manager.find(5).getPosition().x, + 'Sibling nodes are not horizontally aligned', + ); + $assert( + manager.find(1).getPosition().x == manager.find(6).getPosition().x, + 'Sibling nodes are not horizontally aligned', + ); + $assert( + manager.find(1).getPosition().x == manager.find(7).getPosition().x, + 'Sibling nodes are not horizontally aligned', + ); + + console.log('OK!\n\n'); + }, + + testBaselineAligned1() { + console.log('testBaselineAligned1:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(1, 3, 0); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(3, 5, 0); + manager.addNode(6, { width: 140, height: 130 }, position).connectNode(3, 6, 1); + manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(6, 7, 0); + manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(7, 8, 0); + manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(7, 9, 1); + manager.addNode(10, TestSuite.NODE_SIZE, position).connectNode(7, 10, 2); + manager.addNode(11, TestSuite.NODE_SIZE, position).connectNode(7, 11, 3); + manager.addNode(12, TestSuite.NODE_SIZE, position).connectNode(7, 12, 4); + manager.addNode(13, TestSuite.NODE_SIZE, position).connectNode(7, 13, 5); + manager.addNode(14, TestSuite.NODE_SIZE, position).connectNode(7, 14, 6); + manager.addNode(15, TestSuite.NODE_SIZE, position).connectNode(7, 15, 7); + manager.addNode(16, TestSuite.NODE_SIZE, position).connectNode(7, 16, 8); + manager.addNode(17, TestSuite.NODE_SIZE, position).connectNode(7, 17, 9); + manager.addNode(29, TestSuite.NODE_SIZE, position).connectNode(6, 29, 1); + manager.addNode(30, TestSuite.NODE_SIZE, position).connectNode(6, 30, 2); + manager.addNode(31, { width: 100, height: 50 }, position).connectNode(6, 31, 3); + + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 1); + manager.addNode(18, { width: 80, height: 70 }, position).connectNode(4, 18, 0); + manager.addNode(19, TestSuite.NODE_SIZE, position).connectNode(18, 19, 0); + manager.addNode(20, TestSuite.NODE_SIZE, position).connectNode(19, 20, 0); + manager.addNode(21, TestSuite.NODE_SIZE, position).connectNode(20, 21, 0); + + manager.addNode(2, TestSuite.NODE_SIZE, position).connectNode(0, 2, 1); + manager.addNode(22, TestSuite.NODE_SIZE, position).connectNode(2, 22, 0); + manager.addNode(24, TestSuite.NODE_SIZE, position).connectNode(22, 24, 0); + + manager.addNode(23, { width: 80, height: 50 }, position).connectNode(2, 23, 1); + manager.addNode(25, { width: 80, height: 40 }, position).connectNode(23, 25, 0); + manager.addNode(26, { width: 80, height: 80 }, position).connectNode(25, 26, 0); + manager.addNode(27, TestSuite.NODE_SIZE, position).connectNode(26, 27, 0); + manager.addNode(28, { width: 80, height: 80 }, position).connectNode(27, 28, 0); + + // manager.layout(); + // manager.plot("testBaselineAligned1", {width:1600,height:800}); + + console.log('OK!\n\n'); + }, + + testBaselineAligned2() { + console.log('testBaselineAligned2:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0); + manager.addNode(2, { width: 130, height: 200 }, position).connectNode(1, 2, 0); + manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(2, 3, 0); + manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(2, 4, 1); + manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(2, 5, 2); + manager.addNode(6, TestSuite.NODE_SIZE, position).connectNode(2, 6, 3); + + manager.layout(); + manager.plot('testBaselineAligned2', { width: 1600, height: 800 }); + + console.log('OK!\n\n'); + }, + + testEvents() { + console.log('testEvents:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, { x: 0, y: 60 }); + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(1, 3, 0); + + const events = []; + manager.addEvent('change', (event) => { + console.log( + `\tUpdated nodes: {id:${ + event.getId() + }, order: ${ + event.getOrder() + },position: {${ + event.getPosition().x + },${ + event.getPosition().y + }}`, + ); + events.push(event); + }); + manager.layout(true); + manager.plot('testEvents1', { width: 800, height: 200 }); + + console.log('\t--- Layout without changes should not affect the tree ---'); + events.empty(); + manager.layout(true); + manager.plot('testEvents2', { width: 800, height: 200 }); + + // Check no events where fired + $assert(events.length == 0, 'Unnecessary tree updated.'); + + console.log('OK!\n\n'); + }, + + testEventsComplex() { + console.log('testEventsComplex:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, { x: 0, y: 60 }); + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(3, 4, 0); + manager.connectNode(3, 5, 1); + + const events = []; + manager.addEvent('change', (event) => { + console.log( + `\tUpdated nodes: {id:${ + event.getId() + }, order: ${ + event.getOrder() + },position: {${ + event.getPosition().x + },${ + event.getPosition().y + }}`, + ); + events.push(event); + }); + + manager.layout(true); + manager.plot('testEventsComplex1', { width: 800, height: 200 }); + + console.log('\t--- Connect a new node ---'); + + events.empty(); + manager.connectNode(3, 6, 2); + manager.layout(true); + manager.plot('testEventsComplex2', { width: 800, height: 200 }); + + // Check only 4 nodes were repositioned + + console.log(events.length); + + $assert(events.length == 4, 'Only 4 nodes should be repositioned.'); + + console.log('OK!\n\n'); + }, + + testDisconnect() { + console.log('testDisconnect:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 1, 0); + manager.connectNode(1, 2, 0); + manager.connectNode(1, 3, 1); + manager.connectNode(1, 4, 2); + manager.connectNode(4, 5, 0); + manager.connectNode(5, 6, 0); + manager.connectNode(5, 7, 1); + + const events = []; + manager.addEvent('change', (event) => { + const pos = event.getPosition(); + const posStr = pos ? `,position: {${pos.x},${pos.y}` : ''; + const node = manager.find(event.getId()); + console.log( + `\tUpdated nodes: {id:${ + event.getId() + }, order: ${ + event.getOrder() + }${posStr + }}`, + ); + events.push(event); + }); + manager.layout(true); + manager.plot('testDisconnect1', { width: 1200, height: 400 }); + + console.log('--- Disconnect node 2 ---'); + events.empty(); + manager.disconnectNode(2); + manager.layout(true); + manager.plot('testDisconnect2', { width: 1200, height: 400 }); + + // Check that orders have been shifted accordingly + $assert(manager.find(2).getOrder() == 0, 'Node 2 should have order 0'); + $assert(manager.find(3).getOrder() == 0, 'Node 3 should now have order 0'); + $assert(manager.find(4).getOrder() == 1, 'Node 4 should have order 1'); + + console.log('--- Disconnect node 4 ---'); + manager.disconnectNode(4); + manager.layout(true); + manager.plot('testDisconnect3', { width: 1200, height: 400 }); + + // Check that nodes 1 and 3 are now vertically aligned + $assert( + manager.find(1).getPosition().y == manager.find(3).getPosition().y, + 'Nodes 1 and 3 should now be vertically aligned', + ); + + console.log('OK!\n\n'); + }, + + testReconnect() { + console.log('testReconnect:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + manager.addNode(12, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 1, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(0, 4, 3); + manager.connectNode(0, 5, 4); + manager.connectNode(1, 6, 0); + manager.connectNode(1, 7, 1); + manager.connectNode(7, 8, 0); + manager.connectNode(8, 9, 0); + manager.connectNode(5, 10, 0); + manager.connectNode(6, 11, 0); + manager.connectNode(6, 12, 1); + + manager.layout(); + manager.plot('testReconnect1', { width: 1200, height: 400 }); + + // Reconnect node 6 to node 4 + console.log('\tReconnect node 6 to node 4'); + manager.disconnectNode(6); + manager.connectNode(4, 6, 0); + manager.layout(); + manager.plot('testReconnect2', { width: 1200, height: 400 }); + + // Check nodes are left aligned correctly + $assert( + manager.find(1).getPosition().y == manager.find(7).getPosition().y, + 'Nodes 1 and 7 should be vertically aligned', + ); + $assert( + manager.find(4).getPosition().y == manager.find(6).getPosition().y, + 'Nodes 4 and 6 should be vertically aligned', + ); + $assert( + manager.find(4).getPosition().x > manager.find(6).getPosition().x, + 'Node 6 and their children should be to the left of node 4', + ); + $assert( + manager.find(6).getPosition().x > manager.find(11).getPosition().x + && manager.find(11).getPosition().x == manager.find(12).getPosition().x, + 'Nodes 11 and 12 should be to the left of node 6 and horizontally aligned', + ); + + console.log('OK!\n\n'); + }, + + testRemoveNode() { + console.log('testRemoveNode:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, TestSuite.NODE_SIZE, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(6, TestSuite.NODE_SIZE, position); + manager.addNode(7, TestSuite.NODE_SIZE, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(0, 5, 1); + manager.connectNode(0, 6, 2); + manager.connectNode(0, 7, 3); + manager.connectNode(0, 8, 4); + manager.connectNode(0, 9, 5); + manager.connectNode(1, 2, 0); + manager.connectNode(1, 3, 1); + manager.connectNode(3, 4, 0); + + const events = []; + manager.addEvent('change', (event) => { + const pos = event.getPosition(); + const posStr = pos ? `,position: {${pos.x},${event.getPosition().y}` : ''; + events.push(event); + }); + manager.layout(true); + manager.plot('testRemoveNode1', { width: 1000, height: 200 }); + + console.log('\t--- Remove node 3 ---'); + manager.removeNode(3); + manager.layout(true); + manager.plot('testRemoveNode2', { width: 1000, height: 200 }); + + // Check nodes are correctly aligned and node 6 is aligned with the root node + $assert( + manager.find(1).getPosition().y == manager.find(2).getPosition().y, + 'Nodes 1 and 2 should be vertically algined', + ); + $assert( + manager.find(6).getPosition().y == manager.find(0).getPosition().y, + 'Node 6 should be aligned to the root node', + ); + + console.log('\t--- Remove node 6 ---'); + manager.removeNode(6); + manager.layout(true); + manager.plot('testRemoveNode3', { width: 1000, height: 200 }); + + // Check orders were shifted accordingly + $assert(manager.find(8).getOrder() == 2, 'Node 8 should have order 2'); + + console.log('\t--- Remove node 5 ---'); + manager.removeNode(5); + manager.layout(true); + manager.plot('testRemoveNode4', { width: 1000, height: 200 }); + + // Check orders were shifted accordingly + $assert(manager.find(7).getOrder() == 1, 'Node 7 should have order 1'); + $assert(manager.find(9).getOrder() == 3, 'Node 9 should have order 3'); + + console.log('OK!\n\n'); + }, + + testSize() { + console.log('testSize:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, { width: 60, height: 60 }, position); + manager.addNode(2, TestSuite.NODE_SIZE, position); + manager.addNode(3, { width: 260, height: 30 }, position); + manager.addNode(4, TestSuite.NODE_SIZE, position); + manager.addNode(5, TestSuite.NODE_SIZE, position); + manager.addNode(7, { width: 80, height: 80 }, position); + manager.addNode(8, TestSuite.NODE_SIZE, position); + manager.addNode(9, { width: 30, height: 30 }, position); + manager.addNode(10, TestSuite.NODE_SIZE, position); + manager.addNode(11, TestSuite.NODE_SIZE, position); + manager.addNode(12, { width: 100, height: 70 }, position); + manager.addNode(13, TestSuite.NODE_SIZE, position); + manager.addNode(14, TestSuite.NODE_SIZE, position); + manager.addNode(15, TestSuite.NODE_SIZE, position); + manager.addNode(16, TestSuite.NODE_SIZE, position); + manager.addNode(17, TestSuite.NODE_SIZE, position); + + manager.connectNode(0, 1, 0); + manager.connectNode(1, 16, 0); + manager.connectNode(0, 2, 1); + manager.connectNode(0, 3, 2); + manager.connectNode(0, 4, 3); + manager.connectNode(0, 5, 4); + manager.connectNode(4, 7, 0); + manager.connectNode(7, 15, 0); + manager.connectNode(7, 17, 1); + manager.connectNode(4, 8, 1); + manager.connectNode(8, 9, 0); + manager.connectNode(3, 10, 0); + manager.connectNode(3, 11, 1); + manager.connectNode(9, 12, 0); + manager.connectNode(9, 13, 1); + manager.connectNode(13, 14, 0); + + manager.layout(); + manager.plot('testSize1', { width: 1400, height: 400 }); + + // Check that all enlarged nodes shift children accordingly + $assert( + manager.find(10).getPosition().x > manager.find(3).getPosition().x + && manager.find(10).getPosition().x == manager.find(11).getPosition().x, + 'Nodes 10 and 11 should be horizontally algined and to the right of enlarged node 3', + ); + const xPosNode7 = manager.find(7).getPosition().x; + const xPosNode8 = manager.find(8).getPosition().x; + + manager.updateNodeSize(4, { width: 100, height: 30 }); + manager.layout(); + manager.plot('testSize2', { width: 1400, height: 400 }); + + // Check that all enlarged nodes shift children accordingly + $assert( + manager.find(2).getPosition().x - manager.find(4).getPosition().x == 10, + 'Node 4 should have been shifted by 10', + ); + $assert( + xPosNode7 - manager.find(7).getPosition().x == 20, + 'Node 7 should have been shifted by 20', + ); + $assert( + xPosNode8 - manager.find(8).getPosition().x == 20, + 'Node 8 should have been shifted by 20', + ); + + const graph2 = manager.plot('testSize3', { width: 1400, height: 400 }); + this._plotPrediction(graph2, manager.predict(0, null, { x: -145, y: 400 })); + this._plotPrediction(graph2, manager.predict(9, null, { x: -330, y: 70 })); + this._plotPrediction(graph2, manager.predict(9, null, { x: -330, y: 120 })); + this._plotPrediction(graph2, manager.predict(0, null, { x: 15, y: 20 })); + // TODO(gb): make asserts + + const graph3 = manager.plot('testSize4', { width: 1400, height: 400 }); + this._plotPrediction(graph3, manager.predict(0, null, null)); + this._plotPrediction(graph3, manager.predict(9, null, null)); + this._plotPrediction(graph3, manager.predict(3, null, null)); + this._plotPrediction(graph3, manager.predict(1, null, null)); + // TODO(gb): make asserts + + const yPosNode2 = manager.find(2).getPosition().y; + manager.updateNodeSize(7, { width: 80, height: 120 }); + manager.layout(); + manager.plot('testSize5', { width: 1400, height: 400 }); + + // Check that all enlarged nodes shift children accordingly + $assert( + yPosNode2 - manager.find(2).getPosition().y == 20, + 'Node 2 should have been shifted by 20', + ); + + console.log('OK!\n\n'); + }, + + testReconnectSingleNode() { + console.log('testReconnectSingleNode:'); + const position = { x: 0, y: 0 }; + const manager = new mindplot.layout.LayoutManager(0, TestSuite.ROOT_NODE_SIZE); + + // Prepare a sample graph ... + manager.addNode(1, TestSuite.NODE_SIZE, position); + manager.connectNode(0, 1, 0); + manager.layout(); + const graph = manager.plot('testReconnectSingleNode1', { width: 1000, height: 400 }); + const prediction = manager.predict(0, null, { x: -50, y: 0 }); + this._plotPrediction(graph, prediction); + + // Check prediction is to the left of the root node + $assert( + prediction.position.x < manager.find(0).getPosition().x, + 'Prediction should be to the left of the root node', + ); + $assert(prediction.order == 1, 'Prediction should have order 1'); + + manager.disconnectNode(1); + manager.connectNode(0, 1, 1); + manager.layout(); + manager.plot('testReconnectSingleNode2', { width: 1000, height: 400 }); + + // Check reconnected node is to the left of the root node + $assert( + manager.find(1).getPosition().x < manager.find(0).getPosition().x, + 'Node 1 should now be to the left of the root node', + ); + $assert(manager.find(1).getOrder() == 1, 'Node 1 should now have order 0'); + }, + + _plotPrediction(canvas, prediction) { + if(!canvas) { + console.warn('no canvas in _plotPrediction. Remove this method if plot() not in use'); + return; + } + const { position } = prediction; + const { order } = prediction; + console.log( + `\t\tprediction {order:${ + order + }, position: (${ + position.x + },${ + position.y + })}`, + ); + const cx = position.x + canvas.width / 2 - TestSuite.NODE_SIZE.width / 2; + const cy = position.y + canvas.height / 2 - TestSuite.NODE_SIZE.height / 2; + canvas.rect(cx, cy, TestSuite.NODE_SIZE.width, TestSuite.NODE_SIZE.height); + }, +}); + +(TestSuite.NODE_SIZE = { width: 80, height: 30 }), +(TestSuite.ROOT_NODE_SIZE = { width: 120, height: 40 }); + +export default TestSuite; diff --git a/packages/mindplot/test/playground/layout/context-loader.js b/packages/mindplot/test/playground/layout/context-loader.js new file mode 100644 index 00000000..17bf7399 --- /dev/null +++ b/packages/mindplot/test/playground/layout/context-loader.js @@ -0,0 +1,11 @@ +import TestSuite from './TestSuite'; +import BalancedTestSuite from './BalancedTestSuite'; +import SymmetricTestSuite from './SymmetricTestSuite'; +import FreeTestSuite from './FreeTestSuite'; + +window.addEventListener('DOMContentLoaded', () => { + new TestSuite(); + new BalancedTestSuite(); + new SymmetricTestSuite(); + new FreeTestSuite(); +}); diff --git a/packages/mindplot/test/playground/layout.html b/packages/mindplot/test/playground/layout/index.html similarity index 100% rename from packages/mindplot/test/playground/layout.html rename to packages/mindplot/test/playground/layout/index.html diff --git a/packages/mindplot/test/playground/lib/raphael-min.js b/packages/mindplot/test/playground/layout/lib/raphael-min.js similarity index 100% rename from packages/mindplot/test/playground/lib/raphael-min.js rename to packages/mindplot/test/playground/layout/lib/raphael-min.js diff --git a/packages/mindplot/test/playground/layout/lib/raphael-plugins.js b/packages/mindplot/test/playground/layout/lib/raphael-plugins.js new file mode 100644 index 00000000..c823c9a6 --- /dev/null +++ b/packages/mindplot/test/playground/layout/lib/raphael-plugins.js @@ -0,0 +1,29 @@ +Raphael.fn.drawGrid = function (x, y, w, h, wv, hv, color) { + color = color || '#999'; + let path = ['M', x, y, 'L', x + w, y, x + w, y + h, x, y + h, x, y]; + const rowHeight = h / hv; + const columnWidth = w / wv; + for (var i = 0; i < hv + 1; i++) { + var offset = y + i * rowHeight; + path = this.path(['M', x, offset, 'L', x + w, y + i * rowHeight]); + if (offset == 0 || offset == h) { + path.attr({ stroke: '#000' }); + } else if (offset == h / 2) { + path.attr({ stroke: '#c00' }); + } else { + path.attr({ stroke: '#999' }); + } + } + for (var i = 0; i < wv + 1; i++) { + var offset = x + i * columnWidth; + path = this.path(['M', offset, y, 'L', x + i * columnWidth, y + h]); + if (offset == 0 || offset == w) { + path.attr({ stroke: '#000' }); + } else if (offset == w / 2) { + path.attr({ stroke: '#c00' }); + } else { + path.attr({ stroke: '#999' }); + } + } + return this.path; +}; diff --git a/packages/mindplot/test/playground/sample.xml b/packages/mindplot/test/playground/layout/sample.xml similarity index 100% rename from packages/mindplot/test/playground/sample.xml rename to packages/mindplot/test/playground/layout/sample.xml diff --git a/packages/mindplot/test/playground/layout/utils.js b/packages/mindplot/test/playground/layout/utils.js new file mode 100755 index 00000000..655292ab --- /dev/null +++ b/packages/mindplot/test/playground/layout/utils.js @@ -0,0 +1,59 @@ +/* eslint-disable func-names */ +/* + * Copyright [2015] [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. + */ + +Grid = function (parent, colums, rows) { + const cellSize = '10px'; + this._parent = parent; + this._container = this._createContainer(); + const tbody = $(this._container.firstChild.firstChild); + for (let i = 0; i < rows; i++) { + const trElement = $(''); + for (let j = 0; j < colums; j++) { + const tdElement = $(''); + tdElement.css({ + width: cellSize, + height: cellSize, + borderWidth: '1px', + borderStyle: 'dashed', + borderColor: 'lightsteelblue', + }); + trElement.append(tdElement); + } + tbody.append(trElement); + } +}; + +Grid.prototype.setPosition = function (x, y) { + this._container.style.left = x; + this._container.style.top = y; +}; + +Grid.prototype.render = function () { + $(this._parent).append(this._container); +}; + +Grid.prototype._createContainer = function () { + const result = window.document.createElement('div'); + result.style.tableLayout = 'fixed'; + result.style.borderCollapse = 'collapse'; + result.style.emptyCells = 'show'; + result.style.position = 'absolute'; + result.innerHTML = '
'; + return result; +}; diff --git a/packages/mindplot/test/playground/lib/raphael-plugins.js b/packages/mindplot/test/playground/lib/raphael-plugins.js deleted file mode 100644 index f3a06f4a..00000000 --- a/packages/mindplot/test/playground/lib/raphael-plugins.js +++ /dev/null @@ -1,29 +0,0 @@ -Raphael.fn.drawGrid = function (x, y, w, h, wv, hv, color) { - color = color || "#999"; - var path = ["M", x, y, "L", x + w, y, x + w, y + h, x, y + h, x, y], - rowHeight = h / hv, - columnWidth = w / wv; - for (var i = 0; i < hv + 1; i++) { - var offset = y + i * rowHeight; - path = this.path(["M", x, offset, "L", x + w, y + i * rowHeight]); - if (offset == 0 || offset == h) { - path.attr({stroke: "#000"}); - } else if (offset == h/2) { - path.attr({stroke: "#c00"}) - } else { - path.attr({stroke: "#999"}) - } - } - for (var i = 0; i < wv + 1; i++) { - var offset = x + i * columnWidth; - path = this.path(["M", offset, y, "L", x + i * columnWidth, y + h]); - if (offset == 0 || offset == w) { - path.attr({stroke: "#000"}); - } else if (offset == w/2) { - path.attr({stroke: "#c00"}) - } else { - path.attr({stroke: "#999"}) - } - } - return this.path; -}; \ No newline at end of file diff --git a/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.Request.js b/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.Request.js new file mode 100644 index 00000000..4f12b859 --- /dev/null +++ b/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.Request.js @@ -0,0 +1,49 @@ +BootstrapDialog.Request = new Class({ + + Extends: BootstrapDialog, + + initialize: function(url, title, options) { + this.parent(title, options); + this.requestOptions = {}; + this.requestOptions.cache = false; + var me = this; + this.requestOptions.fail = function(xhr) { + // Intercept form requests ... + console.log("Failure:"); + console.log(xhr); + }; + + this.requestOptions.success = function() { + // Intercept form requests ... + var forms = me._native.find('form'); + _.each(forms, function(form) { + $(form).on('submit', function(event) { + // Intercept form ... + me.requestOptions.url = form.action; + me.requestOptions.method = form.method ? form.method : 'post'; + $.ajax(me.requestOptions); + event.stopPropagation(); + return false; + }); + }); + }; + + this._native.find('.modal-body').load(url, function () { + me.acceptButton.unbind('click').click(function () { + submitDialogForm(); + }); + me._native.on('hidden.bs.modal', function () { + $(this).remove(); + }); + me.show(); + }); + }, + + onDialogShown: function() { + if (typeof(onDialogShown) == "function") { + onDialogShown(); + } + } + + +}); diff --git a/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.js b/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.js new file mode 100644 index 00000000..83f37aef --- /dev/null +++ b/packages/mindplot/test/playground/map-render/bootstrap/BootstrapDialog.js @@ -0,0 +1,111 @@ +var BootstrapDialog = new Class({ + Implements: Options, + + options: { + cancelButton: false, + closeButton: false, + acceptButton: true, + removeButton:false, + errorMessage: false, + onEventData:{} + }, + + initialize: function (title, options) { + this.setOptions(options); + this.options.onEventData.dialog = this; + this._native = $('').append(''); + var content = $(''); + var header = this._buildHeader(title); + if (header) { + content.append(header); + } + var body = $(''); + if(this.options.errorMessage){ + var error = $('
'); + error.hide(); + body.append(error); + } + content.append(body); + var footer = this._buildFooter(); + if (footer) { + content.append(footer); + } + this._native.find(".modal-dialog").append(content); + this._native.on('hidden.bs.modal', function() { + $(this).remove(); + }); + this._native.on('shown.bs.modal', this.onDialogShown); + }, + + _buildFooter: function() { + var footer = null; + if (this.options.acceptButton || this.options.removeButton || this.options.cancelButton) { + footer = $('