From 32c6c04748540f750a675c72b2f6799c4ceda55b Mon Sep 17 00:00:00 2001 From: David Benson Date: Sat, 2 Jun 2012 07:02:43 +0100 Subject: [PATCH] 1.10.1.0 release --- .../grapheditor/www/stencils/aws/compute.xml | 720 + .../www/stencils/aws/content_delivery.xml | 445 + .../grapheditor/www/stencils/aws/database.xml | 1358 + .../stencils/aws/deployment_management.xml | 306 + .../grapheditor/www/stencils/aws/groups.xml | 1200 + .../www/stencils/aws/messaging.xml | 670 + .../grapheditor/www/stencils/aws/misc.xml | 274 + .../www/stencils/aws/networking.xml | 872 + .../www/stencils/aws/non_service_specific.xml | 734 + .../www/stencils/aws/on_demand_workforce.xml | 422 + .../grapheditor/www/stencils/aws/storage.xml | 376 + .../www/stencils/electrical/abstract.xml | 764 + .../www/stencils/electrical/capacitors.xml | 413 + .../www/stencils/electrical/diodes.xml | 338 + .../electrical/electro-mechanical.xml | 509 + .../www/stencils/electrical/iec417.xml | 1478 + .../stencils/electrical/iec_logic_gates.xml | 134 + .../www/stencils/electrical/inductors.xml | 631 + .../www/stencils/electrical/instruments.xml | 156 + .../www/stencils/electrical/logic_gates.xml | 934 + .../www/stencils/electrical/miscellaneous.xml | 471 + .../www/stencils/electrical/mosfets1.xml | 907 + .../www/stencils/electrical/mosfets2.xml | 937 + .../www/stencils/electrical/op_amps.xml | 613 + .../stencils/electrical/opto-electronics.xml | 1014 + .../stencils/electrical/opto_electronics.xml | 885 + .../www/stencils/electrical/plc_ladder.xml | 173 + .../electrical/power_semiconductors.xml | 1033 + .../www/stencils/electrical/radio.xml | 367 + .../www/stencils/electrical/resistors.xml | 713 + .../stencils/electrical/signal_sources.xml | 439 + .../electrical/thermionic_devices.xml | 483 + .../www/stencils/electrical/transistors.xml | 674 + .../www/stencils/electrical/waveforms.xml | 355 + .../grapheditor/www/stencils/lean_mapping.xml | 1042 + .../www/stencils/mockup/advertising.xml | 223 + .../www/stencils/mockup/calendars.xml | 1595 + .../www/stencils/mockup/carousel.xml | 599 + .../www/stencils/mockup/charts_and_tables.xml | 626 + .../www/stencils/mockup/controls.xml | 648 + .../www/stencils/mockup/form_elements.xml | 433 + .../www/stencils/mockup/menus_and_buttons.xml | 852 + .../grapheditor/www/stencils/mockup/misc.xml | 2183 + .../grapheditor/www/stencils/mockup/tabs.xml | 193 + .../www/stencils/pid/compressors.xml | 380 + .../www/stencils/pid/heat_exchangers.xml | 378 + .../www/stencils/pid/instruments.xml | 571 + .../grapheditor/www/stencils/pid/pumps.xml | 289 + .../grapheditor/www/stencils/pid/valves.xml | 977 + .../grapheditor/www/stencils/pid/vessels.xml | 430 + .../www/stencils/signs/animals.xml | 1515 + .../grapheditor/www/stencils/signs/food.xml | 614 + .../www/stencils/signs/healthcare.xml | 5753 ++ .../grapheditor/www/stencils/signs/nature.xml | 1049 + .../grapheditor/www/stencils/signs/people.xml | 1603 + .../grapheditor/www/stencils/signs/safety.xml | 1644 + .../www/stencils/signs/science.xml | 434 + .../grapheditor/www/stencils/signs/sports.xml | 6035 ++ .../grapheditor/www/stencils/signs/tech.xml | 1295 + .../www/stencils/signs/transportation.xml | 6297 ++ .../grapheditor/www/stencils/signs/travel.xml | 3450 + javascript/mxClient.js | 78364 +++++++++++++++- .../src/js/handler/mxConnectionHandler.js | 9 +- .../model/mxGraphHierarchyModel.js | 232 +- .../hierarchical/mxHierarchicalLayout.js | 194 +- .../stage/mxCoordinateAssignment.js | 57 +- javascript/src/js/layout/mxGraphLayout.js | 69 +- javascript/src/js/mxClient.js | 2179 +- javascript/src/js/shape/mxActor.js | 5 +- javascript/src/js/shape/mxCylinder.js | 4 +- javascript/src/js/shape/mxStencil.js | 6 +- javascript/src/js/util/mxPanningManager.js | 65 +- javascript/src/js/util/mxResources.js | 55 +- javascript/src/js/util/mxUtils.js | 3 +- javascript/src/js/view/mxGraph.js | 72 +- javascript/src/js/view/mxOutline.js | 56 +- 76 files changed, 142502 insertions(+), 1774 deletions(-) create mode 100644 javascript/examples/grapheditor/www/stencils/aws/compute.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/content_delivery.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/database.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/deployment_management.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/groups.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/messaging.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/misc.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/networking.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/non_service_specific.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/on_demand_workforce.xml create mode 100644 javascript/examples/grapheditor/www/stencils/aws/storage.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/abstract.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/capacitors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/diodes.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/electro-mechanical.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/iec417.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/iec_logic_gates.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/inductors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/instruments.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/logic_gates.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/miscellaneous.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/mosfets1.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/mosfets2.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/op_amps.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/opto-electronics.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/opto_electronics.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/plc_ladder.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/power_semiconductors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/radio.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/resistors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/signal_sources.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/thermionic_devices.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/transistors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/electrical/waveforms.xml create mode 100644 javascript/examples/grapheditor/www/stencils/lean_mapping.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/advertising.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/calendars.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/carousel.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/charts_and_tables.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/controls.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/form_elements.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/menus_and_buttons.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/misc.xml create mode 100644 javascript/examples/grapheditor/www/stencils/mockup/tabs.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/compressors.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/heat_exchangers.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/instruments.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/pumps.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/valves.xml create mode 100644 javascript/examples/grapheditor/www/stencils/pid/vessels.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/animals.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/food.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/healthcare.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/nature.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/people.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/safety.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/science.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/sports.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/tech.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/transportation.xml create mode 100644 javascript/examples/grapheditor/www/stencils/signs/travel.xml diff --git a/javascript/examples/grapheditor/www/stencils/aws/compute.xml b/javascript/examples/grapheditor/www/stencils/aws/compute.xml new file mode 100644 index 000000000..98303274a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/compute.xml @@ -0,0 +1,720 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/content_delivery.xml b/javascript/examples/grapheditor/www/stencils/aws/content_delivery.xml new file mode 100644 index 000000000..8e98a44ba --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/content_delivery.xml @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/database.xml b/javascript/examples/grapheditor/www/stencils/aws/database.xml new file mode 100644 index 000000000..013f87f65 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/database.xml @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/deployment_management.xml b/javascript/examples/grapheditor/www/stencils/aws/deployment_management.xml new file mode 100644 index 000000000..e1cf41c6f --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/deployment_management.xml @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/groups.xml b/javascript/examples/grapheditor/www/stencils/aws/groups.xml new file mode 100644 index 000000000..7a43ccc50 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/groups.xml @@ -0,0 +1,1200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/messaging.xml b/javascript/examples/grapheditor/www/stencils/aws/messaging.xml new file mode 100644 index 000000000..b78e4931a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/messaging.xml @@ -0,0 +1,670 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/misc.xml b/javascript/examples/grapheditor/www/stencils/aws/misc.xml new file mode 100644 index 000000000..57ad6fdd8 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/misc.xml @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/networking.xml b/javascript/examples/grapheditor/www/stencils/aws/networking.xml new file mode 100644 index 000000000..ddeadfe15 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/networking.xml @@ -0,0 +1,872 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/non_service_specific.xml b/javascript/examples/grapheditor/www/stencils/aws/non_service_specific.xml new file mode 100644 index 000000000..4486d740d --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/non_service_specific.xml @@ -0,0 +1,734 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/on_demand_workforce.xml b/javascript/examples/grapheditor/www/stencils/aws/on_demand_workforce.xml new file mode 100644 index 000000000..6e3a9baea --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/on_demand_workforce.xml @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/aws/storage.xml b/javascript/examples/grapheditor/www/stencils/aws/storage.xml new file mode 100644 index 000000000..78ed99277 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/aws/storage.xml @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/abstract.xml b/javascript/examples/grapheditor/www/stencils/electrical/abstract.xml new file mode 100644 index 000000000..287891fff --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/abstract.xml @@ -0,0 +1,764 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/capacitors.xml b/javascript/examples/grapheditor/www/stencils/electrical/capacitors.xml new file mode 100644 index 000000000..ef9af2d20 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/capacitors.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/diodes.xml b/javascript/examples/grapheditor/www/stencils/electrical/diodes.xml new file mode 100644 index 000000000..a72a078da --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/diodes.xml @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/electro-mechanical.xml b/javascript/examples/grapheditor/www/stencils/electrical/electro-mechanical.xml new file mode 100644 index 000000000..f8965a30b --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/electro-mechanical.xml @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/iec417.xml b/javascript/examples/grapheditor/www/stencils/electrical/iec417.xml new file mode 100644 index 000000000..920279829 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/iec417.xml @@ -0,0 +1,1478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/iec_logic_gates.xml b/javascript/examples/grapheditor/www/stencils/electrical/iec_logic_gates.xml new file mode 100644 index 000000000..67a922cd0 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/iec_logic_gates.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/inductors.xml b/javascript/examples/grapheditor/www/stencils/electrical/inductors.xml new file mode 100644 index 000000000..abe158ce6 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/inductors.xml @@ -0,0 +1,631 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/instruments.xml b/javascript/examples/grapheditor/www/stencils/electrical/instruments.xml new file mode 100644 index 000000000..372f3b940 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/instruments.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/logic_gates.xml b/javascript/examples/grapheditor/www/stencils/electrical/logic_gates.xml new file mode 100644 index 000000000..80dba24cf --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/logic_gates.xml @@ -0,0 +1,934 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/miscellaneous.xml b/javascript/examples/grapheditor/www/stencils/electrical/miscellaneous.xml new file mode 100644 index 000000000..0f99ece94 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/miscellaneous.xml @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/mosfets1.xml b/javascript/examples/grapheditor/www/stencils/electrical/mosfets1.xml new file mode 100644 index 000000000..0bf50c8f5 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/mosfets1.xml @@ -0,0 +1,907 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/mosfets2.xml b/javascript/examples/grapheditor/www/stencils/electrical/mosfets2.xml new file mode 100644 index 000000000..f46c0b0fb --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/mosfets2.xml @@ -0,0 +1,937 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/op_amps.xml b/javascript/examples/grapheditor/www/stencils/electrical/op_amps.xml new file mode 100644 index 000000000..973e9d160 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/op_amps.xml @@ -0,0 +1,613 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/opto-electronics.xml b/javascript/examples/grapheditor/www/stencils/electrical/opto-electronics.xml new file mode 100644 index 000000000..372e0c715 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/opto-electronics.xml @@ -0,0 +1,1014 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/javascript/examples/grapheditor/www/stencils/electrical/opto_electronics.xml b/javascript/examples/grapheditor/www/stencils/electrical/opto_electronics.xml new file mode 100644 index 000000000..50caeea7e --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/opto_electronics.xml @@ -0,0 +1,885 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/plc_ladder.xml b/javascript/examples/grapheditor/www/stencils/electrical/plc_ladder.xml new file mode 100644 index 000000000..51ddac315 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/plc_ladder.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/power_semiconductors.xml b/javascript/examples/grapheditor/www/stencils/electrical/power_semiconductors.xml new file mode 100644 index 000000000..94418fc08 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/power_semiconductors.xml @@ -0,0 +1,1033 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/radio.xml b/javascript/examples/grapheditor/www/stencils/electrical/radio.xml new file mode 100644 index 000000000..3d0ce6924 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/radio.xml @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/resistors.xml b/javascript/examples/grapheditor/www/stencils/electrical/resistors.xml new file mode 100644 index 000000000..45c132658 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/resistors.xml @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/signal_sources.xml b/javascript/examples/grapheditor/www/stencils/electrical/signal_sources.xml new file mode 100644 index 000000000..033b04b1c --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/signal_sources.xml @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/thermionic_devices.xml b/javascript/examples/grapheditor/www/stencils/electrical/thermionic_devices.xml new file mode 100644 index 000000000..69f83259f --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/thermionic_devices.xml @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/transistors.xml b/javascript/examples/grapheditor/www/stencils/electrical/transistors.xml new file mode 100644 index 000000000..cb0a062a6 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/transistors.xml @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/electrical/waveforms.xml b/javascript/examples/grapheditor/www/stencils/electrical/waveforms.xml new file mode 100644 index 000000000..0e222b5b0 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/electrical/waveforms.xml @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/lean_mapping.xml b/javascript/examples/grapheditor/www/stencils/lean_mapping.xml new file mode 100644 index 000000000..61bd7c588 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/lean_mapping.xml @@ -0,0 +1,1042 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/advertising.xml b/javascript/examples/grapheditor/www/stencils/mockup/advertising.xml new file mode 100644 index 000000000..790363d9a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/advertising.xml @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/calendars.xml b/javascript/examples/grapheditor/www/stencils/mockup/calendars.xml new file mode 100644 index 000000000..d81328071 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/calendars.xml @@ -0,0 +1,1595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/carousel.xml b/javascript/examples/grapheditor/www/stencils/mockup/carousel.xml new file mode 100644 index 000000000..7979af3e8 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/carousel.xml @@ -0,0 +1,599 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/charts_and_tables.xml b/javascript/examples/grapheditor/www/stencils/mockup/charts_and_tables.xml new file mode 100644 index 000000000..08a693710 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/charts_and_tables.xml @@ -0,0 +1,626 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/controls.xml b/javascript/examples/grapheditor/www/stencils/mockup/controls.xml new file mode 100644 index 000000000..7a185933e --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/controls.xml @@ -0,0 +1,648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/form_elements.xml b/javascript/examples/grapheditor/www/stencils/mockup/form_elements.xml new file mode 100644 index 000000000..baba97cdc --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/form_elements.xml @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/menus_and_buttons.xml b/javascript/examples/grapheditor/www/stencils/mockup/menus_and_buttons.xml new file mode 100644 index 000000000..4669383c2 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/menus_and_buttons.xml @@ -0,0 +1,852 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/misc.xml b/javascript/examples/grapheditor/www/stencils/mockup/misc.xml new file mode 100644 index 000000000..0eca8d402 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/misc.xml @@ -0,0 +1,2183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/mockup/tabs.xml b/javascript/examples/grapheditor/www/stencils/mockup/tabs.xml new file mode 100644 index 000000000..f05de3e5c --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/mockup/tabs.xml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/compressors.xml b/javascript/examples/grapheditor/www/stencils/pid/compressors.xml new file mode 100644 index 000000000..e941cdf57 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/compressors.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/heat_exchangers.xml b/javascript/examples/grapheditor/www/stencils/pid/heat_exchangers.xml new file mode 100644 index 000000000..5489a34b5 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/heat_exchangers.xml @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/instruments.xml b/javascript/examples/grapheditor/www/stencils/pid/instruments.xml new file mode 100644 index 000000000..8e57f4215 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/instruments.xml @@ -0,0 +1,571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/pumps.xml b/javascript/examples/grapheditor/www/stencils/pid/pumps.xml new file mode 100644 index 000000000..ca58f6d89 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/pumps.xml @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/valves.xml b/javascript/examples/grapheditor/www/stencils/pid/valves.xml new file mode 100644 index 000000000..bd4f179c8 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/valves.xml @@ -0,0 +1,977 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/pid/vessels.xml b/javascript/examples/grapheditor/www/stencils/pid/vessels.xml new file mode 100644 index 000000000..834ac537f --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/pid/vessels.xml @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/animals.xml b/javascript/examples/grapheditor/www/stencils/signs/animals.xml new file mode 100644 index 000000000..0b91de57a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/animals.xml @@ -0,0 +1,1515 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/food.xml b/javascript/examples/grapheditor/www/stencils/signs/food.xml new file mode 100644 index 000000000..67c4e38d5 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/food.xml @@ -0,0 +1,614 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/healthcare.xml b/javascript/examples/grapheditor/www/stencils/signs/healthcare.xml new file mode 100644 index 000000000..5e6ee26e9 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/healthcare.xml @@ -0,0 +1,5753 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/nature.xml b/javascript/examples/grapheditor/www/stencils/signs/nature.xml new file mode 100644 index 000000000..32bb25235 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/nature.xml @@ -0,0 +1,1049 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/people.xml b/javascript/examples/grapheditor/www/stencils/signs/people.xml new file mode 100644 index 000000000..032afa34a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/people.xml @@ -0,0 +1,1603 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/safety.xml b/javascript/examples/grapheditor/www/stencils/signs/safety.xml new file mode 100644 index 000000000..069a2018a --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/safety.xml @@ -0,0 +1,1644 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/science.xml b/javascript/examples/grapheditor/www/stencils/signs/science.xml new file mode 100644 index 000000000..b2205f0f9 --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/science.xml @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/sports.xml b/javascript/examples/grapheditor/www/stencils/signs/sports.xml new file mode 100644 index 000000000..365a8d2bb --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/sports.xml @@ -0,0 +1,6035 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/tech.xml b/javascript/examples/grapheditor/www/stencils/signs/tech.xml new file mode 100644 index 000000000..d6ad3a76d --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/tech.xml @@ -0,0 +1,1295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/transportation.xml b/javascript/examples/grapheditor/www/stencils/signs/transportation.xml new file mode 100644 index 000000000..cf18354ed --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/transportation.xml @@ -0,0 +1,6297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/examples/grapheditor/www/stencils/signs/travel.xml b/javascript/examples/grapheditor/www/stencils/signs/travel.xml new file mode 100644 index 000000000..e7094378b --- /dev/null +++ b/javascript/examples/grapheditor/www/stencils/signs/travel.xml @@ -0,0 +1,3450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/mxClient.js b/javascript/mxClient.js index 78ce330f0..e314c5db8 100644 --- a/javascript/mxClient.js +++ b/javascript/mxClient.js @@ -1 +1,78363 @@ -var mxClient={VERSION:'1.10.0.6',IS_IE:navigator.userAgent.indexOf('MSIE')>=0,IS_IE6:navigator.userAgent.indexOf('MSIE 6')>=0,IS_NS:navigator.userAgent.indexOf('Mozilla/')>=0&&navigator.userAgent.indexOf('MSIE')<0,IS_OP:navigator.userAgent.indexOf('Opera/')>=0,IS_OT:navigator.userAgent.indexOf('Presto/2.4.')<0&&navigator.userAgent.indexOf('Presto/2.3.')<0&&navigator.userAgent.indexOf('Presto/2.2.')<0&&navigator.userAgent.indexOf('Presto/2.1.')<0&&navigator.userAgent.indexOf('Presto/2.0.')<0&&navigator.userAgent.indexOf('Presto/1.')<0,IS_SF:navigator.userAgent.indexOf('AppleWebKit/')>=0&&navigator.userAgent.indexOf('Chrome/')<0,IS_GC:navigator.userAgent.indexOf('Chrome/')>=0,IS_MT:(navigator.userAgent.indexOf('Firefox/')>=0&&navigator.userAgent.indexOf('Firefox/1.')<0&&navigator.userAgent.indexOf('Firefox/2.')<0)||(navigator.userAgent.indexOf('Iceweasel/')>=0&&navigator.userAgent.indexOf('Iceweasel/1.')<0&&navigator.userAgent.indexOf('Iceweasel/2.')<0)||(navigator.userAgent.indexOf('SeaMonkey/')>=0&&navigator.userAgent.indexOf('SeaMonkey/1.')<0)||(navigator.userAgent.indexOf('Iceape/')>=0&&navigator.userAgent.indexOf('Iceape/1.')<0),IS_SVG:navigator.userAgent.indexOf('Firefox/')>=0||navigator.userAgent.indexOf('Iceweasel/')>=0||navigator.userAgent.indexOf('Seamonkey/')>=0||navigator.userAgent.indexOf('Iceape/')>=0||navigator.userAgent.indexOf('Galeon/')>=0||navigator.userAgent.indexOf('Epiphany/')>=0||navigator.userAgent.indexOf('AppleWebKit/')>=0||navigator.userAgent.indexOf('Gecko/')>=0||navigator.userAgent.indexOf('Opera/')>=0,NO_FO:navigator.userAgent.indexOf('Firefox/1.')>=0||navigator.userAgent.indexOf('Iceweasel/1.')>=0||navigator.userAgent.indexOf('Firefox/2.')>=0||navigator.userAgent.indexOf('Iceweasel/2.')>=0||navigator.userAgent.indexOf('SeaMonkey/1.')>=0||navigator.userAgent.indexOf('Iceape/1.')>=0||navigator.userAgent.indexOf('Camino/1.')>=0||navigator.userAgent.indexOf('Epiphany/2.')>=0||navigator.userAgent.indexOf('Opera/')>=0||navigator.userAgent.indexOf('MSIE')>=0||navigator.userAgent.indexOf('Mozilla/2.')>=0,IS_VML:navigator.appName.toUpperCase()=='MICROSOFT INTERNET EXPLORER',IS_MAC:navigator.userAgent.toUpperCase().indexOf('MACINTOSH')>0,IS_TOUCH:navigator.userAgent.toUpperCase().indexOf('IPAD')>0||navigator.userAgent.toUpperCase().indexOf('IPOD')>0||navigator.userAgent.toUpperCase().indexOf('IPHONE')>0||navigator.userAgent.toUpperCase().indexOf('ANDROID')>0,IS_LOCAL:document.location.href.indexOf('http://')<0&&document.location.href.indexOf('https://')<0,isBrowserSupported:function(){return mxClient.IS_VML||mxClient.IS_SVG;},link:function(rel,href,doc){doc=doc||document;if(mxClient.IS_IE6){doc.write('');}else{var link=doc.createElement('link');link.setAttribute('rel',rel);link.setAttribute('href',href);link.setAttribute('charset','ISO-8859-1');link.setAttribute('type','text/css');var head=doc.getElementsByTagName('head')[0];head.appendChild(link);}},include:function(src){document.write('');},dispose:function(){for(var i=0;i0){if(mxBasePath.substring(mxBasePath.length-1)=='/'){mxBasePath=mxBasePath.substring(0,mxBasePath.length-1);}mxClient.basePath=mxBasePath;}else{mxClient.basePath='.';}if(typeof(mxImageBasePath)!='undefined'&&mxImageBasePath.length>0){if(mxImageBasePath.substring(mxImageBasePath.length-1)=='/'){mxImageBasePath=mxImageBasePath.substring(0,mxImageBasePath.length-1);}mxClient.imageBasePath=mxImageBasePath;}else{mxClient.imageBasePath=mxClient.basePath+'/images';}if(typeof(mxLanguage)!='undefined'){mxClient.language=mxLanguage;}else{mxClient.language=(mxClient.IS_IE)?navigator.userLanguage:navigator.language;var dash=mxClient.language.indexOf('-');if(dash>0){mxClient.language=mxClient.language.substring(0,dash);}}if(typeof(mxDefaultLanguage)!='undefined'){mxClient.defaultLanguage=mxDefaultLanguage;}else{mxClient.defaultLanguage='en';}if(mxLoadStylesheets){mxClient.link('stylesheet',mxClient.basePath+'/css/common.css');}if(typeof(mxLanguages)!='undefined'){mxClient.languages=mxLanguages;}if(mxClient.IS_IE){if(document.documentMode>=9){mxClient.IS_VML=false;mxClient.IS_SVG=true;}else{if(document.documentMode==8){document.namespaces.add('v','urn:schemas-microsoft-com:vml','#default#VML');document.namespaces.add('o','urn:schemas-microsoft-com:office:office','#default#VML');}else{document.namespaces.add('v','urn:schemas-microsoft-com:vml');document.namespaces.add('o','urn:schemas-microsoft-com:office:office');}var ss=document.createStyleSheet();ss.cssText='v\\:*{behavior:url(#default#VML)}o\\:*{behavior:url(#default#VML)}';if(mxLoadStylesheets){mxClient.link('stylesheet',mxClient.basePath+'/css/explorer.css');}}window.attachEvent('onunload',mxClient.dispose);}var mxLog={consoleName:'Console',TRACE:false,DEBUG:true,WARN:true,buffer:'',init:function(){if(mxLog.window==null&&document.body!=null){var title=mxLog.consoleName+' - mxGraph '+mxClient.VERSION;var table=document.createElement('table');table.setAttribute('width','100%');table.setAttribute('height','100%');var tbody=document.createElement('tbody');var tr=document.createElement('tr');var td=document.createElement('td');td.style.verticalAlign='top';mxLog.textarea=document.createElement('textarea');mxLog.textarea.setAttribute('readOnly','true');mxLog.textarea.style.height='100%';mxLog.textarea.style.resize='none';mxLog.textarea.value=mxLog.buffer;if(mxClient.IS_NS&&document.compatMode!='BackCompat'){mxLog.textarea.style.width='99%';}else{mxLog.textarea.style.width='100%';}td.appendChild(mxLog.textarea);tr.appendChild(td);tbody.appendChild(tr);tr=document.createElement('tr');mxLog.td=document.createElement('td');mxLog.td.style.verticalAlign='top';mxLog.td.setAttribute('height','30px');tr.appendChild(mxLog.td);tbody.appendChild(tr);table.appendChild(tbody);mxLog.addButton('Info',function(evt){mxLog.info();});mxLog.addButton('DOM',function(evt){var content=mxUtils.getInnerHtml(document.body);mxLog.debug(content);});mxLog.addButton('Trace',function(evt){mxLog.TRACE=!mxLog.TRACE;if(mxLog.TRACE){mxLog.debug('Tracing enabled');}else{mxLog.debug('Tracing disabled');}});mxLog.addButton('Copy',function(evt){try{mxUtils.copy(mxLog.textarea.value);}catch(err){mxUtils.alert(err);}});mxLog.addButton('Show',function(evt){try{mxUtils.popup(mxLog.textarea.value);}catch(err){mxUtils.alert(err);}});mxLog.addButton('Clear',function(evt){mxLog.textarea.value='';});var h=(document.body.clientHeight||document.documentElement.clientHeight);var w=document.body.clientWidth;mxLog.window=new mxWindow(title,table,Math.max(0,w-320),Math.max(0,h-210),300,160);mxLog.window.setMaximizable(true);mxLog.window.setScrollable(false);mxLog.window.setResizable(true);mxLog.window.setClosable(true);mxLog.window.destroyOnClose=false;if((mxClient.IS_NS||mxClient.IS_IE)&&!mxClient.IS_GC&&!mxClient.IS_SF&&document.compatMode!='BackCompat'){var elt=mxLog.window.getElement();var resizeHandler=function(sender,evt){mxLog.textarea.style.height=Math.max(0,elt.offsetHeight-70)+'px';};mxLog.window.addListener(mxEvent.RESIZE_END,resizeHandler);mxLog.window.addListener(mxEvent.MAXIMIZE,resizeHandler);mxLog.window.addListener(mxEvent.NORMALIZE,resizeHandler);mxLog.textarea.style.height='92px';}}},info:function(){mxLog.writeln(mxUtils.toString(navigator));},addButton:function(lab,funct){var button=document.createElement('button');mxUtils.write(button,lab);mxEvent.addListener(button,'click',funct);mxLog.td.appendChild(button);},isVisible:function(){if(mxLog.window!=null){return mxLog.window.isVisible();}return false;},show:function(){mxLog.setVisible(true);},setVisible:function(visible){if(mxLog.window==null){mxLog.init();}if(mxLog.window!=null){mxLog.window.setVisible(visible);}},enter:function(string){if(mxLog.TRACE){mxLog.writeln('Entering '+string);return new Date().getTime();}},leave:function(string,t0){if(mxLog.TRACE){var dt=(t0!=0)?' ('+(new Date().getTime()-t0)+' ms)':'';mxLog.writeln('Leaving '+string+dt);}},debug:function(){if(mxLog.DEBUG){mxLog.writeln.apply(this,arguments);}},warn:function(){if(mxLog.WARN){mxLog.writeln.apply(this,arguments);}},write:function(){var string='';for(var i=0;i=0){mxLog.textarea.style.visibility='hidden';mxLog.textarea.style.visibility='visible';}mxLog.textarea.scrollTop=mxLog.textarea.scrollHeight;}else{mxLog.buffer+=string;}},writeln:function(){var string='';for(var i=0;i=0;}return true;},getDefaultBundle:function(basename,lan){if(mxResources.loadDefaultBundle||!mxResources.isLanguageSupported(lan)){return basename+'.properties';}else{return null;}},getSpecialBundle:function(basename,lan){if(mxResources.loadSpecialBundle&&lan!=mxClient.defaultLanguage){return basename+'_'+lan+'.properties';}else{return null;}},add:function(basename,lan){lan=(lan!=null)?lan:mxClient.language;if(lan!=mxConstants.NONE){var defaultBundle=mxResources.getDefaultBundle(basename,lan);if(defaultBundle!=null){try{var req=mxUtils.load(defaultBundle);if(req.isReady()){mxResources.parse(req.getText());}}catch(e){}}if(mxResources.isLanguageSupported(lan)){var specialBundle=mxResources.getSpecialBundle(basename,lan);if(specialBundle!=null){try{var req=mxUtils.load(specialBundle);if(req.isReady()){mxResources.parse(req.getText());}}catch(e){}}}}},parse:function(text){if(text!=null){var lines=text.split('\n');for(var i=0;i0){var key=lines[i].substring(0,index);var idx=lines[i].length;if(lines[i].charCodeAt(idx-1)==13){idx--;}var value=lines[i].substring(index+1,idx);mxResources.resources[key]=unescape(value);}}}},get:function(key,params,defaultValue){var value=mxResources.resources[key];if(value==null){value=defaultValue;}if(value!=null&¶ms!=null){var result=[];var index=null;for(var i=0;i=0&&index0){window.setTimeout(f, delay);}else{node.style.visibility='hidden';if(remove&&node.parentNode){node.parentNode.removeChild(node);}}};window.setTimeout(f, delay);}else{node.style.visibility='hidden';if(remove&&node.parentNode){node.parentNode.removeChild(node);}}}};var mxUtils={errorResource:(mxClient.language!='none')?'error':'',closeResource:(mxClient.language!='none')?'close':'',errorImage:mxClient.imageBasePath+'/error.gif',removeCursors:function(element){if(element.style!=null){element.style.cursor='';}var children=element.childNodes;if(children!=null){var childCount=children.length;for(var i=0;i0||c.scrollTop>0)){var dummy=document.createElement('div');dummy.style.position='absolute';dummy.style.left=pt.x+'px';dummy.style.top=pt.y+'px';dummy.style.width='1px';dummy.style.height='1px';c.appendChild(dummy);c.removeChild(dummy);}}},getCurrentStyle:function(){if(mxClient.IS_IE){return function(element){return(element!=null)?element.currentStyle:null;};}else{return function(element){return(element!=null)?window.getComputedStyle(element,''):null;};}}(),hasScrollbars:function(node){var style=mxUtils.getCurrentStyle(node);return style!=null&&(style.overflow=='scroll'||style.overflow=='auto');},bind:function(scope,funct){return function(){return funct.apply(scope,arguments);};},eval:function(expr){var result=null;if(expr.indexOf('function')>=0){try{eval('var _mxJavaScriptExpression='+expr);result=_mxJavaScriptExpression;_mxJavaScriptExpression=null;}catch(e){mxLog.warn(e.message+' while evaluating '+expr);}}else{try{result=eval(expr);}catch(e){mxLog.warn(e.message+' while evaluating '+expr);}}return result;},findNode:function(node,attr,value){var tmp=node.getAttribute(attr);if(tmp!=null&&tmp==value){return node;}node=node.firstChild;while(node!=null){var result=mxUtils.findNode(node,attr,value);if(result!=null){return result;}node=node.nextSibling;}return null;},findNodeByAttribute:function(){if(document.documentMode>=9){return function(node,attr,value){var result=null;if(node.nodeType==mxConstants.NODETYPE_ELEMENT&&node.getAttribute(attr)==value){result=node;}else{var child=node.firstChild;while(child!=null&&result==null){result=mxUtils.findNodeByAttribute(child,attr,value);child=child.nextSibling;}}return result;};}else if(mxClient.IS_IE){return function(node,attr,value){var expr='//*[@'+attr+'=\''+value+'\']';return node.ownerDocument.selectSingleNode(expr);};}else{return function(node,attr,value){var result=node.ownerDocument.evaluate('//*[@'+attr+'=\''+value+'\']',node.ownerDocument,null,XPathResult.ANY_TYPE,null);return result.iterateNext();};}}(),getFunctionName:function(f){var str=null;if(f!=null){if(f.name!=null){str=f.name;}else{var tmp=f.toString();var idx1=9;while(tmp.charAt(idx1)==' '){idx1++;}var idx2=tmp.indexOf('(',idx1);str=tmp.substring(idx1,idx2);}}return str;},indexOf:function(array,obj){if(array!=null&&obj!=null){for(var i=0;i=0){array.splice(index,1);result=obj;index=mxUtils.indexOf(array,obj);}}for(var key in array){if(array[key]==obj){delete array[key];result=obj;}}return result;},isNode:function(value,nodeName,attributeName,attributeValue){if(value!=null&&!isNaN(value.nodeType)&&(nodeName==null||value.nodeName.toLowerCase()==nodeName.toLowerCase())){return attributeName==null||value.getAttribute(attributeName)==attributeValue;}return false;},getChildNodes:function(node,nodeType){nodeType=nodeType||mxConstants.NODETYPE_ELEMENT;var children=[];var tmp=node.firstChild;while(tmp!=null){if(tmp.nodeType==nodeType){children.push(tmp);}tmp=tmp.nextSibling;}return children;},createXmlDocument:function(){var doc=null;if(document.implementation&&document.implementation.createDocument){doc=document.implementation.createDocument('','',null);}else if(window.ActiveXObject){doc=new ActiveXObject('Microsoft.XMLDOM');}return doc;},parseXml:function(){if(mxClient.IS_IE&&(typeof(document.documentMode)==='undefined'||document.documentMode<9)){return function(xml){var result=mxUtils.createXmlDocument();result.async='false';result.loadXML(xml);return result;};}else{return function(xml){var parser=new DOMParser();return parser.parseFromString(xml,'text/xml');};}}(),clearSelection:function(){if(document.selection){return function(){document.selection.empty();};}else if(window.getSelection){return function(){window.getSelection().removeAllRanges();};}}(),getPrettyXml:function(node,tab,indent){var result=[];if(node!=null){tab=tab||' ';indent=indent||'';if(node.nodeType==mxConstants.NODETYPE_TEXT){result.push(node.nodeValue);}else{result.push(indent+'<'+node.nodeName);var attrs=node.attributes;if(attrs!=null){for(var i=0;i\n');while(tmp!=null){result.push(mxUtils.getPrettyXml(tmp,tab,indent+tab));tmp=tmp.nextSibling;}result.push(indent+'\n');}else{result.push('/>\n');}}}return result.join('');},removeWhitespace:function(node,before){var tmp=(before)?node.previousSibling:node.nextSibling;while(tmp!=null&&tmp.nodeType==mxConstants.NODETYPE_TEXT){var next=(before)?tmp.previousSibling:tmp.nextSibling;var text=mxUtils.getTextContent(tmp);if(mxUtils.trim(text).length==0){tmp.parentNode.removeChild(tmp);}tmp=next;}},htmlEntities:function(s,newline){s=s||'';s=s.replace(/&/g,'&');s=s.replace(/"/g,'"');s=s.replace(/\'/g,''');s=s.replace(//g,'>');if(newline==null||newline){s=s.replace(/\n/g,' ');}return s;},isVml:function(node){return node!=null&&node.tagUrn=='urn:schemas-microsoft-com:vml';},getXml:function(node,linefeed){var xml='';if(node!=null){xml=node.xml;if(xml==null){if(node.innerHTML){xml=node.innerHTML;}else{var xmlSerializer=new XMLSerializer();xml=xmlSerializer.serializeToString(node);}}else{xml=xml.replace(/\r\n\t[\t]*/g,'').replace(/>\r\n/g,'>').replace(/\r\n/g,'\n');}}linefeed=linefeed||' ';xml=xml.replace(/\n/g,linefeed);return xml;},getTextContent:function(node){var result='';if(node!=null){if(node.firstChild!=null){node=node.firstChild;}result=node.nodeValue||'';}return result;},getInnerHtml:function(){if(mxClient.IS_IE){return function(node){if(node!=null){return node.innerHTML;}return '';};}else{return function(node){if(node!=null){var serializer=new XMLSerializer();return serializer.serializeToString(node);}return '';};}}(),getOuterHtml:function(){if(mxClient.IS_IE){return function(node){if(node!=null){if(node.outerHTML!=null){return node.outerHTML;}else{var tmp=[];tmp.push('<'+node.nodeName);var attrs=node.attributes;if(attrs!=null){for(var i=0;i0){tmp.push(' ');tmp.push(attrs[i].nodeName);tmp.push('="');tmp.push(value);tmp.push('"');}}}if(node.innerHTML.length==0){tmp.push('/>');}else{tmp.push('>');tmp.push(node.innerHTML);tmp.push('');}return tmp.join('');}}return '';};}else{return function(node){if(node!=null){var serializer=new XMLSerializer();return serializer.serializeToString(node);}return '';};}}(),write:function(parent,text){doc=parent.ownerDocument;var node=doc.createTextNode(text);if(parent!=null){parent.appendChild(node);}return node;},writeln:function(parent,text){doc=parent.ownerDocument;var node=doc.createTextNode(text);if(parent!=null){parent.appendChild(node);parent.appendChild(document.createElement('br'));}return node;},br:function(parent,count){count=count||1;var br=null;for(var i=0;iright){node.style.left=Math.max((b.scrollLeft||d.scrollLeft),right-width)+'px';}var top=parseInt(node.offsetTop);var height=parseInt(node.offsetHeight);var bottom=(b.scrollTop||d.scrollTop)+Math.max(b.clientHeight||0,d.clientHeight);if(top+height>bottom){node.style.top=Math.max((b.scrollTop||d.scrollTop),bottom-height)+'px';}},open:function(filename){if(mxClient.IS_NS){try{netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');}catch(e){mxUtils.alert('Permission to read file denied.');return '';}var file=Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);file.initWithPath(filename);if(!file.exists()){mxUtils.alert('File not found.');return '';}var is=Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);is.init(file,0x01,00004,null);var sis=Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream);sis.init(is);var output=sis.read(sis.available());return output;}else{var activeXObject=new ActiveXObject('Scripting.FileSystemObject');var newStream=activeXObject.OpenTextFile(filename,1);var text=newStream.readAll();newStream.close();return text;}return null;},save:function(filename,content){if(mxClient.IS_NS){try{netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');}catch(e){mxUtils.alert('Permission to write file denied.');return;}var file=Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);file.initWithPath(filename);if(!file.exists()){file.create(0x00,0644);}var outputStream=Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);outputStream.init(file,0x20|0x02,00004,null);outputStream.write(content,content.length);outputStream.flush();outputStream.close();}else{var fso=new ActiveXObject('Scripting.FileSystemObject');var file=fso.CreateTextFile(filename,true);file.Write(content);file.Close();}},saveAs:function(content){var iframe=document.createElement('iframe');iframe.setAttribute('src','');iframe.style.visibility='hidden';document.body.appendChild(iframe);try{if(mxClient.IS_NS){var doc=iframe.contentDocument;doc.open();doc.write(content);doc.close();try{netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');iframe.focus();saveDocument(doc);}catch(e){mxUtils.alert('Permission to save document denied.');}}else{var doc=iframe.contentWindow.document;doc.write(content);doc.execCommand('SaveAs',false,document.location);}}finally{document.body.removeChild(iframe);}},copy:function(content){if(window.clipboardData){window.clipboardData.setData('Text',content);}else{netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');var clip=Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);if(!clip){return;}var trans=Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);if(!trans){return;}trans.addDataFlavor('text/unicode');var str=Components.classes['@mozilla.org/supports-string;1'].createInstance(Components.interfaces.nsISupportsString);var copytext=content;str.data=copytext;trans.setTransferData('text/unicode',str,copytext.length*2);var clipid=Components.interfaces.nsIClipboard;clip.setData(trans,null,clipid.kGlobalClipboard);}},load:function(url){var req=new mxXmlRequest(url,null,'GET',false);req.send();return req;},get:function(url,onload,onerror){return new mxXmlRequest(url,null,'GET').send(onload,onerror);},post:function(url,params,onload,onerror){return new mxXmlRequest(url,params).send(onload,onerror);},submit:function(url,params,doc,target){return new mxXmlRequest(url,params).simulate(doc,target);},loadInto:function(url,doc,onload){if(mxClient.IS_IE){doc.onreadystatechange=function(){if(doc.readyState==4){onload();}};}else{doc.addEventListener('load',onload,false);}doc.load(url);},getValue:function(array,key,defaultValue){var value=(array!=null)?array[key]:null;if(value==null){value=defaultValue;}return value;},getNumber:function(array,key,defaultValue){var value=(array!=null)?array[key]:null;if(value==null){value=defaultValue||0;}return Number(value);},getColor:function(array,key,defaultValue){var value=(array!=null)?array[key]:null;if(value==null){value=defaultValue;}else if(value==mxConstants.NONE){value=null;}return value;},clone:function(obj,transients,shallow){shallow=(shallow!=null)?shallow:false;var clone=null;if(obj!=null&&typeof(obj.constructor)=='function'){clone=new obj.constructor();for(var i in obj){if(i!=mxObjectIdentity.FIELD_NAME&&(transients==null||mxUtils.indexOf(transients,i)<0)){if(!shallow&&typeof(obj[i])=='object'){clone[i]=mxUtils.clone(obj[i]);}else{clone[i]=obj[i];}}}}return clone;},equalPoints:function(a,b){if((a==null&&b!=null)||(a!=null&&b==null)||(a!=null&&b!=null&&a.length!=b.length)){return false;}else if(a!=null&&b!=null){for(var i=0;i [Function]\n';}else if(typeof(obj[i])=='object'){var ctor=mxUtils.getFunctionName(obj[i].constructor);output+=i+' => ['+ctor+']\n';}else{output+=i+' = '+obj[i]+'\n';}}catch(e){output+=i+'='+e.message;}}return output;},toRadians:function(deg){return Math.PI*deg/180;},arcToCurves:function(x0,y0,r1,r2,angle,largeArcFlag,sweepFlag,x,y){x-=x0;y-=y0;if(r1===0||r2===0){return result;}var fS=sweepFlag;var psai=angle;r1=Math.abs(r1);r2=Math.abs(r2);var ctx=-x/2;var cty=-y/2;var cpsi=Math.cos(psai*Math.PI/180);var spsi=Math.sin(psai*Math.PI/180);var rxd=cpsi*ctx+spsi*cty;var ryd=-1*spsi*ctx+cpsi*cty;var rxdd=rxd*rxd;var rydd=ryd*ryd;var r1x=r1*r1;var r2y=r2*r2;var lamda=rxdd/r1x+rydd/r2y;var sds;if(lamda>1){r1=Math.sqrt(lamda)*r1;r2=Math.sqrt(lamda)*r2;sds=0;}else{var seif=1;if(largeArcFlag===fS){seif=-1;}sds=seif*Math.sqrt((r1x*r2y-r1x*rydd-r2y*rxdd)/(r1x*rydd+r2y*rxdd));}var txd=sds*r1*ryd/r2;var tyd=-1*sds*r2*rxd/r1;var tx=cpsi*txd-spsi*tyd+x/2;var ty=spsi*txd+cpsi*tyd+y/2;var rad=Math.atan2((ryd-tyd)/r2,(rxd-txd)/r1)-Math.atan2(0,1);var s1=(rad>=0)?rad:2*Math.PI+rad;rad=Math.atan2((-ryd-tyd)/r2,(-rxd-txd)/r1)-Math.atan2((ryd-tyd)/r2,(rxd-txd)/r1);var dr=(rad>=0)?rad:2*Math.PI+rad;if(fS==0&&dr>0){dr-=2*Math.PI;}else if(fS!=0&&dr<0){dr+=2*Math.PI;}var sse=dr*2/Math.PI;var seg=Math.ceil(sse<0?-1*sse:sse);var segr=dr/seg;var t=8/3*Math.sin(segr/4)*Math.sin(segr/4)/Math.sin(segr/2);var cpsir1=cpsi*r1;var cpsir2=cpsi*r2;var spsir1=spsi*r1;var spsir2=spsi*r2;var mc=Math.cos(s1);var ms=Math.sin(s1);var x2=-t*(cpsir1*ms+spsir2*mc);var y2=-t*(spsir1*ms-cpsir2*mc);var x3=0;var y3=0;var result=[];for(var n=0;n=0){returnValue|=mxConstants.DIRECTION_MASK_NORTH;}if(directions.indexOf(mxConstants.DIRECTION_WEST)>=0){returnValue|=mxConstants.DIRECTION_MASK_WEST;}if(directions.indexOf(mxConstants.DIRECTION_SOUTH)>=0){returnValue|=mxConstants.DIRECTION_MASK_SOUTH;}if(directions.indexOf(mxConstants.DIRECTION_EAST)>=0){returnValue|=mxConstants.DIRECTION_MASK_EAST;}return returnValue;}},reversePortConstraints:function(constraint){var result=0;result=(constraint&mxConstants.DIRECTION_MASK_WEST)<<3;result|=(constraint&mxConstants.DIRECTION_MASK_NORTH)<<1;result|=(constraint&mxConstants.DIRECTION_MASK_SOUTH)>>1;result|=(constraint&mxConstants.DIRECTION_MASK_EAST)>>3;return result;},findNearestSegment:function(state,x,y){var index=-1;if(state.absolutePoints.length>0){var last=state.absolutePoints[0];var min=null;for(var i=1;ip2.x){minX=p2.x;maxX=p1.x;}if(maxX>right){maxX=right;}if(minXmaxX) {return false;}var minY=p1.y;var maxY=p2.y;var dx=p2.x-p1.x;if(Math.abs(dx)>0.0000001){var a=(p2.y-p1.y)/dx;var b=p1.y-a*p1.x;minY=a*minX+b;maxY=a*maxX+b;}if(minY>maxY){var tmp=maxY;maxY=minY;minY=tmp;}if(maxY>bottom){maxY=bottom;}if(minYmaxY) {return false;}return true;},contains:function(bounds,x,y){return(bounds.x<=x&&bounds.x+bounds.width>=x&&bounds.y<=y&&bounds.y+bounds.height>=y);},intersects:function(a,b){var tw=a.width;var th=a.height;var rw=b.width;var rh=b.height;if(rw<=0||rh<=0||tw<=0||th<=0){return false;}var tx=a.x;var ty=a.y;var rx=b.x;var ry=b.y;rw+=rx;rh+=ry;tw+=tx;th+=ty;return((rwtx)&&(rhty)&&(twrx)&&(thry));},intersectsHotspot:function(state,x,y,hotspot,min,max){hotspot=(hotspot!=null)?hotspot:1;min=(min!=null)?min:0;max=(max!=null)?max:0;if(hotspot>0){var cx=state.getCenterX();var cy=state.getCenterY();var w=state.width;var h=state.height;var start=mxUtils.getValue(state.style,mxConstants.STYLE_STARTSIZE);if(start>0){if(mxUtils.getValue(state.style,mxConstants.STYLE_HORIZONTAL,true)){cy=state.y+start/2;h=start;}else{cx=state.x+start/2;w=start;}}w=Math.max(min,w*hotspot);h=Math.max(min,h*hotspot);if(max>0){w=Math.min(w,max);h=Math.min(h,max);}var rect=new mxRectangle(cx-w/2,cy-h/2,w,h);return mxUtils.contains(rect,x,y);}return true;},getOffset:function(container){var offsetLeft=0;var offsetTop=0;while(container.offsetParent){offsetLeft+=container.offsetLeft;offsetTop+=container.offsetTop;container=container.offsetParent;}return new mxPoint(offsetLeft,offsetTop);},getScrollOrigin:function(node){var b=document.body;var d=document.documentElement;var sl=(b.scrollLeft||d.scrollLeft);var st=(b.scrollTop||d.scrollTop);var result=new mxPoint(sl,st);while(node!=null&&node!=b&&node!=d){if(!isNaN(node.scrollLeft)&&!isNaN(node.scrollTop)){result.x+=node.scrollLeft;result.y+=node.scrollTop;}node=node.parentNode;}return result;},convertPoint:function(container,x,y){var origin=mxUtils.getScrollOrigin(container);var offset=mxUtils.getOffset(container);offset.x-=origin.x;offset.y-=origin.y;return new mxPoint(x-offset.x,y-offset.y);},ltrim:function(str,chars){chars=chars||"\\s";return str.replace(new RegExp("^["+chars+"]+","g"),"");},rtrim:function(str,chars){chars=chars||"\\s";return str.replace(new RegExp("["+chars+"]+$","g"),"");},trim:function(str,chars){return mxUtils.ltrim(mxUtils.rtrim(str,chars),chars);},isNumeric:function(str){return str!=null&&(str.length==null||(str.length>0&&str.indexOf('0x')<0)&&str.indexOf('0X')<0)&&!isNaN(str);},mod:function(n,m){return((n%m)+m)%m;},intersection:function(x0,y0,x1,y1,x2,y2,x3,y3){var denom=((y3-y2)*(x1-x0))-((x3-x2)*(y1-y0));var nume_a=((x3-x2)*(y0-y2))-((y3-y2)*(x0-x2));var nume_b=((x1-x0)*(y0-y2))-((y1-y0)*(x0-x2));var ua=nume_a/denom;var ub=nume_b/denom;if(ua>=0.0&&ua<=1.0&&ub>=0.0&&ub<=1.0){var intersectionX=x0+ua*(x1-x0);var intersectionY=y0+ua*(y1-y0);return new mxPoint(intersectionX,intersectionY);}return null;},ptSegDistSq:function(x1,y1,x2,y2,px,py){x2-=x1;y2-=y1;px-=x1;py-=y1;var dotprod=px*x2+py*y2;var projlenSq;if(dotprod<=0.0){projlenSq=0.0;}else{px=x2-px;py=y2-py;dotprod=px*x2+py*y2;if(dotprod<=0.0){projlenSq=0.0;}else{projlenSq=dotprod*dotprod/(x2*x2+y2*y2);}}var lenSq=px*px+py*py-projlenSq;if(lenSq<0){lenSq=0;}return lenSq;},relativeCcw:function(x1,y1,x2,y2,px,py){x2-=x1;y2-=y1;px-=x1;py-=y1;var ccw=px*y2-py*x2;if(ccw==0.0){ccw=px*x2+py*y2;if(ccw>0.0){px-=x2;py-=y2;ccw=px*x2+py*y2;if(ccw<0.0){ccw=0.0;}}}return(ccw<0.0)?-1:((ccw>0.0)?1:0);},animateChanges:function(graph,changes){mxEffects.animateChanges.apply(this,arguments);},cascadeOpacity:function(graph,cell,opacity){mxEffects.cascadeOpacity.apply(this,arguments);},fadeOut:function(node,from,remove,step,delay,isEnabled){mxEffects.fadeOut.apply(this,arguments);},setOpacity:function(node,value){if(mxUtils.isVml(node)){if(value>=100){node.style.filter=null;}else{node.style.filter='alpha(opacity='+(value/5)+')';}}else if(mxClient.IS_IE&&(typeof(document.documentMode)==='undefined'||document.documentMode<9)){if(value>=100){node.style.filter=null;}else{node.style.filter='alpha(opacity='+value+')';}}else{node.style.opacity=(value/100);}},createImage:function(src){var imageNode=null;if(mxClient.IS_IE6&&document.compatMode!='CSS1Compat'){imageNode=document.createElement('v:image');imageNode.setAttribute('src',src);imageNode.style.borderStyle='none';}else{imageNode=document.createElement('img');imageNode.setAttribute('src',src);imageNode.setAttribute('border','0');}return imageNode;},sortCells:function(cells,ascending){ascending=(ascending!=null)?ascending:true;var lookup=new mxDictionary();cells.sort(function(o1,o2){var p1=lookup.get(o1);if(p1==null){p1=mxCellPath.create(o1).split(mxCellPath.PATH_SEPARATOR);lookup.put(o1,p1);}var p2=lookup.get(o2);if(p2==null){p2=mxCellPath.create(o2).split(mxCellPath.PATH_SEPARATOR);lookup.put(o2,p2);}var comp=mxCellPath.compare(p1,p2);return(comp==0)?0:(((comp>0)==ascending)?1:-1);});return cells;},getStylename:function(style){if(style!=null){var pairs=style.split(';');var stylename=pairs[0];if(stylename.indexOf('=')<0){return stylename;}}return '';},getStylenames:function(style){var result=[];if(style!=null){var pairs=style.split(';');for(var i=0;i0&&style.charAt(style.length-1)!=';'){style+=';';}style+=stylename;}return style;},removeStylename:function(style,stylename){var result=[];if(style!=null){var tokens=style.split(';');for(var i=0;i=0){result.push(tokens[i]);}}}return result.join(';');},setCellStyles:function(model,cells,key,value){if(cells!=null&&cells.length>0){model.beginUpdate();try{for(var i=0;i0);if(style==null||style.length==0){if(isValue){style=key+'='+value;}}else{var index=style.indexOf(key+'=');if(index<0){if(isValue){var sep=(style.charAt(style.length-1)==';')?'':';';style=style+sep+key+'='+value;}}else{var tmp=(isValue)?(key+'='+value):'';var cont=style.indexOf(';',index);if(!isValue){cont++;}style=style.substring(0,index)+tmp+((cont>index)?style.substring(cont):'');}}return style;},setCellStyleFlags:function(model,cells,key,flag,value){if(cells!=null&&cells.length>0){model.beginUpdate();try{for(var i=0;i=0)?style.substring(cont):'');}}return style;},getSizeForString:function(text,fontSize,fontFamily){var div=document.createElement('div');div.style.fontSize=fontSize||mxConstants.DEFAULT_FONTSIZE;div.style.fontFamily=fontFamily||mxConstants.DEFAULT_FONTFAMILY;div.style.position='absolute';div.style.display='inline';div.style.visibility='hidden';div.innerHTML=text;document.body.appendChild(div);var size=new mxRectangle(0,0,div.offsetWidth,div.offsetHeight);document.body.removeChild(div);return size;},getViewXml:function(graph,scale,cells,x0,y0){x0=(x0!=null)?x0:0;y0=(y0!=null)?y0:0;scale=(scale!=null)?scale:1;if(cells==null){var model=graph.getModel();cells=[model.getRoot()];}var view=graph.getView();var result=null;var eventsEnabled=view.isEventsEnabled();view.setEventsEnabled(false);var drawPane=view.drawPane;var overlayPane=view.overlayPane;if(graph.dialect==mxConstants.DIALECT_SVG){view.drawPane=document.createElementNS(mxConstants.NS_SVG,'g');view.canvas.appendChild(view.drawPane);view.overlayPane=document.createElementNS(mxConstants.NS_SVG,'g');view.canvas.appendChild(view.overlayPane);}else{view.drawPane=view.drawPane.cloneNode(false);view.canvas.appendChild(view.drawPane);view.overlayPane=view.overlayPane.cloneNode(false);view.canvas.appendChild(view.overlayPane);}var translate=view.getTranslate();view.translate=new mxPoint(x0,y0);var temp=new mxTemporaryCellStates(graph.getView(),scale,cells);try{var enc=new mxCodec();result=enc.encode(graph.getView());}finally{temp.destroy();view.translate=translate;view.canvas.removeChild(view.drawPane);view.canvas.removeChild(view.overlayPane);view.drawPane=drawPane;view.overlayPane=overlayPane;view.setEventsEnabled(eventsEnabled);}return result;},getScaleForPageCount:function(pageCount,graph,pageFormat,border){if(pageCount<1){return 1;}pageFormat=(pageFormat!=null)?pageFormat:mxConstants.PAGE_FORMAT_A4_PORTRAIT;border=(border!=null)?border:0;var availablePageWidth=pageFormat.width-(border*2);var availablePageHeight=pageFormat.height-(border*2);var graphBounds=graph.getGraphBounds().clone();var sc=graph.getView().getScale();graphBounds.width/=sc;graphBounds.height/=sc;var graphWidth=graphBounds.width;var graphHeight=graphBounds.height;var scale=1;var pageFormatAspectRatio=availablePageWidth/availablePageHeight;var graphAspectRatio=graphWidth/graphHeight;var pagesAspectRatio=graphAspectRatio/pageFormatAspectRatio;var pageRoot=Math.sqrt(pageCount);var pagesAspectRatioSqrt=Math.sqrt(pagesAspectRatio);var numRowPages=pageRoot*pagesAspectRatioSqrt;var numColumnPages=pageRoot/pagesAspectRatioSqrt;if(numRowPages<1&&numColumnPages>pageCount){var scaleChange=numColumnPages/pageCount;numColumnPages=pageCount;numRowPages/=scaleChange;}if(numColumnPages<1&&numRowPages>pageCount){var scaleChange=numRowPages/pageCount;numRowPages=pageCount;numColumnPages/=scaleChange;}var currentTotalPages=Math.ceil(numRowPages)*Math.ceil(numColumnPages);var numLoops=0;while(currentTotalPages>pageCount){var roundRowDownProportion=Math.floor(numRowPages)/numRowPages;var roundColumnDownProportion=Math.floor(numColumnPages)/numColumnPages;if(roundRowDownProportion==1){roundRowDownProportion=Math.floor(numRowPages-1)/numRowPages;}if(roundColumnDownProportion==1){roundColumnDownProportion=Math.floor(numColumnPages-1)/numColumnPages;}var scaleChange=1;if(roundRowDownProportion>roundColumnDownProportion){scaleChange=roundRowDownProportion;}else{scaleChange=roundColumnDownProportion;}numRowPages=numRowPages*scaleChange;numColumnPages=numColumnPages*scaleChange;currentTotalPages=Math.ceil(numRowPages)*Math.ceil(numColumnPages);numLoops++;if(numLoops>10){break;}}var posterWidth=availablePageWidth*numRowPages;scale=posterWidth/graphWidth;return scale*0.99999;},show:function(graph,doc,x0,y0){x0=(x0!=null)?x0:0;y0=(y0!=null)?y0:0;if(doc==null){var wnd=window.open();doc=wnd.document;}else{doc.open();}var bounds=graph.getGraphBounds();var dx=-bounds.x+x0;var dy=-bounds.y+y0;if(mxClient.IS_IE){var html='';html+='';var base=document.getElementsByTagName('base');for(var i=0;i';for(var i=0;i';html+='';html+='';html+=graph.container.innerHTML;html+='';html+='';doc.writeln(html);doc.close();var node=doc.body.getElementsByTagName('DIV')[0];if(node!=null){node.style.position='absolute';node.style.left=dx+'px';node.style.top=dy+'px';}}else{doc.writeln('');var base=document.getElementsByTagName('base');for(var i=0;i');doc.writeln('');doc.close();if(doc.body==null){doc.documentElement.appendChild(doc.createElement('body'));}doc.body.style.overflow='auto';var node=graph.container.firstChild;while(node!=null){var clone=node.cloneNode(true);doc.body.appendChild(clone);node=node.nextSibling;}var node=doc.getElementsByTagName('g')[0];if(node!=null){node.setAttribute('transform','translate('+dx+','+dy+')');var root=node.ownerSVGElement;root.setAttribute('width',bounds.width+Math.max(bounds.x,0)+3);root.setAttribute('height',bounds.height+Math.max(bounds.y,0)+3);}}mxUtils.removeCursors(doc.body);return doc;},printScreen:function(graph){var wnd=window.open();mxUtils.show(graph,wnd.document);var print=function(){wnd.focus();wnd.print();wnd.close();};if(mxClient.IS_GC){wnd.setTimeout(print, 500);}else{print();}},popup:function(content,isInternalWindow){if(isInternalWindow){var div=document.createElement('div');div.style.overflow='scroll';div.style.width='636px';div.style.height='460px';var pre=document.createElement('pre');pre.innerHTML=mxUtils.htmlEntities(content,false).replace(/\n/g,'
').replace(/ /g,' ');div.appendChild(pre);var w=document.body.clientWidth;var h=(document.body.clientHeight||document.documentElement.clientHeight);var wnd=new mxWindow('Popup Window',div,w/2-320,h/2-240,640,480,false,true);wnd.setClosable(true);wnd.setVisible(true);}else{if(mxClient.IS_NS){var wnd=window.open();wnd.document.writeln('
'+mxUtils.htmlEntities(content)+'').replace(/ /g,' ');wnd.document.body.appendChild(pre);}}},alert:function(message){alert(message);},prompt:function(message,defaultValue){return prompt(message,defaultValue);},confirm:function(message){return confirm(message);},error:function(message,width,close,icon){var div=document.createElement('div');div.style.padding='20px';var img=document.createElement('img');img.setAttribute('src',icon||mxUtils.errorImage);img.setAttribute('valign','bottom');img.style.verticalAlign='middle';div.appendChild(img);div.appendChild(document.createTextNode('\u00a0'));div.appendChild(document.createTextNode('\u00a0'));div.appendChild(document.createTextNode('\u00a0'));mxUtils.write(div,message);var w=document.body.clientWidth;var h=(document.body.clientHeight||document.documentElement.clientHeight);var warn=new mxWindow(mxResources.get(mxUtils.errorResource)||mxUtils.errorResource,div,(w-width)/2,h/4,width,null,false,true);if(close){mxUtils.br(div);var tmp=document.createElement('p');var button=document.createElement('button');if(mxClient.IS_IE){button.style.cssText='float:right';}else{button.setAttribute('style','float:right');}mxEvent.addListener(button,'click',function(evt){warn.destroy();});mxUtils.write(button,mxResources.get(mxUtils.closeResource)||mxUtils.closeResource);tmp.appendChild(button);div.appendChild(tmp);mxUtils.br(div);warn.setClosable(true);}warn.setVisible(true);return warn;},makeDraggable:function(element,graphF,funct,dragElement,dx,dy,autoscroll,scalePreview,highlightDropTargets,getDropTarget){var dragSource=new mxDragSource(element,funct);dragSource.dragOffset=new mxPoint((dx!=null)?dx:0,(dy!=null)?dy:mxConstants.TOOLTIP_VERTICAL_OFFSET);dragSource.autoscroll=autoscroll;dragSource.setGuidesEnabled(false);if(highlightDropTargets!=null){dragSource.highlightDropTargets=highlightDropTargets;}if(getDropTarget!=null){dragSource.getDropTarget=getDropTarget;}dragSource.getGraphForEvent=function(evt){return(typeof(graphF)=='function')?graphF(evt):graphF;};if(dragElement!=null){dragSource.createDragElement=function(){return dragElement.cloneNode(true);};if(scalePreview){dragSource.createPreviewElement=function(graph){var elt=dragElement.cloneNode(true);var w=parseInt(elt.style.width);var h=parseInt(elt.style.height);elt.style.width=Math.round(w*graph.view.scale)+'px';elt.style.height=Math.round(h*graph.view.scale)+'px';return elt;};}}return dragSource;}};var mxConstants={DEFAULT_HOTSPOT:0.3,MIN_HOTSPOT_SIZE:8,MAX_HOTSPOT_SIZE:0,RENDERING_HINT_EXACT:'exact',RENDERING_HINT_FASTER:'faster',RENDERING_HINT_FASTEST:'fastest',DIALECT_SVG:'svg',DIALECT_VML:'vml',DIALECT_MIXEDHTML:'mixedHtml',DIALECT_PREFERHTML:'preferHtml',DIALECT_STRICTHTML:'strictHtml',NS_SVG:'http://www.w3.org/2000/svg',NS_XHTML:'http://www.w3.org/1999/xhtml',NS_XLINK:'http://www.w3.org/1999/xlink',SHADOWCOLOR:'gray',SHADOW_OFFSET_X:2,SHADOW_OFFSET_Y:3,SHADOW_OPACITY:1,NODETYPE_ELEMENT:1,NODETYPE_ATTRIBUTE:2,NODETYPE_TEXT:3,NODETYPE_CDATA:4,NODETYPE_ENTITY_REFERENCE:5,NODETYPE_ENTITY:6,NODETYPE_PROCESSING_INSTRUCTION:7,NODETYPE_COMMENT:8,NODETYPE_DOCUMENT:9,NODETYPE_DOCUMENTTYPE:10,NODETYPE_DOCUMENT_FRAGMENT:11,NODETYPE_NOTATION:12,TOOLTIP_VERTICAL_OFFSET:16,DEFAULT_VALID_COLOR:'#00FF00',DEFAULT_INVALID_COLOR:'#FF0000',HIGHLIGHT_STROKEWIDTH:3,CURSOR_MOVABLE_VERTEX:'move',CURSOR_MOVABLE_EDGE:'move',CURSOR_LABEL_HANDLE:'default',CURSOR_BEND_HANDLE:'pointer',CURSOR_CONNECT:'pointer',HIGHLIGHT_COLOR:'#00FF00',CONNECT_TARGET_COLOR:'#0000FF',INVALID_CONNECT_TARGET_COLOR:'#FF0000',DROP_TARGET_COLOR:'#0000FF',VALID_COLOR:'#00FF00',INVALID_COLOR:'#FF0000',EDGE_SELECTION_COLOR:'#00FF00',VERTEX_SELECTION_COLOR:'#00FF00',VERTEX_SELECTION_STROKEWIDTH:1,EDGE_SELECTION_STROKEWIDTH:1,VERTEX_SELECTION_DASHED:true,EDGE_SELECTION_DASHED:true,GUIDE_COLOR:'#FF0000',GUIDE_STROKEWIDTH:1,OUTLINE_COLOR:'#0099FF',OUTLINE_STROKEWIDTH:(mxClient.IS_IE)?2:3,HANDLE_SIZE:7,LABEL_HANDLE_SIZE:4,HANDLE_FILLCOLOR:'#00FF00',HANDLE_STROKECOLOR:'black',LABEL_HANDLE_FILLCOLOR:'yellow',CONNECT_HANDLE_FILLCOLOR:'#0000FF',LOCKED_HANDLE_FILLCOLOR:'#FF0000',OUTLINE_HANDLE_FILLCOLOR:'#00FFFF',OUTLINE_HANDLE_STROKECOLOR:'#0033FF',DEFAULT_FONTFAMILY:'Arial,Helvetica',DEFAULT_FONTSIZE:11,DEFAULT_STARTSIZE:40,DEFAULT_MARKERSIZE:6,DEFAULT_IMAGESIZE:24,ENTITY_SEGMENT:30,RECTANGLE_ROUNDING_FACTOR:0.15,LINE_ARCSIZE:20,ARROW_SPACING:10,ARROW_WIDTH:30,ARROW_SIZE:30,PAGE_FORMAT_A4_PORTRAIT:new mxRectangle(0,0,826,1169),PAGE_FORMAT_A4_LANDSCAPE:new mxRectangle(0,0,1169,826),PAGE_FORMAT_LETTER_PORTRAIT:new mxRectangle(0,0,850,1100),PAGE_FORMAT_LETTER_LANDSCAPE:new mxRectangle(0,0,1100,850),NONE:'none',STYLE_PERIMETER:'perimeter',STYLE_SOURCE_PORT:'sourcePort',STYLE_TARGET_PORT:'targetPort',STYLE_PORT_CONSTRAINT:'portConstraint',STYLE_OPACITY:'opacity',STYLE_TEXT_OPACITY:'textOpacity',STYLE_OVERFLOW:'overflow',STYLE_ORTHOGONAL:'orthogonal',STYLE_EXIT_X:'exitX',STYLE_EXIT_Y:'exitY',STYLE_EXIT_PERIMETER:'exitPerimeter',STYLE_ENTRY_X:'entryX',STYLE_ENTRY_Y:'entryY',STYLE_ENTRY_PERIMETER:'entryPerimeter',STYLE_WHITE_SPACE:'whiteSpace',STYLE_ROTATION:'rotation',STYLE_FILLCOLOR:'fillColor',STYLE_GRADIENTCOLOR:'gradientColor',STYLE_GRADIENT_DIRECTION:'gradientDirection',STYLE_STROKECOLOR:'strokeColor',STYLE_SEPARATORCOLOR:'separatorColor',STYLE_STROKEWIDTH:'strokeWidth',STYLE_ALIGN:'align',STYLE_VERTICAL_ALIGN:'verticalAlign',STYLE_LABEL_POSITION:'labelPosition',STYLE_VERTICAL_LABEL_POSITION:'verticalLabelPosition',STYLE_IMAGE_ASPECT:'imageAspect',STYLE_IMAGE_ALIGN:'imageAlign',STYLE_IMAGE_VERTICAL_ALIGN:'imageVerticalAlign',STYLE_GLASS:'glass',STYLE_IMAGE:'image',STYLE_IMAGE_WIDTH:'imageWidth',STYLE_IMAGE_HEIGHT:'imageHeight',STYLE_IMAGE_BACKGROUND:'imageBackground',STYLE_IMAGE_BORDER:'imageBorder',STYLE_IMAGE_FLIPH:'imageFlipH',STYLE_IMAGE_FLIPV:'imageFlipV',STYLE_STENCIL_FLIPH:'stencilFlipH',STYLE_STENCIL_FLIPV:'stencilFlipV',STYLE_NOLABEL:'noLabel',STYLE_NOEDGESTYLE:'noEdgeStyle',STYLE_LABEL_BACKGROUNDCOLOR:'labelBackgroundColor',STYLE_LABEL_BORDERCOLOR:'labelBorderColor',STYLE_LABEL_PADDING:'labelPadding',STYLE_INDICATOR_SHAPE:'indicatorShape',STYLE_INDICATOR_IMAGE:'indicatorImage',STYLE_INDICATOR_COLOR:'indicatorColor',STYLE_INDICATOR_STROKECOLOR:'indicatorStrokeColor',STYLE_INDICATOR_GRADIENTCOLOR:'indicatorGradientColor',STYLE_INDICATOR_SPACING:'indicatorSpacing',STYLE_INDICATOR_WIDTH:'indicatorWidth',STYLE_INDICATOR_HEIGHT:'indicatorHeight',STYLE_INDICATOR_DIRECTION:'indicatorDirection',STYLE_SHADOW:'shadow',STYLE_SEGMENT:'segment',STYLE_ENDARROW:'endArrow',STYLE_STARTARROW:'startArrow',STYLE_ENDSIZE:'endSize',STYLE_STARTSIZE:'startSize',STYLE_ENDFILL:'endFill',STYLE_STARTFILL:'startFill',STYLE_DASHED:'dashed',STYLE_DASH_PATTERN:'dashPattern',STYLE_ROUNDED:'rounded',STYLE_ARCSIZE:'arcSize',STYLE_SMOOTH:'smooth',STYLE_SOURCE_PERIMETER_SPACING:'sourcePerimeterSpacing',STYLE_TARGET_PERIMETER_SPACING:'targetPerimeterSpacing',STYLE_PERIMETER_SPACING:'perimeterSpacing',STYLE_SPACING:'spacing',STYLE_SPACING_TOP:'spacingTop',STYLE_SPACING_LEFT:'spacingLeft',STYLE_SPACING_BOTTOM:'spacingBottom',STYLE_SPACING_RIGHT:'spacingRight',STYLE_HORIZONTAL:'horizontal',STYLE_DIRECTION:'direction',STYLE_ELBOW:'elbow',STYLE_FONTCOLOR:'fontColor',STYLE_FONTFAMILY:'fontFamily',STYLE_FONTSIZE:'fontSize',STYLE_FONTSTYLE:'fontStyle',STYLE_AUTOSIZE:'autosize',STYLE_FOLDABLE:'foldable',STYLE_EDITABLE:'editable',STYLE_BENDABLE:'bendable',STYLE_MOVABLE:'movable',STYLE_RESIZABLE:'resizable',STYLE_CLONEABLE:'cloneable',STYLE_DELETABLE:'deletable',STYLE_SHAPE:'shape',STYLE_EDGE:'edgeStyle',STYLE_LOOP:'loopStyle',STYLE_ROUTING_CENTER_X:'routingCenterX',STYLE_ROUTING_CENTER_Y:'routingCenterY',FONT_BOLD:1,FONT_ITALIC:2,FONT_UNDERLINE:4,FONT_SHADOW:8,SHAPE_RECTANGLE:'rectangle',SHAPE_ELLIPSE:'ellipse',SHAPE_DOUBLE_ELLIPSE:'doubleEllipse',SHAPE_RHOMBUS:'rhombus',SHAPE_LINE:'line',SHAPE_IMAGE:'image',SHAPE_ARROW:'arrow',SHAPE_LABEL:'label',SHAPE_CYLINDER:'cylinder',SHAPE_SWIMLANE:'swimlane',SHAPE_CONNECTOR:'connector',SHAPE_ACTOR:'actor',SHAPE_CLOUD:'cloud',SHAPE_TRIANGLE:'triangle',SHAPE_HEXAGON:'hexagon',ARROW_CLASSIC:'classic',ARROW_BLOCK:'block',ARROW_OPEN:'open',ARROW_OVAL:'oval',ARROW_DIAMOND:'diamond',ARROW_DIAMOND_THIN:'diamondThin',ALIGN_LEFT:'left',ALIGN_CENTER:'center',ALIGN_RIGHT:'right',ALIGN_TOP:'top',ALIGN_MIDDLE:'middle',ALIGN_BOTTOM:'bottom',DIRECTION_NORTH:'north',DIRECTION_SOUTH:'south',DIRECTION_EAST:'east',DIRECTION_WEST:'west',DIRECTION_MASK_NONE:0,DIRECTION_MASK_WEST:1,DIRECTION_MASK_NORTH:2,DIRECTION_MASK_SOUTH:4,DIRECTION_MASK_EAST:8,DIRECTION_MASK_ALL:15,ELBOW_VERTICAL:'vertical',ELBOW_HORIZONTAL:'horizontal',EDGESTYLE_ELBOW:'elbowEdgeStyle',EDGESTYLE_ENTITY_RELATION:'entityRelationEdgeStyle',EDGESTYLE_LOOP:'loopEdgeStyle',EDGESTYLE_SIDETOSIDE:'sideToSideEdgeStyle',EDGESTYLE_TOPTOBOTTOM:'topToBottomEdgeStyle',EDGESTYLE_ORTHOGONAL:'orthogonalEdgeStyle',EDGESTYLE_SEGMENT:'segmentEdgeStyle',PERIMETER_ELLIPSE:'ellipsePerimeter',PERIMETER_RECTANGLE:'rectanglePerimeter',PERIMETER_RHOMBUS:'rhombusPerimeter',PERIMETER_TRIANGLE:'trianglePerimeter'};function mxEventObject(name){this.name=name;this.properties=[];for(var i=1;i0){var entry=list[0];mxEvent.removeListener(element,entry.name,entry.f);}}},redirectMouseEvents:function(node,graph,state,down,move,up,dblClick){var getState=function(evt){return(typeof(state)=='function')?state(evt):state;};var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(node,md,function(evt){if(down!=null){down(evt);}else if(!mxEvent.isConsumed(evt)){graph.fireMouseEvent(mxEvent.MOUSE_DOWN,new mxMouseEvent(evt,getState(evt)));}});mxEvent.addListener(node,mm,function(evt){if(move!=null){move(evt);}else if(!mxEvent.isConsumed(evt)){graph.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(evt,getState(evt)));}});mxEvent.addListener(node,mu,function(evt){if(up!=null){up(evt);}else if(!mxEvent.isConsumed(evt)){graph.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(evt,getState(evt)));}});mxEvent.addListener(node,'dblclick',function(evt){if(dblClick!=null){dblClick(evt);}else if(!mxEvent.isConsumed(evt)){var tmp=getState(evt);graph.dblClick(evt,(tmp!=null)?tmp.cell:null);}});},release:function(element){if(element!=null){mxEvent.removeAllListeners(element);var children=element.childNodes;if(children!=null){var childCount=children.length;for(var i=0;i0);}};if(mxClient.IS_NS){var eventName=(mxClient.IS_SF||mxClient.IS_GC)?'mousewheel':'DOMMouseScroll';mxEvent.addListener(window,eventName,wheelHandler);}else{mxEvent.addListener(document,'mousewheel',wheelHandler);}}},disableContextMenu:function(){if(mxClient.IS_IE&&(typeof(document.documentMode)==='undefined'||document.documentMode<9)){return function(element){mxEvent.addListener(element,'contextmenu',function(){return false;});};}else{return function(element){element.setAttribute('oncontextmenu','return false;');};}}(),getSource:function(evt){return(evt.srcElement!=null)?evt.srcElement:evt.target;},isConsumed:function(evt){return evt.isConsumed!=null&&evt.isConsumed;},isLeftMouseButton:function(evt){return evt.button==((mxClient.IS_IE&&(typeof(document.documentMode)==='undefined'||document.documentMode<9))?1:0);},isRightMouseButton:function(evt){return evt.button==2;},isPopupTrigger:function(evt){return mxEvent.isRightMouseButton(evt)||(mxEvent.isShiftDown(evt)&&!mxEvent.isControlDown(evt));},isShiftDown:function(evt){return(evt!=null)?evt.shiftKey:false;},isAltDown:function(evt){return(evt!=null)?evt.altKey:false;},isControlDown:function(evt){return(evt!=null)?evt.ctrlKey:false;},isMetaDown:function(evt){return(evt!=null)?evt.metaKey:false;},getMainEvent:function(e){if((e.type=='touchstart'||e.type=='touchmove')&&e.touches!=null&&e.touches[0]!=null){e=e.touches[0];}else if(e.type=='touchend'&&e.changedTouches!=null&&e.changedTouches[0]!=null){e=e.changedTouches[0];}return e;},getClientX:function(e){return mxEvent.getMainEvent(e).clientX;},getClientY:function(e){return mxEvent.getMainEvent(e).clientY;},consume:function(evt,preventDefault,stopPropagation){preventDefault=(preventDefault!=null)?preventDefault:true;stopPropagation=(stopPropagation!=null)?stopPropagation:true;if(preventDefault){if(evt.preventDefault){if(stopPropagation){evt.stopPropagation();}evt.preventDefault();}else if(stopPropagation){evt.cancelBubble=true;}}evt.isConsumed=true;evt.returnValue=false;},LABEL_HANDLE:-1,MOUSE_DOWN:'mouseDown',MOUSE_MOVE:'mouseMove',MOUSE_UP:'mouseUp',ACTIVATE:'activate',RESIZE_START:'resizeStart',RESIZE:'resize',RESIZE_END:'resizeEnd',MOVE_START:'moveStart',MOVE:'move',MOVE_END:'moveEnd',PAN_START:'panStart',PAN:'pan',PAN_END:'panEnd',MINIMIZE:'minimize',NORMALIZE:'normalize',MAXIMIZE:'maximize',HIDE:'hide',SHOW:'show',CLOSE:'close',DESTROY:'destroy',REFRESH:'refresh',SIZE:'size',SELECT:'select',FIRED:'fired',GET:'get',RECEIVE:'receive',CONNECT:'connect',DISCONNECT:'disconnect',SUSPEND:'suspend',RESUME:'resume',MARK:'mark',SESSION:'session',ROOT:'root',POST:'post',OPEN:'open',SAVE:'save',BEFORE_ADD_VERTEX:'beforeAddVertex',ADD_VERTEX:'addVertex',AFTER_ADD_VERTEX:'afterAddVertex',DONE:'done',EXECUTE:'execute',BEGIN_UPDATE:'beginUpdate',END_UPDATE:'endUpdate',BEFORE_UNDO:'beforeUndo',UNDO:'undo',REDO:'redo',CHANGE:'change',NOTIFY:'notify',LAYOUT_CELLS:'layoutCells',CLICK:'click',SCALE:'scale',TRANSLATE:'translate',SCALE_AND_TRANSLATE:'scaleAndTranslate',UP:'up',DOWN:'down',ADD:'add',CLEAR:'clear',ADD_CELLS:'addCells',CELLS_ADDED:'cellsAdded',MOVE_CELLS:'moveCells',CELLS_MOVED:'cellsMoved',RESIZE_CELLS:'resizeCells',CELLS_RESIZED:'cellsResized',TOGGLE_CELLS:'toggleCells',CELLS_TOGGLED:'cellsToggled',ORDER_CELLS:'orderCells',CELLS_ORDERED:'cellsOrdered',REMOVE_CELLS:'removeCells',CELLS_REMOVED:'cellsRemoved',GROUP_CELLS:'groupCells',UNGROUP_CELLS:'ungroupCells',REMOVE_CELLS_FROM_PARENT:'removeCellsFromParent',FOLD_CELLS:'foldCells',CELLS_FOLDED:'cellsFolded',ALIGN_CELLS:'alignCells',LABEL_CHANGED:'labelChanged',CONNECT_CELL:'connectCell',CELL_CONNECTED:'cellConnected',SPLIT_EDGE:'splitEdge',FLIP_EDGE:'flipEdge',START_EDITING:'startEditing',ADD_OVERLAY:'addOverlay',REMOVE_OVERLAY:'removeOverlay',UPDATE_CELL_SIZE:'updateCellSize',ESCAPE:'escape',CLICK:'click',DOUBLE_CLICK:'doubleClick'};function mxXmlRequest(url,params,method,async,username,password){this.url=url;this.params=params;this.method=method||'POST';this.async=(async!=null)?async:true;this.username=username;this.password=password;};mxXmlRequest.prototype.url=null;mxXmlRequest.prototype.params=null;mxXmlRequest.prototype.method=null;mxXmlRequest.prototype.async=null;mxXmlRequest.prototype.binary=false;mxXmlRequest.prototype.username=null;mxXmlRequest.prototype.password=null;mxXmlRequest.prototype.request=null;mxXmlRequest.prototype.isBinary=function(){return this.binary;};mxXmlRequest.prototype.setBinary=function(value){this.binary=value;};mxXmlRequest.prototype.getText=function(){return this.request.responseText;};mxXmlRequest.prototype.isReady=function(){return this.request.readyState==4;};mxXmlRequest.prototype.getDocumentElement=function(){var doc=this.getXml();if(doc!=null){return doc.documentElement;}return null;};mxXmlRequest.prototype.getXml=function(){var xml=this.request.responseXML;if(document.documentMode>=9||xml==null||xml.documentElement==null){xml=mxUtils.parseXml(this.request.responseText);}return xml;};mxXmlRequest.prototype.getText=function(){return this.request.responseText;};mxXmlRequest.prototype.getStatus=function(){return this.request.status;};mxXmlRequest.prototype.create=function(){if(window.XMLHttpRequest){return function(){var req=new XMLHttpRequest();if(this.isBinary()&&req.overrideMimeType){req.overrideMimeType('text/plain; charset=x-user-defined');}return req;};}else if(typeof(ActiveXObject)!="undefined"){return function(){return new ActiveXObject("Microsoft.XMLHTTP");};}}();mxXmlRequest.prototype.send=function(onload,onerror){this.request=this.create();if(this.request!=null){if(onload!=null){this.request.onreadystatechange=mxUtils.bind(this,function(){if(this.isReady()){onload(this);this.onreadystatechaange=null;}});}this.request.open(this.method,this.url,this.async,this.username,this.password);this.setRequestHeaders(this.request,this.params);this.request.send(this.params);}};mxXmlRequest.prototype.setRequestHeaders=function(request,params){if(params!=null){request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');}};mxXmlRequest.prototype.simulate=function(doc,target){doc=doc||document;var old=null;if(doc==document){old=window.onbeforeunload;window.onbeforeunload=null;}var form=doc.createElement('form');form.setAttribute('method',this.method);form.setAttribute('action',this.url);if(target!=null){form.setAttribute('target',target);}form.style.display='none';form.style.visibility='hidden';var pars=(this.params.indexOf('&')>0)?this.params.split('&'):this.params.split();for(var i=0;i0){var name=pars[i].substring(0,pos);var value=pars[i].substring(pos+1);var textarea=doc.createElement('textarea');textarea.setAttribute('name',name);value=value.replace(/\n/g,'
');var content=doc.createTextNode(value);textarea.appendChild(content);form.appendChild(textarea);}}doc.body.appendChild(form);form.submit();doc.body.removeChild(form);if(old!=null){window.onbeforeunload=old;}};var mxClipboard={STEPSIZE:10,insertCount:1,cells:null,isEmpty:function(){return mxClipboard.cells==null;},cut:function(graph,cells){cells=mxClipboard.copy(graph,cells);mxClipboard.insertCount=0;mxClipboard.removeCells(graph,cells);return cells;},removeCells:function(graph,cells){graph.removeCells(cells);},copy:function(graph,cells){cells=cells||graph.getSelectionCells();var result=graph.getExportableCells(cells);mxClipboard.insertCount=1;mxClipboard.cells=graph.cloneCells(result);return result;},paste:function(graph){if(mxClipboard.cells!=null){var cells=graph.getImportableCells(mxClipboard.cells);var delta=mxClipboard.insertCount*mxClipboard.STEPSIZE;var parent=graph.getDefaultParent();cells=graph.importCells(cells,delta,delta,parent);mxClipboard.insertCount++;graph.setSelectionCells(cells);}}};function mxWindow(title,content,x,y,width,height,minimizable,movable,replaceNode,style){if(content!=null){minimizable=(minimizable!=null)?minimizable:true;this.content=content;this.init(x,y,width,height,style);this.installMaximizeHandler();this.installMinimizeHandler();this.installCloseHandler();this.setMinimizable(minimizable);this.setTitle(title);if(movable==null||movable){this.installMoveHandler();}if(replaceNode!=null&&replaceNode.parentNode!=null){replaceNode.parentNode.replaceChild(this.div,replaceNode);}else{document.body.appendChild(this.div);}}};mxWindow.prototype=new mxEventSource();mxWindow.prototype.constructor=mxWindow;mxWindow.prototype.closeImage=mxClient.imageBasePath+'/close.gif';mxWindow.prototype.minimizeImage=mxClient.imageBasePath+'/minimize.gif';mxWindow.prototype.normalizeImage=mxClient.imageBasePath+'/normalize.gif';mxWindow.prototype.maximizeImage=mxClient.imageBasePath+'/maximize.gif';mxWindow.prototype.resizeImage=mxClient.imageBasePath+'/resize.gif';mxWindow.prototype.visible=false;mxWindow.prototype.content=false;mxWindow.prototype.minimumSize=new mxRectangle(0,0,50,40);mxWindow.prototype.title=false;mxWindow.prototype.content=false;mxWindow.prototype.destroyOnClose=true;mxWindow.prototype.init=function(x,y,width,height,style){style=(style!=null)?style:'mxWindow';this.div=document.createElement('div');this.div.className=style;this.div.style.left=x+'px';this.div.style.top=y+'px';this.table=document.createElement('table');this.table.className=style;if(width!=null){if(!mxClient.IS_IE){this.div.style.width=width+'px';}this.table.style.width=width+'px';}if(height!=null){if(!mxClient.IS_IE){this.div.style.height=height+'px';}this.table.style.height=height+'px';}var tbody=document.createElement('tbody');var tr=document.createElement('tr');this.title=document.createElement('td');this.title.className=style+'Title';tr.appendChild(this.title);tbody.appendChild(tr);tr=document.createElement('tr');this.td=document.createElement('td');this.td.className=style+'Pane';this.contentWrapper=document.createElement('div');this.contentWrapper.className=style+'Pane';this.contentWrapper.style.width='100%';this.contentWrapper.appendChild(this.content);if(mxClient.IS_IE||this.content.nodeName.toUpperCase()!='DIV'){this.contentWrapper.style.height='100%';}this.td.appendChild(this.contentWrapper);tr.appendChild(this.td);tbody.appendChild(tr);this.table.appendChild(tbody);this.div.appendChild(this.table);var activator=mxUtils.bind(this,function(evt){this.activate();});var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';mxEvent.addListener(this.title,md,activator);mxEvent.addListener(this.table,md,activator);this.hide();};mxWindow.prototype.setTitle=function(title){var child=this.title.firstChild;while(child!=null){var next=child.nextSibling;if(child.nodeType==mxConstants.NODETYPE_TEXT){child.parentNode.removeChild(child);}child=next;}mxUtils.write(this.title,title||'');};mxWindow.prototype.setScrollable=function(scrollable){if(navigator.userAgent.indexOf('Presto/2.5')<0){if(scrollable){this.contentWrapper.style.overflow='auto';}else{this.contentWrapper.style.overflow='hidden';}}};mxWindow.prototype.activate=function(){if(mxWindow.activeWindow!=this){var style=mxUtils.getCurrentStyle(this.getElement());var index=(style!=null)?style.zIndex:3;if(mxWindow.activeWindow){var elt=mxWindow.activeWindow.getElement();if(elt!=null&&elt.style!=null){elt.style.zIndex=index;}}var previousWindow=mxWindow.activeWindow;this.getElement().style.zIndex=parseInt(index)+1;mxWindow.activeWindow=this;this.fireEvent(new mxEventObject(mxEvent.ACTIVATE,'previousWindow',previousWindow));}};mxWindow.prototype.getElement=function(){return this.div;};mxWindow.prototype.fit=function(){mxUtils.fit(this.div);};mxWindow.prototype.isResizable=function(){if(this.resize!=null){return this.resize.style.display!='none';}return false;};mxWindow.prototype.setResizable=function(resizable){if(resizable){if(this.resize==null){this.resize=document.createElement('img');this.resize.style.position='absolute';this.resize.style.bottom='2px';this.resize.style.right='2px';this.resize.setAttribute('src',mxClient.imageBasePath+'/resize.gif');this.resize.style.cursor='nw-resize';var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(this.resize,md,mxUtils.bind(this,function(evt){this.activate();var startX=mxEvent.getClientX(evt);var startY=mxEvent.getClientY(evt);var width=this.div.offsetWidth;var height=this.div.offsetHeight;var dragHandler=mxUtils.bind(this,function(evt){var dx=mxEvent.getClientX(evt)-startX;var dy=mxEvent.getClientY(evt)-startY;this.setSize(width+dx,height+dy);this.fireEvent(new mxEventObject(mxEvent.RESIZE,'event',evt));mxEvent.consume(evt);});var dropHandler=mxUtils.bind(this,function(evt){mxEvent.removeListener(document,mm,dragHandler);mxEvent.removeListener(document,mu,dropHandler);this.fireEvent(new mxEventObject(mxEvent.RESIZE_END,'event',evt));mxEvent.consume(evt);});mxEvent.addListener(document,mm,dragHandler);mxEvent.addListener(document,mu,dropHandler);this.fireEvent(new mxEventObject(mxEvent.RESIZE_START,'event',evt));mxEvent.consume(evt);}));this.div.appendChild(this.resize);}else{this.resize.style.display='inline';}}else if(this.resize!=null){this.resize.style.display='none';}};mxWindow.prototype.setSize=function(width,height){width=Math.max(this.minimumSize.width,width);height=Math.max(this.minimumSize.height,height);if(!mxClient.IS_IE){this.div.style.width=width+'px';this.div.style.height=height+'px';}this.table.style.width=width+'px';this.table.style.height=height+'px';if(!mxClient.IS_IE){this.contentWrapper.style.height=(this.div.offsetHeight-this.title.offsetHeight-2)+'px';}};mxWindow.prototype.setMinimizable=function(minimizable){this.minimize.style.display=(minimizable)?'':'none';};mxWindow.prototype.getMinimumSize=function(){return new mxRectangle(0,0,0,this.title.offsetHeight);};mxWindow.prototype.installMinimizeHandler=function(){this.minimize=document.createElement('img');this.minimize.setAttribute('src',this.minimizeImage);this.minimize.setAttribute('align','right');this.minimize.setAttribute('title','Minimize');this.minimize.style.cursor='pointer';this.minimize.style.marginRight='1px';this.minimize.style.display='none';this.title.appendChild(this.minimize);var minimized=false;var maxDisplay=null;var height=null;var funct=mxUtils.bind(this,function(evt){this.activate();if(!minimized){minimized=true;this.minimize.setAttribute('src',this.normalizeImage);this.minimize.setAttribute('title','Normalize');this.contentWrapper.style.display='none';maxDisplay=this.maximize.style.display;this.maximize.style.display='none';height=this.table.style.height;var minSize=this.getMinimumSize();if(minSize.height>0){if(!mxClient.IS_IE){this.div.style.height=minSize.height+'px';}this.table.style.height=minSize.height+'px';}if(minSize.width>0){if(!mxClient.IS_IE){this.div.style.width=minSize.width+'px';}this.table.style.width=minSize.width+'px';}if(this.resize!=null){this.resize.style.visibility='hidden';}this.fireEvent(new mxEventObject(mxEvent.MINIMIZE,'event',evt));}else{minimized=false;this.minimize.setAttribute('src',this.minimizeImage);this.minimize.setAttribute('title','Minimize');this.contentWrapper.style.display='';this.maximize.style.display=maxDisplay;if(!mxClient.IS_IE){this.div.style.height=height;}this.table.style.height=height;if(this.resize!=null){this.resize.style.visibility='';}this.fireEvent(new mxEventObject(mxEvent.NORMALIZE,'event',evt));}mxEvent.consume(evt);});var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';mxEvent.addListener(this.minimize,md,funct);};mxWindow.prototype.setMaximizable=function(maximizable){this.maximize.style.display=(maximizable)?'':'none';};mxWindow.prototype.installMaximizeHandler=function(){this.maximize=document.createElement('img');this.maximize.setAttribute('src',this.maximizeImage);this.maximize.setAttribute('align','right');this.maximize.setAttribute('title','Maximize');this.maximize.style.cursor='default';this.maximize.style.marginLeft='1px';this.maximize.style.cursor='pointer';this.maximize.style.display='none';this.title.appendChild(this.maximize);var maximized=false;var x=null;var y=null;var height=null;var width=null;var funct=mxUtils.bind(this,function(evt){this.activate();if(this.maximize.style.display!='none'){if(!maximized){maximized=true;this.maximize.setAttribute('src',this.normalizeImage);this.maximize.setAttribute('title','Normalize');this.contentWrapper.style.display='';this.minimize.style.visibility='hidden';x=parseInt(this.div.style.left);y=parseInt(this.div.style.top);height=this.table.style.height;width=this.table.style.width;this.div.style.left='0px';this.div.style.top='0px';if(!mxClient.IS_IE){this.div.style.height=(document.body.clientHeight-2)+'px';this.div.style.width=(document.body.clientWidth-2)+'px';}this.table.style.width=(document.body.clientWidth-2)+'px';this.table.style.height=(document.body.clientHeight-2)+'px';if(this.resize!=null){this.resize.style.visibility='hidden';}if(!mxClient.IS_IE){var style=mxUtils.getCurrentStyle(this.contentWrapper);if(style.overflow=='auto'||this.resize!=null){this.contentWrapper.style.height=(this.div.offsetHeight-this.title.offsetHeight-2)+'px';}}this.fireEvent(new mxEventObject(mxEvent.MAXIMIZE,'event',evt));}else{maximized=false;this.maximize.setAttribute('src',this.maximizeImage);this.maximize.setAttribute('title','Maximize');this.contentWrapper.style.display='';this.minimize.style.visibility='';this.div.style.left=x+'px';this.div.style.top=y+'px';if(!mxClient.IS_IE){this.div.style.height=height;this.div.style.width=width;var style=mxUtils.getCurrentStyle(this.contentWrapper);if(style.overflow=='auto'||this.resize!=null){this.contentWrapper.style.height=(this.div.offsetHeight-this.title.offsetHeight-2)+'px';}}this.table.style.height=height;this.table.style.width=width;if(this.resize!=null){this.resize.style.visibility='';}this.fireEvent(new mxEventObject(mxEvent.NORMALIZE,'event',evt));}mxEvent.consume(evt);}});var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';mxEvent.addListener(this.maximize,md,funct);mxEvent.addListener(this.title,'dblclick',funct);};mxWindow.prototype.installMoveHandler=function(){this.title.style.cursor='move';var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(this.title,md,mxUtils.bind(this,function(evt){var startX=mxEvent.getClientX(evt);var startY=mxEvent.getClientY(evt);var x=this.getX();var y=this.getY();var dragHandler=mxUtils.bind(this,function(evt){var dx=mxEvent.getClientX(evt)-startX;var dy=mxEvent.getClientY(evt)-startY;this.setLocation(x+dx,y+dy);this.fireEvent(new mxEventObject(mxEvent.MOVE,'event',evt));mxEvent.consume(evt);});var dropHandler=mxUtils.bind(this,function(evt){mxEvent.removeListener(document,mm,dragHandler);mxEvent.removeListener(document,mu,dropHandler);this.fireEvent(new mxEventObject(mxEvent.MOVE_END,'event',evt));mxEvent.consume(evt);});mxEvent.addListener(document,mm,dragHandler);mxEvent.addListener(document,mu,dropHandler);this.fireEvent(new mxEventObject(mxEvent.MOVE_START,'event',evt));mxEvent.consume(evt);}));};mxWindow.prototype.setLocation=function(x,y){this.div.style.left=x+'px';this.div.style.top=y+'px';};mxWindow.prototype.getX=function(){return parseInt(this.div.style.left);};mxWindow.prototype.getY=function(){return parseInt(this.div.style.top);};mxWindow.prototype.installCloseHandler=function(){this.closeImg=document.createElement('img');this.closeImg.setAttribute('src',this.closeImage);this.closeImg.setAttribute('align','right');this.closeImg.setAttribute('title','Close');this.closeImg.style.marginLeft='2px';this.closeImg.style.cursor='pointer';this.closeImg.style.display='none';this.title.insertBefore(this.closeImg,this.title.firstChild);var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';mxEvent.addListener(this.closeImg,md,mxUtils.bind(this,function(evt){this.fireEvent(new mxEventObject(mxEvent.CLOSE,'event',evt));if(this.destroyOnClose){this.destroy();}else{this.setVisible(false);}mxEvent.consume(evt);}));};mxWindow.prototype.setImage=function(image){this.image=document.createElement('img');this.image.setAttribute('src',image);this.image.setAttribute('align','left');this.image.style.marginRight='4px';this.image.style.marginLeft='0px';this.image.style.marginTop='-2px';this.title.insertBefore(this.image,this.title.firstChild);};mxWindow.prototype.setClosable=function(closable){this.closeImg.style.display=(closable)?'':'none';};mxWindow.prototype.isVisible=function(){if(this.div!=null){return this.div.style.visibility!='hidden';}return false;};mxWindow.prototype.setVisible=function(visible){if(this.div!=null&&this.isVisible()!=visible){if(visible){this.show();}else{this.hide();}}};mxWindow.prototype.show=function(){this.div.style.visibility='';this.activate();var style=mxUtils.getCurrentStyle(this.contentWrapper);if(!mxClient.IS_IE&&(style.overflow=='auto'||this.resize!=null)){this.contentWrapper.style.height=(this.div.offsetHeight-this.title.offsetHeight-2)+'px';}this.fireEvent(new mxEventObject(mxEvent.SHOW));};mxWindow.prototype.hide=function(){this.div.style.visibility='hidden';this.fireEvent(new mxEventObject(mxEvent.HIDE));};mxWindow.prototype.destroy=function(){this.fireEvent(new mxEventObject(mxEvent.DESTROY));if(this.div!=null){mxEvent.release(this.div);this.div.parentNode.removeChild(this.div);this.div=null;}this.title=null;this.content=null;this.contentWrapper=null;};function mxForm(className){this.table=document.createElement('table');this.table.className=className;this.body=document.createElement('tbody');this.table.appendChild(this.body);};mxForm.prototype.table=null;mxForm.prototype.body=false;mxForm.prototype.getTable=function(){return this.table;};mxForm.prototype.addButtons=function(okFunct,cancelFunct){var tr=document.createElement('tr');var td=document.createElement('td');tr.appendChild(td);td=document.createElement('td');var button=document.createElement('button');mxUtils.write(button,mxResources.get('ok')||'OK');td.appendChild(button);mxEvent.addListener(button,'click',function(){okFunct();});button=document.createElement('button');mxUtils.write(button,mxResources.get('cancel')||'Cancel');td.appendChild(button);mxEvent.addListener(button,'click',function(){cancelFunct();});tr.appendChild(td);this.body.appendChild(tr);};mxForm.prototype.addText=function(name,value){var input=document.createElement('input');input.setAttribute('type','text');input.value=value;return this.addField(name,input);};mxForm.prototype.addCheckbox=function(name,value){var input=document.createElement('input');input.setAttribute('type','checkbox');this.addField(name,input);if(value){input.checked=true;}return input;};mxForm.prototype.addTextarea=function(name,value,rows){var input=document.createElement('textarea');if(mxClient.IS_NS){rows--;}input.setAttribute('rows',rows||2);input.value=value;return this.addField(name,input);};mxForm.prototype.addCombo=function(name,isMultiSelect,size){var select=document.createElement('select');if(size!=null){select.setAttribute('size',size);}if(isMultiSelect){select.setAttribute('multiple','true');}return this.addField(name,select);};mxForm.prototype.addOption=function(combo,label,value,isSelected){var option=document.createElement('option');mxUtils.writeln(option,label);option.setAttribute('value',value);if(isSelected){option.setAttribute('selected',isSelected);}combo.appendChild(option);};mxForm.prototype.addField=function(name,input){var tr=document.createElement('tr');var td=document.createElement('td');mxUtils.write(td,name);tr.appendChild(td);td=document.createElement('td');td.appendChild(input);tr.appendChild(td);this.body.appendChild(tr);return input;};function mxImage(src,width,height){this.src=src;this.width=width;this.height=height;};mxImage.prototype.src=null;mxImage.prototype.width=null;mxImage.prototype.height=null;function mxDivResizer(div,container){if(div.nodeName.toLowerCase()=='div'){if(container==null){container=window;}this.div=div;var style=mxUtils.getCurrentStyle(div);if(style!=null){this.resizeWidth=style.width=='auto';this.resizeHeight=style.height=='auto';}mxEvent.addListener(container,'resize',mxUtils.bind(this,function(evt){if(!this.handlingResize){this.handlingResize=true;this.resize();this.handlingResize=false;}}));this.resize();}};mxDivResizer.prototype.resizeWidth=true;mxDivResizer.prototype.resizeHeight=true;mxDivResizer.prototype.handlingResize=false;mxDivResizer.prototype.resize=function(){var w=this.getDocumentWidth();var h=this.getDocumentHeight();var l=parseInt(this.div.style.left);var r=parseInt(this.div.style.right);var t=parseInt(this.div.style.top);var b=parseInt(this.div.style.bottom);if(this.resizeWidth&&!isNaN(l)&&!isNaN(r)&&l>=0&&r>=0&&w-r-l>0){this.div.style.width=(w-r-l)+'px';}if(this.resizeHeight&&!isNaN(t)&&!isNaN(b)&&t>=0&&b>=0&&h-t-b>0){this.div.style.height=(h-t-b)+'px';}};mxDivResizer.prototype.getDocumentWidth=function(){return document.body.clientWidth;};mxDivResizer.prototype.getDocumentHeight=function(){return document.body.clientHeight;};function mxDragSource(element,dropHandler){this.element=element;this.dropHandler=dropHandler;var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';mxEvent.addListener(element,md,mxUtils.bind(this,this.mouseDown));};mxDragSource.prototype.element=null;mxDragSource.prototype.dropHandler=null;mxDragSource.prototype.dragOffset=null;mxDragSource.prototype.dragElement=null;mxDragSource.prototype.previewElement=null;mxDragSource.prototype.enabled=true;mxDragSource.prototype.currentGraph=null;mxDragSource.prototype.currentDropTarget=null;mxDragSource.prototype.currentPoint=null;mxDragSource.prototype.currentGuide=null;mxDragSource.prototype.currentHighlight=null;mxDragSource.prototype.autoscroll=true;mxDragSource.prototype.guidesEnabled=true;mxDragSource.prototype.gridEnabled=true;mxDragSource.prototype.highlightDropTargets=true;mxDragSource.prototype.isEnabled=function(){return this.enabled;};mxDragSource.prototype.setEnabled=function(value){this.enabled=value;};mxDragSource.prototype.isGuidesEnabled=function(){return this.guidesEnabled;};mxDragSource.prototype.setGuidesEnabled=function(value){this.guidesEnabled=value;};mxDragSource.prototype.isGridEnabled=function(){return this.gridEnabled;};mxDragSource.prototype.setGridEnabled=function(value){this.gridEnabled=value;};mxDragSource.prototype.getGraphForEvent=function(evt){return null;};mxDragSource.prototype.getDropTarget=function(graph,x,y){return graph.getCellAt(x,y);};mxDragSource.prototype.createDragElement=function(evt){return this.element.cloneNode(true);};mxDragSource.prototype.createPreviewElement=function(graph){return null;};mxDragSource.prototype.mouseDown=function(evt){if(this.enabled&&!mxEvent.isConsumed(evt)){this.startDrag(evt);var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';this.mouseMoveHandler=mxUtils.bind(this,this.mouseMove);mxEvent.addListener(document,mm,this.mouseMoveHandler);this.mouseUpHandler=mxUtils.bind(this,this.mouseUp);mxEvent.addListener(document,mu,this.mouseUpHandler);mxEvent.consume(evt,true,false);}};mxDragSource.prototype.startDrag=function(evt){this.dragElement=this.createDragElement(evt);this.dragElement.style.position='absolute';this.dragElement.style.zIndex='3';mxUtils.setOpacity(this.dragElement,70);};mxDragSource.prototype.stopDrag=function(evt){if(this.dragElement!=null){if(this.dragElement.parentNode!=null){this.dragElement.parentNode.removeChild(this.dragElement);}this.dragElement=null;}};mxDragSource.prototype.graphContainsEvent=function(graph,evt){var x=mxEvent.getClientX(evt);var y=mxEvent.getClientY(evt);var offset=mxUtils.getOffset(graph.container);var origin=mxUtils.getScrollOrigin();return x>=offset.x-origin.x&&y>=offset.y-origin.y&&x<=offset.x-origin.x+graph.container.offsetWidth&&y<=offset.y-origin.y+graph.container.offsetHeight;};mxDragSource.prototype.mouseMove=function(evt){var graph=this.getGraphForEvent(evt);if(graph!=null&&!this.graphContainsEvent(graph,evt)){graph=null;}if(graph!=this.currentGraph){if(this.currentGraph!=null){this.dragExit(this.currentGraph);}this.currentGraph=graph;if(this.currentGraph!=null){this.dragEnter(this.currentGraph);}}if(this.currentGraph!=null){this.dragOver(this.currentGraph,evt);}if(this.dragElement!=null&&(this.previewElement==null||this.previewElement.style.visibility!='visible')){var x=mxEvent.getClientX(evt);var y=mxEvent.getClientY(evt);if(this.dragElement.parentNode==null){document.body.appendChild(this.dragElement);}this.dragElement.style.visibility='visible';if(this.dragOffset!=null){x+=this.dragOffset.x;y+=this.dragOffset.y;}x+=document.body.scrollLeft||document.documentElement.scrollLeft;y+=document.body.scrollTop||document.documentElement.scrollTop;this.dragElement.style.left=x+'px';this.dragElement.style.top=y+'px';}else if(this.dragElement!=null){this.dragElement.style.visibility='hidden';}mxEvent.consume(evt);};mxDragSource.prototype.mouseUp=function(evt){if(this.currentGraph!=null){if(this.currentPoint!=null&&(this.previewElement==null||this.previewElement.style.visibility!='hidden')){var scale=this.currentGraph.view.scale;var tr=this.currentGraph.view.translate;var x=this.currentPoint.x/scale-tr.x;var y=this.currentPoint.y/scale-tr.y;this.drop(this.currentGraph,evt,this.currentDropTarget,x,y);}this.dragExit(this.currentGraph);}this.stopDrag(evt);this.currentGraph=null;if(this.mouseMoveHandler!=null){var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';mxEvent.removeListener(document,mm,this.mouseMoveHandler);this.mouseMoveHandler=null;}if(this.mouseUpHandler!=null){var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.removeListener(document,mu,this.mouseUpHandler);this.mouseUpHandler=null;}mxEvent.consume(evt);};mxDragSource.prototype.dragEnter=function(graph){graph.isMouseDown=true;this.previewElement=this.createPreviewElement(graph);if(this.isGuidesEnabled()&&this.previewElement!=null){this.currentGuide=new mxGuide(graph,graph.graphHandler.getGuideStates());}if(this.highlightDropTargets){this.currentHighlight=new mxCellHighlight(graph,mxConstants.DROP_TARGET_COLOR);}};mxDragSource.prototype.dragExit=function(graph){this.currentDropTarget=null;this.currentPoint=null;graph.isMouseDown=false;if(this.previewElement!=null){if(this.previewElement.parentNode!=null){this.previewElement.parentNode.removeChild(this.previewElement);}this.previewElement=null;}if(this.currentGuide!=null){this.currentGuide.destroy();this.currentGuide=null;}if(this.currentHighlight!=null){this.currentHighlight.destroy();this.currentHighlight=null;}};mxDragSource.prototype.dragOver=function(graph,evt){var offset=mxUtils.getOffset(graph.container);var origin=mxUtils.getScrollOrigin(graph.container);var x=mxEvent.getClientX(evt)-offset.x+origin.x;var y=mxEvent.getClientY(evt)-offset.y+origin.y;if(graph.autoScroll&&(this.autoscroll==null||this.autoscroll)){graph.scrollPointToVisible(x,y,graph.autoExtend);}if(this.currentHighlight!=null&&graph.isDropEnabled()){this.currentDropTarget=this.getDropTarget(graph,x,y);var state=graph.getView().getState(this.currentDropTarget);this.currentHighlight.highlight(state);}if(this.previewElement!=null){if(this.previewElement.parentNode==null){graph.container.appendChild(this.previewElement);this.previewElement.style.zIndex='3';this.previewElement.style.position='absolute';}var gridEnabled=this.isGridEnabled()&&graph.isGridEnabledEvent(evt);var hideGuide=true;if(this.currentGuide!=null&&this.currentGuide.isEnabledForEvent(evt)){var w=parseInt(this.previewElement.style.width);var h=parseInt(this.previewElement.style.height);var bounds=new mxRectangle(0,0,w,h);var delta=new mxPoint(x,y);delta=this.currentGuide.move(bounds,delta,gridEnabled);hideGuide=false;x=delta.x;y=delta.y;}else if(gridEnabled){var scale=graph.view.scale;var tr=graph.view.translate;var off=graph.gridSize/2;x=(graph.snap(x/scale-tr.x-off)+tr.x)*scale;y=(graph.snap(y/scale-tr.y-off)+tr.y)*scale;}if(this.currentGuide!=null&&hideGuide){this.currentGuide.hide();}if(this.previewOffset!=null){x+=this.previewOffset.x;y+=this.previewOffset.y;}this.previewElement.style.left=Math.round(x)+'px';this.previewElement.style.top=Math.round(y)+'px';this.previewElement.style.visibility='visible';}this.currentPoint=new mxPoint(x,y);};mxDragSource.prototype.drop=function(graph,evt,dropTarget,x,y){this.dropHandler(graph,evt,dropTarget,x,y);graph.container.focus();};function mxToolbar(container){this.container=container;};mxToolbar.prototype=new mxEventSource();mxToolbar.prototype.constructor=mxToolbar;mxToolbar.prototype.container=null;mxToolbar.prototype.enabled=true;mxToolbar.prototype.noReset=false;mxToolbar.prototype.updateDefaultMode=true;mxToolbar.prototype.addItem=function(title,icon,funct,pressedIcon,style,factoryMethod){var img=document.createElement((icon!=null)?'img':'button');var initialClassName=style||((factoryMethod!=null)?'mxToolbarMode':'mxToolbarItem');img.className=initialClassName;img.setAttribute('src',icon);if(title!=null){if(icon!=null){img.setAttribute('title',title);}else{mxUtils.write(img,title);}}this.container.appendChild(img);if(funct!=null){mxEvent.addListener(img,(mxClient.IS_TOUCH)?'touchend':'click',funct);}var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(img,md,mxUtils.bind(this,function(evt){if(pressedIcon!=null){img.setAttribute('src',pressedIcon);}else{img.style.backgroundColor='gray';}if(factoryMethod!=null){if(this.menu==null){this.menu=new mxPopupMenu();this.menu.init();}var last=this.currentImg;if(this.menu.isMenuShowing()){this.menu.hideMenu();}if(last!=img){this.currentImg=img;this.menu.factoryMethod=factoryMethod;var point=new mxPoint(img.offsetLeft,img.offsetTop+img.offsetHeight);this.menu.popup(point.x,point.y,null,evt);if(this.menu.isMenuShowing()){img.className=initialClassName+'Selected';this.menu.hideMenu=function(){mxPopupMenu.prototype.hideMenu.apply(this);img.className=initialClassName;this.currentImg=null;};}}}}));var mouseHandler=mxUtils.bind(this,function(evt){if(pressedIcon!=null){img.setAttribute('src',icon);}else{img.style.backgroundColor='';}});mxEvent.addListener(img,mu,mouseHandler);mxEvent.addListener(img,'mouseout',mouseHandler);return img;};mxToolbar.prototype.addCombo=function(style){var div=document.createElement('div');div.style.display='inline';div.className='mxToolbarComboContainer';var select=document.createElement('select');select.className=style||'mxToolbarCombo';div.appendChild(select);this.container.appendChild(div);return select;};mxToolbar.prototype.addActionCombo=function(title,style){var select=document.createElement('select');select.className=style||'mxToolbarCombo';this.addOption(select,title,null);mxEvent.addListener(select,'change',function(evt){var value=select.options[select.selectedIndex];select.selectedIndex=0;if(value.funct!=null){value.funct(evt);}});this.container.appendChild(select);return select;};mxToolbar.prototype.addOption=function(combo,title,value){var option=document.createElement('option');mxUtils.writeln(option,title);if(typeof(value)=='function'){option.funct=value;}else{option.setAttribute('value',value);}combo.appendChild(option);return option;};mxToolbar.prototype.addSwitchMode=function(title,icon,funct,pressedIcon,style){var img=document.createElement('img');img.initialClassName=style||'mxToolbarMode';img.className=img.initialClassName;img.setAttribute('src',icon);img.altIcon=pressedIcon;if(title!=null){img.setAttribute('title',title);}mxEvent.addListener(img,'click',mxUtils.bind(this,function(evt){var tmp=this.selectedMode.altIcon;if(tmp!=null){this.selectedMode.altIcon=this.selectedMode.getAttribute('src');this.selectedMode.setAttribute('src',tmp);}else{this.selectedMode.className=this.selectedMode.initialClassName;}if(this.updateDefaultMode){this.defaultMode=img;}this.selectedMode=img;var tmp=img.altIcon;if(tmp!=null){img.altIcon=img.getAttribute('src');img.setAttribute('src',tmp);}else{img.className=img.initialClassName+'Selected';}this.fireEvent(new mxEventObject(mxEvent.SELECT));funct();}));this.container.appendChild(img);if(this.defaultMode==null){this.defaultMode=img;this.selectedMode=img;var tmp=img.altIcon;if(tmp!=null){img.altIcon=img.getAttribute('src');img.setAttribute('src',tmp);}else{img.className=img.initialClassName+'Selected';}funct();}return img;};mxToolbar.prototype.addMode=function(title,icon,funct,pressedIcon,style,toggle){toggle=(toggle!=null)?toggle:true;var img=document.createElement((icon!=null)?'img':'button');img.initialClassName=style||'mxToolbarMode';img.className=img.initialClassName;img.setAttribute('src',icon);img.altIcon=pressedIcon;if(title!=null){img.setAttribute('title',title);}if(this.enabled&&toggle){mxEvent.addListener(img,'click',mxUtils.bind(this,function(evt){this.selectMode(img,funct);this.noReset=false;}));mxEvent.addListener(img,'dblclick',mxUtils.bind(this,function(evt){this.selectMode(img,funct);this.noReset=true;}));if(this.defaultMode==null){this.defaultMode=img;this.selectedMode=img;var tmp=img.altIcon;if(tmp!=null){img.altIcon=img.getAttribute('src');img.setAttribute('src',tmp);}else{img.className=img.initialClassName+'Selected';}}}this.container.appendChild(img);return img;};mxToolbar.prototype.selectMode=function(domNode,funct){if(this.selectedMode!=domNode){var tmp=this.selectedMode.altIcon;if(tmp!=null){this.selectedMode.altIcon=this.selectedMode.getAttribute('src');this.selectedMode.setAttribute('src',tmp);}else{this.selectedMode.className=this.selectedMode.initialClassName;}this.selectedMode=domNode;var tmp=this.selectedMode.altIcon;if(tmp!=null){this.selectedMode.altIcon=this.selectedMode.getAttribute('src');this.selectedMode.setAttribute('src',tmp);}else{this.selectedMode.className=this.selectedMode.initialClassName+'Selected';}this.fireEvent(new mxEventObject(mxEvent.SELECT,"function",funct));}};mxToolbar.prototype.resetMode=function(forced){if((forced||!this.noReset)&&this.selectedMode!=this.defaultMode){this.selectMode(this.defaultMode,null);}};mxToolbar.prototype.addSeparator=function(icon){return this.addItem(null,icon,null);};mxToolbar.prototype.addBreak=function(){mxUtils.br(this.container);};mxToolbar.prototype.addLine=function(){var hr=document.createElement('hr');hr.style.marginRight='6px';hr.setAttribute('size','1');this.container.appendChild(hr);};mxToolbar.prototype.destroy=function(){mxEvent.release(this.container);this.container=null;this.defaultMode=null;this.selectedMode=null;if(this.menu!=null){this.menu.destroy();}};function mxSession(model,urlInit,urlPoll,urlNotify){this.model=model;this.urlInit=urlInit;this.urlPoll=urlPoll;this.urlNotify=urlNotify;if(model!=null){this.codec=new mxCodec();this.codec.lookup=function(id){return model.getCell(id);};}model.addListener(mxEvent.NOTIFY,mxUtils.bind(this,function(sender,evt){var edit=evt.getProperty('edit');if(edit!=null&&this.debug||(this.connected&&!this.suspended)){this.notify(''+this.encodeChanges(edit.changes,edit.undone)+'');}}));};mxSession.prototype=new mxEventSource();mxSession.prototype.constructor=mxSession;mxSession.prototype.model=null;mxSession.prototype.urlInit=null;mxSession.prototype.urlPoll=null;mxSession.prototype.urlNotify=null;mxSession.prototype.codec=null;mxSession.prototype.linefeed='
';mxSession.prototype.escapePostData=true;mxSession.prototype.significantRemoteChanges=true;mxSession.prototype.sent=0;mxSession.prototype.received=0;mxSession.prototype.debug=false;mxSession.prototype.connected=false;mxSession.prototype.suspended=false;mxSession.prototype.polling=false;mxSession.prototype.start=function(){if(this.debug){this.connected=true;this.fireEvent(new mxEventObject(mxEvent.CONNECT));}else if(!this.connected){this.get(this.urlInit,mxUtils.bind(this,function(req){this.connected=true;this.fireEvent(new mxEventObject(mxEvent.CONNECT));this.poll();}));}};mxSession.prototype.suspend=function(){if(this.connected&&!this.suspended){this.suspended=true;this.fireEvent(new mxEventObject(mxEvent.SUSPEND));}};mxSession.prototype.resume=function(type,attr,value){if(this.connected&&this.suspended){this.suspended=false;this.fireEvent(new mxEventObject(mxEvent.RESUME));if(!this.polling){this.poll();}}};mxSession.prototype.stop=function(reason){if(this.connected){this.connected=false;}this.fireEvent(new mxEventObject(mxEvent.DISCONNECT,'reason',reason));};mxSession.prototype.poll=function(){if(this.connected&&!this.suspended&&this.urlPoll!=null){this.polling=true;this.get(this.urlPoll,mxUtils.bind(this,function(){this.poll();}));}else{this.polling=false;}};mxSession.prototype.notify=function(xml,onLoad,onError){if(xml!=null&&xml.length>0){if(this.urlNotify!=null){if(this.debug){mxLog.show();mxLog.debug('mxSession.notify: '+this.urlNotify+' xml='+xml);}else{xml=''+xml+'';if(this.escapePostData){xml=encodeURIComponent(xml);}mxUtils.post(this.urlNotify,'xml='+xml,onLoad,onError);}}this.sent+=xml.length;this.fireEvent(new mxEventObject(mxEvent.NOTIFY,'url',this.urlNotify,'xml',xml));}};mxSession.prototype.get=function(url,onLoad,onError){if(typeof(mxUtils)!='undefined'){var onErrorWrapper=mxUtils.bind(this,function(ex){if(onError!=null){onError(ex);}else{this.stop(ex);}});var req=mxUtils.get(url,mxUtils.bind(this,function(req){if(typeof(mxUtils)!='undefined'){{if(req.isReady()&&req.getStatus()!=404){this.received+=req.getText().length;this.fireEvent(new mxEventObject(mxEvent.GET,'url',url,'request',req));if(this.isValidResponse(req)){if(req.getText().length>0){var node=req.getDocumentElement();if(node==null){onErrorWrapper('Invalid response: '+req.getText());}else{this.receive(node);}}if(onLoad!=null){onLoad(req);}}}else{onErrorWrapper('Response not ready');}}}}),function(req){onErrorWrapper('Transmission error');});}};mxSession.prototype.isValidResponse=function(req){return req.getText().indexOf('=0&&i0){var edit=this.createUndoableEdit(changes);this.model.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit',edit,'changes',changes));this.model.fireEvent(new mxEventObject(mxEvent.UNDO,'edit',edit));this.fireEvent(new mxEventObject(mxEvent.FIRED,'edit',edit));}};mxSession.prototype.createUndoableEdit=function(changes){var edit=new mxUndoableEdit(this.model,this.significantRemoteChanges);edit.changes=changes;edit.notify=function(){edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit',edit,'changes',edit.changes));edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,'edit',edit,'changes',edit.changes));};return edit;};mxSession.prototype.decodeChanges=function(node){this.codec.document=node.ownerDocument;var changes=[];node=node.firstChild;while(node!=null){if(node.nodeType==mxConstants.NODETYPE_ELEMENT){var change=null;if(node.nodeName=='mxRootChange'){var tmp=new mxCodec(node.ownerDocument);change=tmp.decode(node);}else{change=this.codec.decode(node);}if(change!=null){change.model=this.model;change.execute();if(node.nodeName=='mxChildChange'&&change.parent==null){this.cellRemoved(change.child);}changes.push(change);}}node=node.nextSibling;}return changes;};mxSession.prototype.cellRemoved=function(cell,codec){this.codec.putObject(cell.getId(),cell);var childCount=this.model.getChildCount(cell);for(var i=0;i=0;i--){var change=this.changes[i];if(change.execute!=null){change.execute();}else if(change.undo!=null){change.undo();}}this.undone=true;this.redone=false;}this.notify();};mxUndoableEdit.prototype.redo=function(){if(!this.redone){var count=this.changes.length;for(var i=0;i0;};mxUndoManager.prototype.undo=function(){while(this.indexOfNextAdd>0){var edit=this.history[--this.indexOfNextAdd];edit.undo();if(edit.isSignificant()){this.fireEvent(new mxEventObject(mxEvent.UNDO,'edit',edit));break;}}};mxUndoManager.prototype.canRedo=function(){return this.indexOfNextAdd0&&this.size==this.history.length){this.history.shift();}this.history.push(undoableEdit);this.indexOfNextAdd=this.history.length;this.fireEvent(new mxEventObject(mxEvent.ADD,'edit',undoableEdit));};mxUndoManager.prototype.trim=function(){if(this.history.length>this.indexOfNextAdd){var edits=this.history.splice(this.indexOfNextAdd,this.history.length-this.indexOfNextAdd);for(var i=0;i0){baseUrl=baseUrl.substring(0,tmp+1);}};return{isEnabled:function(){return enabled;},setEnabled:function(value){enabled=value;},getBaseUrl:function(){return baseUrl;},setBaseUrl:function(value){baseUrl=value;},convert:function(url){if(enabled&&url.indexOf('http://')!=0&&url.indexOf('https://')!=0&&url.indexOf('data:image')!=0){if(baseUrl==null){updateBaseUrl();}url=baseUrl+url;}return url;}};};function mxPanningManager(graph){this.thread=null;this.active=false;this.tdx=0;this.tdy=0;this.t0x=0;this.t0y=0;this.dx=0;this.dy=0;this.mouseListener={mouseDown:function(sender,me){},mouseMove:function(sender,me){},mouseUp:mxUtils.bind(this,function(sender,me){if(this.active){this.stop();}})};graph.addMouseListener(this.mouseListener);var createThread=mxUtils.bind(this,function(){return window.setInterval(mxUtils.bind(this,function(){this.tdx-=this.dx;this.tdy-=this.dy;graph.panGraph(this.getDx(),this.getDy());}),this.delay);});this.isActive=function(){return active;};this.getDx=function(){return Math.round(this.tdx);};this.getDy=function(){return Math.round(this.tdy);};this.start=function(){this.t0x=graph.view.translate.x;this.t0y=graph.view.translate.y;this.active=true;};this.panTo=function(x,y,w,h){if(!this.active){this.start();}w=(w!=null)?w:0;h=(h!=null)?h:0;var c=graph.container;this.dx=x+w-c.scrollLeft-c.clientWidth;if(this.dx<0&&Math.abs(this.dx)0&&this.dx0&&this.dyright){row.div.style.left=(parent.div.offsetLeft-width+((mxClient.IS_IE)?6:-6))+'px';}mxUtils.fit(row.div);}};mxPopupMenu.prototype.addSeparator=function(parent,force){parent=parent||this;if(this.smartSeparators&&!force){parent.willAddSeparator=true;}else if(parent.tbody!=null){parent.willAddSeparator=false;var tr=document.createElement('tr');var col1=document.createElement('td');col1.className='mxPopupMenuIcon';col1.style.padding='0 0 0 0px';tr.appendChild(col1);var col2=document.createElement('td');col2.style.padding='0 0 0 0px';col2.setAttribute('colSpan','2');var hr=document.createElement('hr');hr.setAttribute('size','1');col2.appendChild(hr);tr.appendChild(col2);parent.tbody.appendChild(tr);}};mxPopupMenu.prototype.popup=function(x,y,cell,evt){if(this.div!=null&&this.tbody!=null&&this.factoryMethod!=null){this.div.style.left=x+'px';this.div.style.top=y+'px';while(this.tbody.firstChild!=null){mxEvent.release(this.tbody.firstChild);this.tbody.removeChild(this.tbody.firstChild);}this.itemCount=0;this.factoryMethod(this,cell,evt);if(this.itemCount>0){this.showMenu();this.fireEvent(new mxEventObject(mxEvent.SHOW));}}};mxPopupMenu.prototype.isMenuShowing=function(){return this.div!=null&&this.div.parentNode==document.body;};mxPopupMenu.prototype.showMenu=function(){if(document.documentMode>=9){this.div.style.filter='none';}document.body.appendChild(this.div);mxUtils.fit(this.div);};mxPopupMenu.prototype.hideMenu=function(){if(this.div!=null){if(this.div.parentNode!=null){this.div.parentNode.removeChild(this.div);}this.hideSubmenu(this);this.containsItems=false;}};mxPopupMenu.prototype.hideSubmenu=function(parent){if(parent.activeRow!=null){this.hideSubmenu(parent.activeRow);if(parent.activeRow.div.parentNode!=null){parent.activeRow.div.parentNode.removeChild(parent.activeRow.div);}parent.activeRow=null;}};mxPopupMenu.prototype.destroy=function(){if(this.div!=null){mxEvent.release(this.div);if(this.div.parentNode!=null){this.div.parentNode.removeChild(this.div);}this.div=null;}};function mxAutoSaveManager(graph){this.changeHandler=mxUtils.bind(this,function(sender,evt){if(this.isEnabled()){this.graphModelChanged(evt.getProperty('edit').changes);}});this.setGraph(graph);};mxAutoSaveManager.prototype=new mxEventSource();mxAutoSaveManager.prototype.constructor=mxAutoSaveManager;mxAutoSaveManager.prototype.graph=null;mxAutoSaveManager.prototype.autoSaveDelay=10;mxAutoSaveManager.prototype.autoSaveThrottle=2;mxAutoSaveManager.prototype.autoSaveThreshold=5;mxAutoSaveManager.prototype.ignoredChanges=0;mxAutoSaveManager.prototype.lastSnapshot=0;mxAutoSaveManager.prototype.enabled=true;mxAutoSaveManager.prototype.changeHandler=null;mxAutoSaveManager.prototype.isEnabled=function(){return this.enabled;};mxAutoSaveManager.prototype.setEnabled=function(value){this.enabled=value;};mxAutoSaveManager.prototype.setGraph=function(graph){if(this.graph!=null){this.graph.getModel().removeListener(this.changeHandler);}this.graph=graph;if(this.graph!=null){this.graph.getModel().addListener(mxEvent.CHANGE,this.changeHandler);}};mxAutoSaveManager.prototype.save=function(){};mxAutoSaveManager.prototype.graphModelChanged=function(changes){var now=new Date().getTime();var dt=(now-this.lastSnapshot)/1000;if(dt>this.autoSaveDelay||(this.ignoredChanges>=this.autoSaveThreshold&&dt>this.autoSaveThrottle)){this.save();this.reset();}else{this.ignoredChanges++;}};mxAutoSaveManager.prototype.reset=function(){this.lastSnapshot=new Date().getTime();this.ignoredChanges=0;};mxAutoSaveManager.prototype.destroy=function(){this.setGraph(null);};function mxAnimation(delay){this.delay=(delay!=null)?delay:20;};mxAnimation.prototype=new mxEventSource();mxAnimation.prototype.constructor=mxAnimation;mxAnimation.prototype.delay=null;mxAnimation.prototype.thread=null;mxAnimation.prototype.startAnimation=function(){if(this.thread==null){this.thread=window.setInterval(mxUtils.bind(this,this.updateAnimation),this.delay);}};mxAnimation.prototype.updateAnimation=function(){this.fireEvent(new mxEventObject(mxEvent.EXECUTE));};mxAnimation.prototype.stopAnimation=function(){if(this.thread!=null){window.clearInterval(this.thread);this.thread=null;this.fireEvent(new mxEventObject(mxEvent.DONE));}};function mxMorphing(graph,steps,ease,delay){mxAnimation.call(this,delay);this.graph=graph;this.steps=(steps!=null)?steps:6;this.ease=(ease!=null)?ease:1.5;};mxMorphing.prototype=new mxAnimation();mxMorphing.prototype.constructor=mxMorphing;mxMorphing.prototype.graph=null;mxMorphing.prototype.steps=null;mxMorphing.prototype.step=0;mxMorphing.prototype.ease=null;mxMorphing.prototype.cells=null;mxMorphing.prototype.updateAnimation=function(){var move=new mxCellStatePreview(this.graph);if(this.cells!=null){for(var i=0;i=this.steps){this.stopAnimation();}};mxMorphing.prototype.show=function(move){move.show();};mxMorphing.prototype.animateCell=function(cell,move,recurse){var state=this.graph.getView().getState(cell);var delta=null;if(state!=null){delta=this.getDelta(state);if(this.graph.getModel().isVertex(cell)&&(delta.x!=0||delta.y!=0)){var translate=this.graph.view.getTranslate();var scale=this.graph.view.getScale();delta.x+=translate.x*scale;delta.y+=translate.y*scale;move.moveState(state,-delta.x/this.ease,-delta.y/this.ease);}}if(recurse&&!this.stopRecursion(state,delta)){var childCount=this.graph.getModel().getChildCount(cell);for(var i=0;i0){canvas.save();canvas.setAlpha(mxUtils.getValue(state.style,mxConstants.STYLE_TEXT_OPACITY,100)/100);var bounds=new mxRectangle(txt.boundingBox.x,txt.boundingBox.y,txt.boundingBox.width,txt.boundingBox.height);var vert=mxUtils.getValue(state.style,mxConstants.STYLE_HORIZONTAL,1)==0;bounds.y+=2;if(vert){if(txt.dialect!=mxConstants.DIALECT_SVG){var cx=bounds.x+bounds.width/2;var cy=bounds.y+bounds.height/2;var tmp=bounds.width;bounds.width=bounds.height;bounds.height=tmp;bounds.x=cx-bounds.width/2;bounds.y=cy-bounds.height/2;}else if(txt.dialect==mxConstants.DIALECT_SVG){var b=state.y+state.height;var cx=bounds.getCenterX()-state.x;var cy=bounds.getCenterY()-state.y;var y=b-cx-bounds.height/2;bounds.x=state.x+cy-bounds.width/2;bounds.y=y;}}this.drawLabelBackground(state,canvas,bounds,vert);this.drawLabel(state,canvas,bounds,vert,label);canvas.restore();}};mxImageExport.prototype.drawShadow=function(canvas,state,shape,rotation,flipH,flipV,bounds,alpha,filled){var rad=rotation*Math.PI/180;var cos=Math.cos(-rad);var sin=Math.sin(-rad);var offset=mxUtils.getRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSET_X,mxConstants.SHADOW_OFFSET_Y),cos,sin);if(flipH){offset.x*=-1;}if(flipV){offset.y*=-1;}canvas.translate(offset.x,offset.y);if(shape.drawShape(canvas,state,bounds,true,true)){canvas.setAlpha(mxConstants.SHADOW_OPACITY*alpha);canvas.shadow(mxConstants.SHADOWCOLOR,filled);}canvas.translate(-offset.x,-offset.y);};mxImageExport.prototype.drawGlass=function(state,canvas,bounds,shape,size){if(shape.drawShape(canvas,state,bounds,true,false)){canvas.save();canvas.clip();canvas.setGlassGradient(bounds.x,bounds.y,bounds.width,bounds.height);canvas.begin();canvas.moveTo(bounds.x,bounds.y);canvas.lineTo(bounds.x,(bounds.y+bounds.height*size));canvas.quadTo((bounds.x+bounds.width*0.5),(bounds.y+bounds.height*0.7),bounds.x+bounds.width,(bounds.y+bounds.height*size));canvas.lineTo(bounds.x+bounds.width,bounds.y);canvas.close();canvas.fill();canvas.restore();}};mxImageExport.prototype.drawImage=function(state,canvas,bounds,image){var aspect=mxUtils.getValue(state.style,mxConstants.STYLE_IMAGE_ASPECT,1)==1;var flipH=mxUtils.getValue(state.style,mxConstants.STYLE_IMAGE_FLIPH,0)==1;var flipV=mxUtils.getValue(state.style,mxConstants.STYLE_IMAGE_FLIPV,0)==1;canvas.image(bounds.x,bounds.y,bounds.width,bounds.height,image,aspect,flipH,flipV);};mxImageExport.prototype.drawLabelBackground=function(state,canvas,bounds,vert){var stroke=mxUtils.getValue(state.style,mxConstants.STYLE_LABEL_BORDERCOLOR);var fill=mxUtils.getValue(state.style,mxConstants.STYLE_LABEL_BACKGROUNDCOLOR);if(stroke==mxConstants.NONE){stroke=null;}if(fill==mxConstants.NONE){fill=null;}if(stroke!=null||fill!=null){var x=bounds.x;var y=bounds.y-mxUtils.getValue(state.style,mxConstants.STYLE_LABEL_PADDING,0);var w=bounds.width;var h=bounds.height;if(vert){x+=(w-h)/2;y+=(h-w)/2;var tmp=w;w=h;h=tmp;}if(fill!=null){canvas.setFillColor(fill);}if(stroke!=null){canvas.setStrokeColor(stroke);canvas.setStrokeWidth(1);canvas.setDashed(false);}canvas.rect(x,y,w,h);if(fill!=null&&stroke!=null){canvas.fillAndStroke();}else if(fill!=null){canvas.fill();}else if(stroke!=null){canvas.stroke();}}};mxImageExport.prototype.drawLabel=function(state,canvas,bounds,vert,str){var scale=state.view.scale;canvas.setFontColor(mxUtils.getValue(state.style,mxConstants.STYLE_FONTCOLOR,'#000000'));canvas.setFontFamily(mxUtils.getValue(state.style,mxConstants.STYLE_FONTFAMILY,mxConstants.DEFAULT_FONTFAMILY));canvas.setFontStyle(mxUtils.getValue(state.style,mxConstants.STYLE_FONTSTYLE,0));canvas.setFontSize(mxUtils.getValue(state.style,mxConstants.STYLE_FONTSIZE,mxConstants.DEFAULT_FONTSIZE)*scale);var align=mxUtils.getValue(state.style,mxConstants.STYLE_ALIGN,mxConstants.ALIGN_LEFT);if(align=='left'){align=null;}var y=bounds.y-mxUtils.getValue(state.style,mxConstants.STYLE_LABEL_PADDING,0);var wrap=state.view.graph.isWrapping(state.cell);var html=state.view.graph.isHtmlLabel(state.cell);if(html&&mxText.prototype.replaceLinefeeds){str=str.replace(/\n/g,'
');}canvas.text(bounds.x,y,bounds.width,bounds.height,str,align,null,vert,wrap,(html)?'html':'');};mxImageExport.prototype.getBackgroundBounds=function(state){if(state.style[mxConstants.STYLE_SHAPE]==mxConstants.SHAPE_SWIMLANE){var scale=state.view.scale;var start=mxUtils.getValue(state.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE)*scale;var w=state.width;var h=state.height;if(mxUtils.getValue(state.style,mxConstants.STYLE_HORIZONTAL,true)){h=start;}else{w=start;}return new mxRectangle(state.x,state.y,Math.min(state.width,w),Math.min(state.height,h));}else{return new mxRectangle(state.x,state.y,state.width,state.height);}};mxImageExport.prototype.getImageBounds=function(state){var bounds=new mxRectangle(state.x,state.y,state.width,state.height);var style=state.style;if(mxUtils.getValue(style,mxConstants.STYLE_SHAPE)!=mxConstants.SHAPE_IMAGE){var imgAlign=mxUtils.getValue(style,mxConstants.STYLE_IMAGE_ALIGN,mxConstants.ALIGN_LEFT);var imgValign=mxUtils.getValue(style,mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,mxConstants.ALIGN_MIDDLE);var imgWidth=mxUtils.getValue(style,mxConstants.STYLE_IMAGE_WIDTH,mxConstants.DEFAULT_IMAGESIZE);var imgHeight=mxUtils.getValue(style,mxConstants.STYLE_IMAGE_HEIGHT,mxConstants.DEFAULT_IMAGESIZE);var spacing=mxUtils.getValue(style,mxConstants.STYLE_SPACING,2);if(imgAlign==mxConstants.ALIGN_CENTER){bounds.x+=(bounds.width-imgWidth)/2;}else if(imgAlign==mxConstants.ALIGN_RIGHT){bounds.x+=bounds.width-imgWidth-spacing-2;}else {bounds.x+=spacing+4;}if(imgValign==mxConstants.ALIGN_TOP){bounds.y+=spacing;}else if(imgValign==mxConstants.ALIGN_BOTTOM){bounds.y+=bounds.height-imgHeight-spacing;}else {bounds.y+=(bounds.height-imgHeight)/2;}bounds.width=imgWidth;bounds.height=imgHeight;}return bounds;};mxImageExport.prototype.drawMarker=function(canvas,state,source){var offset=null;var pts=state.absolutePoints;var n=pts.length;var p0=(source)?pts[1]:pts[n-2];var pe=(source)?pts[0]:pts[n-1];var dx=pe.x-p0.x;var dy=pe.y-p0.y;var dist=Math.max(1,Math.sqrt(dx*dx+dy*dy));var unitX=dx/dist;var unitY=dy/dist;var size=mxUtils.getValue(state.style,(source)?mxConstants.STYLE_STARTSIZE:mxConstants.STYLE_ENDSIZE,mxConstants.DEFAULT_MARKERSIZE);var sw=mxUtils.getValue(state.style,mxConstants.STYLE_STROKEWIDTH,1);pe=pe.clone();var type=mxUtils.getValue(state.style,(source)?mxConstants.STYLE_STARTARROW:mxConstants.STYLE_ENDARROW);var f=this.markers[type];if(f!=null){offset=f(canvas,state,type,pe,unitX,unitY,size,source,sw);}return offset;};mxImageExport.prototype.initShapes=function(){this.shapes=[];this.shapes['rectangle']={drawShape:function(canvas,state,bounds,background){if(background){if(mxUtils.getValue(state.style,mxConstants.STYLE_ROUNDED,false)){var f=mxUtils.getValue(state.style,mxConstants.STYLE_ARCSIZE,mxConstants.RECTANGLE_ROUNDING_FACTOR*100)/100;var r=Math.min(bounds.width*f,bounds.height*f);canvas.roundrect(bounds.x,bounds.y,bounds.width,bounds.height,r,r);}else{canvas.rect(bounds.x,bounds.y,bounds.width,bounds.height);}return true;}else{canvas.fillAndStroke();}}};this.shapes['swimlane']={drawShape:function(canvas,state,bounds,background){if(background){if(mxUtils.getValue(state.style,mxConstants.STYLE_ROUNDED,false)){var r=Math.min(bounds.width*mxConstants.RECTANGLE_ROUNDING_FACTOR,bounds.height*mxConstants.RECTANGLE_ROUNDING_FACTOR);canvas.roundrect(bounds.x,bounds.y,bounds.width,bounds.height,r,r);}else{canvas.rect(bounds.x,bounds.y,bounds.width,bounds.height);}return true;}else{canvas.fillAndStroke();var x=state.x;var y=state.y;var w=state.width;var h=state.height;if(mxUtils.getValue(state.style,mxConstants.STYLE_HORIZONTAL,1)==0){x+=bounds.width;w-=bounds.width;}else{y+=bounds.height;h-=bounds.height;}canvas.begin();canvas.moveTo(x,y);canvas.lineTo(x,y+h);canvas.lineTo(x+w,y+h);canvas.lineTo(x+w,y);canvas.stroke();}}};this.shapes['image']=this.shapes['rectangle'];this.shapes['label']=this.shapes['rectangle'];var imageExport=this;this.shapes['connector']={translatePoint:function(points,index,offset){if(offset!=null){var pt=points[index].clone();pt.x+=offset.x;pt.y+=offset.y;points[index]=pt;}},drawShape:function(canvas,state,bounds,background,shadow){if(background){var rounded=mxUtils.getValue(state.style,mxConstants.STYLE_ROUNDED,false);var arcSize=mxConstants.LINE_ARCSIZE/2;canvas.setFillColor((shadow)?mxConstants.NONE:mxUtils.getValue(state.style,mxConstants.STYLE_STROKECOLOR,"#000000"));canvas.setDashed(false);var pts=state.absolutePoints.slice();this.translatePoint(pts,0,imageExport.drawMarker(canvas,state,true));this.translatePoint(pts,pts.length-1,imageExport.drawMarker(canvas,state,false));canvas.setDashed(mxUtils.getValue(state.style,mxConstants.STYLE_DASHED,'0')=='1');var pt=pts[0];var pe=pts[pts.length-1];canvas.begin();canvas.moveTo(pt.x,pt.y);for(var i=1;i0&&h>0){canvas.ellipse(x,y,w,h);}canvas.stroke();}}};this.shapes['triangle']={drawShape:function(canvas,state,bounds,background){if(background){var x=bounds.x;var y=bounds.y;var w=bounds.width;var h=bounds.height;canvas.begin();canvas.moveTo(x,y);canvas.lineTo(x+w,y+h/2);canvas.lineTo(x,y+h);canvas.close();return true;}else{canvas.fillAndStroke();}}};this.shapes['rhombus']={drawShape:function(canvas,state,bounds,background){if(background){var x=bounds.x;var y=bounds.y;var w=bounds.width;var h=bounds.height;var hw=w/2;var hh=h/2;canvas.begin();canvas.moveTo(x+hw,y);canvas.lineTo(x+w,y+hh);canvas.lineTo(x+hw,y+h);canvas.lineTo(x,y+hh);canvas.close();return true;}else{canvas.fillAndStroke();}}};this.shapes['hexagon']={drawShape:function(canvas,state,bounds,background){if(background){var x=bounds.x;var y=bounds.y;var w=bounds.width;var h=bounds.height;canvas.begin();canvas.moveTo(x+0.25*w,y);canvas.lineTo(x+0.75*w,y);canvas.lineTo(x+w,y+0.5*h);canvas.lineTo(x+0.75*w,y+h);canvas.lineTo(x+0.25*w,y+h);canvas.lineTo(x,y+0.5*h);canvas.close();return true;}else{canvas.fillAndStroke();}}};this.shapes['actor']={drawShape:function(canvas,state,bounds,background){if(background){var x=bounds.x;var y=bounds.y;var w=bounds.width;var h=bounds.height;var width=w*2/6;canvas.begin();canvas.moveTo(x,y+h);canvas.curveTo(x,y+3*h/5,x,y+2*h/5,x+w/2,y+2*h/5);canvas.curveTo(x+w/2-width,y+2*h/5,x+w/2-width,y,x+w/2,y);canvas.curveTo(x+w/2+width,y,x+w/2+width,y+2*h/5,x+w/2,y+2*h/5);canvas.curveTo(x+w,y+2*h/5,x+w,y+3*h/5,x+w,y+h);canvas.close();return true;}else{canvas.fillAndStroke();}}};this.shapes['cloud']={drawShape:function(canvas,state,bounds,background){if(background){var x=bounds.x;var y=bounds.y;var w=bounds.width;var h=bounds.height;canvas.begin();canvas.moveTo(x+0.25*w,y+0.25*h);canvas.curveTo(x+0.05*w,y+0.25*h,x,y+0.5*h,x+0.16*w,y+0.55*h);canvas.curveTo(x,y+0.66*h,x+0.18*w,y+0.9*h,x+0.31*w,y+0.8*h);canvas.curveTo(x+0.4*w,y+h,x+0.7*w,y+h,x+0.8*w,y+0.8*h);canvas.curveTo(x+w,y+0.8*h,x+w,y+0.6*h,x+0.875*w,y+0.5*h);canvas.curveTo(x+w,y+0.3*h,x+0.8*w,y+0.1*h,x+0.625*w,y+0.2*h);canvas.curveTo(x+0.5*w,y+0.05*h,x+0.3*w,y+0.05*h,x+0.25*w,y+0.25*h);canvas.close();return true;}else{canvas.fillAndStroke();}}};};mxImageExport.prototype.initMarkers=function(){this.markers=[];var tmp=function(canvas,state,type,pe,unitX,unitY,size,source,sw){var endOffsetX=unitX*sw*1.118;var endOffsetY=unitY*sw*1.118;pe.x-=endOffsetX;pe.y-=endOffsetY;unitX=unitX*(size+sw);unitY=unitY*(size+sw);canvas.begin();canvas.moveTo(pe.x,pe.y);canvas.lineTo(pe.x-unitX-unitY/2,pe.y-unitY+unitX/2);if(type==mxConstants.ARROW_CLASSIC){canvas.lineTo(pe.x-unitX*3/4,pe.y-unitY*3/4);}canvas.lineTo(pe.x+unitY/2-unitX,pe.y-unitY-unitX/2);canvas.close();var key=(source)?mxConstants.STYLE_STARTFILL:mxConstants.STYLE_ENDFILL;if(state.style[key]==0){canvas.stroke();}else{canvas.fillAndStroke();}var f=(type!=mxConstants.ARROW_CLASSIC)?1:3/4;return new mxPoint(-unitX*f-endOffsetX,-unitY*f-endOffsetY);};this.markers['classic']=tmp;this.markers['block']=tmp;this.markers['open']=function(canvas,state,type,pe,unitX,unitY,size,source,sw){var endOffsetX=unitX*sw*1.118;var endOffsetY=unitY*sw*1.118;pe.x-=endOffsetX;pe.y-=endOffsetY;unitX=unitX*(size+sw);unitY=unitY*(size+sw);canvas.begin();canvas.moveTo(pe.x-unitX-unitY/2,pe.y-unitY+unitX/2);canvas.lineTo(pe.x,pe.y);canvas.lineTo(pe.x+unitY/2-unitX,pe.y-unitY-unitX/2);canvas.stroke();return new mxPoint(-endOffsetX*2,-endOffsetY*2);};this.markers['oval']=function(canvas,state,type,pe,unitX,unitY,size,source,sw){var a=size/2;canvas.ellipse(pe.x-a,pe.y-a,size,size);var key=(source)?mxConstants.STYLE_STARTFILL:mxConstants.STYLE_ENDFILL;if(state.style[key]==0){canvas.stroke();}else{canvas.fillAndStroke();}return new mxPoint(-unitX/2,-unitY/2);};var tmp_diamond=function(canvas,state,type,pe,unitX,unitY,size,source,sw){var swFactor=(type==mxConstants.ARROW_DIAMOND)?0.7071:0.9862;var endOffsetX=unitX*sw*swFactor;var endOffsetY=unitY*sw*swFactor;unitX=unitX*(size+sw);unitY=unitY*(size+sw);pe.x-=endOffsetX;pe.y-=endOffsetY;var tk=((type==mxConstants.ARROW_DIAMOND)?2:3.4);canvas.begin();canvas.moveTo(pe.x,pe.y);canvas.lineTo(pe.x-unitX/2-unitY/tk,pe.y+unitX/tk-unitY/2);canvas.lineTo(pe.x-unitX,pe.y-unitY);canvas.lineTo(pe.x-unitX/2+unitY/tk,pe.y-unitY/2-unitX/tk);canvas.close();var key=(source)?mxConstants.STYLE_STARTFILL:mxConstants.STYLE_ENDFILL;if(state.style[key]==0){canvas.stroke();}else{canvas.fillAndStroke();}return new mxPoint(-endOffsetX-unitX,-endOffsetY-unitY);};this.markers['diamond']=tmp_diamond;this.markers['diamondThin']=tmp_diamond;};var mxXmlCanvas2D=function(root){var converter=new mxUrlConverter();var compressed=true;var textEnabled=true;var doc=root.ownerDocument;var stack=[];var state={alpha:1,dashed:false,strokewidth:1,fontsize:mxConstants.DEFAULT_FONTSIZE,fontfamily:mxConstants.DEFAULT_FONTFAMILY,fontcolor:'#000000'};var f2=function(x){return Math.round(parseFloat(x)*100)/100;};return{getConverter:function(){return converter;},isCompressed:function(){return compressed;},setCompressed:function(value){compressed=value;},isTextEnabled:function(){return textEnabled;},setTextEnabled:function(value){textEnabled=value;},getDocument:function(){return doc;},save:function(){if(compressed){stack.push(state);state=mxUtils.clone(state);}root.appendChild(doc.createElement('save'));},restore:function(){if(compressed){state=stack.pop();}root.appendChild(doc.createElement('restore'));},scale:function(value){var elem=doc.createElement('scale');elem.setAttribute('scale',value);root.appendChild(elem);},translate:function(dx,dy){var elem=doc.createElement('translate');elem.setAttribute('dx',f2(dx));elem.setAttribute('dy',f2(dy));root.appendChild(elem);},rotate:function(theta,flipH,flipV,cx,cy){var elem=doc.createElement('rotate');elem.setAttribute('theta',f2(theta));elem.setAttribute('flipH',(flipH)?'1':'0');elem.setAttribute('flipV',(flipV)?'1':'0');elem.setAttribute('cx',f2(cx));elem.setAttribute('cy',f2(cy));root.appendChild(elem);},setStrokeWidth:function(value){if(compressed){if(state.strokewidth==value){return;}state.strokewidth=value;}var elem=doc.createElement('strokewidth');elem.setAttribute('width',f2(value));root.appendChild(elem);},setStrokeColor:function(value){var elem=doc.createElement('strokecolor');elem.setAttribute('color',value);root.appendChild(elem);},setDashed:function(value){if(compressed){if(state.dashed==value){return;}state.dashed=value;}var elem=doc.createElement('dashed');elem.setAttribute('dashed',(value)?'1':'0');root.appendChild(elem);},setDashPattern:function(value){var elem=doc.createElement('dashpattern');elem.setAttribute('pattern',value);root.appendChild(elem);},setLineCap:function(value){var elem=doc.createElement('linecap');elem.setAttribute('cap',value);root.appendChild(elem);},setLineJoin:function(value){var elem=doc.createElement('linejoin');elem.setAttribute('join',value);root.appendChild(elem);},setMiterLimit:function(value){var elem=doc.createElement('miterlimit');elem.setAttribute('limit',value);root.appendChild(elem);},setFontSize:function(value){if(textEnabled){if(compressed){if(state.fontsize==value){return;}state.fontsize=value;}var elem=doc.createElement('fontsize');elem.setAttribute('size',value);root.appendChild(elem);}},setFontColor:function(value){if(textEnabled){if(compressed){if(state.fontcolor==value){return;}state.fontcolor=value;}var elem=doc.createElement('fontcolor');elem.setAttribute('color',value);root.appendChild(elem);}},setFontFamily:function(value){if(textEnabled){if(compressed){if(state.fontfamily==value){return;}state.fontfamily=value;}var elem=doc.createElement('fontfamily');elem.setAttribute('family',value);root.appendChild(elem);}},setFontStyle:function(value){if(textEnabled){var elem=doc.createElement('fontstyle');elem.setAttribute('style',value);root.appendChild(elem);}},setAlpha:function(alpha){if(compressed){if(state.alpha==alpha){return;}state.alpha=alpha;}var elem=doc.createElement('alpha');elem.setAttribute('alpha',f2(alpha));root.appendChild(elem);},setFillColor:function(value){var elem=doc.createElement('fillcolor');elem.setAttribute('color',value);root.appendChild(elem);},setGradient:function(color1,color2,x,y,w,h,direction){var elem=doc.createElement('gradient');elem.setAttribute('c1',color1);elem.setAttribute('c2',color2);elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));if(direction!=null){elem.setAttribute('direction',direction);}root.appendChild(elem);},setGlassGradient:function(x,y,w,h){var elem=doc.createElement('glass');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));root.appendChild(elem);},rect:function(x,y,w,h){var elem=doc.createElement('rect');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));root.appendChild(elem);},roundrect:function(x,y,w,h,dx,dy){var elem=doc.createElement('roundrect');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));elem.setAttribute('dx',f2(dx));elem.setAttribute('dy',f2(dy));root.appendChild(elem);},ellipse:function(x,y,w,h){var elem=doc.createElement('ellipse');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));root.appendChild(elem);},image:function(x,y,w,h,src,aspect,flipH,flipV){src=converter.convert(src);var elem=doc.createElement('image');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));elem.setAttribute('src',src);elem.setAttribute('aspect',(aspect)?'1':'0');elem.setAttribute('flipH',(flipH)?'1':'0');elem.setAttribute('flipV',(flipV)?'1':'0');root.appendChild(elem);},text:function(x,y,w,h,str,align,valign,vertical,wrap,format){if(textEnabled){var elem=doc.createElement('text');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));elem.setAttribute('w',f2(w));elem.setAttribute('h',f2(h));elem.setAttribute('str',str);if(align!=null){elem.setAttribute('align',align);}if(valign!=null){elem.setAttribute('valign',valign);}elem.setAttribute('vertical',(vertical)?'1':'0');elem.setAttribute('wrap',(wrap)?'1':'0');elem.setAttribute('format',format);root.appendChild(elem);}},begin:function(){root.appendChild(doc.createElement('begin'));},moveTo:function(x,y){var elem=doc.createElement('move');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));root.appendChild(elem);},lineTo:function(x,y){var elem=doc.createElement('line');elem.setAttribute('x',f2(x));elem.setAttribute('y',f2(y));root.appendChild(elem);},quadTo:function(x1,y1,x2,y2){var elem=doc.createElement('quad');elem.setAttribute('x1',f2(x1));elem.setAttribute('y1',f2(y1));elem.setAttribute('x2',f2(x2));elem.setAttribute('y2',f2(y2));root.appendChild(elem);},curveTo:function(x1,y1,x2,y2,x3,y3){var elem=doc.createElement('curve');elem.setAttribute('x1',f2(x1));elem.setAttribute('y1',f2(y1));elem.setAttribute('x2',f2(x2));elem.setAttribute('y2',f2(y2));elem.setAttribute('x3',f2(x3));elem.setAttribute('y3',f2(y3));root.appendChild(elem);},close:function(){root.appendChild(doc.createElement('close'));},stroke:function(){root.appendChild(doc.createElement('stroke'));},fill:function(){root.appendChild(doc.createElement('fill'));},fillAndStroke:function(){root.appendChild(doc.createElement('fillstroke'));},shadow:function(value,filled){var elem=doc.createElement('shadow');elem.setAttribute('value',value);if(filled!=null){elem.setAttribute('filled',(filled)?'1':'0');}root.appendChild(elem);},clip:function(){root.appendChild(doc.createElement('clip'));}};};var mxSvgCanvas2D=function(root,styleEnabled){styleEnabled=(styleEnabled!=null)?styleEnabled:false;var converter=new mxUrlConverter();var autoAntiAlias=true;var textEnabled=true;var foEnabled=true;var create=function(tagName,namespace){if(root.ownerDocument.createElementNS!=null){return root.ownerDocument.createElementNS(namespace||mxConstants.NS_SVG,tagName);}else{var elt=root.ownerDocument.createElement(tagName);if(namespace!=null){elt.setAttribute('xmlns',namespace);}return elt;}};var defs=create('defs');if(styleEnabled){var style=create('style');style.setAttribute('type','text/css');mxUtils.write(style,'svg{font-family:'+mxConstants.DEFAULT_FONTFAMILY+';font-size:'+mxConstants.DEFAULT_FONTSIZE+';fill:none;stroke-miterlimit:10}');if(autoAntiAlias){mxUtils.write(style,'rect{shape-rendering:crispEdges}');}defs.appendChild(style);}root.appendChild(defs);var currentState={dx:0,dy:0,scale:1,transform:'',fill:null,gradient:null,stroke:null,strokeWidth:1,dashed:false,dashpattern:'3 3',alpha:1,linecap:'flat',linejoin:'miter',miterlimit:10,fontColor:'#000000',fontSize:mxConstants.DEFAULT_FONTSIZE,fontFamily:mxConstants.DEFAULT_FONTFAMILY,fontStyle:0};var currentPathIsOrthogonal=true;var glassGradient=null;var currentNode=null;var currentPath=null;var lastPoint=null;var gradients=[];var refCount=0;var stack=[];var createGradientId=function(start,end,direction){if(start.charAt(0)=='#'){start=start.substring(1);}if(end.charAt(0)=='#'){end=end.substring(1);}start=start.toLowerCase();end=end.toLowerCase();var dir=null;if(direction==null||direction==mxConstants.DIRECTION_SOUTH){dir='s';}else if(direction==mxConstants.DIRECTION_EAST){dir='e';}else{var tmp=start;start=end;end=tmp;if(direction==mxConstants.DIRECTION_NORTH){dir='s';}else if(direction==mxConstants.DIRECTION_WEST){dir='e';}}return start+'-'+end+'-'+dir;};var createHtmlBody=function(str,align,valign){var style='margin:0px;font-size:'+Math.floor(currentState.fontSize)+'px;'+'font-family:'+currentState.fontFamily+';color:'+currentState.fontColor+';';if((currentState.fontStyle&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD){style+='font-weight:bold;';}if((currentState.fontStyle&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC){style+='font-style:italic;';}if((currentState.fontStyle&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE){style+='font-decoration:underline;';}if(align==mxConstants.ALIGN_CENTER){style+='text-align:center;';}else if(align==mxConstants.ALIGN_RIGHT){style+='text-align:right;';}var body=create('body','http://www.w3.org/1999/xhtml');body.setAttribute('style',style);var node=mxUtils.parseXml('
'+str+'
').documentElement;if(body.ownerDocument.importNode!=null){node=body.ownerDocument.importNode(node,true);}body.appendChild(node);return body;};var getSvgGradient=function(start,end,direction){var id=createGradientId(start,end,direction);var gradient=gradients[id];if(gradient==null){gradient=create('linearGradient');gradient.setAttribute('id',++refCount);gradient.setAttribute('x1','0%');gradient.setAttribute('y1','0%');gradient.setAttribute('x2','0%');gradient.setAttribute('y2','0%');if(direction==null||direction==mxConstants.DIRECTION_SOUTH){gradient.setAttribute('y2','100%');}else if(direction==mxConstants.DIRECTION_EAST){gradient.setAttribute('x2','100%');}else if(direction==mxConstants.DIRECTION_NORTH){gradient.setAttribute('y1','100%');}else if(direction==mxConstants.DIRECTION_WEST){gradient.setAttribute('x1','100%');}var stop=create('stop');stop.setAttribute('offset','0%');stop.setAttribute('style','stop-color:'+start);gradient.appendChild(stop);stop=create('stop');stop.setAttribute('offset','100%');stop.setAttribute('style','stop-color:'+end);gradient.appendChild(stop);defs.appendChild(gradient);gradients[id]=gradient;}return gradient.getAttribute('id');};var appendNode=function(node,state,filled,stroked){if(node!=null){if(state.clip!=null){node.setAttribute('clip-path','url(#'+state.clip+')');state.clip=null;}if(currentPath!=null){node.setAttribute('d',currentPath.join(' '));currentPath=null;if(autoAntiAlias&¤tPathIsOrthogonal){node.setAttribute('shape-rendering','crispEdges');state.strokeWidth=Math.max(1,state.strokeWidth);}}if(state.alpha<1){node.setAttribute('opacity',state.alpha);}if(filled&&(state.fill!=null||state.gradient!=null)){if(state.gradient!=null){node.setAttribute('fill','url(#'+state.gradient+')');}else{node.setAttribute('fill',state.fill.toLowerCase());}}else if(!styleEnabled){node.setAttribute('fill','none');}if(stroked&&state.stroke!=null){node.setAttribute('stroke',state.stroke.toLowerCase());if(state.strokeWidth!=1){if(node.nodeName=='rect'&&autoAntiAlias){state.strokeWidth=Math.max(1,state.strokeWidth);}node.setAttribute('stroke-width',state.strokeWidth);}if(node.nodeName=='path'){if(state.linejoin!=null&&state.linejoin!='miter'){node.setAttribute('stroke-linejoin',state.linejoin);}if(state.linecap!=null){var value=state.linecap;if(value=='flat'){value='butt';}if(value!='butt'){node.setAttribute('stroke-linecap',value);}}if(state.miterlimit!=null&&(!styleEnabled||state.miterlimit!=10)){node.setAttribute('stroke-miterlimit',state.miterlimit);}}if(state.dashed){var dash=state.dashpattern.split(' ');if(dash.length>0){var pat=[];for(var i=0;i0){node.setAttribute('transform',state.transform);}root.appendChild(node);}};var f2=function(x){return Math.round(parseFloat(x)*100)/100;};return{getConverter:function(){return converter;},isAutoAntiAlias:function(){return autoAntiAlias;},setAutoAntiAlias:function(value){autoAntiAlias=value;},isTextEnabled:function(){return textEnabled;},setTextEnabled:function(value){textEnabled=value;},isFoEnabled:function(){return foEnabled;},setFoEnabled:function(value){foEnabled=value;},save:function(){stack.push(currentState);currentState=mxUtils.clone(currentState);},restore:function(){currentState=stack.pop();},scale:function(value){currentState.scale*=value;currentState.strokeWidth*=value;},translate:function(dx,dy){currentState.dx+=dx;currentState.dy+=dy;},rotate:function(theta,flipH,flipV,cx,cy){cx+=currentState.dx;cy+=currentState.dy;cx*=currentState.scale;cy*=currentState.scale;if(flipH^flipV){var tx=(flipH)?cx:0;var sx=(flipH)?-1:1;var ty=(flipV)?cy:0;var sy=(flipV)?-1:1;currentState.transform+='translate('+f2(tx)+','+f2(ty)+')';currentState.transform+='scale('+f2(sx)+','+f2(sy)+')';currentState.transform+='translate('+f2(-tx)+' '+f2(-ty)+')';}currentState.transform+='rotate('+f2(theta)+','+f2(cx)+','+f2(cy)+')';},setStrokeWidth:function(value){currentState.strokeWidth=value*currentState.scale;},setStrokeColor:function(value){currentState.stroke=value;},setDashed:function(value){currentState.dashed=value;},setDashPattern:function(value){currentState.dashpattern=value;},setLineCap:function(value){currentState.linecap=value;},setLineJoin:function(value){currentState.linejoin=value;},setMiterLimit:function(value){currentState.miterlimit=value;},setFontSize:function(value){currentState.fontSize=value;},setFontColor:function(value){currentState.fontColor=value;},setFontFamily:function(value){currentState.fontFamily=value;},setFontStyle:function(value){currentState.fontStyle=value;},setAlpha:function(alpha){currentState.alpha=alpha;},setFillColor:function(value){currentState.fill=value;currentState.gradient=null;},setGradient:function(color1,color2,x,y,w,h,direction){if(color1!=null&&color2!=null){currentState.gradient=getSvgGradient(color1,color2,direction);currentState.fill=color1;}},setGlassGradient:function(x,y,w,h){if(glassGradient==null){glassGradient=create('linearGradient');glassGradient.setAttribute('id','0');glassGradient.setAttribute('x1','0%');glassGradient.setAttribute('y1','0%');glassGradient.setAttribute('x2','0%');glassGradient.setAttribute('y2','100%');var stop1=create('stop');stop1.setAttribute('offset','0%');stop1.setAttribute('style','stop-color:#ffffff;stop-opacity:0.9');glassGradient.appendChild(stop1);var stop2=create('stop');stop2.setAttribute('offset','100%');stop2.setAttribute('style','stop-color:#ffffff;stop-opacity:0.1');glassGradient.appendChild(stop2);if(defs.firstChild.nextSibling!=null){defs.insertBefore(glassGradient,defs.firstChild.nextSibling);}else{defs.appendChild(glassGradient);}}currentState.gradient='0';},rect:function(x,y,w,h){x+=currentState.dx;y+=currentState.dy;currentNode=create('rect');currentNode.setAttribute('x',f2(x*currentState.scale));currentNode.setAttribute('y',f2(y*currentState.scale));currentNode.setAttribute('width',f2(w*currentState.scale));currentNode.setAttribute('height',f2(h*currentState.scale));if(!styleEnabled&&autoAntiAlias){currentNode.setAttribute('shape-rendering','crispEdges');}},roundrect:function(x,y,w,h,dx,dy){x+=currentState.dx;y+=currentState.dy;currentNode=create('rect');currentNode.setAttribute('x',f2(x*currentState.scale));currentNode.setAttribute('y',f2(y*currentState.scale));currentNode.setAttribute('width',f2(w*currentState.scale));currentNode.setAttribute('height',f2(h*currentState.scale));if(dx>0){currentNode.setAttribute('rx',f2(dx*currentState.scale));}if(dy>0){currentNode.setAttribute('ry',f2(dy*currentState.scale));}if(!styleEnabled&&autoAntiAlias){currentNode.setAttribute('shape-rendering','crispEdges');}},ellipse:function(x,y,w,h){x+=currentState.dx;y+=currentState.dy;currentNode=create('ellipse');currentNode.setAttribute('cx',f2((x+w/2)*currentState.scale));currentNode.setAttribute('cy',f2((y+h/2)*currentState.scale));currentNode.setAttribute('rx',f2(w/2*currentState.scale));currentNode.setAttribute('ry',f2(h/2*currentState.scale));},image:function(x,y,w,h,src,aspect,flipH,flipV){src=converter.convert(src);aspect=(aspect!=null)?aspect:true;flipH=(flipH!=null)?flipH:false;flipV=(flipV!=null)?flipV:false;x+=currentState.dx;y+=currentState.dy;var node=create('image');node.setAttribute('x',f2(x*currentState.scale));node.setAttribute('y',f2(y*currentState.scale));node.setAttribute('width',f2(w*currentState.scale));node.setAttribute('height',f2(h*currentState.scale));if(mxClient.IS_VML){node.setAttribute('xlink:href',src);}else{node.setAttributeNS(mxConstants.NS_XLINK,'xlink:href',src);}if(!aspect){node.setAttribute('preserveAspectRatio','none');}if(currentState.alpha<1){node.setAttribute('opacity',currentState.alpha);}var tr=currentState.transform;if(flipH||flipV){var sx=1;var sy=1;var dx=0;var dy=0;if(flipH){sx=-1;dx=-w-2*x;}if(flipV){sy=-1;dy=-h-2*y;}tr+='scale('+sx+','+sy+')translate('+dx+','+dy+')';}if(tr.length>0){node.setAttribute('transform',tr);}root.appendChild(node);},text:function(x,y,w,h,str,align,valign,vertical,wrap,format){if(textEnabled){x+=currentState.dx;y+=currentState.dy;if(foEnabled&&format=='html'){var node=create('g');node.setAttribute('transform',currentState.transform+'scale('+currentState.scale+','+currentState.scale+')');if(currentState.alpha<1){node.setAttribute('opacity',currentState.alpha);}var fo=create('foreignObject');fo.setAttribute('x',Math.round(x));fo.setAttribute('y',Math.round(y));fo.setAttribute('width',Math.round(w));fo.setAttribute('height',Math.round(h));fo.appendChild(createHtmlBody(str,align,valign));node.appendChild(fo);root.appendChild(node);}else{var size=Math.floor(currentState.fontSize);var node=create('g');var tr=currentState.transform;if(vertical){var cx=x+w/2;var cy=y+h/2;tr+='rotate(-90,'+f2(cx*currentState.scale)+','+f2(cy*currentState.scale)+')';}if(tr.length>0){node.setAttribute('transform',tr);}if(currentState.alpha<1){node.setAttribute('opacity',currentState.alpha);}var anchor=(align==mxConstants.ALIGN_RIGHT)?'end':(align==mxConstants.ALIGN_CENTER)?'middle':'start';if(anchor=='end'){x+=Math.max(0,w-2);}else if(anchor=='middle'){x+=w/2;}else{x+=(w>0)?2:0;}if((currentState.fontStyle&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD){node.setAttribute('font-weight','bold');}if((currentState.fontStyle&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC){node.setAttribute('font-style','italic');}if((currentState.fontStyle&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE){node.setAttribute('text-decoration','underline');}if(anchor!='start'){node.setAttribute('text-anchor',anchor);}if(!styleEnabled||size!=mxConstants.DEFAULT_FONTSIZE){node.setAttribute('font-size',Math.floor(size*currentState.scale)+'px');}if(!styleEnabled||currentState.fontFamily!=mxConstants.DEFAULT_FONTFAMILY){node.setAttribute('font-family',currentState.fontFamily);}node.setAttribute('fill',currentState.fontColor);var lines=str.split('\n');var lineHeight=size*1.25;var textHeight=(h>0)?size+(lines.length-1)*lineHeight:lines.length*lineHeight-1;var dy=h-textHeight;if(valign==null||valign==mxConstants.ALIGN_TOP){y=Math.max(y-3*currentState.scale,y+dy/2+((h>0)?lineHeight/2-8:0));}else if(valign==mxConstants.ALIGN_MIDDLE){y=y+dy/2;}else if(valign==mxConstants.ALIGN_BOTTOM){y=Math.min(y,y+dy+2*currentState.scale);}y+=size;for(var i=0;i=1&&!this.isRounded){this.innerNode.setAttribute('shape-rendering','optimizeSpeed');}this.shadowNode=this.createSvgShadow(this.innerNode);if(this.shadowNode!=null){g.appendChild(this.shadowNode);}g.appendChild(this.innerNode);return g;};mxShape.prototype.createSvgShadow=function(node){if(this.isShadow){var shadow=node.cloneNode(true);shadow.setAttribute('opacity',mxConstants.SHADOW_OPACITY);if(this.fill!=null&&this.fill!=mxConstants.NONE){shadow.setAttribute('fill',mxConstants.SHADOWCOLOR);}if(this.stroke!=null&&this.stroke!=mxConstants.NONE){shadow.setAttribute('stroke',mxConstants.SHADOWCOLOR);}return shadow;}return null;};mxShape.prototype.configureHtmlShape=function(node){if(mxUtils.isVml(node)){this.configureVmlShape(node);}else{node.style.position='absolute';node.style.overflow='hidden';var color=this.stroke;if(color!=null&&color!=mxConstants.NONE){node.style.borderColor=color;if(this.isDashed){node.style.borderStyle='dashed';}else if(this.strokewidth>0){node.style.borderStyle='solid';}node.style.borderWidth=Math.ceil(this.strokewidth*this.scale)+'px';}else{node.style.borderWidth='0px';}color=this.fill;node.style.background='';if(color!=null&&color!=mxConstants.NONE){node.style.backgroundColor=color;}else if(this.points==null){this.configureTransparentBackground(node);}if(this.opacity!=null){mxUtils.setOpacity(node,this.opacity);}}};mxShape.prototype.updateVmlFill=function(node,c1,c2,dir,alpha){node.color=c1;if(alpha!=null&&alpha!=100){node.opacity=alpha+'%';if(c2!=null){node.setAttribute('o:opacity2',alpha+'%');}}if(c2!=null){node.type='gradient';node.color2=c2;var angle='180';if(this.gradientDirection==mxConstants.DIRECTION_EAST){angle='270';}else if(this.gradientDirection==mxConstants.DIRECTION_WEST){angle='90';}else if(this.gradientDirection==mxConstants.DIRECTION_NORTH){angle='0';}node.angle=angle;}};mxShape.prototype.updateVmlStrokeNode=function(parent){if(this.strokeNode==null){this.strokeNode=document.createElement('v:stroke');this.strokeNode.joinstyle='miter';this.strokeNode.miterlimit=4;parent.appendChild(this.strokeNode);}if(this.opacity!=null){this.strokeNode.opacity=this.opacity+'%';}this.updateVmlDashStyle();};mxShape.prototype.updateVmlStrokeColor=function(node){var color=this.stroke;if(color!=null&&color!=mxConstants.NONE){node.stroked='true';node.strokecolor=color;}else{node.stroked='false';}};mxShape.prototype.configureVmlShape=function(node){node.style.position='absolute';this.updateVmlStrokeColor(node);node.style.background='';var color=this.fill;if(color!=null&&color!=mxConstants.NONE){if(this.fillNode==null){this.fillNode=document.createElement('v:fill');node.appendChild(this.fillNode);}this.updateVmlFill(this.fillNode,color,this.gradient,this.gradientDirection,this.opacity);}else{node.filled='false';if(this.points==null){this.configureTransparentBackground(node);}}this.updateVmlStrokeNode(node);if(this.isShadow){this.createVmlShadow(node);}if(node.nodeName=='roundrect'){try{var f=mxConstants.RECTANGLE_ROUNDING_FACTOR*100;if(this.style!=null){f=mxUtils.getValue(this.style,mxConstants.STYLE_ARCSIZE,f);}node.setAttribute('arcsize',String(f)+'%');}catch(e){}}};mxShape.prototype.createVmlShadow=function(node){if(this.shadowNode==null){this.shadowNode=document.createElement('v:shadow');this.shadowNode.on='true';this.shadowNode.color=mxConstants.SHADOWCOLOR;this.shadowNode.opacity=(mxConstants.SHADOW_OPACITY*100)+'%';this.shadowStrokeNode=document.createElement('v:stroke');this.shadowNode.appendChild(this.shadowStrokeNode);node.appendChild(this.shadowNode);}};mxShape.prototype.configureTransparentBackground=function(node){node.style.background='url(\''+mxClient.imageBasePath+'/transparent.gif\')';};mxShape.prototype.configureSvgShape=function(node){var color=this.stroke;if(color!=null&&color!=mxConstants.NONE){node.setAttribute('stroke',color);}else{node.setAttribute('stroke','none');}color=this.fill;if(color!=null&&color!=mxConstants.NONE){if(this.gradient!=null){var id=this.getGradientId(color,this.gradient);if(this.gradientNode!=null&&this.gradientNode.getAttribute('id')!=id){this.gradientNode=null;node.setAttribute('fill','');}if(this.gradientNode==null){this.gradientNode=this.createSvgGradient(id,color,this.gradient,node);node.setAttribute('fill','url(#'+id+')');}}else{this.gradientNode=null;node.setAttribute('fill',color);}}else{node.setAttribute('fill','none');}if(this.opacity!=null){node.setAttribute('fill-opacity',this.opacity/100);node.setAttribute('stroke-opacity',this.opacity/100);}};mxShape.prototype.getGradientId=function(start,end){if(start.charAt(0)=='#'){start=start.substring(1);}if(end.charAt(0)=='#'){end=end.substring(1);}start=start.toLowerCase();end=end.toLowerCase();var dir=null;if(this.gradientDirection==null||this.gradientDirection==mxConstants.DIRECTION_SOUTH){dir='south';}else if(this.gradientDirection==mxConstants.DIRECTION_EAST){dir='east';}else{var tmp=start;start=end;end=tmp;if(this.gradientDirection==mxConstants.DIRECTION_NORTH){dir='south';}else if(this.gradientDirection==mxConstants.DIRECTION_WEST){dir='east';}}return 'mx-gradient-'+start+'-'+end+'-'+dir;};mxShape.prototype.createSvgPipe=function(id,start,end,node){var pipe=document.createElementNS(mxConstants.NS_SVG,'path');pipe.setAttribute('pointer-events','stroke');pipe.setAttribute('fill','none');pipe.setAttribute('visibility','hidden');pipe.setAttribute('stroke',(mxClient.IS_OP)?'none':'white');return pipe;};mxShape.prototype.createSvgGradient=function(id,start,end,node){var gradient=this.insertGradientNode;if(gradient==null){gradient=document.createElementNS(mxConstants.NS_SVG,'linearGradient');gradient.setAttribute('id',id);gradient.setAttribute('x1','0%');gradient.setAttribute('y1','0%');gradient.setAttribute('x2','0%');gradient.setAttribute('y2','0%');if(this.gradientDirection==null||this.gradientDirection==mxConstants.DIRECTION_SOUTH){gradient.setAttribute('y2','100%');}else if(this.gradientDirection==mxConstants.DIRECTION_EAST){gradient.setAttribute('x2','100%');}else if(this.gradientDirection==mxConstants.DIRECTION_NORTH){gradient.setAttribute('y1','100%');}else if(this.gradientDirection==mxConstants.DIRECTION_WEST){gradient.setAttribute('x1','100%');}var stop=document.createElementNS(mxConstants.NS_SVG,'stop');stop.setAttribute('offset','0%');stop.setAttribute('style','stop-color:'+start);gradient.appendChild(stop);stop=document.createElementNS(mxConstants.NS_SVG,'stop');stop.setAttribute('offset','100%');stop.setAttribute('style','stop-color:'+end);gradient.appendChild(stop);}this.insertGradientNode=gradient;return gradient;};mxShape.prototype.createPoints=function(moveCmd,lineCmd,curveCmd,isRelative){var offsetX=(isRelative)?this.bounds.x:0;var offsetY=(isRelative)?this.bounds.y:0;var crisp=(this.crisp&&this.dialect==mxConstants.DIALECT_SVG&&mxClient.IS_IE)?0.5:0;if(isNaN(this.points[0].x)||isNaN(this.points[0].y)){return null;}var size=mxConstants.LINE_ARCSIZE*this.scale;var p0=this.points[0];if(this.startOffset!=null){p0=p0.clone();p0.x+=this.startOffset.x;p0.y+=this.startOffset.y;}var points=moveCmd+' '+(Math.round(p0.x-offsetX)+crisp)+' '+(Math.round(p0.y-offsetY)+crisp)+' ';for(var i=1;i0.3){var dist=Math.sqrt(dx*dx+dy*dy);var nx1=dx*Math.min(size,dist/2)/dist;var ny1=dy*Math.min(size,dist/2)/dist;points+=lineCmd+' '+(Math.round(pt.x+nx1-offsetX)+crisp)+' '+(Math.round(pt.y+ny1-offsetY)+crisp)+' ';var pe=this.points[i+1];dx=pe.x-pt.x;dy=pe.y-pt.y;dist=Math.max(1,Math.sqrt(dx*dx+dy*dy));if(dist!=0){var nx2=dx*Math.min(size,dist/2)/dist;var ny2=dy*Math.min(size,dist/2)/dist;points+=curveCmd+' '+Math.round(pt.x-offsetX)+' '+Math.round(pt.y-offsetY)+' '+Math.round(pt.x-offsetX)+','+Math.round(pt.y-offsetY)+' '+(Math.round(pt.x+nx2-offsetX)+crisp)+' '+(Math.round(pt.y+ny2-offsetY)+crisp)+' ';}}else{points+=lineCmd+' '+(Math.round(pt.x-offsetX)+crisp)+' '+(Math.round(pt.y-offsetY)+crisp)+' ';}}return points;};mxShape.prototype.updateHtmlShape=function(node){if(node!=null){if(mxUtils.isVml(node)){this.updateVmlShape(node);}else{var sw=Math.ceil(this.strokewidth*this.scale);node.style.borderWidth=Math.max(1,sw)+'px';if(this.bounds!=null&&!isNaN(this.bounds.x)&&!isNaN(this.bounds.y)&&!isNaN(this.bounds.width)&&!isNaN(this.bounds.height)){node.style.left=Math.round(this.bounds.x-sw/2)+'px';node.style.top=Math.round(this.bounds.y-sw/2)+'px';if(document.compatMode=='CSS1Compat'){sw=-sw;}node.style.width=Math.round(Math.max(0,this.bounds.width+sw))+'px';node.style.height=Math.round(Math.max(0,this.bounds.height+sw))+'px';if(this.bounds.width==0||this.bounds.height==0){node.style.visibility='hidden';}else{node.style.visibility='visible';}}}if(this.points!=null&&this.bounds!=null&&!mxUtils.isVml(node)){if(this.divContainer==null){this.divContainer=node;}while(this.divContainer.firstChild!=null){mxEvent.release(this.divContainer.firstChild);this.divContainer.removeChild(this.divContainer.firstChild);}node.style.borderStyle='';node.style.background='';if(this.points.length==2){var p0=this.points[0];var pe=this.points[1];var dx=pe.x-p0.x;var dy=pe.y-p0.y;if(dx==0||dy==0){node.style.borderStyle='solid';}else{node.style.width=Math.round(this.bounds.width+1)+'px';node.style.height=Math.round(this.bounds.height+1)+'px';var length=Math.sqrt(dx*dx+dy*dy);var dotCount=1+(length/(8*this.scale));var nx=dx/dotCount;var ny=dy/dotCount;var x=p0.x-this.bounds.x;var y=p0.y-this.bounds.y;for(var i=0;i3){var x0=this.bounds.x;var y0=this.bounds.y;points='m '+Math.round(pts[0].x-x0)+' '+Math.round(pts[0].y-y0)+' qb';for(var i=1;i3){var points='M '+pts[0].x+' '+pts[0].y+' ';points+=' Q '+pts[1].x+' '+pts[1].y+' '+' '+pts[2].x+' '+pts[2].y;for(var i=3;i0){this.constraints=[];for(var i=0;i0){currentPath.setAttribute('transform',svgTransform);}if(node.getAttribute('crisp')=='1'){currentPath.setAttribute('shape-rendering','crispEdges');}}var childNode=node.firstChild;while(childNode!=null){if(childNode.nodeType==mxConstants.NODETYPE_ELEMENT){renderNode.call(this,childNode);}childNode=childNode.nextSibling;}if(vml){addToPath('e');currentPath.path=currentPoints.join('');}else{currentPath.setAttribute('d',currentPoints.join(''));}}else if(name=='move'){var op=(vml)?'m':'M';this.lastMoveX=round(x0+Number(node.getAttribute('x'))*sx);this.lastMoveY=round(y0+Number(node.getAttribute('y'))*sy);addToPath(op+' '+this.lastMoveX+' '+this.lastMoveY);}else if(name=='line'){var op=(vml)?'l':'L';this.lastMoveX=round(x0+Number(node.getAttribute('x'))*sx);this.lastMoveY=round(y0+Number(node.getAttribute('y'))*sy);addToPath(op+' '+this.lastMoveX+' '+this.lastMoveY);}else if(name=='quad'){if(vml){var cpx0=this.lastMoveX;var cpy0=this.lastMoveY;var qpx1=x0+Number(node.getAttribute('x1'))*sx;var qpy1=y0+Number(node.getAttribute('y1'))*sy;var cpx3=x0+Number(node.getAttribute('x2'))*sx;var cpy3=y0+Number(node.getAttribute('y2'))*sy;var cpx1=cpx0+2/3*(qpx1-cpx0);var cpy1=cpy0+2/3*(qpy1-cpy0);var cpx2=cpx3+2/3*(qpx1-cpx3);var cpy2=cpy3+2/3*(qpy1-cpy3);addToPath('c '+Math.round(cpx1)+' '+Math.round(cpy1)+' '+Math.round(cpx2)+' '+Math.round(cpy2)+' '+Math.round(cpx3)+' '+Math.round(cpy3));this.lastMoveX=cpx3;this.lastMoveY=cpy3;}else{this.lastMoveX=x0+Number(node.getAttribute('x2'))*sx;this.lastMoveY=y0+Number(node.getAttribute('y2'))*sy;addToPath('Q '+(x0+Number(node.getAttribute('x1'))*sx)+' '+(y0+Number(node.getAttribute('y1'))*sy)+' '+this.lastMoveX+' '+this.lastMoveY);}}else if(name=='curve'){var op=(vml)?'c':'C';this.lastMoveX=round(x0+Number(node.getAttribute('x3'))*sx);this.lastMoveY=round(y0+Number(node.getAttribute('y3'))*sy);addToPath(op+' '+round(x0+Number(node.getAttribute('x1'))*sx)+' '+round(y0+Number(node.getAttribute('y1'))*sy)+' '+round(x0+Number(node.getAttribute('x2'))*sx)+' '+round(y0+Number(node.getAttribute('y2'))*sy)+' '+this.lastMoveX+' '+this.lastMoveY);}else if(name=='close'){addToPath((vml)?'x':'Z');}else if(name=='rect'||name=='roundrect'){var rounded=name=='roundrect';var x=round(x0+Number(node.getAttribute('x'))*sx);var y=round(y0+Number(node.getAttribute('y'))*sy);var w=round(Number(node.getAttribute('w'))*sx);var h=round(Number(node.getAttribute('h'))*sy);var arcsize=node.getAttribute('arcsize');if(arcsize==0){arcsize=mxConstants.RECTANGLE_ROUNDING_FACTOR*100;}if(vml){currentPath=document.createElement((rounded)?'v:roundrect':'v:rect');currentPath.style.left=x+'px';currentPath.style.top=y+'px';currentPath.style.width=w+'px';currentPath.style.height=h+'px';if(rounded){currentPath.setAttribute('arcsize',String(arcsize)+'%');}}else{currentPath=document.createElementNS(mxConstants.NS_SVG,'rect');currentPath.setAttribute('x',x);currentPath.setAttribute('y',y);currentPath.setAttribute('width',w);currentPath.setAttribute('height',h);if(rounded){var factor=Number(arcsize)/100;var r=Math.min(w*factor,h*factor);currentPath.setAttribute('rx',r);currentPath.setAttribute('ry',r);}if(svgTransform.length>0){currentPath.setAttribute('transform',svgTransform);}if(node.getAttribute('crisp')=='1'){currentPath.setAttribute('shape-rendering','crispEdges');}}configurePath.call(this,currentPath,currentState);}else if(name=='ellipse'){var x=round(x0+Number(node.getAttribute('x'))*sx);var y=round(y0+Number(node.getAttribute('y'))*sy);var w=round(Number(node.getAttribute('w'))*sx);var h=round(Number(node.getAttribute('h'))*sy);if(vml){currentPath=document.createElement('v:arc');currentPath.startangle='0';currentPath.endangle='360';currentPath.style.left=x+'px';currentPath.style.top=y+'px';currentPath.style.width=w+'px';currentPath.style.height=h+'px';}else{currentPath=document.createElementNS(mxConstants.NS_SVG,'ellipse');currentPath.setAttribute('cx',x+w/2);currentPath.setAttribute('cy',y+h/2);currentPath.setAttribute('rx',w/2);currentPath.setAttribute('ry',h/2);if(svgTransform.length>0){currentPath.setAttribute('transform',svgTransform);}}configurePath.call(this,currentPath,currentState);}else if(name=='arc'){var r1=Number(node.getAttribute('rx'))*sx;var r2=Number(node.getAttribute('ry'))*sy;var angle=Number(node.getAttribute('x-axis-rotation'));var largeArcFlag=Number(node.getAttribute('large-arc-flag'));var sweepFlag=Number(node.getAttribute('sweep-flag'));var x=x0+Number(node.getAttribute('x'))*sx;var y=y0+Number(node.getAttribute('y'))*sy;if(vml){var curves=mxUtils.arcToCurves(this.lastMoveX,this.lastMoveY,r1,r2,angle,largeArcFlag,sweepFlag,x,y);for(var i=0;i0){currentPath.setAttribute('transform',svgTransform);}}addToParent(currentPath);}}else if(fillOp||strokeOp||fillStrokeOp){if(currentPath!=null){var pattern=null;if(currentState.dashed){var f=(vml)?minScale:Number(currentPath.getAttribute('stroke-width'));var pat=[];for(var i=0;i0){pat.push(Number(tmp[i])*minScale);}}value=pat.join(' ');canvas.setDashPattern(value);}}else if(name=='strokecolor'){canvas.setStrokeColor(node.getAttribute('color'));}else if(name=='linecap'){canvas.setLineCap(node.getAttribute('cap'));}else if(name=='linejoin'){canvas.setLineJoin(node.getAttribute('join'));}else if(name=='miterlimit'){canvas.setMiterLimit(Number(node.getAttribute('limit')));}else if(name=='fillcolor'){canvas.setFillColor(node.getAttribute('color'));}else if(name=='fontcolor'){canvas.setFontColor(node.getAttribute('color'));}else if(name=='fontstyle'){canvas.setFontStyle(node.getAttribute('style'));}else if(name=='fontfamily'){canvas.setFontFamily(node.getAttribute('family'));}else if(name=='fontsize'){canvas.setFontSize(Number(node.getAttribute('size'))*minScale);}};var mxStencilRegistry={stencils:[],addStencil:function(name,stencil){mxStencilRegistry.stencils[name]=stencil;},getStencil:function(name){return mxStencilRegistry.stencils[name];}};function mxStencilShape(stencil){this.stencil=stencil;};mxStencilShape.prototype=new mxShape();mxStencilShape.prototype.constructor=mxStencilShape;mxStencilShape.prototype.mixedModeHtml=false;mxStencilShape.prototype.preferModeHtml=false;mxStencilShape.prototype.stencil=null;mxStencilShape.prototype.state=null;mxStencilShape.prototype.vmlScale=4;mxStencilShape.prototype.apply=function(state){this.state=state;mxShape.prototype.apply.apply(this,arguments);};mxStencilShape.prototype.createSvg=function(){var node=document.createElementNS(mxConstants.NS_SVG,'g');this.configureSvgShape(node);return node;};mxStencilShape.prototype.configureHtmlShape=function(node){mxShape.prototype.configureHtmlShape.apply(this,arguments);if(!mxUtils.isVml(node)){node.style.overflow='visible';}};mxStencilShape.prototype.createVml=function(){var name=(document.documentMode==8)?'div':'v:group';var node=document.createElement(name);this.configureTransparentBackground(node);node.style.position='absolute';return node;};mxStencilShape.prototype.configureVmlShape=function(node){};mxStencilShape.prototype.redraw=function(){this.updateBoundingBox();if(this.dialect==mxConstants.DIALECT_SVG){this.redrawShape();}else{this.node.style.visibility='hidden';this.redrawShape();this.node.style.visibility='visible';}};mxStencilShape.prototype.redrawShape=function(){if(this.dialect!=mxConstants.DIALECT_SVG){this.node.innerHTML='';this.node.style.left=Math.round(this.bounds.x)+'px';this.node.style.top=Math.round(this.bounds.y)+'px';var w=Math.round(this.bounds.width);var h=Math.round(this.bounds.height);this.node.style.width=w+'px';this.node.style.height=h+'px';if(mxUtils.isVml(this.node)){this.node.coordsize=(w*this.vmlScale)+','+(h*this.vmlScale);}}else{while(this.node.firstChild!=null){this.node.removeChild(this.node.firstChild);}}this.stencil.renderDom(this,this.bounds,this.node);};var mxMarker={markers:[],paintMarker:function(node,type,p0,pe,color,strokewidth,size,scale,x0,y0,source,style){var marker=mxMarker.markers[type];var result=null;if(marker!=null){var isVml=mxUtils.isVml(node);var dx=pe.x-p0.x;var dy=pe.y-p0.y;if(isNaN(dx)||isNaN(dy)){return;}var dist=Math.max(1,Math.sqrt(dx*dx+dy*dy));var nx=dx*scale/dist;var ny=dy*scale/dist;pe=pe.clone();if(isVml){pe.x-=x0;pe.y-=y0;}var filled=true;var key=(source)?mxConstants.STYLE_STARTFILL:mxConstants.STYLE_ENDFILL;if(style[key]==0){filled=false;}if(isVml){node.strokecolor=color;if(filled){node.fillcolor=color;}else{node.filled='false';}}else{node.setAttribute('stroke',color);var op=(style.opacity!=null)?style.opacity/100:1;node.setAttribute('stroke-opacity',op);if(filled){node.setAttribute('fill',color);node.setAttribute('fill-opacity',op);}else{node.setAttribute('fill','none');}}result=marker.call(this,node,type,pe,nx,ny,strokewidth,size,scale,isVml);}return result;}};(function(){var tmp=function(node,type,pe,nx,ny,strokewidth,size,scale,isVml){var endOffsetX=nx*strokewidth*1.118;var endOffsetY=ny*strokewidth*1.118;pe.x-=endOffsetX;pe.y-=endOffsetY;nx=nx*(size+strokewidth);ny=ny*(size+strokewidth);if(isVml){node.path='m'+Math.round(pe.x)+','+Math.round(pe.y)+' l'+Math.round(pe.x-nx-ny/2)+' '+Math.round(pe.y-ny+nx/2)+((type!=mxConstants.ARROW_CLASSIC)?'':' '+Math.round(pe.x-nx*3/4)+' '+Math.round(pe.y-ny*3/4))+' '+Math.round(pe.x+ny/2-nx)+' '+Math.round(pe.y-ny-nx/2)+' x e';node.setAttribute('strokeweight',(strokewidth*scale)+'px');}else{node.setAttribute('d','M '+pe.x+' '+pe.y+' L '+(pe.x-nx-ny/2)+' '+(pe.y-ny+nx/2)+((type!=mxConstants.ARROW_CLASSIC)?'':' L '+(pe.x-nx*3/4)+' '+(pe.y-ny*3/4))+' L '+(pe.x+ny/2-nx)+' '+(pe.y-ny-nx/2)+' z');node.setAttribute('stroke-width',strokewidth*scale);}var f=(type!=mxConstants.ARROW_CLASSIC)?1:3/4;return new mxPoint(-nx*f-endOffsetX,-ny*f-endOffsetY);};mxMarker.markers[mxConstants.ARROW_CLASSIC]=tmp;mxMarker.markers[mxConstants.ARROW_BLOCK]=tmp;}());mxMarker.markers[mxConstants.ARROW_OPEN]=function(node,type,pe,nx,ny,strokewidth,size,scale,isVml){var endOffsetX=nx*strokewidth*1.118;var endOffsetY=ny*strokewidth*1.118;pe.x-=endOffsetX;pe.y-=endOffsetY;nx=nx*(size+strokewidth);ny=ny*(size+strokewidth);if(isVml){node.path='m'+Math.round(pe.x-nx-ny/2)+' '+Math.round(pe.y-ny+nx/2)+' l'+Math.round(pe.x)+' '+Math.round(pe.y)+' '+Math.round(pe.x+ny/2-nx)+' '+Math.round(pe.y-ny-nx/2)+' e nf';node.setAttribute('strokeweight',(strokewidth*scale)+'px');}else{node.setAttribute('d','M '+(pe.x-nx-ny/2)+' '+(pe.y-ny+nx/2)+' L '+(pe.x)+' '+(pe.y)+' L '+(pe.x+ny/2-nx)+' '+(pe.y-ny-nx/2));node.setAttribute('stroke-width',strokewidth*scale);node.setAttribute('fill','none');}return new mxPoint(-endOffsetX*2,-endOffsetY*2);};mxMarker.markers[mxConstants.ARROW_OVAL]=function(node,type,pe,nx,ny,strokewidth,size,scale,isVml){nx*=size;ny*=size;nx*=0.5+strokewidth/2;ny*=0.5+strokewidth/2;var absSize=size*scale;var radius=absSize/2;if(isVml){node.path='m'+Math.round(pe.x+radius)+' '+Math.round(pe.y)+' at '+Math.round(pe.x-radius)+' '+Math.round(pe.y-radius)+' '+Math.round(pe.x+radius)+' '+Math.round(pe.y+radius)+' '+Math.round(pe.x+radius)+' '+Math.round(pe.y)+' '+Math.round(pe.x+radius)+' '+Math.round(pe.y)+' x e';node.setAttribute('strokeweight',(strokewidth*scale)+'px');}else{node.setAttribute('d','M '+(pe.x-radius)+' '+(pe.y)+' a '+(radius)+' '+(radius)+' 0 1,1 '+(absSize)+' 0'+' a '+(radius)+' '+(radius)+' 0 1,1 '+(-absSize)+' 0 z');node.setAttribute('stroke-width',strokewidth*scale);}return new mxPoint(-nx/(2+strokewidth),-ny/(2+strokewidth));};(function(){var tmp_diamond=function(node,type,pe,nx,ny,strokewidth,size,scale,isVml){var swFactor=(type==mxConstants.ARROW_DIAMOND)?0.7071:0.9862;var endOffsetX=nx*strokewidth*swFactor;var endOffsetY=ny*strokewidth*swFactor;nx=nx*(size+strokewidth);ny=ny*(size+strokewidth);pe.x-=endOffsetX+nx/2;pe.y-=endOffsetY+ny/2;var tk=((type==mxConstants.ARROW_DIAMOND)?2:3.4);if(isVml){node.path='m'+Math.round(pe.x+nx/2)+' '+Math.round(pe.y+ny/2)+' l'+Math.round(pe.x-ny/tk)+' '+Math.round(pe.y+nx/tk)+' '+Math.round(pe.x-nx/2)+' '+Math.round(pe.y-ny/2)+' '+Math.round(pe.x+ny/tk)+' '+Math.round(pe.y-nx/tk)+' x e';node.setAttribute('strokeweight',(strokewidth*scale)+'px');}else{node.setAttribute('d','M '+(pe.x+nx/2)+' '+(pe.y+ny/2)+' L '+(pe.x-ny/tk)+' '+(pe.y+nx/tk)+' L '+(pe.x-nx/2)+' '+(pe.y-ny/2)+' L '+(pe.x+ny/tk)+' '+(pe.y-nx/tk)+' z');node.setAttribute('stroke-width',strokewidth*scale);}return new mxPoint(-endOffsetX-nx,-endOffsetY-ny);};mxMarker.markers[mxConstants.ARROW_DIAMOND]=tmp_diamond;mxMarker.markers[mxConstants.ARROW_DIAMOND_THIN]=tmp_diamond;}());function mxActor(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxActor.prototype=new mxShape();mxActor.prototype.constructor=mxActor;mxActor.prototype.mixedModeHtml=false;mxActor.prototype.preferModeHtml=false;mxActor.prototype.vmlScale=2;mxActor.prototype.createVml=function(){var node=document.createElement('v:shape');node.style.position='absolute';this.configureVmlShape(node);return node;};mxActor.prototype.redrawVml=function(){this.updateVmlShape(this.node);this.node.path=this.createPath();};mxActor.prototype.createSvg=function(){return this.createSvgGroup('path');};mxActor.prototype.redrawSvg=function(){var strokeWidth=Math.round(Math.max(1,this.strokewidth*this.scale));this.innerNode.setAttribute('stroke-width',strokeWidth);this.innerNode.setAttribute('stroke-linejoin','round');if(this.crisp){this.innerNode.setAttribute('shape-rendering','crispEdges');}else{this.innerNode.removeAttribute('shape-rendering');}var d=this.createPath();if(d.length>0){this.innerNode.setAttribute('d',d);if(this.shadowNode!=null){this.shadowNode.setAttribute('transform',this.getSvgShadowTransform());this.shadowNode.setAttribute('stroke-width',strokeWidth);this.shadowNode.setAttribute('d',d);}}else{this.innerNode.removeAttribute('d');if(this.shadowNode!=null){this.shadowNode.removeAttribute('d');}}if(this.isDashed){var phase=Math.max(1,Math.round(3*this.scale*this.strokewidth));this.innerNode.setAttribute('stroke-dasharray',phase+' '+phase);}};mxActor.prototype.redrawPath=function(path,x,y,w,h){var width=w/3;path.moveTo(0,h);path.curveTo(0,3*h/5,0,2*h/5,w/2,2*h/5);path.curveTo(w/2-width,2*h/5,w/2-width,0,w/2,0);path.curveTo(w/2+width,0,w/2+width,2*h/5,w/2,2*h/5);path.curveTo(w,2*h/5,w,3*h/5,w,h);path.close();};function mxCloud(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxCloud.prototype=new mxActor();mxCloud.prototype.constructor=mxActor;mxCloud.prototype.redrawPath=function(path,x,y,w,h){path.moveTo(0.25*w,0.25*h);path.curveTo(0.05*w,0.25*h,0,0.5*h,0.16*w,0.55*h);path.curveTo(0,0.66*h,0.18*w,0.9*h,0.31*w,0.8*h);path.curveTo(0.4*w,h,0.7*w,h,0.8*w,0.8*h);path.curveTo(w,0.8*h,w,0.6*h,0.875*w,0.5*h);path.curveTo(w,0.3*h,0.8*w,0.1*h,0.625*w,0.2*h);path.curveTo(0.5*w,0.05*h,0.3*w,0.05*h,0.25*w,0.25*h);path.close();};function mxRectangleShape(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxRectangleShape.prototype=new mxShape();mxRectangleShape.prototype.constructor=mxRectangleShape;mxRectangleShape.prototype.createHtml=function(){var node=document.createElement('DIV');this.configureHtmlShape(node);return node;};mxRectangleShape.prototype.createVml=function(){var name=(this.isRounded)?'v:roundrect':'v:rect';var node=document.createElement(name);this.configureVmlShape(node);return node;};mxRectangleShape.prototype.createSvg=function(){return this.createSvgGroup('rect');};function mxEllipse(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxEllipse.prototype=new mxShape();mxEllipse.prototype.constructor=mxEllipse;mxEllipse.prototype.mixedModeHtml=false;mxEllipse.prototype.preferModeHtml=false;mxEllipse.prototype.createVml=function(){var node=document.createElement('v:arc');node.startangle='0';node.endangle='360';this.configureVmlShape(node);return node;};mxEllipse.prototype.createSvg=function(){return this.createSvgGroup('ellipse');};mxEllipse.prototype.redrawSvg=function(){if(this.crisp){this.innerNode.setAttribute('shape-rendering','crispEdges');}else{this.innerNode.removeAttribute('shape-rendering');}this.updateSvgNode(this.innerNode);this.updateSvgNode(this.shadowNode);};mxEllipse.prototype.updateSvgNode=function(node){if(node!=null){var strokeWidth=Math.round(Math.max(1,this.strokewidth*this.scale));node.setAttribute('stroke-width',strokeWidth);node.setAttribute('cx',this.bounds.x+this.bounds.width/2);node.setAttribute('cy',this.bounds.y+this.bounds.height/2);node.setAttribute('rx',this.bounds.width/2);node.setAttribute('ry',this.bounds.height/2);if(this.shadowNode!=null){this.shadowNode.setAttribute('transform',this.getSvgShadowTransform());}if(this.isDashed){var phase=Math.max(1,Math.round(3*this.scale*this.strokewidth));node.setAttribute('stroke-dasharray',phase+' '+phase);}}};function mxDoubleEllipse(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxDoubleEllipse.prototype=new mxShape();mxDoubleEllipse.prototype.constructor=mxDoubleEllipse;mxDoubleEllipse.prototype.vmlNodes=mxDoubleEllipse.prototype.vmlNodes.concat(['background','foreground']);mxDoubleEllipse.prototype.mixedModeHtml=false;mxDoubleEllipse.prototype.preferModeHtml=false;mxDoubleEllipse.prototype.vmlScale=2;mxDoubleEllipse.prototype.createVml=function(){var node=document.createElement('v:group');this.background=document.createElement('v:arc');this.background.startangle='0';this.background.endangle='360';this.configureVmlShape(this.background);node.appendChild(this.background);this.label=this.background;this.isShadow=false;this.fill=null;this.foreground=document.createElement('v:oval');this.configureVmlShape(this.foreground);node.appendChild(this.foreground);this.stroke=null;this.configureVmlShape(node);return node;};mxDoubleEllipse.prototype.redrawVml=function(){this.updateVmlShape(this.node);this.updateVmlShape(this.background);this.updateVmlShape(this.foreground);var inset=Math.round((this.strokewidth+3)*this.scale)*this.vmlScale;var w=Math.round(this.bounds.width*this.vmlScale);var h=Math.round(this.bounds.height*this.vmlScale);this.foreground.style.top=inset+'px';this.foreground.style.left=inset+'px';this.foreground.style.width=Math.max(0,w-2*inset)+'px';this.foreground.style.height=Math.max(0,h-2*inset)+'px';};mxDoubleEllipse.prototype.createSvg=function(){var g=this.createSvgGroup('ellipse');this.foreground=document.createElementNS(mxConstants.NS_SVG,'ellipse');if(this.stroke!=null){this.foreground.setAttribute('stroke',this.stroke);}else{this.foreground.setAttribute('stroke','none');}this.foreground.setAttribute('fill','none');g.appendChild(this.foreground);return g;};mxDoubleEllipse.prototype.redrawSvg=function(){if(this.crisp){this.innerNode.setAttribute('shape-rendering','crispEdges');this.foreground.setAttribute('shape-rendering','crispEdges');}else{this.innerNode.removeAttribute('shape-rendering');this.foreground.removeAttribute('shape-rendering');}this.updateSvgNode(this.innerNode);this.updateSvgNode(this.shadowNode);this.updateSvgNode(this.foreground,(this.strokewidth+3)*this.scale);if(this.isDashed){var phase=Math.max(1,Math.round(3*this.scale*this.strokewidth));this.innerNode.setAttribute('stroke-dasharray',phase+' '+phase);}};mxDoubleEllipse.prototype.updateSvgNode=function(node,inset){inset=(inset!=null)?inset:0;if(node!=null){var strokeWidth=Math.round(Math.max(1,this.strokewidth*this.scale));node.setAttribute('stroke-width',strokeWidth);node.setAttribute('cx',this.bounds.x+this.bounds.width/2);node.setAttribute('cy',this.bounds.y+this.bounds.height/2);node.setAttribute('rx',Math.max(0,this.bounds.width/2-inset));node.setAttribute('ry',Math.max(0,this.bounds.height/2-inset));if(this.shadowNode!=null){this.shadowNode.setAttribute('transform',this.getSvgShadowTransform());}}};function mxRhombus(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxRhombus.prototype=new mxShape();mxRhombus.prototype.constructor=mxRhombus;mxRhombus.prototype.mixedModeHtml=false;mxRhombus.prototype.preferModeHtml=false;mxRhombus.prototype.createHtml=function(){var node=document.createElement('DIV');this.configureHtmlShape(node);return node;};mxRhombus.prototype.createVml=function(){var node=document.createElement('v:shape');this.configureVmlShape(node);return node;};mxRhombus.prototype.createSvg=function(){return this.createSvgGroup('path');};mxRhombus.prototype.redrawVml=function(){this.updateVmlShape(this.node);var x=0;var y=0;var w=Math.round(this.bounds.width);var h=Math.round(this.bounds.height);this.node.path='m '+Math.round(x+w/2)+' '+y+' l '+(x+w)+' '+Math.round(y+h/2)+' l '+Math.round(x+w/2)+' '+(y+h)+' l '+x+' '+Math.round(y+h/2)+' x e';};mxRhombus.prototype.redrawHtml=function(){this.updateHtmlShape(this.node);};mxRhombus.prototype.redrawSvg=function(){this.updateSvgNode(this.innerNode);if(this.shadowNode!=null){this.updateSvgNode(this.shadowNode);}};mxRhombus.prototype.updateSvgNode=function(node){var strokeWidth=Math.round(Math.max(1,this.strokewidth*this.scale));node.setAttribute('stroke-width',strokeWidth);var x=this.bounds.x;var y=this.bounds.y;var w=this.bounds.width;var h=this.bounds.height;var d='M '+Math.round(x+w/2)+' '+Math.round(y)+' L '+Math.round(x+w)+' '+Math.round(y+h/2)+' L '+Math.round(x+w/2)+' '+Math.round(y+h)+' L '+Math.round(x)+' '+Math.round(y+h/2)+' Z ';node.setAttribute('d',d);this.updateSvgTransform(node,node==this.shadowNode);if(this.isDashed){var phase=Math.max(1,Math.round(3*this.scale*this.strokewidth));node.setAttribute('stroke-dasharray',phase+' '+phase);}};function mxPolyline(points,stroke,strokewidth){this.points=points;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxPolyline.prototype=new mxShape();mxPolyline.prototype.constructor=mxPolyline;mxPolyline.prototype.addPipe=true;mxPolyline.prototype.create=function(){var node=null;if(this.dialect==mxConstants.DIALECT_SVG){node=this.createSvg();}else if(this.dialect==mxConstants.DIALECT_STRICTHTML||(this.dialect==mxConstants.DIALECT_PREFERHTML&&this.points!=null&&this.points.length>0)){node=document.createElement('DIV');this.configureHtmlShape(node);node.style.borderStyle='';node.style.background='';}else{node=document.createElement('v:shape');this.configureVmlShape(node);var strokeNode=document.createElement('v:stroke');if(this.opacity!=null){strokeNode.opacity=this.opacity+'%';}node.appendChild(strokeNode);}return node;};mxPolyline.prototype.redrawVml=function(){if(this.points!=null&&this.points.length>0&&this.points[0]!=null){this.bounds=new mxRectangle(this.points[0].x,this.points[0].y,0,0);for(var i=1;i=9){td.style.height='100%';}tr.appendChild(td);tbody.appendChild(tr);table.appendChild(tbody);return table;};mxText.prototype.updateHtmlTable=function(table,scale){scale=(scale!=null)?scale:1;var td=table.firstChild.firstChild.firstChild;if(this.wrap){table.style.width='';}if(mxUtils.isNode(this.value)){if(td.firstChild!=this.value){if(td.firstChild!=null){td.removeChild(td.firstChild);}td.appendChild(this.value);}}else{if(this.lastValue!=this.value){td.innerHTML=(this.replaceLinefeeds)?this.value.replace(/\n/g,'
'):this.value;this.lastValue=this.value;}}var fontSize=Math.round(this.size*scale);if(fontSize<=0){table.style.visibility='hidden';}else{table.style.visibility='';}table.style.fontSize=fontSize+'px';table.style.color=this.color;table.style.fontFamily=this.family;if(this.isStyleSet(mxConstants.FONT_BOLD)){table.style.fontWeight='bold';}else{table.style.fontWeight='normal';}if(this.isStyleSet(mxConstants.FONT_ITALIC)){table.style.fontStyle='italic';}else{table.style.fontStyle='';}if(this.isStyleSet(mxConstants.FONT_UNDERLINE)){table.style.textDecoration='underline';}else{table.style.textDecoration='';}if(mxClient.IS_IE){if(this.isStyleSet(mxConstants.FONT_SHADOW)){td.style.filter='Shadow(Color=#666666,'+'Direction=135,Strength=%)';}else{td.style.removeAttribute('filter');}}td.style.textAlign=(this.align==mxConstants.ALIGN_RIGHT)?'right':((this.align==mxConstants.ALIGN_CENTER)?'center':'left');td.style.verticalAlign=(this.valign==mxConstants.ALIGN_BOTTOM)?'bottom':((this.valign==mxConstants.ALIGN_MIDDLE)?'middle':'top');if(this.value.length>0&&this.background!=null){td.style.background=this.background;}else{td.style.background='';}td.style.padding=this.labelPadding+'px';if(this.value.length>0&&this.border!=null){table.style.borderColor=this.border;table.style.borderWidth='1px';table.style.borderStyle='solid';}else{table.style.borderStyle='none';}};mxText.prototype.getTableSize=function(table){return new mxRectangle(0,0,table.offsetWidth,table.offsetHeight);};mxText.prototype.updateTableWidth=function(table){var td=table.firstChild.firstChild.firstChild;if(this.wrap&&this.bounds.width>0&&this.dialect!=mxConstants.DIALECT_SVG){td.style.whiteSpace='nowrap';var size=this.getTableSize(table);var space=Math.min(size.width,((this.horizontal||mxUtils.isVml(this.node))?this.bounds.width:this.bounds.height)/this.scale);if(mxClient.IS_OP){space*=this.scale;}table.style.width=Math.round(space)+'px';td.style.whiteSpace='normal';}else{table.style.width='';}if(!this.wrap){td.style.whiteSpace='nowrap';}else{td.style.whiteSpace='normal';}};mxText.prototype.redrawVml=function(){if(this.node.nodeName=='g'){this.redrawForeignObject();}else if(mxUtils.isVml(this.node)){this.redrawTextbox();}else{this.redrawHtmlTable();}};mxText.prototype.redrawTextbox=function(){var textbox=this.node;if(textbox.firstChild==null){textbox.appendChild(this.createHtmlTable());}var table=textbox.firstChild;this.updateHtmlTable(table);this.updateTableWidth(table);if(this.opacity!=null){mxUtils.setOpacity(table,this.opacity);}table.style.filter='';textbox.inset='0px,0px,0px,0px';if(this.overflow!='fill'){var size=this.getTableSize(table);var w=size.width*this.scale;var h=size.height*this.scale;var offset=this.getOffset(this.bounds.width,this.bounds.height,w,h);if(!this.horizontal){table.style.filter=this.ieVerticalFilter;}var spacing=this.getSpacing();var x=this.bounds.x-offset.x+spacing.x*this.scale;var y=this.bounds.y-offset.y+spacing.y*this.scale;var x0=this.bounds.x;var y0=this.bounds.y;var ow=this.bounds.width;var oh=this.bounds.height;if(this.horizontal){var tx=Math.round(x-x0);var ty=Math.round(y-y0);var r=Math.min(0,Math.round(x0+ow-x-w-1));var b=Math.min(0,Math.round(y0+oh-y-h-1));textbox.inset=tx+'px,'+ty+'px,'+r+'px,'+b+'px';}else{var t=0;var l=0;var r=0;var b=0;if(this.align==mxConstants.ALIGN_CENTER){t=(oh-w)/2;b=t;}else if(this.align==mxConstants.ALIGN_LEFT){t=oh-w;}else{b=oh-w;}if(this.valign==mxConstants.ALIGN_MIDDLE){l=(ow-h)/2;r=l;}else if(this.valign==mxConstants.ALIGN_BOTTOM){l=ow-h;}else{r=ow-h;}textbox.inset=l+'px,'+t+'px,'+r+'px,'+b+'px';}textbox.style.zoom=this.scale;if(this.clipped&&this.bounds.width>0&&this.bounds.height>0){this.boundingBox=this.bounds.clone();var dx=Math.round(x0-x);var dy=Math.round(y0-y);textbox.style.clip='rect('+(dy/this.scale)+' '+((dx+this.bounds.width)/this.scale)+' '+((dy+this.bounds.height)/this.scale)+' '+(dx/this.scale)+')';}else{this.boundingBox=new mxRectangle(x,y,w,h);}}else{this.boundingBox=this.bounds.clone();}};mxText.prototype.redrawHtmlTable=function(){if(isNaN(this.bounds.x)||isNaN(this.bounds.y)||isNaN(this.bounds.width)||isNaN(this.bounds.height)){return;}var table=this.node;var td=table.firstChild.firstChild.firstChild;var oldBrowser=false;var fallbackScale=1;if(mxClient.IS_IE){table.style.removeAttribute('filter');}else if(mxClient.IS_SF||mxClient.IS_GC){table.style.WebkitTransform='';}else if(mxClient.IS_MT){table.style.MozTransform='';td.style.MozTransform='';}else{if(mxClient.IS_OT){table.style.OTransform='';}fallbackScale=this.scale;oldBrowser=true;}td.style.zoom='';this.updateHtmlTable(table,fallbackScale);this.updateTableWidth(table);if(this.opacity!=null){mxUtils.setOpacity(table,this.opacity);}table.style.left='';table.style.top='';table.style.height='';var currentZoom=parseFloat(td.style.zoom)||1;var w=this.bounds.width;var h=this.bounds.height;var ignoreStringSize=this.forceIgnoreStringSize||this.overflow=='fill'||(this.align==mxConstants.ALIGN_LEFT&&this.background==null&&this.border==null);if(!ignoreStringSize){var size=this.getTableSize(table);w=size.width/currentZoom;h=size.height/currentZoom;}var offset=this.getOffset(this.bounds.width/this.scale,this.bounds.height/this.scale,w,h,oldBrowser||this.horizontal);var spacing=this.getSpacing(oldBrowser||this.horizontal);var x=this.bounds.x/this.scale-offset.x+spacing.x;var y=this.bounds.y/this.scale-offset.y+spacing.y;var s=this.scale;var s2=1;var shiftX=0;var shiftY=0;if(!this.horizontal){if(mxClient.IS_IE&&mxClient.IS_SVG){table.style.msTransform='rotate('+this.verticalTextDegree+'deg)';}else if(mxClient.IS_IE){table.style.filter=this.ieVerticalFilter;shiftX=(w-h)/2;shiftY=-shiftX;}else if(mxClient.IS_SF||mxClient.IS_GC){table.style.WebkitTransform='rotate('+this.verticalTextDegree+'deg)';}else if(mxClient.IS_OT){table.style.OTransform='rotate('+this.verticalTextDegree+'deg)';}else if(mxClient.IS_MT){table.style.MozTransform='rotate('+this.verticalTextDegree+'deg)';td.style.MozTransform='rotate(0deg)';s2=1/this.scale;s=1;}}var correction=true;if(mxClient.IS_MT||oldBrowser){if(mxClient.IS_MT){table.style.MozTransform+=' scale('+this.scale+')';s2=1/this.scale;}else if(mxClient.IS_OT){td.style.OTransform='scale('+this.scale+')';table.style.borderWidth=Math.round(this.scale*parseInt(table.style.borderWidth))+'px';}}else if(!oldBrowser){if(document.documentMode>=9){td.style.msTransform='scale('+this.scale+')';}else if(mxClient.IS_SF||mxClient.IS_GC){td.style.WebkitTransform='scale('+this.scale+')';}else{td.style.zoom=this.scale;if(table.style.borderWidth!=''&&document.documentMode!=8){table.style.borderWidth=Math.round(this.scale*parseInt(table.style.borderWidth))+'px';}if(document.documentMode==8||!mxClient.IS_IE){s=1;}correction=false;}}if(correction){shiftX=(this.scale-1)*w/(2*this.scale);shiftY=(this.scale-1)*h/(2*this.scale);s=1;}if(this.overflow!='fill'){var rect=new mxRectangle(Math.round((x+shiftX)*this.scale),Math.round((y+shiftY)*this.scale),Math.round(w*s),Math.round(h*s));table.style.left=rect.x+'px';table.style.top=rect.y+'px';table.style.width=rect.width+'px';table.style.height=rect.height+'px';if((this.background!=null||this.border!=null)&&document.documentMode>=8){var html=(this.replaceLinefeeds)?this.value.replace(/\n/g,'
'):this.value;td.innerHTML='
'+html+'
';td.style.padding='0px';td.style.background='';table.style.border='';}if(this.clipped&&this.bounds.width>0&&this.bounds.height>0){this.boundingBox=this.bounds.clone();if(this.horizontal||(oldBrowser&&!mxClient.IS_OT)){var dx=Math.max(0,offset.x*s);var dy=Math.max(0,offset.y*s);table.style.clip='rect('+(dy)+'px '+(dx+this.bounds.width*s2)+'px '+(dy+this.bounds.height*s2)+'px '+(dx)+'px)';}else{if(mxClient.IS_IE){var uw=this.bounds.width;var uh=this.bounds.height;var dx=0;var dy=0;if(this.align==mxConstants.ALIGN_LEFT){dx=Math.max(0,w-uh/this.scale)*this.scale;}else if(this.align==mxConstants.ALIGN_CENTER){dx=Math.max(0,w-uh/this.scale)*this.scale/2;}if(this.valign==mxConstants.ALIGN_BOTTOM){dy=Math.max(0,h-uw/this.scale)*this.scale;}else if(this.valign==mxConstants.ALIGN_MIDDLE){dy=Math.max(0,h-uw/this.scale)*this.scale/2;}table.style.clip='rect('+(dx)+'px '+(dy+uw-1)+'px '+(dx+uh-1)+'px '+(dy)+'px)';}else{var uw=this.bounds.width/this.scale;var uh=this.bounds.height/this.scale;if(mxClient.IS_OT){uw=this.bounds.width;uh=this.bounds.height;}var dx=0;var dy=0;if(this.align==mxConstants.ALIGN_RIGHT){dx=Math.max(0,w-uh);}else if(this.align==mxConstants.ALIGN_CENTER){dx=Math.max(0,w-uh)/2;}if(this.valign==mxConstants.ALIGN_BOTTOM){dy=Math.max(0,h-uw);}else if(this.valign==mxConstants.ALIGN_MIDDLE){dy=Math.max(0,h-uw)/2;}if(mxClient.IS_GC||mxClient.IS_SF){dx*=this.scale;dy*=this.scale;uw*=this.scale;uh*=this.scale;}table.style.clip='rect('+(dy)+' '+(dx+uh)+' '+(dy+uw)+' '+(dx)+')';}}}else{this.boundingBox=rect;}}else{this.boundingBox=this.bounds.clone();if(document.documentMode>=9||mxClient.IS_SVG){table.style.left=Math.round(this.bounds.x+this.scale/2+shiftX)+'px';table.style.top=Math.round(this.bounds.y+this.scale/2+shiftY)+'px';table.style.width=Math.round((this.bounds.width-this.scale)/this.scale)+'px';table.style.height=Math.round((this.bounds.height-this.scale)/this.scale)+'px';}else{table.style.left=Math.round(this.bounds.x+this.scale/2)+'px';table.style.top=Math.round(this.bounds.y+this.scale/2)+'px';table.style.width=Math.round(this.bounds.width-this.scale)+'px';table.style.height=Math.round(this.bounds.height-this.scale)+'px';}}};mxText.prototype.getVerticalOffset=function(offset){return new mxPoint(offset.y,-offset.x);};mxText.prototype.redrawForeignObject=function(){var group=this.node;var fo=group.firstChild;while(fo==this.backgroundNode){fo=fo.nextSibling;}var body=fo.firstChild;if(body.firstChild==null){body.appendChild(this.createHtmlTable());}var table=body.firstChild;this.updateHtmlTable(table);if(this.opacity!=null){fo.setAttribute('opacity',this.opacity/100);}if(mxClient.IS_SF){table.style.borderStyle='none';table.firstChild.firstChild.firstChild.style.background='';if(this.backgroundNode==null&&(this.background!=null||this.border!=null)){this.backgroundNode=document.createElementNS(mxConstants.NS_SVG,'rect');group.insertBefore(this.backgroundNode,group.firstChild);}else if(this.backgroundNode!=null&&this.background==null&&this.border==null){this.backgroundNode.parentNode.removeChild(this.backgroundNode);this.backgroundNode=null;}if(this.backgroundNode!=null){if(this.background!=null){this.backgroundNode.setAttribute('fill',this.background);}else{this.backgroundNode.setAttribute('fill','none');}if(this.border!=null){this.backgroundNode.setAttribute('stroke',this.border);}else{this.backgroundNode.setAttribute('stroke','none');}}}var tr='';if(this.overflow!='fill'){fo.removeAttribute('width');fo.removeAttribute('height');fo.style.width='';fo.style.height='';fo.style.clip='';if(this.wrap||(!mxClient.IS_GC&&!mxClient.IS_SF)){document.body.appendChild(table);}this.updateTableWidth(table);var size=this.getTableSize(table);var w=size.width;var h=size.height;if(table.parentNode!=body){body.appendChild(table);}var spacing=this.getSpacing();var x=this.bounds.x/this.scale+spacing.x;var y=this.bounds.y/this.scale+spacing.y;var uw=this.bounds.width/this.scale;var uh=this.bounds.height/this.scale;var offset=this.getOffset(uw,uh,w,h);if(this.horizontal){x-=offset.x;y-=offset.y;tr='scale('+this.scale+')';}else{var x0=x+w/2;var y0=y+h/2;tr='scale('+this.scale+') rotate('+this.verticalTextDegree+' '+x0+' '+y0+')';var tmp=this.getVerticalOffset(offset);x+=tmp.x;y+=tmp.y;}tr+=' translate('+x+' '+y+')';if(this.backgroundNode!=null){this.backgroundNode.setAttribute('width',w);this.backgroundNode.setAttribute('height',h);}fo.setAttribute('width',w);fo.setAttribute('height',h);if(this.clipped&&this.bounds.width>0&&this.bounds.height>0){this.boundingBox=this.bounds.clone();var dx=Math.max(0,offset.x);var dy=Math.max(0,offset.y);if(this.horizontal){fo.style.clip='rect('+dy+'px,'+(dx+uw)+'px,'+(dy+uh)+'px,'+(dx)+'px)';}else{var dx=0;var dy=0;if(this.align==mxConstants.ALIGN_RIGHT){dx=Math.max(0,w-uh);}else if(this.align==mxConstants.ALIGN_CENTER){dx=Math.max(0,w-uh)/2;}if(this.valign==mxConstants.ALIGN_BOTTOM){dy=Math.max(0,h-uw);}else if(this.valign==mxConstants.ALIGN_MIDDLE){dy=Math.max(0,h-uw)/2;}fo.style.clip='rect('+(dy)+'px,'+(dx+uh)+'px,'+(dy+uw)+'px,'+(dx)+'px)';}if(this.backgroundNode!=null){x=this.bounds.x/this.scale;y=this.bounds.y/this.scale;if(!this.horizontal){x+=(h+w)/2-uh;y+=(h-w)/2;var tmp=uw;uw=uh;uh=tmp;}if(!mxClient.IS_GC){var clip=this.getSvgClip(this.node.ownerSVGElement,x,y,uw,uh);if(clip!=this.clip){this.releaseSvgClip();this.clip=clip;clip.refCount++;}this.backgroundNode.setAttribute('clip-path','url(#'+clip.getAttribute('id')+')');}}}else{this.releaseSvgClip();if(this.backgroundNode!=null){this.backgroundNode.removeAttribute('clip-path');}if(this.horizontal){this.boundingBox=new mxRectangle(x*this.scale,y*this.scale,w*this.scale,h*this.scale);}else{this.boundingBox=new mxRectangle(x*this.scale,y*this.scale,h*this.scale,w*this.scale);}}}else{this.boundingBox=this.bounds.clone();var s=this.scale;var w=this.bounds.width/s;var h=this.bounds.height/s;fo.setAttribute('width',w);fo.setAttribute('height',h);table.style.width=w+'px';table.style.height=h+'px';if(this.backgroundNode!=null){this.backgroundNode.setAttribute('width',table.clientWidth);this.backgroundNode.setAttribute('height',table.offsetHeight);}tr='scale('+s+') translate('+(this.bounds.x/s)+' '+(this.bounds.y/s)+')';if(!this.wrap){var td=table.firstChild.firstChild.firstChild;td.style.whiteSpace='nowrap';}}group.setAttribute('transform',tr);};mxText.prototype.createSvg=function(){var node=document.createElementNS(mxConstants.NS_SVG,'g');var uline=this.isStyleSet(mxConstants.FONT_UNDERLINE)?'underline':'none';var weight=this.isStyleSet(mxConstants.FONT_BOLD)?'bold':'normal';var s=this.isStyleSet(mxConstants.FONT_ITALIC)?'italic':null;node.setAttribute('text-decoration',uline);node.setAttribute('font-family',this.family);node.setAttribute('font-weight',weight);node.setAttribute('font-size',Math.round(this.size*this.scale)+'px');node.setAttribute('fill',this.color);var align=(this.align==mxConstants.ALIGN_RIGHT)?'end':(this.align==mxConstants.ALIGN_CENTER)?'middle':'start';node.setAttribute('text-anchor',align);if(s!=null){node.setAttribute('font-style',s);}if(this.background!=null||this.border!=null){this.backgroundNode=document.createElementNS(mxConstants.NS_SVG,'rect');this.backgroundNode.setAttribute('shape-rendering','crispEdges');if(this.background!=null){this.backgroundNode.setAttribute('fill',this.background);}else{this.backgroundNode.setAttribute('fill','none');}if(this.border!=null){this.backgroundNode.setAttribute('stroke',this.border);}else{this.backgroundNode.setAttribute('stroke','none');}}this.updateSvgValue(node);return node;};mxText.prototype.updateSvgValue=function(node){if(this.currentValue!=this.value){while(node.firstChild!=null){node.removeChild(node.firstChild);}if(this.value!=null){var uline=this.isStyleSet(mxConstants.FONT_UNDERLINE)?'underline':'none';var lines=this.value.split('\n');this.textNodes=new Array(lines.length);for(var i=0;i0&&this.backgroundNode!=null&&this.node.firstChild!=null){if(this.node.firstChild!=this.backgroundNode){this.node.insertBefore(this.backgroundNode,this.node.firstChild);}this.backgroundNode.setAttribute('x',this.boundingBox.x+this.scale/2+1*this.scale);this.backgroundNode.setAttribute('y',this.boundingBox.y+this.scale/2+2*this.scale-this.labelPadding);this.backgroundNode.setAttribute('width',this.boundingBox.width-this.scale-2*this.scale);this.backgroundNode.setAttribute('height',this.boundingBox.height-this.scale);var strokeWidth=Math.round(Math.max(1,this.scale));this.backgroundNode.setAttribute('stroke-width',strokeWidth);}if(!mxClient.IS_GC){if(this.clipped&&this.bounds.width>0&&this.bounds.height>0){this.boundingBox=this.bounds.clone();if(!this.horizontal){this.boundingBox.width=this.bounds.height;this.boundingBox.height=this.bounds.width;}x=this.bounds.x;y=this.bounds.y;if(this.horizontal){w=this.bounds.width;h=this.bounds.height;}else{w=this.bounds.height;h=this.bounds.width;}var clip=this.getSvgClip(this.node.ownerSVGElement,x,y,w,h);if(clip!=this.clip){this.releaseSvgClip();this.clip=clip;clip.refCount++;}this.node.setAttribute('clip-path','url(#'+clip.getAttribute('id')+')');}else{this.releaseSvgClip();this.node.removeAttribute('clip-path');}}};mxText.prototype.redrawSvgTextNodes=function(x,y,dy){if(this.textNodes!=null){var currentY=y;for(var i=0;i=9){this.imageNode=document.createElement('img');this.imageNode.setAttribute('src',this.image);this.imageNode.setAttribute('border','0');this.imageNode.style.position='absolute';this.imageNode.style.width='100%';this.imageNode.style.height='100%';node=document.createElement('DIV');this.configureHtmlShape(node);node.appendChild(this.imageNode);}else{this.imageNode=document.createElement('v:image');this.imageNode.style.position='absolute';this.imageNode.src=this.image;node=document.createElement('DIV');this.configureHtmlShape(node);node.style.overflow='visible';node.appendChild(this.imageNode);}}return node;};mxImageShape.prototype.updateAspect=function(w,h){var s=Math.min(this.bounds.width/w,this.bounds.height/h);w=Math.max(0,Math.round(w*s));h=Math.max(0,Math.round(h*s));var x0=Math.max(0,Math.round((this.bounds.width-w)/2));var y0=Math.max(0,Math.round((this.bounds.height-h)/2));var st=this.imageNode.style;if(this.imageNode.parentNode==this.node){this.node.style.paddingLeft=x0+'px';this.node.style.paddingTop=y0+'px';}else{st.left=(Math.round(this.bounds.x)+x0)+'px';st.top=(Math.round(this.bounds.y)+y0)+'px';}st.width=w+'px';st.height=h+'px';};mxImageShape.prototype.scheduleUpdateAspect=function(){var img=new Image();img.onload=mxUtils.bind(this,function(){mxImageShape.prototype.updateAspect.call(this,img.width,img.height);});img.src=this.image;};mxImageShape.prototype.redraw=function(){mxShape.prototype.redraw.apply(this,arguments);if(this.imageNode!=null&&this.bounds!=null){var flipH=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_FLIPH,0)==1;var flipV=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_FLIPV,0)==1;if(this.dialect==mxConstants.DIALECT_SVG){var sx=1;var sy=1;var dx=0;var dy=0;if(flipH){sx=-1;dx=-this.bounds.width-2*this.bounds.x;}if(flipV){sy=-1;dy=-this.bounds.height-2*this.bounds.y;}var transform=(this.imageNode.getAttribute('transform')||'')+' scale('+sx+' '+sy+')'+' translate('+dx+' '+dy+')';this.imageNode.setAttribute('transform',transform);}else{if(this.imageNode.nodeName!='DIV'){this.imageNode.style.width=Math.max(0,Math.round(this.bounds.width))+'px';this.imageNode.style.height=Math.max(0,Math.round(this.bounds.height))+'px';}if(this.preserveImageAspect){this.scheduleUpdateAspect();}if(flipH||flipV){if(mxUtils.isVml(this.imageNode)){if(flipH&&flipV){this.imageNode.style.rotation='180';}else if(flipH){this.imageNode.style.flip='x';}else{this.imageNode.style.flip='y';}}else{var filter=(this.imageNode.nodeName=='DIV')?'progid:DXImageTransform.Microsoft.AlphaImageLoader '+'(src=\''+this.image+'\', sizingMethod=\'scale\')':'';if(flipH&&flipV){filter+='progid:DXImageTransform.Microsoft.BasicImage(rotation=2)';}else if(flipH){filter+='progid:DXImageTransform.Microsoft.BasicImage(mirror=1)';}else{filter+='progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)';}if(this.imageNode.style.filter!=filter){this.imageNode.style.filter=filter;}}}}}};mxImageShape.prototype.configureTransparentBackground=function(node){};mxImageShape.prototype.redrawSvg=function(){this.updateSvgShape(this.innerNode);this.updateSvgShape(this.imageNode);if(this.bg!=null){this.updateSvgShape(this.bg);if(this.fill!=null){this.bg.setAttribute('fill',this.fill);}else{this.bg.setAttribute('fill','none');}if(this.stroke!=null){this.bg.setAttribute('stroke',this.stroke);}else{this.bg.setAttribute('stroke','none');}this.bg.setAttribute('shape-rendering','crispEdges');}};mxImageShape.prototype.configureSvgShape=function(node){mxShape.prototype.configureSvgShape.apply(this,arguments);if(this.imageNode!=null){if(this.opacity!=null){this.imageNode.setAttribute('opacity',this.opacity/100);}else{this.imageNode.removeAttribute('opacity');}}};function mxLabel(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxLabel.prototype=new mxShape();mxLabel.prototype.constructor=mxLabel;mxLabel.prototype.vmlNodes=mxLabel.prototype.vmlNodes.concat(['label','imageNode','indicatorImageNode','rectNode']);mxLabel.prototype.imageSize=mxConstants.DEFAULT_IMAGESIZE;mxLabel.prototype.spacing=2;mxLabel.prototype.indicatorSize=10;mxLabel.prototype.indicatorSpacing=2;mxLabel.prototype.opaqueVmlImages=false;mxLabel.prototype.init=function(container){mxShape.prototype.init.apply(this,arguments);if(this.indicatorColor!=null&&this.indicatorShape!=null){this.indicator=new this.indicatorShape();this.indicator.dialect=this.dialect;this.indicator.bounds=this.bounds;this.indicator.fill=this.indicatorColor;this.indicator.stroke=this.indicatorColor;this.indicator.gradient=this.indicatorGradientColor;this.indicator.direction=this.indicatorDirection;this.indicator.init(this.node);this.indicatorShape=null;}};mxLabel.prototype.reconfigure=function(){mxShape.prototype.reconfigure.apply(this);if(this.indicator!=null){this.indicator.fill=this.indicatorColor;this.indicator.stroke=this.indicatorColor;this.indicator.gradient=this.indicatorGradientColor;this.indicator.direction=this.indicatorDirection;this.indicator.reconfigure();}};mxLabel.prototype.createHtml=function(){var name='DIV';var node=document.createElement(name);this.configureHtmlShape(node);if(this.indicatorImage!=null){this.indicatorImageNode=mxUtils.createImage(this.indicatorImage);this.indicatorImageNode.style.position='absolute';node.appendChild(this.indicatorImageNode);}if(this.image!=null){this.imageNode=mxUtils.createImage(this.image);this.stroke=null;this.configureHtmlShape(this.imageNode);mxUtils.setOpacity(this.imageNode,'100');node.appendChild(this.imageNode);}return node;};mxLabel.prototype.createVml=function(){var node=document.createElement('v:group');var name=(this.isRounded)?'v:roundrect':'v:rect';this.rectNode=document.createElement(name);this.configureVmlShape(this.rectNode);this.isShadow=false;this.configureVmlShape(node);node.coordorigin='0,0';node.appendChild(this.rectNode);if(this.indicatorImage!=null){this.indicatorImageNode=this.createVmlImage(this.indicatorImage,(this.opaqueVmlImages)?null:this.opacity);node.appendChild(this.indicatorImageNode);}if(this.image!=null){this.imageNode=this.createVmlImage(this.image,(this.opaqueVmlImages)?null:this.opacity);node.appendChild(this.imageNode);}this.label=document.createElement('v:rect');this.label.style.top='0px';this.label.style.left='0px';this.label.filled='false';this.label.stroked='false';node.appendChild(this.label);return node;};mxLabel.prototype.createVmlImage=function(src,opacity){var result=null;if(src.substring(0,5)=='data:'||opacity!=null){result=document.createElement('img');mxUtils.setOpacity(result,opacity);result.setAttribute('border','0');result.style.position='absolute';result.setAttribute('src',src);}else{result=document.createElement('v:image');result.src=src;}return result;};mxLabel.prototype.createSvg=function(){var g=this.createSvgGroup('rect');if(this.indicatorImage!=null){this.indicatorImageNode=document.createElementNS(mxConstants.NS_SVG,'image');this.indicatorImageNode.setAttributeNS(mxConstants.NS_XLINK,'href',this.indicatorImage);g.appendChild(this.indicatorImageNode);if(this.opacity!=null){this.indicatorImageNode.setAttribute('opacity',this.opacity/100);}}if(this.image!=null){this.imageNode=document.createElementNS(mxConstants.NS_SVG,'image');this.imageNode.setAttributeNS(mxConstants.NS_XLINK,'href',this.image);if(this.opacity!=null){this.imageNode.setAttribute('opacity',this.opacity/100);}this.imageNode.setAttribute('style','pointer-events:none');this.configureSvgShape(this.imageNode);g.appendChild(this.imageNode);}return g;};mxLabel.prototype.redraw=function(){this.updateBoundingBox();var isSvg=(this.dialect==mxConstants.DIALECT_SVG);var isVml=mxUtils.isVml(this.node);if(isSvg){this.updateSvgShape(this.innerNode);if(this.shadowNode!=null){this.updateSvgShape(this.shadowNode);}this.updateSvgGlassPane();}else if(isVml){this.updateVmlShape(this.node);this.updateVmlShape(this.rectNode);this.label.style.width=this.node.style.width;this.label.style.height=this.node.style.height;this.updateVmlGlassPane();}else{this.updateHtmlShape(this.node);}var imageWidth=0;var imageHeight=0;if(this.imageNode!=null){imageWidth=(this.style[mxConstants.STYLE_IMAGE_WIDTH]||this.imageSize)*this.scale;imageHeight=(this.style[mxConstants.STYLE_IMAGE_HEIGHT]||this.imageSize)*this.scale;}var indicatorSpacing=0;var indicatorWidth=0;var indicatorHeight=0;if(this.indicator!=null||this.indicatorImageNode!=null){indicatorSpacing=(this.style[mxConstants.STYLE_INDICATOR_SPACING]||this.indicatorSpacing)*this.scale;indicatorWidth=(this.style[mxConstants.STYLE_INDICATOR_WIDTH]||this.indicatorSize)*this.scale;indicatorHeight=(this.style[mxConstants.STYLE_INDICATOR_HEIGHT]||this.indicatorSize)*this.scale;}var align=this.style[mxConstants.STYLE_IMAGE_ALIGN];var valign=this.style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN];var inset=this.spacing*this.scale+5;var width=Math.max(imageWidth,indicatorWidth);var height=imageHeight+indicatorSpacing+indicatorHeight;var x=(isSvg)?this.bounds.x:0;if(align==mxConstants.ALIGN_RIGHT){x+=this.bounds.width-width-inset;}else if(align==mxConstants.ALIGN_CENTER){x+=(this.bounds.width-width)/2;}else {x+=inset;}var y=(isSvg)?this.bounds.y:0;if(valign==mxConstants.ALIGN_BOTTOM){y+=this.bounds.height-height-inset;}else if(valign==mxConstants.ALIGN_TOP){y+=inset;}else {y+=(this.bounds.height-height)/2;}if(this.imageNode!=null){if(isSvg){this.imageNode.setAttribute('x',(x+(width-imageWidth)/2)+'px');this.imageNode.setAttribute('y',y+'px');this.imageNode.setAttribute('width',imageWidth+'px');this.imageNode.setAttribute('height',imageHeight+'px');}else{this.imageNode.style.left=(x+width-imageWidth)+'px';this.imageNode.style.top=y+'px';this.imageNode.style.width=imageWidth+'px';this.imageNode.style.height=imageHeight+'px';this.imageNode.stroked='false';}}if(this.indicator!=null){this.indicator.bounds=new mxRectangle(x+(width-indicatorWidth)/2,y+imageHeight+indicatorSpacing,indicatorWidth,indicatorHeight);this.indicator.redraw();}else if(this.indicatorImageNode!=null){if(isSvg){this.indicatorImageNode.setAttribute('x',(x+(width-indicatorWidth)/2)+'px');this.indicatorImageNode.setAttribute('y',(y+imageHeight+indicatorSpacing)+'px');this.indicatorImageNode.setAttribute('width',indicatorWidth+'px');this.indicatorImageNode.setAttribute('height',indicatorHeight+'px');}else{this.indicatorImageNode.style.left=(x+(width-indicatorWidth)/2)+'px';this.indicatorImageNode.style.top=(y+imageHeight+indicatorSpacing)+'px';this.indicatorImageNode.style.width=indicatorWidth+'px';this.indicatorImageNode.style.height=indicatorHeight+'px';}}};function mxCylinder(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxCylinder.prototype=new mxShape();mxCylinder.prototype.constructor=mxCylinder;mxCylinder.prototype.vmlNodes=mxCylinder.prototype.vmlNodes.concat(['background','foreground']);mxCylinder.prototype.mixedModeHtml=false;mxCylinder.prototype.preferModeHtml=false;mxCylinder.prototype.addPipe=false;mxCylinder.prototype.strokedBackground=true;mxCylinder.prototype.maxHeight=40;mxCylinder.prototype.vmlScale=2;mxCylinder.prototype.create=function(container){if(this.stroke==null){this.stroke=this.fill;}return mxShape.prototype.create.apply(this,arguments);};mxCylinder.prototype.reconfigure=function(){if(this.dialect==mxConstants.DIALECT_SVG){this.configureSvgShape(this.foreground);this.foreground.setAttribute('fill','none');}else if(mxUtils.isVml(this.node)){this.configureVmlShape(this.background);this.configureVmlShape(this.foreground);}mxShape.prototype.reconfigure.apply(this);};mxCylinder.prototype.createVml=function(){var node=document.createElement('v:group');this.background=document.createElement('v:shape');this.label=this.background;this.configureVmlShape(this.background);node.appendChild(this.background);this.fill=null;this.isShadow=false;this.configureVmlShape(node);this.foreground=document.createElement('v:shape');this.configureVmlShape(this.foreground);this.fgStrokeNode=document.createElement('v:stroke');this.fgStrokeNode.joinstyle='miter';this.fgStrokeNode.miterlimit=4;this.foreground.appendChild(this.fgStrokeNode);node.appendChild(this.foreground);return node;};mxCylinder.prototype.redrawVml=function(){this.updateVmlShape(this.node);this.updateVmlShape(this.background);this.updateVmlShape(this.foreground);this.background.path=this.createPath(false);this.foreground.path=this.createPath(true);this.fgStrokeNode.dashstyle=this.strokeNode.dashstyle;};mxCylinder.prototype.createSvg=function(){var g=this.createSvgGroup('path');this.foreground=document.createElementNS(mxConstants.NS_SVG,'path');if(this.stroke!=null&&this.stroke!=mxConstants.NONE){this.foreground.setAttribute('stroke',this.stroke);}else{this.foreground.setAttribute('stroke','none');}this.foreground.setAttribute('fill','none');g.appendChild(this.foreground);if(this.addPipe){this.pipe=this.createSvgPipe();g.appendChild(this.pipe);}return g;};mxCylinder.prototype.redrawSvg=function(){var strokeWidth=Math.round(Math.max(1,this.strokewidth*this.scale));this.innerNode.setAttribute('stroke-width',strokeWidth);if(this.crisp){this.innerNode.setAttribute('shape-rendering','crispEdges');this.foreground.setAttribute('shape-rendering','crispEdges');}else{this.innerNode.removeAttribute('shape-rendering');this.foreground.removeAttribute('shape-rendering');}var d=this.createPath(false);if(d.length>0){this.innerNode.setAttribute('d',d);if(this.pipe!=null){this.pipe.setAttribute('d',d);this.pipe.setAttribute('stroke-width',strokeWidth+mxShape.prototype.SVG_STROKE_TOLERANCE);}}else{this.innerNode.removeAttribute('d');if(this.pipe!=null){this.pipe.removeAttribute('d');}}if(!this.strokedBackground){this.innerNode.setAttribute('stroke','none');}if(this.shadowNode!=null){this.shadowNode.setAttribute('stroke-width',strokeWidth);this.shadowNode.setAttribute('d',d);this.shadowNode.setAttribute('transform',this.getSvgShadowTransform());}d=this.createPath(true);if(d.length>0){this.foreground.setAttribute('stroke-width',strokeWidth);this.foreground.setAttribute('d',d);}else{this.foreground.removeAttribute('d');}if(this.isDashed){var phase=Math.max(1,Math.round(3*this.scale*this.strokewidth));this.innerNode.setAttribute('stroke-dasharray',phase+' '+phase);this.foreground.setAttribute('stroke-dasharray',phase+' '+phase);}};mxCylinder.prototype.redrawPath=function(path,x,y,w,h,isForeground){var dy=Math.min(this.maxHeight,Math.round(h/5));if(isForeground){path.moveTo(0,dy);path.curveTo(0,2*dy,w,2*dy,w,dy);}else{path.moveTo(0,dy);path.curveTo(0,-dy/3,w,-dy/3,w,dy);path.lineTo(w,h-dy);path.curveTo(w,h+dy/3,0,h+dy/3,0,h-dy);path.close();}};function mxConnector(points,stroke,strokewidth){this.points=points;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxConnector.prototype=new mxShape();mxConnector.prototype.constructor=mxConnector;mxConnector.prototype.vmlNodes=mxConnector.prototype.vmlNodes.concat(['shapeNode','start','end','startStroke','endStroke','startFill','endFill']);mxConnector.prototype.mixedModeHtml=false;mxConnector.prototype.preferModeHtml=false;mxConnector.prototype.allowCrispMarkers=false;mxConnector.prototype.addPipe=true;mxConnector.prototype.configureHtmlShape=function(node){mxShape.prototype.configureHtmlShape.apply(this,arguments);node.style.borderStyle='';node.style.background='';};mxConnector.prototype.createVml=function(){var node=document.createElement('v:group');node.style.position='absolute';this.shapeNode=document.createElement('v:shape');this.updateVmlStrokeColor(this.shapeNode);this.updateVmlStrokeNode(this.shapeNode);node.appendChild(this.shapeNode);this.shapeNode.filled='false';if(this.isShadow){this.createVmlShadow(this.shapeNode);}if(this.startArrow!=null){this.start=document.createElement('v:shape');this.start.style.position='absolute';this.startStroke=document.createElement('v:stroke');this.startStroke.joinstyle='miter';this.start.appendChild(this.startStroke);this.startFill=document.createElement('v:fill');this.start.appendChild(this.startFill);node.appendChild(this.start);}if(this.endArrow!=null){this.end=document.createElement('v:shape');this.end.style.position='absolute';this.endStroke=document.createElement('v:stroke');this.endStroke.joinstyle='miter';this.end.appendChild(this.endStroke);this.endFill=document.createElement('v:fill');this.end.appendChild(this.endFill);node.appendChild(this.end);}this.updateVmlMarkerOpacity();return node;};mxConnector.prototype.updateVmlMarkerOpacity=function(){var op=(this.opacity!=null)?(this.opacity+'%'):'100%';if(this.start!=null){this.startFill.opacity=op;this.startStroke.opacity=op;}if(this.end!=null){this.endFill.opacity=op;this.endStroke.opacity=op;}};mxConnector.prototype.reconfigure=function(){this.fill=null;if(mxUtils.isVml(this.node)){this.node.style.visibility='hidden';this.configureVmlShape(this.shapeNode);this.updateVmlMarkerOpacity();this.node.style.visibility='visible';}else{mxShape.prototype.reconfigure.apply(this,arguments);}};mxConnector.prototype.redrawVml=function(){if(this.node!=null&&this.points!=null&&this.bounds!=null&&!isNaN(this.bounds.x)&&!isNaN(this.bounds.y)&&!isNaN(this.bounds.width)&&!isNaN(this.bounds.height)){var w=Math.max(0,Math.round(this.bounds.width));var h=Math.max(0,Math.round(this.bounds.height));var cs=w+','+h;w+='px';h+='px';if(this.start!=null){this.start.style.width=w;this.start.style.height=h;this.start.coordsize=cs;var p0=this.points[1];var pe=this.points[0];var size=mxUtils.getNumber(this.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_MARKERSIZE);this.startOffset=this.redrawMarker(this.start,this.startArrow,p0,pe,this.stroke,size);}if(this.end!=null){this.end.style.width=w;this.end.style.height=h;this.end.coordsize=cs;var n=this.points.length;var p0=this.points[n-2];var pe=this.points[n-1];var size=mxUtils.getNumber(this.style,mxConstants.STYLE_ENDSIZE,mxConstants.DEFAULT_MARKERSIZE);this.endOffset=this.redrawMarker(this.end,this.endArrow,p0,pe,this.stroke,size);}this.updateVmlShape(this.node);this.updateVmlShape(this.shapeNode);this.shapeNode.filled='false';if(this.isDashed){var pat=mxUtils.getValue(this.style,'dashStyle',null);if(pat!=null){this.strokeNode.dashstyle=pat;}if(this.shadowStrokeNode!=null){this.shadowStrokeNode.dashstyle=this.strokeNode.dashstyle;}}}};mxConnector.prototype.createSvg=function(){this.fill=null;var g=this.createSvgGroup('path');if(this.startArrow!=null){this.start=document.createElementNS(mxConstants.NS_SVG,'path');g.appendChild(this.start);}if(this.endArrow!=null){this.end=document.createElementNS(mxConstants.NS_SVG,'path');g.appendChild(this.end);}if(this.addPipe){this.pipe=this.createSvgPipe();g.appendChild(this.pipe);}return g;};mxConnector.prototype.redrawSvg=function(){if(this.points!=null&&this.points[0]!=null){var color=this.innerNode.getAttribute('stroke');if(this.start!=null){var p0=this.points[1];var pe=this.points[0];var size=mxUtils.getNumber(this.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_MARKERSIZE);this.startOffset=this.redrawMarker(this.start,this.startArrow,p0,pe,color,size);if(this.allowCrispMarkers&&this.crisp){this.start.setAttribute('shape-rendering','crispEdges');}else{this.start.removeAttribute('shape-rendering');}}if(this.end!=null){var n=this.points.length;var p0=this.points[n-2];var pe=this.points[n-1];var size=mxUtils.getNumber(this.style,mxConstants.STYLE_ENDSIZE,mxConstants.DEFAULT_MARKERSIZE);this.endOffset=this.redrawMarker(this.end,this.endArrow,p0,pe,color,size);if(this.allowCrispMarkers&&this.crisp){this.end.setAttribute('shape-rendering','crispEdges');}else{this.end.removeAttribute('shape-rendering');}}}this.updateSvgShape(this.innerNode);var d=this.innerNode.getAttribute('d');if(d!=null){var strokeWidth=Math.round(this.strokewidth*this.scale);if(this.pipe!=null){this.pipe.setAttribute('d',this.innerNode.getAttribute('d'));this.pipe.setAttribute('stroke-width',strokeWidth+mxShape.prototype.SVG_STROKE_TOLERANCE);}if(this.shadowNode!=null){this.shadowNode.setAttribute('transform',this.getSvgShadowTransform());this.shadowNode.setAttribute('d',d);this.shadowNode.setAttribute('stroke-width',strokeWidth);}}if(this.isDashed){var pat=this.createDashPattern(this.scale*this.strokewidth);if(pat!=null){this.innerNode.setAttribute('stroke-dasharray',pat);}}if(this.shadowNode!=null){var pat=this.innerNode.getAttribute('stroke-dasharray');if(pat!=null){this.shadowNode.setAttribute('stroke-dasharray',pat);}}};mxConnector.prototype.createDashPattern=function(factor){var value=mxUtils.getValue(this.style,'dashPattern',null);if(value!=null){var tmp=value.split(' ');var pat=[];for(var i=0;i0){pat.push(Math.round(Number(tmp[i])*factor));}}return pat.join(' ');}return null;};mxConnector.prototype.redrawMarker=function(node,type,p0,pe,color,size){return mxMarker.paintMarker(node,type,p0,pe,color,this.strokewidth,size,this.scale,this.bounds.x,this.bounds.y,this.start==node,this.style);};function mxSwimlane(bounds,fill,stroke,strokewidth){this.bounds=bounds;this.fill=fill;this.stroke=stroke;this.strokewidth=(strokewidth!=null)?strokewidth:1;};mxSwimlane.prototype=new mxShape();mxSwimlane.prototype.constructor=mxSwimlane;mxSwimlane.prototype.vmlNodes=mxSwimlane.prototype.vmlNodes.concat(['label','content','imageNode','separator']);mxSwimlane.prototype.imageSize=16;mxSwimlane.prototype.mixedModeHtml=false;mxRhombus.prototype.preferModeHtml=false;mxSwimlane.prototype.createHtml=function(){var node=document.createElement('DIV');this.configureHtmlShape(node);node.style.background='';node.style.backgroundColor='';node.style.borderStyle='none';this.label=document.createElement('DIV');this.configureHtmlShape(this.label);node.appendChild(this.label);this.content=document.createElement('DIV');this.configureHtmlShape(this.content);this.content.style.backgroundColor='';if(mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,true)){this.content.style.borderTopStyle='none';}else{this.content.style.borderLeftStyle='none';}this.content.style.cursor='default';node.appendChild(this.content);var color=this.style[mxConstants.STYLE_SEPARATORCOLOR];if(color!=null){this.separator=document.createElement('DIV');this.separator.style.borderColor=color;this.separator.style.borderLeftStyle='dashed';node.appendChild(this.separator);}if(this.image!=null){this.imageNode=mxUtils.createImage(this.image);this.configureHtmlShape(this.imageNode);this.imageNode.style.borderStyle='none';node.appendChild(this.imageNode);}return node;};mxSwimlane.prototype.reconfigure=function(node){mxShape.prototype.reconfigure.apply(this,arguments);if(this.dialect==mxConstants.DIALECT_SVG){if(this.shadowNode!=null){this.updateSvgShape(this.shadowNode);if(mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,true)){this.shadowNode.setAttribute('height',this.startSize*this.scale);}else{this.shadowNode.setAttribute('width',this.startSize*this.scale);}}}else if(!mxUtils.isVml(this.node)){this.node.style.background='';this.node.style.backgroundColor='';}};mxSwimlane.prototype.redrawHtml=function(){this.updateHtmlShape(this.node);this.node.style.background='';this.node.style.backgroundColor='';this.startSize=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE));this.updateHtmlShape(this.label);this.label.style.top='0px';this.label.style.left='0px';if(mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,true)){this.startSize=Math.min(this.startSize,this.bounds.height);this.label.style.height=(this.startSize*this.scale)+'px';this.updateHtmlShape(this.content);this.content.style.background='';this.content.style.backgroundColor='';var h=this.startSize*this.scale;this.content.style.top=h+'px';this.content.style.left='0px';this.content.style.height=Math.max(1,this.bounds.height-h)+'px';if(this.separator!=null){this.separator.style.left=Math.round(this.bounds.width)+'px';this.separator.style.top=Math.round(this.startSize*this.scale)+'px';this.separator.style.width='1px';this.separator.style.height=Math.round(this.bounds.height)+'px';this.separator.style.borderWidth=Math.round(this.scale)+'px';}if(this.imageNode!=null){this.imageNode.style.left=(this.bounds.width-this.imageSize-4)+'px';this.imageNode.style.top='0px';this.imageNode.style.width=Math.round(this.imageSize*this.scale)+'px';this.imageNode.style.height=Math.round(this.imageSize*this.scale)+'px';}}else{this.startSize=Math.min(this.startSize,this.bounds.width);this.label.style.width=(this.startSize*this.scale)+'px';this.updateHtmlShape(this.content);this.content.style.background='';this.content.style.backgroundColor='';var w=this.startSize*this.scale;this.content.style.top='0px';this.content.style.left=w+'px';this.content.style.width=Math.max(0,this.bounds.width-w)+'px';if(this.separator!=null){this.separator.style.left=Math.round(this.startSize*this.scale)+'px';this.separator.style.top=Math.round(this.bounds.height)+'px';this.separator.style.width=Math.round(this.bounds.width)+'px';this.separator.style.height='1px';}if(this.imageNode!=null){this.imageNode.style.left=(this.bounds.width-this.imageSize-4)+'px';this.imageNode.style.top='0px';this.imageNode.style.width=this.imageSize*this.scale+'px';this.imageNode.style.height=this.imageSize*this.scale+'px';}}};mxSwimlane.prototype.createVml=function(){var node=document.createElement('v:group');var name=(this.isRounded)?'v:roundrect':'v:rect';this.label=document.createElement(name);this.configureVmlShape(this.label);if(this.isRounded){this.label.setAttribute('arcsize','20%');}this.isShadow=false;this.configureVmlShape(node);node.coordorigin='0,0';node.appendChild(this.label);this.content=document.createElement(name);var tmp=this.fill;this.fill=null;this.configureVmlShape(this.content);node.style.background='';if(this.isRounded){this.content.setAttribute('arcsize','4%');}this.fill=tmp;this.content.style.borderBottom='0px';node.appendChild(this.content);var color=this.style[mxConstants.STYLE_SEPARATORCOLOR];if(color!=null){this.separator=document.createElement('v:shape');this.separator.style.position='absolute';this.separator.strokecolor=color;var strokeNode=document.createElement('v:stroke');strokeNode.dashstyle='2 2';this.separator.appendChild(strokeNode);node.appendChild(this.separator);}if(this.image!=null){this.imageNode=document.createElement('v:image');this.imageNode.src=this.image;this.configureVmlShape(this.imageNode);this.imageNode.stroked='false';node.appendChild(this.imageNode);}return node;};mxSwimlane.prototype.redrawVml=function(){var x=Math.round(this.bounds.x);var y=Math.round(this.bounds.y);var w=Math.round(this.bounds.width);var h=Math.round(this.bounds.height);this.updateVmlShape(this.node);this.node.coordsize=w+','+h;this.updateVmlShape(this.label);this.label.style.top='0px';this.label.style.left='0px';this.label.style.rotation=null;this.startSize=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE));var start=Math.round(this.startSize*this.scale);if(this.separator!=null){this.separator.coordsize=w+','+h;this.separator.style.left=x+'px';this.separator.style.top=y+'px';this.separator.style.width=w+'px';this.separator.style.height=h+'px';}if(mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,true)){start=Math.min(start,this.bounds.height);this.label.style.height=start+'px';this.updateVmlShape(this.content);this.content.style.background='';this.content.style.top=start+'px';this.content.style.left='0px';this.content.style.height=Math.max(0,h-start)+'px';if(this.separator!=null){var d='m '+(w-x)+' '+(start-y)+' l '+(w-x)+' '+(h-y)+' e';this.separator.path=d;}if(this.imageNode!=null){var img=Math.round(this.imageSize*this.scale);this.imageNode.style.left=(w-img-4)+'px';this.imageNode.style.top='0px';this.imageNode.style.width=img+'px';this.imageNode.style.height=img+'px';}}else{start=Math.min(start,this.bounds.width);this.label.style.width=start+'px';this.updateVmlShape(this.content);this.content.style.background='';this.content.style.top='0px';this.content.style.left=start+'px';this.content.style.width=Math.max(0,w-start)+'px';if(this.separator!=null){var d='m '+(start-x)+' '+(h-y)+' l '+(w-x)+' '+(h-y)+' e';this.separator.path=d;}if(this.imageNode!=null){var img=Math.round(this.imageSize*this.scale);this.imageNode.style.left=(w-img-4)+'px';this.imageNode.style.top='0px';this.imageNode.style.width=img+'px';this.imageNode.style.height=img+'px';}}this.content.style.rotation=null;};mxSwimlane.prototype.createSvg=function(){var node=this.createSvgGroup('rect');if(this.isRounded){this.innerNode.setAttribute('rx',10);this.innerNode.setAttribute('ry',10);}this.content=document.createElementNS(mxConstants.NS_SVG,'path');this.configureSvgShape(this.content);this.content.setAttribute('fill','none');if(this.isRounded){this.content.setAttribute('rx',10);this.content.setAttribute('ry',10);}node.appendChild(this.content);var color=this.style[mxConstants.STYLE_SEPARATORCOLOR];if(color!=null){this.separator=document.createElementNS(mxConstants.NS_SVG,'line');this.separator.setAttribute('stroke',color);this.separator.setAttribute('fill','none');this.separator.setAttribute('stroke-dasharray','2, 2');node.appendChild(this.separator);}if(this.image!=null){this.imageNode=document.createElementNS(mxConstants.NS_SVG,'image');this.imageNode.setAttributeNS(mxConstants.NS_XLINK,'href',this.image);this.configureSvgShape(this.imageNode);node.appendChild(this.imageNode);}return node;};mxSwimlane.prototype.redrawSvg=function(){var tmp=this.isRounded;this.isRounded=false;this.updateSvgShape(this.innerNode);this.updateSvgShape(this.content);var horizontal=mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,true);this.startSize=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE));var ss=this.startSize*this.scale;if(this.shadowNode!=null){this.updateSvgShape(this.shadowNode);if(horizontal){this.shadowNode.setAttribute('height',ss);}else{this.shadowNode.setAttribute('width',ss);}}this.isRounded=tmp;this.content.removeAttribute('x');this.content.removeAttribute('y');this.content.removeAttribute('width');this.content.removeAttribute('height');var crisp=(this.crisp&&mxClient.IS_IE)?0.5:0;var x=Math.round(this.bounds.x)+crisp;var y=Math.round(this.bounds.y)+crisp;var w=Math.round(this.bounds.width);var h=Math.round(this.bounds.height);if(horizontal){ss=Math.min(ss,h);this.innerNode.setAttribute('height',ss);var points='M '+x+' '+(y+ss)+' l 0 '+(h-ss)+' l '+w+' 0'+' l 0 '+(ss-h);this.content.setAttribute('d',points);if(this.separator!=null){this.separator.setAttribute('x1',x+w);this.separator.setAttribute('y1',y+ss);this.separator.setAttribute('x2',x+w);this.separator.setAttribute('y2',y+h);}if(this.imageNode!=null){this.imageNode.setAttribute('x',x+w-this.imageSize-4);this.imageNode.setAttribute('y',y);this.imageNode.setAttribute('width',this.imageSize*this.scale+'px');this.imageNode.setAttribute('height',this.imageSize*this.scale+'px');}}else{ss=Math.min(ss,w);this.innerNode.setAttribute('width',ss);var points='M '+(x+ss)+' '+y+' l '+(w-ss)+' 0'+' l 0 '+h+' l '+(ss-w)+' 0';this.content.setAttribute('d',points);if(this.separator!=null){this.separator.setAttribute('x1',x+ss);this.separator.setAttribute('y1',y+h);this.separator.setAttribute('x2',x+w);this.separator.setAttribute('y2',y+h);}if(this.imageNode!=null){this.imageNode.setAttribute('x',x+w-this.imageSize-4);this.imageNode.setAttribute('y',y);this.imageNode.setAttribute('width',this.imageSize*this.scale+'px');this.imageNode.setAttribute('height',this.imageSize*this.scale+'px');}}};function mxGraphLayout(graph){this.graph=graph;};mxGraphLayout.prototype.graph=null;mxGraphLayout.prototype.useBoundingBox=true;mxGraphLayout.prototype.parent=null;mxGraphLayout.prototype.moveCell=function(cell,x,y){};mxGraphLayout.prototype.execute=function(parent){};mxGraphLayout.prototype.getGraph=function(){return this.graph;};mxGraphLayout.prototype.getConstraint=function(key,cell,edge,source){var state=this.graph.view.getState(cell);var style=(state!=null)?state.style:this.graph.getCellStyle(cell);return(style!=null)?style[key]:null;};mxGraphLayout.prototype.isVertexMovable=function(cell){return this.graph.isCellMovable(cell);};mxGraphLayout.prototype.isVertexIgnored=function(vertex){return!this.graph.getModel().isVertex(vertex)||!this.graph.isCellVisible(vertex);};mxGraphLayout.prototype.isEdgeIgnored=function(edge){var model=this.graph.getModel();return!model.isEdge(edge)||!this.graph.isCellVisible(edge)||model.getTerminal(edge,true)==null||model.getTerminal(edge,false)==null;};mxGraphLayout.prototype.setEdgeStyleEnabled=function(edge,value){this.graph.setCellStyles(mxConstants.STYLE_NOEDGESTYLE,(value)?'0':'1',[edge]);};mxGraphLayout.prototype.setOrthogonalEdge=function(edge,value){this.graph.setCellStyles(mxConstants.STYLE_ORTHOGONAL,(value)?'1':'0',[edge]);};mxGraphLayout.prototype.getParentOffset=function(parent){var result=new mxPoint();if(parent!=null&&parent!=this.parent){var model=this.graph.getModel();if(model.isAncestor(this.parent,parent)){var parentGeo=model.getGeometry(parent);while(parent!=this.parent){result.x=result.x+parentGeo.x;result.y=result.y+parentGeo.y;parent=model.getParent(parent);;parentGeo=model.getGeometry(parent);}}}return result;};mxGraphLayout.prototype.setEdgePoints=function(edge,points){if(edge!=null){var model=this.graph.model;var geometry=model.getGeometry(edge);if(geometry==null){geometry=new mxGeometry();geometry.setRelative(true);}else{geometry=geometry.clone();}if(this.parent!=null&&points!=null){var parent=model.getParent(edge);var parentOffset=this.getParentOffset(parent);for(var i=0;i=0;i--){var group=groups[i];var children=this.graph.getChildVertices(group);var bounds=this.graph.getBoundingBoxFromGeometry(children);var geometry=this.graph.getCellGeometry(group);var left=0;var top=0;if(this.graph.isSwimlane(group)){var size=this.graph.getStartSize(group);left=size.width;top=size.height;}if(bounds!=null&&geometry!=null){geometry=geometry.clone();geometry.x=geometry.x+bounds.x-border-left;geometry.y=geometry.y+bounds.y-border-top;geometry.width=bounds.width+2*border+left;geometry.height=bounds.height+2*border+top;this.graph.getModel().setGeometry(group,geometry);this.graph.moveCells(children,border+left-bounds.x,border+top-bounds.y);}}}finally{this.graph.getModel().endUpdate();}};function mxStackLayout(graph,horizontal,spacing,x0,y0,border){mxGraphLayout.call(this,graph);this.horizontal=(horizontal!=null)?horizontal:true;this.spacing=(spacing!=null)?spacing:0;this.x0=(x0!=null)?x0:0;this.y0=(y0!=null)?y0:0;this.border=(border!=null)?border:0;};mxStackLayout.prototype=new mxGraphLayout();mxStackLayout.prototype.constructor=mxStackLayout;mxStackLayout.prototype.horizontal=null;mxStackLayout.prototype.spacing=null;mxStackLayout.prototype.x0=null;mxStackLayout.prototype.y0=null;mxStackLayout.prototype.border=0;mxStackLayout.prototype.keepFirstLocation=false;mxStackLayout.prototype.fill=false;mxStackLayout.prototype.resizeParent=false;mxStackLayout.prototype.resizeLast=false;mxStackLayout.prototype.wrap=null;mxStackLayout.prototype.isHorizontal=function(){return this.horizontal;};mxStackLayout.prototype.moveCell=function(cell,x,y){var model=this.graph.getModel();var parent=model.getParent(cell);var horizontal=this.isHorizontal();if(cell!=null&&parent!=null){var i=0;var last=0;var childCount=model.getChildCount(parent);var value=(horizontal)?x:y;var pstate=this.graph.getView().getState(parent);if(pstate!=null){value-=(horizontal)?pstate.x:pstate.y;}for(i=0;ivalue){break;}last=tmp;}}}var idx=parent.getIndex(cell);idx=Math.max(0,i-((i>idx)?1:0));model.add(parent,cell,idx);}};mxStackLayout.prototype.getParentSize=function(parent){var model=this.graph.getModel();var pgeo=model.getGeometry(parent);if(this.graph.container!=null&&((pgeo==null&&model.isLayer(parent))||parent==this.graph.getView().currentRoot)){var width=this.graph.container.offsetWidth-1;var height=this.graph.container.offsetHeight-1;pgeo=new mxRectangle(0,0,width,height);}return pgeo;};mxStackLayout.prototype.execute=function(parent){if(parent!=null){var horizontal=this.isHorizontal();var model=this.graph.getModel();var pgeo=this.getParentSize(parent);var fillValue=0;if(pgeo!=null){fillValue=(horizontal)?pgeo.height:pgeo.width;}fillValue-=2*this.spacing+2*this.border;var size=(this.graph.isSwimlane(parent))?this.graph.getStartSize(parent):new mxRectangle();fillValue-=(horizontal)?size.height:size.width;var x0=this.x0+size.width+this.border;var y0=this.y0+size.height+this.border;model.beginUpdate();try{var tmp=0;var last=null;var childCount=model.getChildCount(parent);for(var i=0;ithis.wrap)||(!horizontal&&last.y+last.height+geo.height+2*this.spacing>this.wrap)){last=null;if(horizontal){y0+=tmp+this.spacing;}else{x0+=tmp+this.spacing;}tmp=0;}}tmp=Math.max(tmp,(horizontal)?geo.height:geo.width);if(last!=null){if(horizontal){geo.x=last.x+last.width+this.spacing;}else{geo.y=last.y+last.height+this.spacing;}}else if(!this.keepFirstLocation){if(horizontal){geo.x=x0;}else{geo.y=y0;}}if(horizontal){geo.y=y0;}else{geo.x=x0;}if(this.fill&&fillValue>0){if(horizontal){geo.height=fillValue;}else{geo.width=fillValue;}}model.setGeometry(child,geo);last=geo;}}}if(this.resizeParent&&pgeo!=null&&last!=null&&!this.graph.isCellCollapsed(parent)){pgeo=pgeo.clone();if(horizontal){pgeo.width=last.x+last.width+this.spacing;}else{pgeo.height=last.y+last.height+this.spacing;}model.setGeometry(parent,pgeo);}else if(this.resizeLast&&pgeo!=null&&last!=null){if(horizontal){last.width=pgeo.width-last.x-this.spacing;}else{last.height=pgeo.height-last.y-this.spacing;}}}finally{model.endUpdate();}}};function mxPartitionLayout(graph,horizontal,spacing,border){mxGraphLayout.call(this,graph);this.horizontal=(horizontal!=null)?horizontal:true;this.spacing=spacing||0;this.border=border||0;};mxPartitionLayout.prototype=new mxGraphLayout();mxPartitionLayout.prototype.constructor=mxPartitionLayout;mxPartitionLayout.prototype.horizontal=null;mxPartitionLayout.prototype.spacing=null;mxPartitionLayout.prototype.border=null;mxPartitionLayout.prototype.resizeVertices=true;mxPartitionLayout.prototype.isHorizontal=function(){return this.horizontal;};mxPartitionLayout.prototype.moveCell=function(cell,x,y){var model=this.graph.getModel();var parent=model.getParent(cell);if(cell!=null&&parent!=null){var i=0;var last=0;var childCount=model.getChildCount(parent);for(i=0;ix){break;}last=tmp;}}var idx=parent.getIndex(cell);idx=Math.max(0,i-((i>idx)?1:0));model.add(parent,cell,idx);}};mxPartitionLayout.prototype.execute=function(parent){var horizontal=this.isHorizontal();var model=this.graph.getModel();var pgeo=model.getGeometry(parent);if(this.graph.container!=null&&((pgeo==null&&model.isLayer(parent))||parent==this.graph.getView().currentRoot)){var width=this.graph.container.offsetWidth-1;var height=this.graph.container.offsetHeight-1;pgeo=new mxRectangle(0,0,width,height);}if(pgeo!=null){var children=[];var childCount=model.getChildCount(parent);for(var i=0;i0){var x0=this.border;var y0=this.border;var other=(horizontal)?pgeo.height:pgeo.width;other-=2*this.border;var size=(this.graph.isSwimlane(parent))?this.graph.getStartSize(parent):new mxRectangle();other-=(horizontal)?size.height:size.width;x0=x0+size.width;y0=y0+size.height;var tmp=this.border+(n-1)*this.spacing;var value=(horizontal)?((pgeo.width-x0-tmp)/n):((pgeo.height-y0-tmp)/n);if(value>0){model.beginUpdate();try{for(var i=0;i0){root=parent;}else{var roots=this.graph.findTreeRoots(parent,true,this.invert);if(roots.length>0){for(var i=0;i0){root=roots[i];break;}}}}}if(root!=null){if(this.resizeParent){this.parentsChanged=new Object();}else{this.parentsChanged=null;}model.beginUpdate();try{var node=this.dfs(root,parent);if(node!=null){this.layout(node);var x0=this.graph.gridSize;var y0=x0;if(!this.moveTree){var g=this.getVertexBounds(root);if(g!=null){x0=g.x;y0=g.y;}}var bounds=null;if(this.isHorizontal()){bounds=this.horizontalLayout(node,x0,y0);}else{bounds=this.verticalLayout(node,null,x0,y0);}if(bounds!=null){var dx=0;var dy=0;if(bounds.x<0){dx=Math.abs(x0-bounds.x);}if(bounds.y<0){dy=Math.abs(y0-bounds.y);}if(dx!=0||dy!=0){this.moveNode(node,dx,dy);}if(this.resizeParent){this.adjustParents();}if(this.edgeRouting){this.localEdgeProcessing(node);}}}}finally{model.endUpdate();}}};mxCompactTreeLayout.prototype.moveNode=function(node,dx,dy){node.x+=dx;node.y+=dy;this.apply(node);var child=node.child;while(child!=null){this.moveNode(child,dx,dy);child=child.next;}};mxCompactTreeLayout.prototype.dfs=function(cell,parent,visited){visited=(visited!=null)?visited:[];var id=mxCellPath.create(cell);var node=null;if(cell!=null&&visited[id]==null&&!this.isVertexIgnored(cell)){visited[id]=cell;node=this.createNode(cell);var model=this.graph.getModel();var prev=null;var out=this.graph.getEdges(cell,parent,this.invert,!this.invert,false,true);var view=this.graph.getView();for(var i=0;i0){if(p1<0){var s=p1*a2;d=s/a1-p2;}else if(p1>0){var s=p1*b2;d=s/b1-p2;}else{d=-p2;}}else if(b1p1+a1){var s=(a1+p1)*b2;d=s/b1-(p2+a2);}else{d=b2-(p2+a2);}if(d>0){return d;}else{return 0;}};mxCompactTreeLayout.prototype.bridge=function(line1,x1,y1,line2,x2,y2){var dx=x2+line2.dx-x1;var dy=0;var s=0;if(line2.dx==0){dy=line2.dy;}else{s=dx*line2.dy;dy=s/line2.dx;}var r=this.createLine(dx,dy,line2.next);line1.next=this.createLine(0,y2+line2.dy-dy-y1,r);return r;};mxCompactTreeLayout.prototype.createNode=function(cell){var node=new Object();node.cell=cell;node.x=0;node.y=0;node.width=0;node.height=0;var geo=this.getVertexBounds(cell);if(geo!=null){if(this.isHorizontal()){node.width=geo.height;node.height=geo.width;}else{node.width=geo.width;node.height=geo.height;}}node.offsetX=0;node.offsetY=0;node.contour=new Object();return node;};mxCompactTreeLayout.prototype.apply=function(node,bounds){var model=this.graph.getModel();var cell=node.cell;var g=model.getGeometry(cell);if(cell!=null&&g!=null){if(this.isVertexMovable(cell)){g=this.setVertexLocation(cell,node.x,node.y);if(this.resizeParent){var parent=model.getParent(cell);var id=mxCellPath.create(parent);if(this.parentsChanged[id]==null){this.parentsChanged[id]=parent;}}}if(bounds==null){bounds=new mxRectangle(g.x,g.y,g.width,g.height);}else{bounds=new mxRectangle(Math.min(bounds.x,g.x),Math.min(bounds.y,g.y),Math.max(bounds.x+bounds.width,g.x+g.width),Math.max(bounds.y+bounds.height,g.y+g.height));}}return bounds;};mxCompactTreeLayout.prototype.createLine=function(dx,dy,next){var line=new Object();line.dx=dx;line.dy=dy;line.next=next;return line;};mxCompactTreeLayout.prototype.adjustParents=function(){var tmp=[];for(var id in this.parentsChanged){tmp.push(this.parentsChanged[id]);}this.arrangeGroups(mxUtils.sortCells(tmp,true),this.groupPadding);};mxCompactTreeLayout.prototype.localEdgeProcessing=function(node){this.processNodeOutgoing(node);var child=node.child;while(child!=null){this.localEdgeProcessing(child);child=child.next;}};mxCompactTreeLayout.prototype.processNodeOutgoing=function(node){var child=node.child;var parentCell=node.cell;var childCount=0;var sortedCells=[];while(child!=null){childCount++;var sortingCriterion=child.x;if(this.horizontal){sortingCriterion=child.y;}sortedCells.push(new WeightedCellSorter(child,sortingCriterion));child=child.next;}sortedCells.sort(WeightedCellSorter.prototype.compare);var availableWidth=node.width;var requiredWidth=(childCount+1)*this.prefHozEdgeSep;if(availableWidth>requiredWidth+(2*this.prefHozEdgeSep)){availableWidth-=2*this.prefHozEdgeSep;}var edgeSpacing=availableWidth/childCount;var currentXOffset=edgeSpacing/2.0;if(availableWidth>requiredWidth+(2*this.prefHozEdgeSep)){currentXOffset+=this.prefHozEdgeSep;}var currentYOffset=this.minEdgeJetty-this.prefVertEdgeOff;var maxYOffset=0;var parentBounds=this.getVertexBounds(parentCell);child=node.child;for(var j=0;jchildCount/2){currentYOffset-=this.prefVertEdgeOff;}currentXOffset+=edgeSpacing;maxYOffset=Math.max(maxYOffset,currentYOffset);}};function WeightedCellSorter(cell,weightedValue){this.cell=cell;this.weightedValue=weightedValue;};WeightedCellSorter.prototype.weightedValue=0;WeightedCellSorter.prototype.nudge=false;WeightedCellSorter.prototype.visited=false;WeightedCellSorter.prototype.rankIndex=null;WeightedCellSorter.prototype.cell=null;WeightedCellSorter.prototype.compare=function(a,b){if(a!=null&&b!=null){if(b.weightedValue>a.weightedValue){return 1;}else if(b.weightedValuethis.maxDistanceLimit){continue;}if(deltaLengthWithRadius1){this.layout(parallels);}}}finally{this.graph.model.endUpdate();}};mxParallelEdgeLayout.prototype.findParallels=function(parent){var model=this.graph.getModel();var lookup=[];var childCount=model.getChildCount(parent);for(var i=0;itrg)?trg+'-'+src:src+'-'+trg;}return null;};mxParallelEdgeLayout.prototype.layout=function(parallels){var edge=parallels[0];var model=this.graph.getModel();var src=model.getGeometry(model.getTerminal(edge,true));var trg=model.getGeometry(model.getTerminal(edge,false));if(src==trg){var x0=src.x+src.width+this.spacing;var y0=src.y+src.height/2;for(var i=0;i0){var internalEdge=new mxGraphHierarchyEdge(edges);for(var k=0;k0){var internalNode=startNodes[0];var layerDeterminingEdges;var edgesToBeMarked;if(this.scanRanksFromSinks){layerDeterminingEdges=internalNode.connectsAsSource;edgesToBeMarked=internalNode.connectsAsTarget;}else{layerDeterminingEdges=internalNode.connectsAsTarget;edgesToBeMarked=internalNode.connectsAsSource;}var allEdgesScanned=true;var minimumLayer=0;if(!this.scanRanksFromSinks){minimumLayer=this.SOURCESCANSTARTRANK;}for(var i=0;i1){edge.maxRank=parent.maxRank;edge.minRank=node.maxRank;edge.temp=[];edge.x=[];edge.y=[];for(var i=edge.minRank+1;irightAbovePositions[ik]){totalCurrentCrossings++;}if(leftAbovePositions[k]rightBelowPositions[ik]){totalCurrentCrossings++;}if(leftBelowPositions[k]=0;j--){this.medianRank(j,downwardSweep);}}else{for(var j=1;ja.medianValue){return-1;}else if(b.medianValue0){possibleNewRoots=mxUtils.clone(unseenNodes,null,true);}var seenNodesCopy=mxUtils.clone(seenNodes,null,true);model.visit(function(parent,node,connectingEdge,layer,seen){if(node.isAncestor(parent)){connectingEdge.invert();mxUtils.remove(connectingEdge,parent.connectsAsSource);node.connectsAsSource.push(connectingEdge);parent.connectsAsTarget.push(connectingEdge);mxUtils.remove(connectingEdge,node.connectsAsTarget);}var cellId=mxCellPath.create(node.cell);seenNodes[cellId]=node;delete unseenNodes[cellId];},unseenNodes,true,seenNodesCopy);var graph=this.layout.getGraph();if(possibleNewRoots!=null&&possibleNewRoots.length>0){var roots=model.roots;for(var i=0;i0&&count<=maxTries){var cellWrapper=nodeList.shift();var cell=cellWrapper.cell;var rankValue=cellWrapper.weightedValue;var rankIndex=parseInt(cellWrapper.rankIndex);var nextLayerConnectedCells=cell.getNextLayerConnectedCells(rankValue);var previousLayerConnectedCells=cell.getPreviousLayerConnectedCells(rankValue);var numNextLayerConnected=nextLayerConnectedCells.length;var numPreviousLayerConnected=previousLayerConnectedCells.length;var medianNextLevel=this.medianXValue(nextLayerConnectedCells,rankValue+1);var medianPreviousLevel=this.medianXValue(previousLayerConnectedCells,rankValue-1);var numConnectedNeighbours=numNextLayerConnected+numPreviousLayerConnected;var currentPosition=cell.getGeneralPurposeVariable(rankValue);var cellMedian=currentPosition;if(numConnectedNeighbours>0){cellMedian=(medianNextLevel*numNextLayerConnected+medianPreviousLevel*numPreviousLayerConnected)/numConnectedNeighbours;}var positionChanged=false;if(cellMediancurrentPosition+tolerance){var rankSize=rank[rankValue].length;if(rankIndex==rankSize-1){cell.setGeneralPurposeVariable(rankValue,cellMedian);positionChanged=true;}else{var rightCell=rank[rankValue][rankIndex+1];var rightLimit=rightCell.getGeneralPurposeVariable(rankValue);rightLimit=rightLimit-rightCell.width/2-this.intraCellSpacing-cell.width/2;if(rightLimit>cellMedian){cell.setGeneralPurposeVariable(rankValue,cellMedian);positionChanged=true;}else if(rightLimit>cell.getGeneralPurposeVariable(rankValue)+tolerance){cell.setGeneralPurposeVariable(rankValue,rightLimit);positionChanged=true;}}}if(positionChanged){for(var i=0;i0;j--){this.rankMedianPosition(j-1,model,j);}}else{for(var j=0;j0){medianNextLevel=this.medianXValue(nextLayerConnectedCells,nextRankValue);}else{medianNextLevel=cell.getGeneralPurposeVariable(rankValue);}}var leftBuffer=0.0;var leftLimit=-100000000.0;for(var j=weightedValues[i].rankIndex-1;j>=0;){var rankId=mxCellPath.create(rank[j].cell);var weightedValue=cellMap[rankId];if(weightedValue!=null){var leftCell=weightedValue.cell;if(weightedValue.visited){leftLimit=leftCell.getGeneralPurposeVariable(rankValue)+leftCell.width/2.0+this.intraCellSpacing+leftBuffer+cell.width/2.0;j=-1;}else{leftBuffer+=leftCell.width+this.intraCellSpacing;j--;}}}var rightBuffer=0.0;var rightLimit=100000000.0;for(var j=weightedValues[i].rankIndex+1;j=leftLimit&&medianNextLevel<=rightLimit){cell.setGeneralPurposeVariable(rankValue,medianNextLevel);}else if(medianNextLevelrightLimit){cell.setGeneralPurposeVariable(rankValue,rightLimit);this.currentXDelta+=medianNextLevel-rightLimit;}weightedValues[i].visited=true;}};mxCoordinateAssignment.prototype.calculatedWeightedValue=function(currentCell,collection){var totalWeight=0;for(var i=0;i=0;i--){if(i0){this.rankCoordinates(i,facade,model);}}};mxCoordinateAssignment.prototype.rankCoordinates=function(rankValue,graph,model){var rank=model.ranks[rankValue];var maxY=0.0;var localX=this.initialX+(this.widestRankValue-this.rankWidths[rankValue])/2;var boundsWarning=false;for(var i=0;i=0;rankValue--){var maxCellHeight=0.0;var rank=model.ranks[rankValue];var localX=this.initialX;var boundsWarning=false;for(var i=0;ithis.widestRankValue){this.widestRankValue=localX;this.widestRank=rankValue;}this.rankWidths[rankValue]=localX;}if(boundsWarning==true){mxLog.warn('At least one cell has no bounds');}this.rankY[rankValue]=y;var distanceToNextRank=maxCellHeight/2.0+lastRankMaxCellHeight/2.0+this.interRankCellSpacing;lastRankMaxCellHeight=maxCellHeight;if(this.orientation==mxConstants.DIRECTION_NORTH||this.orientation==mxConstants.DIRECTION_WEST){y+=distanceToNextRank;}else{y-=distanceToNextRank;}for(var i=0;icell.minRank+1;i--){var nextX=cell.getX(i-1);if(currentX==nextX){downXPositions[i-cell.minRank-2]=currentX;downSegCount++;}else if(this.repositionValid(model,cell,i-1,currentX)){downXPositions[i-cell.minRank-2]=currentX;downSegCount++;}else{downXPositions[i-cell.minRank-2]=cell.getX(i);currentX=nextX;}}if(downSegCount>refSegCount||upSegCount>refSegCount){if(downSegCount>upSegCount){for(var i=cell.maxRank-2;i>cell.minRank;i--){cell.setX(i,downXPositions[i-cell.minRank-1]);}}else if(upSegCount>downSegCount){for(var i=cell.minRank+2;icurrentX){if(rankIndex==rankArray.length-1){return true;}var rightCell=rankArray[rankIndex+1];var rightLimit=rightCell.getGeneralPurposeVariable(rank);rightLimit=rightLimit-rightCell.width/2-this.intraCellSpacing-cell.width/2;if(rightLimit>=position){return true;}else{return false;}}return true;};mxCoordinateAssignment.prototype.setCellLocations=function(graph,model){this.rankTopY=[];this.rankBottomY=[];for(var i=0;i-1&¤tRank0){var sortedCells=[];for(var j=0;jrequiredWidth+(2*this.prefHozEdgeSep)){leftLimit+=this.prefHozEdgeSep;rightLimit-=this.prefHozEdgeSep;}var availableWidth=rightLimit-leftLimit;var edgeSpacing=availableWidth/connectedEdgeCount;var currentX=leftLimit+edgeSpacing/2.0;var currentYOffset=this.minEdgeJetty-this.prefVertEdgeOff;var maxYOffset=0;for(var j=0;jconnectedEdgeCount/2){currentYOffset-=this.prefVertEdgeOff;}for(var m=0;m0){offsetX=-offsetX;}else{offsetX=-offsetX+this.parallelEdgeSpacing;}parallelEdgeCount++;}cell.temp[0]=101207;}};mxCoordinateAssignment.prototype.setVertexLocation=function(cell){var realCell=cell.cell;var positionX=cell.x[0]-cell.width/2;var positionY=cell.y[0]-cell.height/2;this.rankTopY[cell.minRank]=Math.min(this.rankTopY[cell.minRank],positionY);this.rankBottomY[cell.minRank]=Math.max(this.rankBottomY[cell.minRank],positionY+cell.height);if(this.orientation==mxConstants.DIRECTION_NORTH||this.orientation==mxConstants.DIRECTION_SOUTH){this.layout.setVertexLocation(realCell,positionX,positionY);}else{this.layout.setVertexLocation(realCell,positionY,positionX);}this.limitX=Math.max(this.limitX,positionX+cell.width);};mxCoordinateAssignment.prototype.processReversedEdge=function(graph,model){};function WeightedCellSorter(cell,weightedValue){this.cell=cell;this.weightedValue=weightedValue;};WeightedCellSorter.prototype.weightedValue=0;WeightedCellSorter.prototype.nudge=false;WeightedCellSorter.prototype.visited=false;WeightedCellSorter.prototype.rankIndex=null;WeightedCellSorter.prototype.cell=null;WeightedCellSorter.prototype.compare=function(a,b){if(a!=null&&b!=null){if(b.weightedValue>a.weightedValue){return-1;}else if(b.weightedValue0){var cell=cellsStack.shift();var cellId=mxCellPath.create(cell);if(vertexSet[cellId]==null){vertexSet[cellId]=cell;if(this.fixRoots){var tmp=this.graph.getIncomingEdges(cell,parent);for(var k=0;k0){var cell=cell1;var current=mxCellPath.create(cell);if(path.length=0;i--){this.cellRemoved(this.getChildAt(cell,i));}if(this.cells!=null&&cell.getId()!=null){delete this.cells[cell.getId()];}}};mxGraphModel.prototype.parentForCellChanged=function(cell,parent,index){var previous=this.getParent(cell);if(parent!=null){if(parent!=previous||previous.getIndex(cell)!=index){parent.insert(cell,index);}}else if(previous!=null){var oldIndex=previous.getIndex(cell);previous.remove(oldIndex);}if(!this.contains(previous)&&parent!=null){this.cellAdded(cell);}else if(parent==null){this.cellRemoved(cell);}return previous;};mxGraphModel.prototype.getChildCount=function(cell){return(cell!=null)?cell.getChildCount():0;};mxGraphModel.prototype.getChildAt=function(cell,index){return(cell!=null)?cell.getChildAt(index):null;};mxGraphModel.prototype.getChildren=function(cell){return(cell!=null)?cell.children:null;};mxGraphModel.prototype.getChildVertices=function(parent){return this.getChildCells(parent,true,false);};mxGraphModel.prototype.getChildEdges=function(parent){return this.getChildCells(parent,false,true);};mxGraphModel.prototype.getChildCells=function(parent,vertices,edges){vertices=(vertices!=null)?vertices:false;edges=(edges!=null)?edges:false;var childCount=this.getChildCount(parent);var result=[];for(var i=0;i=0){topmost=false;break;}parent=this.getParent(parent);}if(topmost){tmp.push(cell);}}return tmp;};mxGraphModel.prototype.isVertex=function(cell){return(cell!=null)?cell.isVertex():false;};mxGraphModel.prototype.isEdge=function(cell){return(cell!=null)?cell.isEdge():false;};mxGraphModel.prototype.isConnectable=function(cell){return(cell!=null)?cell.isConnectable():false;};mxGraphModel.prototype.getValue=function(cell){return(cell!=null)?cell.getValue():null;};mxGraphModel.prototype.setValue=function(cell,value){this.execute(new mxValueChange(this,cell,value));return value;};mxGraphModel.prototype.valueForCellChanged=function(cell,value){return cell.valueChanged(value);};mxGraphModel.prototype.getGeometry=function(cell,geometry){return(cell!=null)?cell.getGeometry():null;};mxGraphModel.prototype.setGeometry=function(cell,geometry){if(geometry!=this.getGeometry(cell)){this.execute(new mxGeometryChange(this,cell,geometry));}return geometry;};mxGraphModel.prototype.geometryForCellChanged=function(cell,geometry){var previous=this.getGeometry(cell);cell.setGeometry(geometry);return previous;};mxGraphModel.prototype.getStyle=function(cell){return(cell!=null)?cell.getStyle():null;};mxGraphModel.prototype.setStyle=function(cell,style){if(style!=this.getStyle(cell)){this.execute(new mxStyleChange(this,cell,style));}return style;};mxGraphModel.prototype.styleForCellChanged=function(cell,style){var previous=this.getStyle(cell);cell.setStyle(style);return previous;};mxGraphModel.prototype.isCollapsed=function(cell){return(cell!=null)?cell.isCollapsed():false;};mxGraphModel.prototype.setCollapsed=function(cell,collapsed){if(collapsed!=this.isCollapsed(cell)){this.execute(new mxCollapseChange(this,cell,collapsed));}return collapsed;};mxGraphModel.prototype.collapsedStateForCellChanged=function(cell,collapsed){var previous=this.isCollapsed(cell);cell.setCollapsed(collapsed);return previous;};mxGraphModel.prototype.isVisible=function(cell){return(cell!=null)?cell.isVisible():false;};mxGraphModel.prototype.setVisible=function(cell,visible){if(visible!=this.isVisible(cell)){this.execute(new mxVisibleChange(this,cell,visible));}return visible;};mxGraphModel.prototype.visibleStateForCellChanged=function(cell,visible){var previous=this.isVisible(cell);cell.setVisible(visible);return previous;};mxGraphModel.prototype.execute=function(change){change.execute();this.beginUpdate();this.currentEdit.add(change);this.fireEvent(new mxEventObject(mxEvent.EXECUTE,'change',change));this.endUpdate();};mxGraphModel.prototype.beginUpdate=function(){this.updateLevel++;this.fireEvent(new mxEventObject(mxEvent.BEGIN_UPDATE));};mxGraphModel.prototype.endUpdate=function(){this.updateLevel--;if(!this.endingUpdate){this.endingUpdate=this.updateLevel==0;this.fireEvent(new mxEventObject(mxEvent.END_UPDATE,'edit',this.currentEdit));try{if(this.endingUpdate&&!this.currentEdit.isEmpty()){this.fireEvent(new mxEventObject(mxEvent.BEFORE_UNDO,'edit',this.currentEdit));var tmp=this.currentEdit;this.currentEdit=this.createUndoableEdit();tmp.notify();this.fireEvent(new mxEventObject(mxEvent.UNDO,'edit',tmp));}}finally{this.endingUpdate=false;}}};mxGraphModel.prototype.createUndoableEdit=function(){var edit=new mxUndoableEdit(this,true);edit.notify=function(){edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,'edit',edit,'changes',edit.changes));edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,'edit',edit,'changes',edit.changes));};return edit;};mxGraphModel.prototype.mergeChildren=function(from,to,cloneAllEdges){cloneAllEdges=(cloneAllEdges!=null)?cloneAllEdges:true;this.beginUpdate();try{var mapping=new Object();this.mergeChildrenImpl(from,to,cloneAllEdges,mapping);for(var key in mapping){var cell=mapping[key];var terminal=this.getTerminal(cell,true);if(terminal!=null){terminal=mapping[mxCellPath.create(terminal)];this.setTerminal(cell,terminal,true);}terminal=this.getTerminal(cell,false);if(terminal!=null){terminal=mapping[mxCellPath.create(terminal)];this.setTerminal(cell,terminal,false);}}}finally{this.endUpdate();}};mxGraphModel.prototype.mergeChildrenImpl=function(from,to,cloneAllEdges,mapping){this.beginUpdate();try{var childCount=from.getChildCount();for(var i=0;i=0){child=this.getChildAt(index);if(child!=null){this.children.splice(index,1);child.setParent(null);}}return child;};mxCell.prototype.removeFromParent=function(){if(this.parent!=null){var index=this.parent.getIndex(this);this.parent.remove(index);}};mxCell.prototype.getEdgeCount=function(){return(this.edges==null)?0:this.edges.length;};mxCell.prototype.getEdgeIndex=function(edge){return mxUtils.indexOf(this.edges,edge);};mxCell.prototype.getEdgeAt=function(index){return(this.edges==null)?null:this.edges[index];};mxCell.prototype.insertEdge=function(edge,isOutgoing){if(edge!=null){edge.removeFromTerminal(isOutgoing);edge.setTerminal(this,isOutgoing);if(this.edges==null||edge.getTerminal(!isOutgoing)!=this||mxUtils.indexOf(this.edges,edge)<0){if(this.edges==null){this.edges=[];}this.edges.push(edge);}}return edge;};mxCell.prototype.removeEdge=function(edge,isOutgoing){if(edge!=null){if(edge.getTerminal(!isOutgoing)!=this&&this.edges!=null){var index=this.getEdgeIndex(edge);if(index>=0){this.edges.splice(index,1);}}edge.setTerminal(null,isOutgoing);}return edge;};mxCell.prototype.removeFromTerminal=function(isSource){var terminal=this.getTerminal(isSource);if(terminal!=null){terminal.removeEdge(this,isSource);}};mxCell.prototype.getAttribute=function(name,defaultValue){var userObject=this.getValue();var val=(userObject!=null&&userObject.nodeType==mxConstants.NODETYPE_ELEMENT)?userObject.getAttribute(name):null;return val||defaultValue;};mxCell.prototype.setAttribute=function(name,value){var userObject=this.getValue();if(userObject!=null&&userObject.nodeType==mxConstants.NODETYPE_ELEMENT){userObject.setAttribute(name,value);}};mxCell.prototype.clone=function(){var clone=mxUtils.clone(this,this.mxTransient);clone.setValue(this.cloneValue());return clone;};mxCell.prototype.cloneValue=function(){var value=this.getValue();if(value!=null){if(typeof(value.clone)=='function'){value=value.clone();}else if(!isNaN(value.nodeType)){value=value.cloneNode(true);}}return value;};function mxGeometry(x,y,width,height){mxRectangle.call(this,x,y,width,height);};mxGeometry.prototype=new mxRectangle();mxGeometry.prototype.constructor=mxGeometry;mxGeometry.prototype.TRANSLATE_CONTROL_POINTS=true;mxGeometry.prototype.alternateBounds=null;mxGeometry.prototype.sourcePoint=null;mxGeometry.prototype.targetPoint=null;mxGeometry.prototype.points=null;mxGeometry.prototype.offset=null;mxGeometry.prototype.relative=false;mxGeometry.prototype.swap=function(){if(this.alternateBounds!=null){var old=new mxRectangle(this.x,this.y,this.width,this.height);this.x=this.alternateBounds.x;this.y=this.alternateBounds.y;this.width=this.alternateBounds.width;this.height=this.alternateBounds.height;this.alternateBounds=old;}};mxGeometry.prototype.getTerminalPoint=function(isSource){return(isSource)?this.sourcePoint:this.targetPoint;};mxGeometry.prototype.setTerminalPoint=function(point,isSource){if(isSource){this.sourcePoint=point;}else{this.targetPoint=point;}return point;};mxGeometry.prototype.translate=function(dx,dy){var clone=this.clone();if(!this.relative){this.x+=dx;this.y+=dy;}if(this.sourcePoint!=null){this.sourcePoint.x+=dx;this.sourcePoint.y+=dy;}if(this.targetPoint!=null){this.targetPoint.x+=dx;this.targetPoint.y+=dy;}if(this.TRANSLATE_CONTROL_POINTS&&this.points!=null){var count=this.points.length;for(var i=0;i1){result=result.substring(0,n-1);}return result;},getParentPath:function(path){if(path!=null){var index=path.lastIndexOf(mxCellPath.PATH_SEPARATOR);if(index>=0){return path.substring(0,index);}else if(path.length>0){return '';}}return null;},resolve:function(root,path){var parent=root;if(path!=null){var tokens=path.split(mxCellPath.PATH_SEPARATOR);for(var i=0;ip2[i])?1:-1);}else{var t1=parseInt(p1[i]);var t2=parseInt(p2[i]);comp=(t1==t2)?0:((t1>t2)?1:-1);}break;}}if(comp==0){var t1=p1.length;var t2=p2.length;if(t1!=t2){comp=(t1>t2)?1:-1;}}return comp;}};var mxPerimeter={RectanglePerimeter:function(bounds,vertex,next,orthogonal){var cx=bounds.getCenterX();var cy=bounds.getCenterY();var dx=next.x-cx;var dy=next.y-cy;var alpha=Math.atan2(dy,dx);var p=new mxPoint(0,0);var pi=Math.PI;var pi2=Math.PI/2;var beta=pi2-alpha;var t=Math.atan2(bounds.height,bounds.width);if(alpha<-pi+t||alpha>pi-t){p.x=bounds.x;p.y=cy-bounds.width*Math.tan(alpha)/2;}else if(alpha<-t){p.y=bounds.y;p.x=cx-bounds.height*Math.tan(beta)/2;}else if(alpha=bounds.x&&next.x<=bounds.x+bounds.width){p.x=next.x;}else if(next.y>=bounds.y&&next.y<=bounds.y+bounds.height){p.y=next.y;}if(next.xbounds.x+bounds.width){p.x=bounds.x+bounds.width;}if(next.ybounds.y+bounds.height){p.y=bounds.y+bounds.height;}}return p;},EllipsePerimeter:function(bounds,vertex,next,orthogonal){var x=bounds.x;var y=bounds.y;var a=bounds.width/2;var b=bounds.height/2;var cx=x+a;var cy=y+b;var px=next.x;var py=next.y;var dx=parseInt(px-cx);var dy=parseInt(py-cy);if(dx==0&&dy!=0){return new mxPoint(cx,cy+b*dy/Math.abs(dy));}else if(dx==0&&dy==0){return new mxPoint(px,py);}if(orthogonal){if(py>=y&&py<=y+bounds.height){var ty=py-cy;var tx=Math.sqrt(a*a*(1-(ty*ty)/(b*b)))||0;if(px<=x){tx=-tx;}return new mxPoint(cx+tx,py);}if(px>=x&&px<=x+bounds.width){var tx=px-cx;var ty=Math.sqrt(b*b*(1-(tx*tx)/(a*a)))||0;if(py<=y){ty=-ty;}return new mxPoint(px,cy+ty);}}var d=dy/dx;var h=cy-d*cx;var e=a*a*d*d+b*b;var f=-2*cx*e;var g=a*a*d*d*cx*cx+b*b*cx*cx-a*a*b*b;var det=Math.sqrt(f*f-4*e*g);var xout1=(-f+det)/(2*e);var xout2=(-f-det)/(2*e);var yout1=d*xout1+h;var yout2=d*xout2+h;var dist1=Math.sqrt(Math.pow((xout1-px),2)+Math.pow((yout1-py),2));var dist2=Math.sqrt(Math.pow((xout2-px),2)+Math.pow((yout2-py),2));var xout=0;var yout=0;if(dist1py){return new mxPoint(cx,y);}else{return new mxPoint(cx,y+h);}}else if(cy==py){if(cx>px){return new mxPoint(x,cy);}else{return new mxPoint(x+w,cy);}}var tx=cx;var ty=cy;if(orthogonal){if(px>=x&&px<=x+w){tx=px;}else if(py>=y&&py<=y+h){ty=py;}}if(px-t&&alphaMath.PI-t;}var result=null;if(base){if(orthogonal&&((vertical&&next.x>=start.x&&next.x<=end.x)||(!vertical&&next.y>=start.y&&next.y<=end.y))){if(vertical){result=new mxPoint(next.x,start.y);}else{result=new mxPoint(start.x,next.y);}}else{if(direction==mxConstants.DIRECTION_NORTH){result=new mxPoint(x+w/2+h*Math.tan(alpha)/2,y+h);}else if(direction==mxConstants.DIRECTION_SOUTH){result=new mxPoint(x+w/2-h*Math.tan(alpha)/2,y);}else if(direction==mxConstants.DIRECTION_WEST){result=new mxPoint(x+w,y+h/2+w*Math.tan(alpha)/2);}else{result=new mxPoint(x,y+h/2-w*Math.tan(alpha)/2);}}}else{if(orthogonal){var pt=new mxPoint(cx,cy);if(next.y>=y&&next.y<=y+h){pt.x=(vertical)?cx:((direction==mxConstants.DIRECTION_WEST)?x+w:x);pt.y=next.y;}else if(next.x>=x&&next.x<=x+w){pt.x=next.x;pt.y=(!vertical)?cy:((direction==mxConstants.DIRECTION_NORTH)?y+h:y);}dx=next.x-pt.x;dy=next.y-pt.y;cx=pt.x;cy=pt.y;}if((vertical&&next.x<=x+w/2)||(!vertical&&next.y<=y+h/2)){result=mxUtils.intersection(next.x,next.y,cx,cy,start.x,start.y,corner.x,corner.y);}else{result=mxUtils.intersection(next.x,next.y,cx,cy,corner.x,corner.y,end.x,end.y);}}if(result==null){result=new mxPoint(cx,cy);}return result;}};function mxPrintPreview(graph,scale,pageFormat,border,x0,y0,borderColor,title,pageSelector){this.graph=graph;this.scale=(scale!=null)?scale:1/graph.pageScale;this.border=(border!=null)?border:0;this.pageFormat=(pageFormat!=null)?pageFormat:graph.pageFormat;this.title=(title!=null)?title:'Printer-friendly version';this.x0=(x0!=null)?x0:0;this.y0=(y0!=null)?y0:0;this.borderColor=borderColor;this.pageSelector=(pageSelector!=null)?pageSelector:true;};mxPrintPreview.prototype.graph=null;mxPrintPreview.prototype.pageFormat=null;mxPrintPreview.prototype.scale=null;mxPrintPreview.prototype.border=0;mxPrintPreview.prototype.x0=0;mxPrintPreview.prototype.y0=0;mxPrintPreview.prototype.autoOrigin=true;mxPrintPreview.prototype.printOverlays=false;mxPrintPreview.prototype.borderColor=null;mxPrintPreview.prototype.title=null;mxPrintPreview.prototype.pageSelector=null;mxPrintPreview.prototype.wnd=null;mxPrintPreview.prototype.pageCount=0;mxPrintPreview.prototype.getWindow=function(){return this.wnd;};mxPrintPreview.prototype.getDoctype=function(){return '';};mxPrintPreview.prototype.open=function(css){var previousInitializeOverlay=this.graph.cellRenderer.initializeOverlay;var div=null;try{if(this.printOverlays){this.graph.cellRenderer.initializeOverlay=function(state,overlay){overlay.init(state.view.getDrawPane());};}if(this.wnd==null){this.wnd=window.open();var doc=this.wnd.document;var dt=this.getDoctype();if(dt!=null&&dt.length>0){doc.writeln(dt);}doc.writeln('');doc.writeln('');this.writeHead(doc,css);doc.writeln('');doc.writeln('');mxClient.link('stylesheet',mxClient.basePath+'/css/common.css',doc);if(mxClient.IS_IE&&document.documentMode!=9){doc.namespaces.add('v','urn:schemas-microsoft-com:vml');doc.namespaces.add('o','urn:schemas-microsoft-com:office:office');var ss=doc.createStyleSheet();ss.cssText='v\\:*{behavior:url(#default#VML)}o\\:*{behavior:url(#default#VML)}';mxClient.link('stylesheet',mxClient.basePath+'/css/explorer.css',doc);}var bounds=this.graph.getGraphBounds().clone();var currentScale=this.graph.getView().getScale();var sc=currentScale/this.scale;var tr=this.graph.getView().getTranslate();if(!this.autoOrigin){this.x0=-tr.x*this.scale;this.y0=-tr.y*this.scale;bounds.width+=bounds.x;bounds.height+=bounds.y;bounds.x=0;bounds.y=0;this.border=0;}bounds.width/=sc;bounds.height/=sc;var availableWidth=this.pageFormat.width-(this.border*2);var availableHeight=this.pageFormat.height-(this.border*2);var hpages=Math.max(1,Math.ceil((bounds.width+this.x0)/availableWidth));var vpages=Math.max(1,Math.ceil((bounds.height+this.y0)/availableHeight));this.pageCount=hpages*vpages;var writePageSelector=mxUtils.bind(this,function(){if(this.pageSelector&&(vpages>1||hpages>1)){var table=this.createPageSelector(vpages,hpages);doc.body.appendChild(table);if(mxClient.IS_IE){table.style.position='absolute';var update=function(){table.style.top=(doc.body.scrollTop+10)+'px';};mxEvent.addListener(this.wnd,'scroll',function(evt){update();});mxEvent.addListener(this.wnd,'resize',function(evt){update();});}}});var pages=null;if(mxClient.IS_IE&&document.documentMode!=9){pages=[];var waitCounter=0;var isDone=false;var mxImageShapeScheduleUpdateAspect=mxImageShape.prototype.scheduleUpdateAspect;var mxImageShapeUpdateAspect=mxImageShape.prototype.updateAspect;var writePages=function(){if(isDone&&waitCounter==0){mxImageShape.prototype.scheduleUpdateAspect=mxImageShapeScheduleUpdateAspect;mxImageShape.prototype.updateAspect=mxImageShapeUpdateAspect;var markup='';for(var i=0;i';}}doc.body.innerHTML=markup;writePageSelector();}};mxImageShape.prototype.scheduleUpdateAspect=function(){waitCounter++;mxImageShapeScheduleUpdateAspect.apply(this,arguments);};mxImageShape.prototype.updateAspect=function(){mxImageShapeUpdateAspect.apply(this,arguments);waitCounter--;writePages();};}for(var i=0;i');doc.writeln('');doc.close();if(pages!=null){isDone=true;writePages();}else{writePageSelector();}mxEvent.release(doc.body);}this.wnd.focus();}catch(e){if(div!=null&&div.parentNode!=null){div.parentNode.removeChild(div);}}finally{this.graph.cellRenderer.initializeOverlay=previousInitializeOverlay;}return this.wnd;};mxPrintPreview.prototype.writeHead=function(doc,css){if(this.title!=null){doc.writeln(''+this.title+'');}doc.writeln('');};mxPrintPreview.prototype.createPageSelector=function(vpages,hpages){var doc=this.wnd.document;var table=doc.createElement('table');table.className='mxPageSelector';table.setAttribute('border','0');var tbody=doc.createElement('tbody');for(var i=0;i0){var pairs=name.split(';');if(style!=null&&name.charAt(0)!=';'){style=mxUtils.clone(style);}else{style=new Object();}for(var i=0;i=0){var key=tmp.substring(0,pos);var value=tmp.substring(pos+1);if(value==mxConstants.NONE){delete style[key];}else if(mxUtils.isNumeric(value)){style[key]=parseFloat(value);}else{style[key]=value;}}else{var tmpStyle=this.styles[tmp];if(tmpStyle!=null){for(var key in tmpStyle){style[key]=tmpStyle[key];}}}}}return style;};function mxCellState(view,cell,style){this.view=view;this.cell=cell;this.style=style;this.origin=new mxPoint();this.absoluteOffset=new mxPoint();};mxCellState.prototype=new mxRectangle();mxCellState.prototype.constructor=mxCellState;mxCellState.prototype.view=null;mxCellState.prototype.cell=null;mxCellState.prototype.style=null;mxCellState.prototype.invalid=true;mxCellState.prototype.invalidOrder=false;mxCellState.prototype.orderChanged=false;mxCellState.prototype.origin=null;mxCellState.prototype.absolutePoints=null;mxCellState.prototype.absoluteOffset=null;mxCellState.prototype.visibleSourceState=null;mxCellState.prototype.visibleTargetState=null;mxCellState.prototype.terminalDistance=0;mxCellState.prototype.length=0;mxCellState.prototype.segments=null;mxCellState.prototype.shape=null;mxCellState.prototype.text=null;mxCellState.prototype.getPerimeterBounds=function(border,bounds){border=border||0;bounds=(bounds!=null)?bounds:new mxRectangle(this.x,this.y,this.width,this.height);if(this.shape!=null&&this.shape.stencil!=null){var aspect=this.shape.stencil.computeAspect(this,bounds,null);bounds.x=aspect.x;bounds.y=aspect.y;bounds.width=this.shape.stencil.w0*aspect.width;bounds.height=this.shape.stencil.h0*aspect.height;}if(border!=0){bounds.grow(border);}return bounds;};mxCellState.prototype.setAbsoluteTerminalPoint=function(point,isSource){if(isSource){if(this.absolutePoints==null){this.absolutePoints=[];}if(this.absolutePoints.length==0){this.absolutePoints.push(point);}else{this.absolutePoints[0]=point;}}else{if(this.absolutePoints==null){this.absolutePoints=[];this.absolutePoints.push(null);this.absolutePoints.push(point);}else if(this.absolutePoints.length==1){this.absolutePoints.push(point);}else{this.absolutePoints[this.absolutePoints.length-1]=point;}}};mxCellState.prototype.setCursor=function(cursor){if(this.shape!=null){this.shape.setCursor(cursor);}if(this.text!=null){this.text.setCursor(cursor);}};mxCellState.prototype.getVisibleTerminal=function(source){var tmp=this.getVisibleTerminalState(source);return(tmp!=null)?tmp.cell:null;};mxCellState.prototype.getVisibleTerminalState=function(source){return(source)?this.visibleSourceState:this.visibleTargetState;};mxCellState.prototype.setVisibleTerminalState=function(terminalState,source){if(source){this.visibleSourceState=terminalState;}else{this.visibleTargetState=terminalState;}};mxCellState.prototype.destroy=function(){this.view.graph.cellRenderer.destroy(this);};mxCellState.prototype.clone=function(){var clone=new mxCellState(this.view,this.cell,this.style);if(this.absolutePoints!=null){clone.absolutePoints=[];for(var i=0;i=0;}return false;};mxGraphSelectionModel.prototype.isEmpty=function(){return this.cells.length==0;};mxGraphSelectionModel.prototype.clear=function(){this.changeSelection(null,this.cells);};mxGraphSelectionModel.prototype.setCell=function(cell){if(cell!=null){this.setCells([cell]);}};mxGraphSelectionModel.prototype.setCells=function(cells){if(cells!=null){if(this.singleSelection){cells=[this.getFirstSelectableCell(cells)];}var tmp=[];for(var i=0;i0&&added[0]!=null)||(removed!=null&&removed.length>0&&removed[0]!=null)){var change=new mxSelectionChange(this,added,removed);change.execute();var edit=new mxUndoableEdit(this,false);edit.add(change);this.fireEvent(new mxEventObject(mxEvent.UNDO,'edit',edit));}};mxGraphSelectionModel.prototype.cellAdded=function(cell){if(cell!=null&&!this.isSelected(cell)){this.cells.push(cell);}};mxGraphSelectionModel.prototype.cellRemoved=function(cell){if(cell!=null){var index=mxUtils.indexOf(this.cells,cell);if(index>=0){this.cells.splice(index,1);}}};function mxSelectionChange(selectionModel,added,removed){this.selectionModel=selectionModel;this.added=(added!=null)?added.slice():null;this.removed=(removed!=null)?removed.slice():null;};mxSelectionChange.prototype.execute=function(){var t0=mxLog.enter('mxSelectionChange.execute');window.status=mxResources.get(this.selectionModel.updatingSelectionResource)||this.selectionModel.updatingSelectionResource;if(this.removed!=null){for(var i=0;i0){result.x=state.text.boundingBox.x;}if(state.text.boundingBox.y>0){result.y=state.text.boundingBox.y;}}}else if(state.text!=null&&state.text.boundingBox!=null){result.x=Math.min(result.x,state.text.boundingBox.x);result.y=Math.min(result.y,state.text.boundingBox.y);}result.x+=spacingLeft;result.y+=spacingTop;if(state.text!=null&&state.text.boundingBox!=null){if(!isEdge){result.width=Math.max(result.width,state.text.boundingBox.width);result.height=Math.max(result.height,state.text.boundingBox.height);}else{result.width=Math.max(minWidth,state.text.boundingBox.width);result.height=Math.max(minHeight,state.text.boundingBox.height);}}if(this.graph.getModel().isVertex(state.cell)){var horizontal=mxUtils.getValue(state.style,mxConstants.STYLE_LABEL_POSITION,mxConstants.ALIGN_CENTER);if(horizontal==mxConstants.ALIGN_LEFT){result.x-=state.width;}else if(horizontal==mxConstants.ALIGN_RIGHT){result.x+=state.width;}var vertical=mxUtils.getValue(state.style,mxConstants.STYLE_VERTICAL_LABEL_POSITION,mxConstants.ALIGN_MIDDLE);if(vertical==mxConstants.ALIGN_TOP){result.y-=state.height;}else if(vertical==mxConstants.ALIGN_BOTTOM){result.y+=state.height;}}return result;};mxCellEditor.prototype.getEmptyLabelText=function(cell){return this.emptyLabelText;};mxCellEditor.prototype.getEditingCell=function(){return this.editingCell;};mxCellEditor.prototype.destroy=function(){if(this.textarea!=null){mxEvent.release(this.textarea);if(this.textarea.parentNode!=null){this.textarea.parentNode.removeChild(this.textarea);}this.textarea=null;}};function mxCellRenderer(){this.shapes=mxUtils.clone(this.defaultShapes);};mxCellRenderer.prototype.shapes=null;mxCellRenderer.prototype.defaultEdgeShape=mxConnector;mxCellRenderer.prototype.defaultVertexShape=mxRectangleShape;mxCellRenderer.prototype.defaultShapes=new Object();mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ARROW]=mxArrow;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_RECTANGLE]=mxRectangleShape;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ELLIPSE]=mxEllipse;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_DOUBLE_ELLIPSE]=mxDoubleEllipse;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_RHOMBUS]=mxRhombus;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_IMAGE]=mxImageShape;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_LINE]=mxLine;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_LABEL]=mxLabel;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CYLINDER]=mxCylinder;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_SWIMLANE]=mxSwimlane;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CONNECTOR]=mxConnector;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_ACTOR]=mxActor;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_CLOUD]=mxCloud;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_TRIANGLE]=mxTriangle;mxCellRenderer.prototype.defaultShapes[mxConstants.SHAPE_HEXAGON]=mxHexagon;mxCellRenderer.prototype.registerShape=function(key,shape){this.shapes[key]=shape;};mxCellRenderer.prototype.initialize=function(state,rendering){var model=state.view.graph.getModel();if(state.view.graph.container!=null&&state.shape==null&&state.cell!=state.view.currentRoot&&(model.isVertex(state.cell)||model.isEdge(state.cell))){this.createShape(state);if(state.shape!=null&&(rendering==null||rendering)){this.initializeShape(state);if(state.view.graph.ordered||model.isEdge(state.cell)){state.invalidOrder=true;}else if(state.view.graph.keepEdgesInForeground&&this.firstEdge!=null){if(this.firstEdge.parentNode==state.shape.node.parentNode){this.insertState(state,this.firstEdge);}else{this.firstEdge=null;}}state.shape.scale=state.view.scale;this.createCellOverlays(state);this.installListeners(state);}}};mxCellRenderer.prototype.initializeShape=function(state){state.shape.init(state.view.getDrawPane());};mxCellRenderer.prototype.getPreviousStateInContainer=function(state,container){var result=null;var graph=state.view.graph;var model=graph.getModel();var child=state.cell;var p=model.getParent(child);while(p!=null&&result==null){result=this.findPreviousStateInContainer(graph,p,child,container);child=p;p=model.getParent(child);}return result;};mxCellRenderer.prototype.findPreviousStateInContainer=function(graph,cell,stop,container){var result=null;var model=graph.getModel();if(stop!=null){var start=cell.getIndex(stop);for(var i=start-1;i>=0&&result==null;i--){result=this.findPreviousStateInContainer(graph,model.getChildAt(cell,i),null,container);}}else{var childCount=model.getChildCount(cell);for(var i=childCount-1;i>=0&&result==null;i--){result=this.findPreviousStateInContainer(graph,model.getChildAt(cell,i),null,container);}}if(result==null){result=graph.view.getState(cell);if(result!=null&&(result.shape==null||result.shape.node==null||result.shape.node.parentNode!=container)){result=null;}}return result;};mxCellRenderer.prototype.order=function(state){var container=state.shape.node.parentNode;var previous=this.getPreviousStateInContainer(state,container);var nextNode=container.firstChild;if(previous!=null){nextNode=previous.shape.node;if(previous.text!=null&&previous.text.node!=null&&previous.text.node.parentNode==container){nextNode=previous.text.node;}nextNode=nextNode.nextSibling;}this.insertState(state,nextNode);};mxCellRenderer.prototype.orderEdge=function(state){var view=state.view;var model=view.graph.getModel();if(view.graph.keepEdgesInForeground){if(this.firstEdge==null||this.firstEdge.parentNode==null||this.firstEdge.parentNode!=state.shape.node.parentNode){this.firstEdge=state.shape.node;}}else if(view.graph.keepEdgesInBackground){var node=state.shape.node;var parent=node.parentNode;var pcell=model.getParent(state.cell);var pstate=view.getState(pcell);if(pstate!=null&&pstate.shape!=null&&pstate.shape.node!=null){var child=pstate.shape.node.nextSibling;if(child!=null&&child!=node){this.insertState(state,child);}}else{var child=parent.firstChild;if(child!=null&&child!=node){this.insertState(state,child);}}}};mxCellRenderer.prototype.insertState=function(state,nextNode){state.shape.node.parentNode.insertBefore(state.shape.node,nextNode);if(state.text!=null&&state.text.node!=null&&state.text.node.parentNode==state.shape.node.parentNode){state.shape.node.parentNode.insertBefore(state.text.node,state.shape.node.nextSibling);}};mxCellRenderer.prototype.createShape=function(state){if(state.style!=null){var key=state.style[mxConstants.STYLE_SHAPE];var stencil=mxStencilRegistry.getStencil(key);if(stencil!=null){state.shape=new mxStencilShape(stencil);}else{var ctor=this.getShapeConstructor(state);state.shape=new ctor();}state.shape.points=state.absolutePoints;state.shape.bounds=new mxRectangle(state.x,state.y,state.width,state.height);state.shape.dialect=state.view.graph.dialect;this.configureShape(state);}};mxCellRenderer.prototype.getShapeConstructor=function(state){var key=state.style[mxConstants.STYLE_SHAPE];var ctor=(key!=null)?this.shapes[key]:null;if(ctor==null){ctor=(state.view.graph.getModel().isEdge(state.cell))?this.defaultEdgeShape:this.defaultVertexShape;}return ctor;};mxCellRenderer.prototype.configureShape=function(state){state.shape.apply(state);var image=state.view.graph.getImage(state);if(image!=null){state.shape.image=image;}var indicator=state.view.graph.getIndicatorColor(state);var key=state.view.graph.getIndicatorShape(state);var ctor=(key!=null)?this.shapes[key]:null;if(indicator!=null){state.shape.indicatorShape=ctor;state.shape.indicatorColor=indicator;state.shape.indicatorGradientColor=state.view.graph.getIndicatorGradientColor(state);state.shape.indicatorDirection=state.style[mxConstants.STYLE_INDICATOR_DIRECTION];}else{var indicator=state.view.graph.getIndicatorImage(state);if(indicator!=null){state.shape.indicatorImage=indicator;}}this.postConfigureShape(state);};mxCellRenderer.prototype.postConfigureShape=function(state){if(state.shape!=null){this.resolveColor(state,'indicatorColor',mxConstants.STYLE_FILLCOLOR);this.resolveColor(state,'indicatorGradientColor',mxConstants.STYLE_GRADIENTCOLOR);this.resolveColor(state,'fill',mxConstants.STYLE_FILLCOLOR);this.resolveColor(state,'stroke',mxConstants.STYLE_STROKECOLOR);this.resolveColor(state,'gradient',mxConstants.STYLE_GRADIENTCOLOR);}};mxCellRenderer.prototype.resolveColor=function(state,field,key){var value=state.shape[field];var graph=state.view.graph;var referenced=null;if(value=='inherit'){referenced=graph.model.getParent(state.cell);}else if(value=='swimlane'){if(graph.model.getTerminal(state.cell,false)!=null){referenced=graph.model.getTerminal(state.cell,false);}else{referenced=state.cell;}referenced=graph.getSwimlane(referenced);key=graph.swimlaneIndicatorColorAttribute;}else if(value=='indicated'){state.shape[field]=state.shape.indicatorColor;}if(referenced!=null){var rstate=graph.getView().getState(referenced);state.shape[field]=null;if(rstate!=null){if(rstate.shape!=null&&field!='indicatorColor'){state.shape[field]=rstate.shape[field];}else{state.shape[field]=rstate.style[key];}}}};mxCellRenderer.prototype.getLabelValue=function(state){var graph=state.view.graph;var value=graph.getLabel(state.cell);if(!graph.isHtmlLabel(state.cell)&&!mxUtils.isNode(value)&&graph.dialect!=mxConstants.DIALECT_SVG&&value!=null){value=mxUtils.htmlEntities(value,false);}return value;};mxCellRenderer.prototype.createLabel=function(state,value){var graph=state.view.graph;var isEdge=graph.getModel().isEdge(state.cell);if(state.style[mxConstants.STYLE_FONTSIZE]>0||state.style[mxConstants.STYLE_FONTSIZE]==null){var isForceHtml=(graph.isHtmlLabel(state.cell)||(value!=null&&mxUtils.isNode(value)))&&graph.dialect==mxConstants.DIALECT_SVG;state.text=new mxText(value,new mxRectangle(),(state.style[mxConstants.STYLE_ALIGN]||mxConstants.ALIGN_CENTER),graph.getVerticalAlign(state),state.style[mxConstants.STYLE_FONTCOLOR],state.style[mxConstants.STYLE_FONTFAMILY],state.style[mxConstants.STYLE_FONTSIZE],state.style[mxConstants.STYLE_FONTSTYLE],state.style[mxConstants.STYLE_SPACING],state.style[mxConstants.STYLE_SPACING_TOP],state.style[mxConstants.STYLE_SPACING_RIGHT],state.style[mxConstants.STYLE_SPACING_BOTTOM],state.style[mxConstants.STYLE_SPACING_LEFT],state.style[mxConstants.STYLE_HORIZONTAL],state.style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR],state.style[mxConstants.STYLE_LABEL_BORDERCOLOR],graph.isWrapping(state.cell)&&graph.isHtmlLabel(state.cell),graph.isLabelClipped(state.cell),state.style[mxConstants.STYLE_OVERFLOW],state.style[mxConstants.STYLE_LABEL_PADDING]);state.text.opacity=state.style[mxConstants.STYLE_TEXT_OPACITY];state.text.dialect=(isForceHtml)?mxConstants.DIALECT_STRICTHTML:state.view.graph.dialect;this.initializeLabel(state);var forceGetCell=false;var getState=function(evt){var result=state;if(mxClient.IS_TOUCH||forceGetCell){var x=mxEvent.getClientX(evt);var y=mxEvent.getClientY(evt);var pt=mxUtils.convertPoint(graph.container,x,y);result=graph.view.getState(graph.getCellAt(pt.x,pt.y));}return result;};var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(state.text.node,md,mxUtils.bind(this,function(evt){if(this.isLabelEvent(state,evt)){graph.fireMouseEvent(mxEvent.MOUSE_DOWN,new mxMouseEvent(evt,state));forceGetCell=graph.dialect!=mxConstants.DIALECT_SVG&&mxEvent.getSource(evt).nodeName=='IMG';}}));mxEvent.addListener(state.text.node,mm,mxUtils.bind(this,function(evt){if(this.isLabelEvent(state,evt)){graph.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(evt,getState(evt)));}}));mxEvent.addListener(state.text.node,mu,mxUtils.bind(this,function(evt){if(this.isLabelEvent(state,evt)){graph.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(evt,getState(evt)));forceGetCell=false;}}));mxEvent.addListener(state.text.node,'dblclick',mxUtils.bind(this,function(evt){if(this.isLabelEvent(state,evt)){graph.dblClick(evt,state.cell);mxEvent.consume(evt);}}));}};mxCellRenderer.prototype.initializeLabel=function(state){var graph=state.view.graph;if(state.text.dialect!=mxConstants.DIALECT_SVG){if(mxClient.IS_SVG&&mxClient.NO_FO){state.text.init(graph.container);}else if(mxUtils.isVml(state.view.getDrawPane())){if(state.shape.label!=null){state.text.init(state.shape.label);}else{state.text.init(state.shape.node);}}}if(state.text.node==null){state.text.init(state.view.getDrawPane());if(state.shape!=null&&state.text!=null){state.shape.node.parentNode.insertBefore(state.text.node,state.shape.node.nextSibling);}}};mxCellRenderer.prototype.createCellOverlays=function(state){var graph=state.view.graph;var overlays=graph.getCellOverlays(state.cell);if(overlays!=null){if(state.overlays==null){state.overlays=[];}for(var i=0;i0)){this.createLabel(state,value);}else if(state.text!=null&&(value==null||value.length==0)){state.text.destroy();state.text=null;}if(state.text!=null){var graph=state.view.graph;var wrapping=graph.isWrapping(state.cell);var clipping=graph.isLabelClipped(state.cell);var bounds=this.getLabelBounds(state);if(state.text.value!=value||state.text.isWrapping!=wrapping||state.text.isClipping!=clipping||state.text.scale!=state.view.scale||!state.text.bounds.equals(bounds)){state.text.value=value;state.text.bounds=bounds;state.text.scale=this.getTextScale(state);state.text.isWrapping=wrapping;state.text.isClipping=clipping;state.text.redraw();}}};mxCellRenderer.prototype.getTextScale=function(state){return state.view.scale;};mxCellRenderer.prototype.getLabelBounds=function(state){var graph=state.view.graph;var isEdge=graph.getModel().isEdge(state.cell);var bounds=new mxRectangle(state.absoluteOffset.x,state.absoluteOffset.y);if(!isEdge){bounds.x+=state.x;bounds.y+=state.y;bounds.width=Math.max(1,state.width);bounds.height=Math.max(1,state.height);if(graph.isSwimlane(state.cell)){var scale=graph.view.scale;var size=graph.getStartSize(state.cell);if(size.width>0){bounds.width=size.width*scale;}else if(size.height>0){bounds.height=size.height*scale;}}}return bounds;};mxCellRenderer.prototype.redrawCellOverlays=function(state){var overlays=state.view.graph.getCellOverlays(state.cell);var oldCount=(state.overlays!=null)?state.overlays.length:0;var newCount=(overlays!=null)?overlays.length:0;if(oldCount!=newCount){if(oldCount>0){var newOverlayShapes=[];for(var i=0;i=0){newOverlayShapes[index]=state.overlays[i];}else{state.overlays[i].destroy();}}state.overlays=newOverlayShapes;}if(newCount>0){this.createCellOverlays(state);}else{state.overlays=null;}}if(state.overlays!=null){for(var i=0;i0)?points[0]:null;if(pt!=null){pt=view.transformControlPoint(state,pt);if(mxUtils.contains(source,pt.x,pt.y)){pt=null;}}var x=0;var dx=0;var y=0;var dy=0;var seg=mxUtils.getValue(state.style,mxConstants.STYLE_SEGMENT,graph.gridSize)*view.scale;var dir=mxUtils.getValue(state.style,mxConstants.STYLE_DIRECTION,mxConstants.DIRECTION_WEST);if(dir==mxConstants.DIRECTION_NORTH||dir==mxConstants.DIRECTION_SOUTH){x=view.getRoutingCenterX(source);dx=seg;}else{y=view.getRoutingCenterY(source);dy=seg;}if(pt==null||pt.xsource.x+source.width){if(pt!=null){x=pt.x;dy=Math.max(Math.abs(y-pt.y),dy);}else{if(dir==mxConstants.DIRECTION_NORTH){y=source.y-2*dx;}else if(dir==mxConstants.DIRECTION_SOUTH){y=source.y+source.height+2*dx;}else if(dir==mxConstants.DIRECTION_EAST){x=source.x-2*dy;}else{x=source.x+source.width+2*dy;}}}else if(pt!=null){x=view.getRoutingCenterX(source);dx=Math.max(Math.abs(x-pt.x),dy);y=pt.y;dy=0;}result.push(new mxPoint(x-dx,y-dy));result.push(new mxPoint(x+dx,y+dy));}},ElbowConnector:function(state,source,target,points,result){var pt=(points!=null&&points.length>0)?points[0]:null;var vertical=false;var horizontal=false;if(source!=null&&target!=null){if(pt!=null){var left=Math.min(source.x,target.x);var right=Math.max(source.x+source.width,target.x+target.width);var top=Math.min(source.y,target.y);var bottom=Math.max(source.y+source.height,target.y+target.height);pt=state.view.transformControlPoint(state,pt);vertical=pt.ybottom;horizontal=pt.xright;}else{var left=Math.max(source.x,target.x);var right=Math.min(source.x+source.width,target.x+target.width);vertical=left==right;if(!vertical){var top=Math.max(source.y,target.y);var bottom=Math.min(source.y+source.height,target.y+target.height);horizontal=top==bottom;}}}if(!horizontal&&(vertical||state.style[mxConstants.STYLE_ELBOW]==mxConstants.ELBOW_VERTICAL)){mxEdgeStyle.TopToBottom(state,source,target,points,result);}else{mxEdgeStyle.SideToSide(state,source,target,points,result);}},SideToSide:function(state,source,target,points,result){var view=state.view;var pt=(points!=null&&points.length>0)?points[0]:null;var pts=state.absolutePoints;var p0=pts[0];var pe=pts[pts.length-1];if(pt!=null){pt=view.transformControlPoint(state,pt);}if(p0!=null){source=new mxCellState();source.x=p0.x;source.y=p0.y;}if(pe!=null){target=new mxCellState();target.x=pe.x;target.y=pe.y;}if(source!=null&&target!=null){var l=Math.max(source.x,target.x);var r=Math.min(source.x+source.width,target.x+target.width);var x=(pt!=null)?pt.x:r+(l-r)/2;var y1=view.getRoutingCenterY(source);var y2=view.getRoutingCenterY(target);if(pt!=null){if(p0!=null&&pt.y>=source.y&&pt.y<=source.y+source.height){y1=pt.y;}if(pe!=null&&pt.y>=target.y&&pt.y<=target.y+target.height){y2=pt.y;}}if(!mxUtils.contains(target,x,y1)&&!mxUtils.contains(source,x,y1)){result.push(new mxPoint(x,y1));}if(!mxUtils.contains(target,x,y2)&&!mxUtils.contains(source,x,y2)){result.push(new mxPoint(x,y2));}if(result.length==1){if(pt!=null){if(!mxUtils.contains(target,x,pt.y)&&!mxUtils.contains(source,x,pt.y)){result.push(new mxPoint(x,pt.y));}}else{var t=Math.max(source.y,target.y);var b=Math.min(source.y+source.height,target.y+target.height);result.push(new mxPoint(x,t+(b-t)/2));}}}},TopToBottom:function(state,source,target,points,result){var view=state.view;var pt=(points!=null&&points.length>0)?points[0]:null;var pts=state.absolutePoints;var p0=pts[0];var pe=pts[pts.length-1];if(pt!=null){pt=view.transformControlPoint(state,pt);}if(p0!=null){source=new mxCellState();source.x=p0.x;source.y=p0.y;}if(pe!=null){target=new mxCellState();target.x=pe.x;target.y=pe.y;}if(source!=null&&target!=null){var t=Math.max(source.y,target.y);var b=Math.min(source.y+source.height,target.y+target.height);var x=view.getRoutingCenterX(source);if(pt!=null&&pt.x>=source.x&&pt.x<=source.x+source.width){x=pt.x;}var y=(pt!=null)?pt.y:b+(t-b)/2;if(!mxUtils.contains(target,x,y)&&!mxUtils.contains(source,x,y)){result.push(new mxPoint(x,y));}if(pt!=null&&pt.x>=target.x&&pt.x<=target.x+target.width){x=pt.x;}else{x=view.getRoutingCenterX(target);}if(!mxUtils.contains(target,x,y)&&!mxUtils.contains(source,x,y)){result.push(new mxPoint(x,y));}if(result.length==1){if(pt!=null&&result.length==1){if(!mxUtils.contains(target,pt.x,y)&&!mxUtils.contains(source,pt.x,y)){result.push(new mxPoint(pt.x,y));}}else{var l=Math.max(source.x,target.x);var r=Math.min(source.x+source.width,target.x+target.width);result.push(new mxPoint(l+(r-l)/2,y));}}}},SegmentConnector:function(state,source,target,hints,result){var pts=state.absolutePoints;var horizontal=true;var hint=null;var pt=pts[0];if(pt==null&&source!=null){pt=new mxPoint(state.view.getRoutingCenterX(source),state.view.getRoutingCenterY(source));}else if(pt!=null){pt=pt.clone();}var lastInx=pts.length-1;if(hints!=null&&hints.length>0){hint=state.view.transformControlPoint(state,hints[0]);var currentTerm=source;var currentPt=pts[0];var hozChan=false;var vertChan=false;var currentHint=hint;var hintsLen=hints.length;for(var i=0;i<2;i++){var fixedVertAlign=currentPt!=null&¤tPt.x==currentHint.x;var fixedHozAlign=currentPt!=null&¤tPt.y==currentHint.y;var inHozChan=currentTerm!=null&&(currentHint.y>=currentTerm.y&¤tHint.y<=currentTerm.y+currentTerm.height);var inVertChan=currentTerm!=null&&(currentHint.x>=currentTerm.x&¤tHint.x<=currentTerm.x+currentTerm.width);hozChan=fixedHozAlign||(currentPt==null&&inHozChan);vertChan=fixedVertAlign||(currentPt==null&&inVertChan);if(currentPt!=null&&(!fixedHozAlign&&!fixedVertAlign)&&(inHozChan||inVertChan)){horizontal=inHozChan?false:true;break;}if(vertChan||hozChan){horizontal=hozChan;if(i==1){horizontal=hints.length%2==0?hozChan:vertChan;}break;}currentTerm=target;currentPt=pts[lastInx];currentHint=state.view.transformControlPoint(state,hints[hintsLen-1]);}if(horizontal&&((pts[0]!=null&&pts[0].y!=hint.y)||(pts[0]==null&&source!=null&&(hint.ysource.y+source.height)))){result.push(new mxPoint(pt.x,hint.y));}else if(!horizontal&&((pts[0]!=null&&pts[0].x!=hint.x)||(pts[0]==null&&source!=null&&(hint.xsource.x+source.width)))){result.push(new mxPoint(hint.x,pt.y));}if(horizontal){pt.y=hint.y;}else{pt.x=hint.x;}for(var i=0;itarget.y+target.height)))){result.push(new mxPoint(pt.x,hint.y));}else if(!horizontal&&((pts[lastInx]!=null&&pts[lastInx].x!=hint.x)||(pts[lastInx]==null&&target!=null&&(hint.xtarget.x+target.width)))){result.push(new mxPoint(hint.x,pt.y));}if(pts[0]==null&&source!=null){while(result.length>1&&mxUtils.contains(source,result[1].x,result[1].y)){result=result.splice(1,1);}}if(pts[lastInx]==null&&target!=null){while(result.length>1&&mxUtils.contains(target,result[result.length-1].x,result[result.length-1].y)){result=result.splice(result.length-1,1);}}},orthBuffer:10,dirVectors:[[-1,0],[0,-1],[1,0],[0,1],[-1,0],[0,-1],[1,0]],wayPoints1:[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],routePatterns:[[[513,2308,2081,2562],[513,1090,514,2184,2114,2561],[513,1090,514,2564,2184,2562],[513,2308,2561,1090,514,2568,2308]],[[514,1057,513,2308,2081,2562],[514,2184,2114,2561],[514,2184,2562,1057,513,2564,2184],[514,1057,513,2568,2308,2561]],[[1090,514,1057,513,2308,2081,2562],[2114,2561],[1090,2562,1057,513,2564,2184],[1090,514,1057,513,2308,2561,2568]],[[2081,2562],[1057,513,1090,514,2184,2114,2561],[1057,513,1090,514,2184,2562,2564],[1057,2561,1090,514,2568,2308]]],inlineRoutePatterns:[[null,[2114,2568],null,null],[null,[514,2081,2114,2568],null,null],[null,[2114,2561],null,null],[[2081,2562],[1057,2114,2568],[2184,2562],null]],vertexSeperations:[],limits:[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]],LEFT_MASK:32,TOP_MASK:64,RIGHT_MASK:128,BOTTOM_MASK:256,LEFT:1,TOP:2,RIGHT:4,BOTTOM:8,SIDE_MASK:480,CENTER_MASK:512,SOURCE_MASK:1024,TARGET_MASK:2048,VERTEX_MASK:3072,OrthConnector:function(state,source,target,points,result){var graph=state.view.graph;var sourceEdge=source==null?false:graph.getModel().isEdge(source.cell);var targetEdge=target==null?false:graph.getModel().isEdge(target.cell);if((points!=null&&points.length>0)||(sourceEdge)||(targetEdge)){mxEdgeStyle.SegmentConnector(state,source,target,points,result);return;}var pts=state.absolutePoints;var p0=pts[0];var pe=pts[pts.length-1];var sourceX=source!=null?source.x:p0.x;var sourceY=source!=null?source.y:p0.y;var sourceWidth=source!=null?source.width:1;var sourceHeight=source!=null?source.height:1;var targetX=target!=null?target.x:pe.x;var targetY=target!=null?target.y:pe.y;var targetWidth=target!=null?target.width:1;var targetHeight=target!=null?target.height:1;var scaledOrthBuffer=state.view.scale*mxEdgeStyle.orthBuffer;var portConstraint=[mxConstants.DIRECTION_MASK_ALL,mxConstants.DIRECTION_MASK_ALL];if(source!=null){portConstraint[0]=mxUtils.getPortConstraints(source,state,true,mxConstants.DIRECTION_MASK_ALL);}if(target!=null){portConstraint[1]=mxUtils.getPortConstraints(target,state,false,mxConstants.DIRECTION_MASK_ALL);}var dir=[0,0];var geo=[[sourceX,sourceY,sourceWidth,sourceHeight],[targetX,targetY,targetWidth,targetHeight]];for(var i=0;i<2;i++){mxEdgeStyle.limits[i][1]=geo[i][0]-scaledOrthBuffer;mxEdgeStyle.limits[i][2]=geo[i][1]-scaledOrthBuffer;mxEdgeStyle.limits[i][4]=geo[i][0]+geo[i][2]+scaledOrthBuffer;mxEdgeStyle.limits[i][8]=geo[i][1]+geo[i][3]+scaledOrthBuffer;}var sourceCenX=geo[0][0]+geo[0][2]/2.0;var sourceCenY=geo[0][1]+geo[0][3]/2.0;var targetCenX=geo[1][0]+geo[1][2]/2.0;var targetCenY=geo[1][1]+geo[1][3]/2.0;var dx=sourceCenX-targetCenX;var dy=sourceCenY-targetCenY;var quad=0;if(dx<0){if(dy<0){quad=2;}else{quad=1;}}else{if(dy<=0){quad=3;if(dx==0){quad=2;}}}var currentTerm=null;if(source!=null){currentTerm=p0;}var constraint=[[0.5,0.5],[0.5,0.5]];for(var i=0;i<2;i++){if(currentTerm!=null){constraint[i][0]=(currentTerm.x-geo[i][0])/geo[i][2];if(constraint[i][0]<0.01){dir[i]=mxConstants.DIRECTION_MASK_WEST;}else if(constraint[i][0]>0.99){dir[i]=mxConstants.DIRECTION_MASK_EAST;}constraint[i][1]=(currentTerm.y-geo[i][1])/geo[i][3];if(constraint[i][1]<0.01){dir[i]=mxConstants.DIRECTION_MASK_NORTH;}else if(constraint[i][1]>0.99){dir[i]=mxConstants.DIRECTION_MASK_SOUTH;}}currentTerm=null;if(target!=null){currentTerm=pe;}}var sourceTopDist=geo[0][1]-(geo[1][1]+geo[1][3]);var sourceLeftDist=geo[0][0]-(geo[1][0]+geo[1][2]);var sourceBottomDist=geo[1][1]-(geo[0][1]+geo[0][3]);var sourceRightDist=geo[1][0]-(geo[0][0]+geo[0][2]);mxEdgeStyle.vertexSeperations[1]=Math.max(sourceLeftDist-2*scaledOrthBuffer,0);mxEdgeStyle.vertexSeperations[2]=Math.max(sourceTopDist-2*scaledOrthBuffer,0);mxEdgeStyle.vertexSeperations[4]=Math.max(sourceBottomDist-2*scaledOrthBuffer,0);mxEdgeStyle.vertexSeperations[3]=Math.max(sourceRightDist-2*scaledOrthBuffer,0);var dirPref=[];var horPref=[];var vertPref=[];horPref[0]=(sourceLeftDist>=sourceRightDist)?mxConstants.DIRECTION_MASK_WEST:mxConstants.DIRECTION_MASK_EAST;vertPref[0]=(sourceTopDist>=sourceBottomDist)?mxConstants.DIRECTION_MASK_NORTH:mxConstants.DIRECTION_MASK_SOUTH;horPref[1]=mxUtils.reversePortConstraints(horPref[0]);vertPref[1]=mxUtils.reversePortConstraints(vertPref[0]);var preferredHorizDist=sourceLeftDist>=sourceRightDist?sourceLeftDist:sourceRightDist;var preferredVertDist=sourceTopDist>=sourceBottomDist?sourceTopDist:sourceBottomDist;var prefOrdering=[[0,0],[0,0]];var preferredOrderSet=false;for(var i=0;i<2;i++){if(dir[i]!=0x0){continue;}if((horPref[i]&portConstraint[i])==0){horPref[i]=mxUtils.reversePortConstraints(horPref[i]);}if((vertPref[i]&portConstraint[i])==0){vertPref[i]=mxUtils.reversePortConstraints(vertPref[i]);}prefOrdering[i][0]=vertPref[i];prefOrdering[i][1]=horPref[i];}if(preferredVertDist>scaledOrthBuffer*2&&preferredHorizDist>scaledOrthBuffer*2){if(((horPref[0]&portConstraint[0])>0)&&((vertPref[1]&portConstraint[1])>0)){prefOrdering[0][0]=horPref[0];prefOrdering[0][1]=vertPref[0];prefOrdering[1][0]=vertPref[1];prefOrdering[1][1]=horPref[1];preferredOrderSet=true;}else if(((vertPref[0]&portConstraint[0])>0)&&((horPref[1]&portConstraint[1])>0)){prefOrdering[0][0]=vertPref[0];prefOrdering[0][1]=horPref[0];prefOrdering[1][0]=horPref[1];prefOrdering[1][1]=vertPref[1];preferredOrderSet=true;}}if(preferredVertDist>scaledOrthBuffer*2&&!preferredOrderSet){prefOrdering[0][0]=vertPref[0];prefOrdering[0][1]=horPref[0];prefOrdering[1][0]=vertPref[1];prefOrdering[1][1]=horPref[1];preferredOrderSet=true;}if(preferredHorizDist>scaledOrthBuffer*2&&!preferredOrderSet){prefOrdering[0][0]=horPref[0];prefOrdering[0][1]=vertPref[0];prefOrdering[1][0]=horPref[1];prefOrdering[1][1]=vertPref[1];preferredOrderSet=true;}for(var i=0;i<2;i++){if(dir[i]!=0x0){continue;}if((prefOrdering[i][0]&portConstraint[i])==0){prefOrdering[i][0]=prefOrdering[i][1];}dirPref[i]=prefOrdering[i][0]&portConstraint[i];dirPref[i]|=(prefOrdering[i][1]&portConstraint[i])<<8;dirPref[i]|=(prefOrdering[1-i][i]&portConstraint[i])<<16;dirPref[i]|=(prefOrdering[1-i][1-i]&portConstraint[i])<<24;if((dirPref[i]&0xF)==0){dirPref[i]=dirPref[i]<<8;}if((dirPref[i]&0xF00)==0){dirPref[i]=(dirPref[i]&0xF)|dirPref[i]>>8;}if((dirPref[i]&0xF0000)==0){dirPref[i]=(dirPref[i]&0xFFFF)|((dirPref[i]&0xF000000)>>8);}dir[i]=dirPref[i]&0xF;if(portConstraint[i]==mxConstants.DIRECTION_MASK_WEST||portConstraint[i]==mxConstants.DIRECTION_MASK_NORTH||portConstraint[i]==mxConstants.DIRECTION_MASK_EAST||portConstraint[i]==mxConstants.DIRECTION_MASK_SOUTH){dir[i]=portConstraint[i];}}var sourceIndex=dir[0]==mxConstants.DIRECTION_MASK_EAST?3:dir[0];var targetIndex=dir[1]==mxConstants.DIRECTION_MASK_EAST?3:dir[1];sourceIndex-=quad;targetIndex-=quad;if(sourceIndex<1){sourceIndex+=4;}if(targetIndex<1){targetIndex+=4;}var routePattern=mxEdgeStyle.routePatterns[sourceIndex-1][targetIndex-1];mxEdgeStyle.wayPoints1[0][0]=geo[0][0];mxEdgeStyle.wayPoints1[0][1]=geo[0][1];switch(dir[0]){case mxConstants.DIRECTION_MASK_WEST:mxEdgeStyle.wayPoints1[0][0]-=scaledOrthBuffer;mxEdgeStyle.wayPoints1[0][1]+=constraint[0][1]*geo[0][3];break;case mxConstants.DIRECTION_MASK_SOUTH:mxEdgeStyle.wayPoints1[0][0]+=constraint[0][0]*geo[0][2];mxEdgeStyle.wayPoints1[0][1]+=geo[0][3]+scaledOrthBuffer;break;case mxConstants.DIRECTION_MASK_EAST:mxEdgeStyle.wayPoints1[0][0]+=geo[0][2]+scaledOrthBuffer;mxEdgeStyle.wayPoints1[0][1]+=constraint[0][1]*geo[0][3];break;case mxConstants.DIRECTION_MASK_NORTH:mxEdgeStyle.wayPoints1[0][0]+=constraint[0][0]*geo[0][2];mxEdgeStyle.wayPoints1[0][1]-=scaledOrthBuffer;break;}var currentIndex=0;var lastOrientation=(dir[0]&(mxConstants.DIRECTION_MASK_EAST|mxConstants.DIRECTION_MASK_WEST))>0?0:1;var initialOrientation=lastOrientation;var currentOrientation=0;for(var i=0;i4){directionIndex-=4;}var direction=mxEdgeStyle.dirVectors[directionIndex-1];currentOrientation=(directionIndex%2>0)?0:1;if(currentOrientation!=lastOrientation){currentIndex++;mxEdgeStyle.wayPoints1[currentIndex][0]=mxEdgeStyle.wayPoints1[currentIndex-1][0];mxEdgeStyle.wayPoints1[currentIndex][1]=mxEdgeStyle.wayPoints1[currentIndex-1][1];}var tar=(routePattern[i]&mxEdgeStyle.TARGET_MASK)>0;var sou=(routePattern[i]&mxEdgeStyle.SOURCE_MASK)>0;var side=(routePattern[i]&mxEdgeStyle.SIDE_MASK)>>5;side=side<0xF){side=side>>4;}var center=(routePattern[i]&mxEdgeStyle.CENTER_MASK)>0;if((sou||tar)&&side<9){var limit=0;var souTar=sou?0:1;if(center&¤tOrientation==0){limit=geo[souTar][0]+constraint[souTar][0]*geo[souTar][2];}else if(center){limit=geo[souTar][1]+constraint[souTar][1]*geo[souTar][3];}else{limit=mxEdgeStyle.limits[souTar][side];}if(currentOrientation==0){var lastX=mxEdgeStyle.wayPoints1[currentIndex][0];var deltaX=(limit-lastX)*direction[0];if(deltaX>0){mxEdgeStyle.wayPoints1[currentIndex][0]+=direction[0]*deltaX;}}else{var lastY=mxEdgeStyle.wayPoints1[currentIndex][1];var deltaY=(limit-lastY)*direction[1];if(deltaY>0){mxEdgeStyle.wayPoints1[currentIndex][1]+=direction[1]*deltaY;}}}else if(center){mxEdgeStyle.wayPoints1[currentIndex][0]+=direction[0]*Math.abs(mxEdgeStyle.vertexSeperations[directionIndex]/2);mxEdgeStyle.wayPoints1[currentIndex][1]+=direction[1]*Math.abs(mxEdgeStyle.vertexSeperations[directionIndex]/2);}if(currentIndex>0&&mxEdgeStyle.wayPoints1[currentIndex][currentOrientation]==mxEdgeStyle.wayPoints1[currentIndex-1][currentOrientation]){currentIndex--;}else{lastOrientation=currentOrientation;}}for(var i=0;i<=currentIndex;i++){if(i==currentIndex){var targetOrientation=(dir[1]&(mxConstants.DIRECTION_MASK_EAST|mxConstants.DIRECTION_MASK_WEST))>0?0:1;var sameOrient=targetOrientation==initialOrientation?0:1;if(sameOrient!=(currentIndex+1)%2){break;}}result.push(new mxPoint(mxEdgeStyle.wayPoints1[i][0],mxEdgeStyle.wayPoints1[i][1]));}},getRoutePattern:function(dir,quad,dx,dy){var sourceIndex=dir[0]==mxConstants.DIRECTION_MASK_EAST?3:dir[0];var targetIndex=dir[1]==mxConstants.DIRECTION_MASK_EAST?3:dir[1];sourceIndex-=quad;targetIndex-=quad;if(sourceIndex<1){sourceIndex+=4;}if(targetIndex<1){targetIndex+=4;}var result=routePatterns[sourceIndex-1][targetIndex-1];if(dx==0||dy==0){if(inlineRoutePatterns[sourceIndex-1][targetIndex-1]!=null){result=inlineRoutePatterns[sourceIndex-1][targetIndex-1];}}return result;}};var mxStyleRegistry={values:[],putValue:function(name,obj){mxStyleRegistry.values[name]=obj;},getValue:function(name){return mxStyleRegistry.values[name];},getName:function(value){for(var key in mxStyleRegistry.values){if(mxStyleRegistry.values[key]==value){return key;}}return null;}};mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ELBOW,mxEdgeStyle.ElbowConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ENTITY_RELATION,mxEdgeStyle.EntityRelation);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_LOOP,mxEdgeStyle.Loop);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SIDETOSIDE,mxEdgeStyle.SideToSide);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_TOPTOBOTTOM,mxEdgeStyle.TopToBottom);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ORTHOGONAL,mxEdgeStyle.OrthConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SEGMENT,mxEdgeStyle.SegmentConnector);mxStyleRegistry.putValue(mxConstants.PERIMETER_ELLIPSE,mxPerimeter.EllipsePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_RECTANGLE,mxPerimeter.RectanglePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_RHOMBUS,mxPerimeter.RhombusPerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_TRIANGLE,mxPerimeter.TrianglePerimeter);function mxGraphView(graph){this.graph=graph;this.translate=new mxPoint();this.graphBounds=new mxRectangle();this.states=new mxDictionary();};mxGraphView.prototype=new mxEventSource();mxGraphView.prototype.constructor=mxGraphView;mxGraphView.prototype.EMPTY_POINT=new mxPoint();mxGraphView.prototype.doneResource=(mxClient.language!='none')?'done':'';mxGraphView.prototype.updatingDocumentResource=(mxClient.language!='none')?'updatingDocument':'';mxGraphView.prototype.allowEval=false;mxGraphView.prototype.captureDocumentGesture=true;mxGraphView.prototype.rendering=true;mxGraphView.prototype.graph=null;mxGraphView.prototype.currentRoot=null;mxGraphView.prototype.graphBounds=null;mxGraphView.prototype.scale=1;mxGraphView.prototype.translate=null;mxGraphView.prototype.updateStyle=false;mxGraphView.prototype.getGraphBounds=function(){return this.graphBounds;};mxGraphView.prototype.setGraphBounds=function(value){this.graphBounds=value;};mxGraphView.prototype.getBounds=function(cells){var result=null;if(cells!=null&&cells.length>0){var model=this.graph.getModel();for(var i=0;i0||bounds.height>0){point=perimeter(bounds,terminal,next,orthogonal);}}if(point==null){point=this.getPoint(terminal);}}return point;};mxGraphView.prototype.getRoutingCenterX=function(state){var f=(state.style!=null)?parseFloat(state.style[mxConstants.STYLE_ROUTING_CENTER_X])||0:0;return state.getCenterX()+f*state.width;};mxGraphView.prototype.getRoutingCenterY=function(state){var f=(state.style!=null)?parseFloat(state.style[mxConstants.STYLE_ROUTING_CENTER_Y])||0:0;return state.getCenterY()+f*state.height;};mxGraphView.prototype.getPerimeterBounds=function(terminal,border){border=(border!=null)?border:0;if(terminal!=null){border+=parseFloat(terminal.style[mxConstants.STYLE_PERIMETER_SPACING]||0);}return terminal.getPerimeterBounds(border*this.scale);};mxGraphView.prototype.getPerimeterFunction=function(state){var perimeter=state.style[mxConstants.STYLE_PERIMETER];if(typeof(perimeter)=="string"){var tmp=mxStyleRegistry.getValue(perimeter);if(tmp==null&&this.isAllowEval()){tmp=mxUtils.eval(perimeter);}perimeter=tmp;}if(typeof(perimeter)=="function"){return perimeter;}return null;};mxGraphView.prototype.getNextPoint=function(edge,opposite,source){var pts=edge.absolutePoints;var point=null;if(pts!=null&&(source||pts.length>2||opposite==null)){var count=pts.length;point=pts[(source)?Math.min(1,count-1):Math.max(0,count-2)];}if(point==null&&opposite!=null){point=new mxPoint(opposite.getCenterX(),opposite.getCenterY());}return point;};mxGraphView.prototype.getVisibleTerminal=function(edge,source){var model=this.graph.getModel();var result=model.getTerminal(edge,source);var best=result;while(result!=null&&result!=this.currentRoot){if(!this.graph.isCellVisible(best)||this.graph.isCellCollapsed(result)){best=result;}result=model.getParent(result);}if(model.getParent(best)==model.getRoot()){best=null;}return best;};mxGraphView.prototype.updateEdgeBounds=function(state){var points=state.absolutePoints;state.length=0;if(points!=null&&points.length>0){var p0=points[0];var pe=points[points.length-1];if(p0==null||pe==null){this.clear(state.cell,true);}else{if(p0.x!=pe.x||p0.y!=pe.y){var dx=pe.x-p0.x;var dy=pe.y-p0.y;state.terminalDistance=Math.sqrt(dx*dx+dy*dy);}else{state.terminalDistance=0;}var length=0;var segments=[];var pt=p0;if(pt!=null){var minX=pt.x;var minY=pt.y;var maxX=minX;var maxY=minY;for(var i=1;ilength+segment&&index1){var totalLength=edgeState.length;var segments=edgeState.segments;var p0=edgeState.absolutePoints[0];var pe=edgeState.absolutePoints[1];var minDist=mxUtils.ptSegDistSq(p0.x,p0.y,pe.x,pe.y,x,y);var index=0;var tmp=0;var length=0;for(var i=2;iseg){projlen=seg;}var yDistance=Math.sqrt(mxUtils.ptSegDistSq(p0.x,p0.y,pe.x,pe.y,x,y));var direction=mxUtils.relativeCcw(p0.x,p0.y,pe.x,pe.y,x,y);if(direction==-1){yDistance=-yDistance;}return new mxPoint(((totalLength/2-length-projlen)/totalLength)*-2,yDistance/this.scale);}}return new mxPoint();};mxGraphView.prototype.updateEdgeLabelOffset=function(state){var points=state.absolutePoints;state.absoluteOffset.x=state.getCenterX();state.absoluteOffset.y=state.getCenterY();if(points!=null&&points.length>0&&state.segments!=null){var geometry=this.graph.getCellGeometry(state.cell);if(geometry.relative){var offset=this.getPoint(state,geometry);if(offset!=null){state.absoluteOffset=offset;}}else{var p0=points[0];var pe=points[points.length-1];if(p0!=null&&pe!=null){var dx=pe.x-p0.x;var dy=pe.y-p0.y;var x0=0;var y0=0;var off=geometry.offset;if(off!=null){x0=off.x;y0=off.y;}var x=p0.x+dx/2+x0*this.scale;var y=p0.y+dy/2+y0*this.scale;state.absoluteOffset.x=x;state.absoluteOffset.y=y;}}}};mxGraphView.prototype.getState=function(cell,create){create=create||false;var state=null;if(cell!=null){state=this.states.get(cell);if(this.graph.isCellVisible(cell)){if(state==null&&create&&this.graph.isCellVisible(cell)){state=this.createState(cell);this.states.put(cell,state);}else if(create&&state!=null&&this.updateStyle){state.style=this.graph.getCellStyle(cell);}}}return state;};mxGraphView.prototype.isRendering=function(){return this.rendering;};mxGraphView.prototype.setRendering=function(value){this.rendering=value;};mxGraphView.prototype.isAllowEval=function(){return this.allowEval;};mxGraphView.prototype.setAllowEval=function(value){this.allowEval=value;};mxGraphView.prototype.getStates=function(){return this.states;};mxGraphView.prototype.setStates=function(value){this.states=value;};mxGraphView.prototype.getCellStates=function(cells){if(cells==null){return this.states;}else{var result=[];for(var i=0;iinWidth&&pt.x>inWidth+2&&pt.x<=outWidth){return true;}var outHeight=this.graph.container.offsetHeight;var inHeight=this.graph.container.clientHeight;if(outHeight>inHeight&&pt.y>inHeight+2&&pt.y<=outHeight){return true;}return false;};mxGraphView.prototype.init=function(){this.installListeners();var graph=this.graph;if(graph.dialect==mxConstants.DIALECT_SVG){this.createSvg();}else if(graph.dialect==mxConstants.DIALECT_VML){this.createVml();}else{this.createHtml();}};mxGraphView.prototype.installListeners=function(){var graph=this.graph;var container=graph.container;if(container!=null){var md=(mxClient.IS_TOUCH)?'touchstart':'mousedown';var mm=(mxClient.IS_TOUCH)?'touchmove':'mousemove';var mu=(mxClient.IS_TOUCH)?'touchend':'mouseup';mxEvent.addListener(container,md,mxUtils.bind(this,function(evt){if(mxClient.IS_TOUCH&&graph.isEditing()){graph.stopEditing(!graph.isInvokesStopCellEditing());}if(this.isContainerEvent(evt)&&((!mxClient.IS_IE&&!mxClient.IS_GC&&!mxClient.IS_OP&&!mxClient.IS_SF)||!this.isScrollEvent(evt))){graph.fireMouseEvent(mxEvent.MOUSE_DOWN,new mxMouseEvent(evt));}}));mxEvent.addListener(container,mm,mxUtils.bind(this,function(evt){if(this.isContainerEvent(evt)){graph.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(evt));}}));mxEvent.addListener(container,mu,mxUtils.bind(this,function(evt){if(this.isContainerEvent(evt)){graph.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(evt));}}));mxEvent.addListener(container,'dblclick',mxUtils.bind(this,function(evt){graph.dblClick(evt);}));var getState=function(evt){var state=null;if(mxClient.IS_TOUCH){var x=mxEvent.getClientX(evt);var y=mxEvent.getClientY(evt);var pt=mxUtils.convertPoint(container,x,y);state=graph.view.getState(graph.getCellAt(pt.x,pt.y));}return state;};graph.addMouseListener({mouseDown:function(sender,me){graph.panningHandler.hideMenu();},mouseMove:function(){},mouseUp:function(){}});mxEvent.addListener(document,mm,mxUtils.bind(this,function(evt){if(graph.tooltipHandler!=null&&graph.tooltipHandler.isHideOnHover()){graph.tooltipHandler.hide();}if(this.captureDocumentGesture&&graph.isMouseDown&&!mxEvent.isConsumed(evt)){graph.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(evt,getState(evt)));}}));mxEvent.addListener(document,mu,mxUtils.bind(this,function(evt){if(this.captureDocumentGesture){graph.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(evt));}}));}};mxGraphView.prototype.createHtml=function(){var container=this.graph.container;if(container!=null){this.canvas=this.createHtmlPane();this.backgroundPane=this.createHtmlPane(1,1);this.drawPane=this.createHtmlPane(1,1);this.overlayPane=this.createHtmlPane(1,1);this.canvas.appendChild(this.backgroundPane);this.canvas.appendChild(this.drawPane);this.canvas.appendChild(this.overlayPane);container.appendChild(this.canvas);}};mxGraphView.prototype.createHtmlPane=function(width,height){var pane=document.createElement('DIV');if(width!=null&&height!=null){pane.style.position='absolute';pane.style.left='0px';pane.style.top='0px';pane.style.width=width+'px';pane.style.height=height+'px';}else{pane.style.position='relative';}return pane;};mxGraphView.prototype.createVml=function(){var container=this.graph.container;if(container!=null){var width=container.offsetWidth;var height=container.offsetHeight;this.canvas=this.createVmlPane(width,height);this.backgroundPane=this.createVmlPane(width,height);this.drawPane=this.createVmlPane(width,height);this.overlayPane=this.createVmlPane(width,height);this.canvas.appendChild(this.backgroundPane);this.canvas.appendChild(this.drawPane);this.canvas.appendChild(this.overlayPane);container.appendChild(this.canvas);}};mxGraphView.prototype.createVmlPane=function(width,height){var pane=document.createElement('v:group');pane.style.position='absolute';pane.style.left='0px';pane.style.top='0px';pane.style.width=width+'px';pane.style.height=height+'px';pane.setAttribute('coordsize',width+','+height);pane.setAttribute('coordorigin','0,0');return pane;};mxGraphView.prototype.createSvg=function(){var container=this.graph.container;this.canvas=document.createElementNS(mxConstants.NS_SVG,'g');this.backgroundPane=document.createElementNS(mxConstants.NS_SVG,'g');this.canvas.appendChild(this.backgroundPane);this.drawPane=document.createElementNS(mxConstants.NS_SVG,'g');this.canvas.appendChild(this.drawPane);this.overlayPane=document.createElementNS(mxConstants.NS_SVG,'g');this.canvas.appendChild(this.overlayPane);var root=document.createElementNS(mxConstants.NS_SVG,'svg');var onResize=mxUtils.bind(this,function(evt){if(this.graph.container!=null){var width=this.graph.container.offsetWidth;var height=this.graph.container.offsetHeight;var bounds=this.getGraphBounds();root.setAttribute('width',Math.max(width,bounds.width));root.setAttribute('height',Math.max(height,bounds.height));}});mxEvent.addListener(window,'resize',onResize);if(mxClient.IS_OP){onResize();}root.appendChild(this.canvas);if(container!=null){container.appendChild(root);var style=mxUtils.getCurrentStyle(container);if(style.position=='static'){container.style.position='relative';}}};mxGraphView.prototype.destroy=function(){var root=(this.canvas!=null)?this.canvas.ownerSVGElement:null;if(root==null){root=this.canvas;}if(root!=null&&root.parentNode!=null){this.clear(this.currentRoot,true);mxEvent.removeAllListeners(document);mxEvent.release(this.graph.container);root.parentNode.removeChild(root);this.canvas=null;this.backgroundPane=null;this.drawPane=null;this.overlayPane=null;}};function mxCurrentRootChange(view,root){this.view=view;this.root=root;this.previous=root;this.isUp=root==null;if(!this.isUp){var tmp=this.view.currentRoot;var model=this.view.graph.getModel();while(tmp!=null){if(tmp==root){this.isUp=true;break;}tmp=model.getParent(tmp);}}};mxCurrentRootChange.prototype.execute=function(){var tmp=this.view.currentRoot;this.view.currentRoot=this.previous;this.previous=tmp;var translate=this.view.graph.getTranslateForRoot(this.view.currentRoot);if(translate!=null){this.view.translate=new mxPoint(-translate.x,-translate.y);}var name=(this.isUp)?mxEvent.UP:mxEvent.DOWN;this.view.fireEvent(new mxEventObject(name,'root',this.view.currentRoot,'previous',this.previous));if(this.isUp){this.view.clear(this.view.currentRoot,true);this.view.validate();}else{this.view.refresh();}this.isUp=!this.isUp;};function mxGraph(container,model,renderHint,stylesheet){this.mouseListeners=null;this.renderHint=renderHint;if(mxClient.IS_SVG){this.dialect=mxConstants.DIALECT_SVG;}else if(renderHint==mxConstants.RENDERING_HINT_EXACT&&mxClient.IS_VML){this.dialect=mxConstants.DIALECT_VML;}else if(renderHint==mxConstants.RENDERING_HINT_FASTEST){this.dialect=mxConstants.DIALECT_STRICTHTML;}else if(renderHint==mxConstants.RENDERING_HINT_FASTER){this.dialect=mxConstants.DIALECT_PREFERHTML;}else {this.dialect=mxConstants.DIALECT_MIXEDHTML;}this.model=(model!=null)?model:new mxGraphModel();this.multiplicities=[];this.imageBundles=[];this.cellRenderer=this.createCellRenderer();this.setSelectionModel(this.createSelectionModel());this.setStylesheet((stylesheet!=null)?stylesheet:this.createStylesheet());this.view=this.createGraphView();this.graphModelChangeListener=mxUtils.bind(this,function(sender,evt){this.graphModelChanged(evt.getProperty('edit').changes);});this.model.addListener(mxEvent.CHANGE,this.graphModelChangeListener);this.createHandlers();if(container!=null){this.init(container);}this.view.revalidate();};if(mxLoadResources){mxResources.add(mxClient.basePath+'/resources/graph');}mxGraph.prototype=new mxEventSource();mxGraph.prototype.constructor=mxGraph;mxGraph.prototype.EMPTY_ARRAY=[];mxGraph.prototype.mouseListeners=null;mxGraph.prototype.isMouseDown=false;mxGraph.prototype.model=null;mxGraph.prototype.view=null;mxGraph.prototype.stylesheet=null;mxGraph.prototype.selectionModel=null;mxGraph.prototype.cellEditor=null;mxGraph.prototype.cellRenderer=null;mxGraph.prototype.multiplicities=null;mxGraph.prototype.renderHint=null;mxGraph.prototype.dialect=null;mxGraph.prototype.gridSize=10;mxGraph.prototype.gridEnabled=true;mxGraph.prototype.portsEnabled=true;mxGraph.prototype.doubleTapEnabled=true;mxGraph.prototype.doubleTapTimeout=700;mxGraph.prototype.doubleTapTolerance=25;mxGraph.prototype.lastTouchY=0;mxGraph.prototype.lastTouchY=0;mxGraph.prototype.lastTouchTime=0;mxGraph.prototype.gestureEnabled=true;mxGraph.prototype.tolerance=4;mxGraph.prototype.defaultOverlap=0.5;mxGraph.prototype.defaultParent=null;mxGraph.prototype.alternateEdgeStyle=null;mxGraph.prototype.backgroundImage=null;mxGraph.prototype.pageVisible=false;mxGraph.prototype.pageBreaksVisible=false;mxGraph.prototype.pageBreakColor='gray';mxGraph.prototype.pageBreakDashed=true;mxGraph.prototype.minPageBreakDist=20;mxGraph.prototype.preferPageSize=false;mxGraph.prototype.pageFormat=mxConstants.PAGE_FORMAT_A4_PORTRAIT;mxGraph.prototype.pageScale=1.5;mxGraph.prototype.enabled=true;mxGraph.prototype.escapeEnabled=true;mxGraph.prototype.invokesStopCellEditing=true;mxGraph.prototype.enterStopsCellEditing=false;mxGraph.prototype.useScrollbarsForPanning=true;mxGraph.prototype.exportEnabled=true;mxGraph.prototype.importEnabled=true;mxGraph.prototype.cellsLocked=false;mxGraph.prototype.cellsCloneable=true;mxGraph.prototype.foldingEnabled=true;mxGraph.prototype.cellsEditable=true;mxGraph.prototype.cellsDeletable=true;mxGraph.prototype.cellsMovable=true;mxGraph.prototype.edgeLabelsMovable=true;mxGraph.prototype.vertexLabelsMovable=false;mxGraph.prototype.dropEnabled=false;mxGraph.prototype.splitEnabled=true;mxGraph.prototype.cellsResizable=true;mxGraph.prototype.cellsBendable=true;mxGraph.prototype.cellsSelectable=true;mxGraph.prototype.cellsDisconnectable=true;mxGraph.prototype.autoSizeCells=false;mxGraph.prototype.autoScroll=true;mxGraph.prototype.allowAutoPanning=false;mxGraph.prototype.ignoreScrollbars=false;mxGraph.prototype.autoExtend=true;mxGraph.prototype.maximumGraphBounds=null;mxGraph.prototype.minimumGraphSize=null;mxGraph.prototype.minimumContainerSize=null;mxGraph.prototype.maximumContainerSize=null;mxGraph.prototype.resizeContainer=false;mxGraph.prototype.border=0;mxGraph.prototype.ordered=true;mxGraph.prototype.keepEdgesInForeground=false;mxGraph.prototype.keepEdgesInBackground=true;mxGraph.prototype.allowNegativeCoordinates=true;mxGraph.prototype.constrainChildren=true;mxGraph.prototype.extendParents=true;mxGraph.prototype.extendParentsOnAdd=true;mxGraph.prototype.collapseToPreferredSize=true;mxGraph.prototype.zoomFactor=1.2;mxGraph.prototype.keepSelectionVisibleOnZoom=false;mxGraph.prototype.centerZoom=true;mxGraph.prototype.resetViewOnRootChange=true;mxGraph.prototype.resetEdgesOnResize=false;mxGraph.prototype.resetEdgesOnMove=false;mxGraph.prototype.resetEdgesOnConnect=true;mxGraph.prototype.allowLoops=false;mxGraph.prototype.defaultLoopStyle=mxEdgeStyle.Loop;mxGraph.prototype.multigraph=true;mxGraph.prototype.connectableEdges=false;mxGraph.prototype.allowDanglingEdges=true;mxGraph.prototype.cloneInvalidEdges=false;mxGraph.prototype.disconnectOnMove=true;mxGraph.prototype.labelsVisible=true;mxGraph.prototype.htmlLabels=false;mxGraph.prototype.swimlaneSelectionEnabled=true;mxGraph.prototype.swimlaneNesting=true;mxGraph.prototype.swimlaneIndicatorColorAttribute=mxConstants.STYLE_FILLCOLOR;mxGraph.prototype.imageBundles=null;mxGraph.prototype.minFitScale=0.1;mxGraph.prototype.maxFitScale=8;mxGraph.prototype.panDx=0;mxGraph.prototype.panDy=0;mxGraph.prototype.collapsedImage=new mxImage(mxClient.imageBasePath+'/collapsed.gif',9,9);mxGraph.prototype.expandedImage=new mxImage(mxClient.imageBasePath+'/expanded.gif',9,9);mxGraph.prototype.warningImage=new mxImage(mxClient.imageBasePath+'/warning'+((mxClient.IS_MAC)?'.png':'.gif'),16,16);mxGraph.prototype.alreadyConnectedResource=(mxClient.language!='none')?'alreadyConnected':'';mxGraph.prototype.containsValidationErrorsResource=(mxClient.language!='none')?'containsValidationErrors':'';mxGraph.prototype.collapseExpandResource=(mxClient.language!='none')?'collapse-expand':'';mxGraph.prototype.init=function(container){this.container=container;this.cellEditor=this.createCellEditor();this.view.init();this.sizeDidChange();if(mxClient.IS_IE){mxEvent.addListener(window,'unload',mxUtils.bind(this,function(){this.destroy();}));mxEvent.addListener(container,'selectstart',mxUtils.bind(this,function(){return this.isEditing();}));}};mxGraph.prototype.createHandlers=function(container){this.tooltipHandler=new mxTooltipHandler(this);this.tooltipHandler.setEnabled(false);this.panningHandler=new mxPanningHandler(this);this.panningHandler.panningEnabled=false;this.selectionCellsHandler=new mxSelectionCellsHandler(this);this.connectionHandler=new mxConnectionHandler(this);this.connectionHandler.setEnabled(false);this.graphHandler=new mxGraphHandler(this);};mxGraph.prototype.createSelectionModel=function(){return new mxGraphSelectionModel(this);};mxGraph.prototype.createStylesheet=function(){return new mxStylesheet();};mxGraph.prototype.createGraphView=function(){return new mxGraphView(this);};mxGraph.prototype.createCellRenderer=function(){return new mxCellRenderer();};mxGraph.prototype.createCellEditor=function(){return new mxCellEditor(this);};mxGraph.prototype.getModel=function(){return this.model;};mxGraph.prototype.getView=function(){return this.view;};mxGraph.prototype.getStylesheet=function(){return this.stylesheet;};mxGraph.prototype.setStylesheet=function(stylesheet){this.stylesheet=stylesheet;};mxGraph.prototype.getSelectionModel=function(){return this.selectionModel;};mxGraph.prototype.setSelectionModel=function(selectionModel){this.selectionModel=selectionModel;};mxGraph.prototype.getSelectionCellsForChanges=function(changes){var cells=[];for(var i=0;i=0){cell.overlays.splice(index,1);if(cell.overlays.length==0){cell.overlays=null;}var state=this.view.getState(cell);if(state!=null){this.cellRenderer.redraw(state);}this.fireEvent(new mxEventObject(mxEvent.REMOVE_OVERLAY,'cell',cell,'overlay',overlay));}else{overlay=null;}}return overlay;};mxGraph.prototype.removeCellOverlays=function(cell){var overlays=cell.overlays;if(overlays!=null){cell.overlays=null;var state=this.view.getState(cell);if(state!=null){this.cellRenderer.redraw(state);}for(var i=0;i0){img=(img!=null)?img:this.warningImage;var overlay=new mxCellOverlay(img,''+warning+'');if(isSelect){overlay.addListener(mxEvent.CLICK,mxUtils.bind(this,function(sender,evt){if(this.isEnabled()){this.setSelectionCell(cell);}}));}return this.addCellOverlay(cell,overlay);}else{this.removeCellOverlays(cell);}return null;};mxGraph.prototype.startEditing=function(evt){this.startEditingAtCell(null,evt);};mxGraph.prototype.startEditingAtCell=function(cell,evt){if(cell==null){cell=this.getSelectionCell();if(cell!=null&&!this.isCellEditable(cell)){cell=null;}}if(cell!=null){this.fireEvent(new mxEventObject(mxEvent.START_EDITING,'cell',cell,'event',evt));this.cellEditor.startEditing(cell,evt);}};mxGraph.prototype.getEditingValue=function(cell,evt){return this.convertValueToString(cell);};mxGraph.prototype.stopEditing=function(cancel){this.cellEditor.stopEditing(cancel);};mxGraph.prototype.labelChanged=function(cell,value,evt){this.model.beginUpdate();try{this.cellLabelChanged(cell,value,this.isAutoSizeCell(cell));this.fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED,'cell',cell,'value',value,'event',evt));}finally{this.model.endUpdate();}return cell;};mxGraph.prototype.cellLabelChanged=function(cell,value,autoSize){this.model.beginUpdate();try{this.model.setValue(cell,value);if(autoSize){this.cellSizeUpdated(cell,false);}}finally{this.model.endUpdate();}};mxGraph.prototype.escape=function(evt){this.stopEditing(true);this.connectionHandler.reset();this.graphHandler.reset();var cells=this.getSelectionCells();for(var i=0;i=c.scrollLeft&&y>=c.scrollTop&&x<=c.scrollLeft+c.clientWidth&&y<=c.scrollTop+c.clientHeight){var dx=c.scrollLeft+c.clientWidth-x;if(dxthis.minPageBreakDist;bounds.x=mxUtils.mod(bounds.x,bounds.width);bounds.y=mxUtils.mod(bounds.y,bounds.height);var horizontalCount=(visible)?Math.ceil((width-bounds.x)/bounds.width):0;var verticalCount=(visible)?Math.ceil((height-bounds.y)/bounds.height):0;var right=width;var bottom=height;if(this.horizontalPageBreaks==null&&horizontalCount>0){this.horizontalPageBreaks=[];}if(this.horizontalPageBreaks!=null){for(var i=0;i<=horizontalCount;i++){var pts=[new mxPoint(bounds.x+i*bounds.width,1),new mxPoint(bounds.x+i*bounds.width,bottom)];if(this.horizontalPageBreaks[i]!=null){this.horizontalPageBreaks[i].scale=1;this.horizontalPageBreaks[i].points=pts;this.horizontalPageBreaks[i].redraw();}else{var pageBreak=new mxPolyline(pts,this.pageBreakColor,this.scale);pageBreak.dialect=this.dialect;pageBreak.isDashed=this.pageBreakDashed;pageBreak.scale=scale;pageBreak.crisp=true;pageBreak.init(this.view.backgroundPane);pageBreak.redraw();this.horizontalPageBreaks[i]=pageBreak;}}for(var i=horizontalCount;i0){this.verticalPageBreaks=[];}if(this.verticalPageBreaks!=null){for(var i=0;i<=verticalCount;i++){var pts=[new mxPoint(1,bounds.y+i*bounds.height),new mxPoint(right,bounds.y+i*bounds.height)];if(this.verticalPageBreaks[i]!=null){this.verticalPageBreaks[i].scale=1;this.verticalPageBreaks[i].points=pts;this.verticalPageBreaks[i].redraw();}else{var pageBreak=new mxPolyline(pts,this.pageBreakColor,scale);pageBreak.dialect=this.dialect;pageBreak.isDashed=this.pageBreakDashed;pageBreak.scale=scale;pageBreak.crisp=true;pageBreak.init(this.view.backgroundPane);pageBreak.redraw();this.verticalPageBreaks[i]=pageBreak;}}for(var i=verticalCount;i0){image=image.substring(0,comma)+";base64,"+image.substring(comma+1);}style[mxConstants.STYLE_IMAGE]=image;}}return style;};mxGraph.prototype.setCellStyle=function(style,cells){cells=cells||this.getSelectionCells();if(cells!=null){this.model.beginUpdate();try{for(var i=0;i0){var state=this.view.getState(cells[0]);var style=(state!=null)?state.style:this.getCellStyle(cells[0]);if(style!=null){var val=(mxUtils.getValue(style,key,defaultValue))?0:1;this.setCellStyles(key,val,cells);}}};mxGraph.prototype.setCellStyles=function(key,value,cells){cells=cells||this.getSelectionCells();mxUtils.setCellStyles(this.model,cells,key,value);};mxGraph.prototype.toggleCellStyleFlags=function(key,flag,cells){this.setCellStyleFlags(key,flag,null,cells);};mxGraph.prototype.setCellStyleFlags=function(key,flag,value,cells){cells=cells||this.getSelectionCells();if(cells!=null&&cells.length>0){if(value==null){var state=this.view.getState(cells[0]);var style=(state!=null)?state.style:this.getCellStyle(cells[0]);if(style!=null){var current=parseInt(style[key]||0);value=!((current&flag)==flag);}}mxUtils.setCellStyleFlags(this.model,cells,key,flag,value);}};mxGraph.prototype.alignCells=function(align,cells,param){if(cells==null){cells=this.getSelectionCells();}if(cells!=null&&cells.length>1){if(param==null){for(var i=0;i0&&bounds!=null){var parent=this.model.getParent(group);if(parent==null){parent=this.model.getParent(cells[0]);}this.model.beginUpdate();try{if(this.getCellGeometry(group)==null){this.model.setGeometry(group,new mxGeometry());}var index=this.model.getChildCount(group);this.cellsAdded(cells,group,index,null,null,false,false);this.cellsMoved(cells,-bounds.x,-bounds.y,false,true);index=this.model.getChildCount(parent);this.cellsAdded([group],parent,index,null,null,false);this.cellsResized([group],[bounds]);this.fireEvent(new mxEventObject(mxEvent.GROUP_CELLS,'group',group,'border',border,'cells',cells));}finally{this.model.endUpdate();}}return group;};mxGraph.prototype.getCellsForGroup=function(cells){var result=[];if(cells!=null&&cells.length>0){var parent=this.model.getParent(cells[0]);result.push(cells[0]);for(var i=1;i0){tmp.push(cells[i]);}}cells=tmp;}if(cells!=null&&cells.length>0){this.model.beginUpdate();try{for(var i=0;i0){children=children.slice();var parent=this.model.getParent(cells[i]);var index=this.model.getChildCount(parent);this.cellsAdded(children,parent,index,null,null,true);result=result.concat(children);}}this.cellsRemoved(this.addAllEdges(cells));this.fireEvent(new mxEventObject(mxEvent.UNGROUP_CELLS,'cells',cells));}finally{this.model.endUpdate();}}return result;};mxGraph.prototype.removeCellsFromParent=function(cells){if(cells==null){cells=this.getSelectionCells();}this.model.beginUpdate();try{var parent=this.getDefaultParent();var index=this.model.getChildCount(parent);this.cellsAdded(cells,parent,index,null,null,true);this.fireEvent(new mxEventObject(mxEvent.REMOVE_CELLS_FROM_PARENT,'cells',cells));}finally{this.model.endUpdate();}return cells;};mxGraph.prototype.updateGroupBounds=function(cells,border,moveGroup){if(cells==null){cells=this.getSelectionCells();}border=(border!=null)?border:0;moveGroup=(moveGroup!=null)?moveGroup:false;this.model.beginUpdate();try{for(var i=0;i0){var childBounds=this.getBoundingBoxFromGeometry(children);if(childBounds.width>0&&childBounds.height>0){var size=(this.isSwimlane(cells[i]))?this.getStartSize(cells[i]):new mxRectangle();geo=geo.clone();if(moveGroup){geo.x+=childBounds.x-size.width-border;geo.y+=childBounds.y-size.height-border;}geo.width=childBounds.width+size.width+2*border;geo.height=childBounds.height+size.height+2*border;this.model.setGeometry(cells[i],geo);this.moveCells(children,-childBounds.x+size.width+border,-childBounds.y+size.height+border);}}}}}finally{this.model.endUpdate();}return cells;};mxGraph.prototype.cloneCells=function(cells,allowInvalidEdges){allowInvalidEdges=(allowInvalidEdges!=null)?allowInvalidEdges:true;var clones=null;if(cells!=null){var hash=new Object();var tmp=[];for(var i=0;i0){var scale=this.view.scale;var trans=this.view.translate;clones=this.model.cloneCells(cells,true);for(var i=0;i0){var scale=this.view.scale;var tr=this.view.translate;this.model.beginUpdate();try{var hash=new Object();for(var i=0;i0){this.model.beginUpdate();try{for(var i=0;i0){this.model.beginUpdate();try{for(var i=0;i0){bounds.height=Math.max(bounds.height,startSize);}}}geo.alternateBounds=new mxRectangle(geo.x,geo.y,bounds.width,bounds.height);}else{geo.alternateBounds.x=geo.x;geo.alternateBounds.y=geo.y;}}};mxGraph.prototype.addAllEdges=function(cells){var allCells=cells.slice();allCells=allCells.concat(this.getAllEdges(cells));return allCells;};mxGraph.prototype.getAllEdges=function(cells){var edges=[];if(cells!=null){for(var i=0;i0){if(!this.isHtmlLabel(cell)){value=value.replace(/\n/g,'
');}var size=mxUtils.getSizeForString(value,fontSize,style[mxConstants.STYLE_FONTFAMILY]);var width=size.width+dx;var height=size.height+dy;if(!mxUtils.getValue(style,mxConstants.STYLE_HORIZONTAL,true)){var tmp=height;height=width;width=tmp;}if(this.gridEnabled){width=this.snap(width+this.gridSize/2);height=this.snap(height+this.gridSize/2);}result=new mxRectangle(0,0,width,height);}else{var gs2=4*this.gridSize;result=new mxRectangle(0,0,gs2,gs2);}}}return result;};mxGraph.prototype.handleGesture=function(state,evt){if(Math.abs(1-evt.scale)>0.2){var scale=this.view.scale;var tr=this.view.translate;var w=state.width*evt.scale;var h=state.height*evt.scale;var x=state.x-(w-state.width)/2;var y=state.y-(h-state.height)/2;var bounds=new mxRectangle(this.snap(x/scale)-tr.x,this.snap(y/scale)-tr.y,this.snap(w/scale),this.snap(h/scale));this.resizeCell(state.cell,bounds);}};mxGraph.prototype.resizeCell=function(cell,bounds){return this.resizeCells([cell],[bounds])[0];};mxGraph.prototype.resizeCells=function(cells,bounds){this.model.beginUpdate();try{this.cellsResized(cells,bounds);this.fireEvent(new mxEventObject(mxEvent.RESIZE_CELLS,'cells',cells,'bounds',bounds));}finally{this.model.endUpdate();}return cells;};mxGraph.prototype.cellsResized=function(cells,bounds){if(cells!=null&&bounds!=null&&cells.length==bounds.length){this.model.beginUpdate();try{for(var i=0;i0){geo.x=Math.min(geo.x,area.x+area.width-(1-overlap)*geo.width);}if(area.height>0){geo.y=Math.min(geo.y,area.y+area.height-(1-overlap)*geo.height);}geo.x=Math.max(geo.x,area.x-geo.width*overlap);geo.y=Math.max(geo.y,area.y-geo.height*overlap);}}}};mxGraph.prototype.resetEdges=function(cells){if(cells!=null){var hash=new Object();for(var i=0;i0){geo=geo.clone();geo.points=[];this.model.setGeometry(edge,geo);}return edge;};mxGraph.prototype.getAllConnectionConstraints=function(terminal,source){if(terminal!=null&&terminal.shape!=null&&terminal.shape instanceof mxStencilShape){if(terminal.shape.stencil!=null){return terminal.shape.stencil.constraints;}}return null;};mxGraph.prototype.getConnectionConstraint=function(edge,terminal,source){var point=null;var x=edge.style[(source)?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X];if(x!=null){var y=edge.style[(source)?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y];if(y!=null){point=new mxPoint(parseFloat(x),parseFloat(y));}}var perimeter=false;if(point!=null){perimeter=mxUtils.getValue(edge.style,(source)?mxConstants.STYLE_EXIT_PERIMETER:mxConstants.STYLE_ENTRY_PERIMETER,true);}return new mxConnectionConstraint(point,perimeter);};mxGraph.prototype.setConnectionConstraint=function(edge,terminal,source,constraint){if(constraint!=null){this.model.beginUpdate();try{if(constraint==null||constraint.point==null){this.setCellStyles((source)?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X,null,[edge]);this.setCellStyles((source)?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y,null,[edge]);this.setCellStyles((source)?mxConstants.STYLE_EXIT_PERIMETER:mxConstants.STYLE_ENTRY_PERIMETER,null,[edge]);}else if(constraint.point!=null){this.setCellStyles((source)?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X,constraint.point.x,[edge]);this.setCellStyles((source)?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y,constraint.point.y,[edge]);if(!constraint.perimeter){this.setCellStyles((source)?mxConstants.STYLE_EXIT_PERIMETER:mxConstants.STYLE_ENTRY_PERIMETER,'0',[edge]);}else{this.setCellStyles((source)?mxConstants.STYLE_EXIT_PERIMETER:mxConstants.STYLE_ENTRY_PERIMETER,null,[edge]);}}}finally{this.model.endUpdate();}}};mxGraph.prototype.getConnectionPoint=function(vertex,constraint){var point=null;if(vertex!=null){var bounds=this.view.getPerimeterBounds(vertex);var cx=new mxPoint(bounds.getCenterX(),bounds.getCenterY());var direction=vertex.style[mxConstants.STYLE_DIRECTION];var r1=0;if(direction!=null){if(direction=='north'){r1+=270;}else if(direction=='west'){r1+=180;}else if(direction=='south'){r1+=90;}if(direction=='north'||direction=='south'){bounds.x+=bounds.width/2-bounds.height/2;bounds.y+=bounds.height/2-bounds.width/2;var tmp=bounds.width;bounds.width=bounds.height;bounds.height=tmp;}}if(constraint.point!=null){point=new mxPoint(bounds.x+constraint.point.x*bounds.width,bounds.y+constraint.point.y*bounds.height);}var r2=vertex.style[mxConstants.STYLE_ROTATION]||0;if(constraint.perimeter){if(r1!=0&&point!=null){var cos=0;var sin=0;if(r1==90){sin=1;}else if(r1==180){cos=-1;}else if(r2==270){sin=-1;}point=mxUtils.getRotatedPoint(point,cos,sin,cx);}if(point!=null&&constraint.perimeter){point=this.view.getPerimeterPoint(vertex,point,false);}}else{r2+=r1;}if(r2!=0&&point!=null){var rad=mxUtils.toRadians(r2);var cos=Math.cos(rad);var sin=Math.sin(rad);point=mxUtils.getRotatedPoint(point,cos,sin,cx);}}return point;};mxGraph.prototype.connectCell=function(edge,terminal,source,constraint){this.model.beginUpdate();try{var previous=this.model.getTerminal(edge,source);this.cellConnected(edge,terminal,source,constraint);this.fireEvent(new mxEventObject(mxEvent.CONNECT_CELL,'edge',edge,'terminal',terminal,'source',source,'previous',previous));}finally{this.model.endUpdate();}return edge;};mxGraph.prototype.cellConnected=function(edge,terminal,source,constraint){if(edge!=null){this.model.beginUpdate();try{var previous=this.model.getTerminal(edge,source);this.setConnectionConstraint(edge,terminal,source,constraint);if(this.isPortsEnabled()){var id=null;if(this.isPort(terminal)){id=terminal.getId();terminal=this.getTerminalForPort(terminal,source);}var key=(source)?mxConstants.STYLE_SOURCE_PORT:mxConstants.STYLE_TARGET_PORT;this.setCellStyles(key,id,[edge]);}this.model.setTerminal(edge,terminal,source);if(this.resetEdgesOnConnect){this.resetEdge(edge);}this.fireEvent(new mxEventObject(mxEvent.CELL_CONNECTED,'edge',edge,'terminal',terminal,'source',source,'previous',previous));}finally{this.model.endUpdate();}}};mxGraph.prototype.disconnectGraph=function(cells){if(cells!=null){this.model.beginUpdate();try{var scale=this.view.scale;var tr=this.view.translate;var hash=new Object();for(var i=0;i0){var tmp=new mxRectangle(pts[0].x,pts[0].y,0,0);var addPoint=function(pt){if(pt!=null){tmp.add(new mxRectangle(pt.x,pt.y,0,0));}};for(var j=1;j1){var f=(factor-1)/(scale*2);dx*=-f;dy*=-f;}else{var f=(1/factor-1)/(this.view.scale*2);dx*=f;dy*=f;}this.view.scaleAndTranslate(scale,this.view.translate.x+dx,this.view.translate.y+dy);}else{this.view.setScale(scale);}};mxGraph.prototype.fit=function(border,keepOrigin){if(this.container!=null){border=(border!=null)?border:0;keepOrigin=(keepOrigin!=null)?keepOrigin:false;var w1=this.container.offsetWidth-3;var h1=this.container.offsetHeight-3;var bounds=this.view.getGraphBounds();if(keepOrigin&&bounds.x!=null&&bounds.y!=null){bounds.width+=bounds.x;bounds.height+=bounds.y;bounds.x=0;bounds.y=0;}var s=this.view.scale;var w2=bounds.width/s;var h2=bounds.height/s;if(this.backgroundImage!=null){w2=Math.max(w2,this.backgroundImage.width-bounds.x/s);h2=Math.max(h2,this.backgroundImage.height-bounds.y/s);}var b=(keepOrigin)?border:2*border;var s2=Math.floor(Math.min(w1/(w2+b),h1/(h2+b))*100)/100;if(s2>this.minFitScale&&s20){c.scrollLeft-=dx+2;}else{dx=rect.x+widthLimit-c.scrollLeft-c.clientWidth;if(dx>0){c.scrollLeft+=dx+2;}}var dy=c.scrollTop-rect.y;var ddy=Math.max(0,dy-c.scrollTop);if(dy>0){c.scrollTop-=dy+2;}else{dy=rect.y+heightLimit-c.scrollTop-c.clientHeight;if(dy>0){c.scrollTop+=dy+2;}}if(!this.useScrollbarsForPanning&&(ddx!=0||ddy!=0)){this.view.setTranslate(ddx,ddy);}}else{var x=-this.view.translate.x;var y=-this.view.translate.y;var s=this.view.scale;if(rect.x+widthLimit>x+w){this.view.translate.x-=(rect.x+widthLimit-w-x)/s;isChanged=true;}if(rect.y+heightLimit>y+h){this.view.translate.y-=(rect.y+heightLimit-h-y)/s;isChanged=true;}if(rect.x1||(tmp.length==1&&tmp[0]!=edge)){error+=(mxResources.get(this.alreadyConnectedResource)||this.alreadyConnectedResource)+'\n';}}var sourceOut=this.model.getDirectedEdgeCount(source,true,edge);var targetIn=this.model.getDirectedEdgeCount(target,false,edge);if(this.multiplicities!=null){for(var i=0;i0)?error:null;}return(this.allowDanglingEdges)?null:'';};mxGraph.prototype.validateEdge=function(edge,source,target){return null;};mxGraph.prototype.validateGraph=function(cell,context){cell=(cell!=null)?cell:this.model.getRoot();context=(context!=null)?context:new Object();var isValid=true;var childCount=this.model.getChildCount(cell);for(var i=0;i'));}else{this.setCellWarning(tmp,null);}isValid=isValid&&warn==null;}var warning='';if(this.isCellCollapsed(cell)&&!isValid){warning+=(mxResources.get(this.containsValidationErrorsResource)||this.containsValidationErrorsResource)+'\n';}if(this.model.isEdge(cell)){warning+=this.getEdgeValidationError(cell,this.model.getTerminal(cell,true),this.model.getTerminal(cell,false))||'';}else{warning+=this.getCellValidationError(cell)||'';}var err=this.validateCell(cell,context);if(err!=null){warning+=err;}if(this.model.getParent(cell)==null){this.view.validate();}return(warning.length>0||!isValid)?warning:null;};mxGraph.prototype.getCellValidationError=function(cell){var outCount=this.model.getDirectedEdgeCount(cell,true);var inCount=this.model.getDirectedEdgeCount(cell,false);var value=this.model.getValue(cell);var error='';if(this.multiplicities!=null){for(var i=0;i0)||(rule.min==1&&outCount==0)||(rule.max==1&&outCount>1))){error+=rule.countError+'\n';}else if(!rule.source&&mxUtils.isNode(value,rule.type,rule.attr,rule.value)&&((rule.max==0&&inCount>0)||(rule.min==1&&inCount==0)||(rule.max==1&&inCount>1))){error+=rule.countError+'\n';}}}return(error.length>0)?error:null;};mxGraph.prototype.validateCell=function(cell,context){return null;};mxGraph.prototype.getBackgroundImage=function(){return this.backgroundImage;};mxGraph.prototype.setBackgroundImage=function(image){this.backgroundImage=image;};mxGraph.prototype.getFoldingImage=function(state){if(state!=null&&this.foldingEnabled&&!this.getModel().isEdge(state.cell)){var tmp=this.isCellCollapsed(state.cell);if(this.isCellFoldable(state.cell,!tmp)){return(tmp)?this.collapsedImage:this.expandedImage;}}return null;};mxGraph.prototype.convertValueToString=function(cell){var value=this.model.getValue(cell);if(value!=null){if(mxUtils.isNode(value)){return value.nodeName;}else if(typeof(value.toString)=='function'){return value.toString();}}return '';};mxGraph.prototype.getLabel=function(cell){var result='';if(this.labelsVisible&&cell!=null){var state=this.view.getState(cell);var style=(state!=null)?state.style:this.getCellStyle(cell);if(!mxUtils.getValue(style,mxConstants.STYLE_NOLABEL,false)){result=this.convertValueToString(cell);}}return result;};mxGraph.prototype.isHtmlLabel=function(cell){return this.isHtmlLabels();};mxGraph.prototype.isHtmlLabels=function(){return this.htmlLabels;};mxGraph.prototype.setHtmlLabels=function(value){this.htmlLabels=value;};mxGraph.prototype.isWrapping=function(cell){var state=this.view.getState(cell);var style=(state!=null)?state.style:this.getCellStyle(cell);return(style!=null)?style[mxConstants.STYLE_WHITE_SPACE]=='wrap':false;};mxGraph.prototype.isLabelClipped=function(cell){var state=this.view.getState(cell);var style=(state!=null)?state.style:this.getCellStyle(cell);return(style!=null)?style[mxConstants.STYLE_OVERFLOW]=='hidden':false;};mxGraph.prototype.getTooltip=function(state,node,x,y){var tip=null;if(state!=null){if(state.control!=null&&(node==state.control.node||node.parentNode==state.control.node)){tip=this.collapseExpandResource;tip=mxResources.get(tip)||tip;}if(tip==null&&state.overlays!=null){for(var i=0;i0&&style[mxConstants.STYLE_FOLDABLE]!=0;};mxGraph.prototype.isValidDropTarget=function(cell,cells,evt){return cell!=null&&((this.isSplitEnabled()&&this.isSplitTarget(cell,cells,evt))||(!this.model.isEdge(cell)&&(this.isSwimlane(cell)||(this.model.getChildCount(cell)>0&&!this.isCellCollapsed(cell)))));};mxGraph.prototype.isSplitTarget=function(target,cells,evt){if(this.model.isEdge(target)&&cells!=null&&cells.length==1&&this.isCellConnectable(cells[0])&&this.getEdgeValidationError(target,this.model.getTerminal(target,true),cells[0])==null){var src=this.model.getTerminal(target,true);var trg=this.model.getTerminal(target,false);return(!this.model.isAncestor(cells[0],src)&&!this.model.isAncestor(cells[0],trg));}return false;};mxGraph.prototype.getDropTarget=function(cells,evt,cell){if(!this.isSwimlaneNesting()){for(var i=0;i=0;i--){var cell=this.model.getChildAt(parent,i);var result=this.getCellAt(x,y,cell,vertices,edges);if(result!=null){return result;}else if(this.isCellVisible(cell)&&(edges&&this.model.isEdge(cell)||vertices&&this.model.isVertex(cell))){var state=this.view.getState(cell);if(this.intersects(state,x,y)){return cell;}}}}return null;};mxGraph.prototype.intersects=function(state,x,y){if(state!=null){var pts=state.absolutePoints;if(pts!=null){var t2=this.tolerance*this.tolerance;var pt=pts[0];for(var i=1;i0&&x>0&&x>size.width*scale){return true;}else if(size.height>0&&y>0&&y>size.height*scale){return true;}}return false;};mxGraph.prototype.getChildVertices=function(parent){return this.getChildCells(parent,true,false);};mxGraph.prototype.getChildEdges=function(parent){return this.getChildCells(parent,false,true);};mxGraph.prototype.getChildCells=function(parent,vertices,edges){parent=(parent!=null)?parent:this.getDefaultParent();vertices=(vertices!=null)?vertices:false;edges=(edges!=null)?edges:false;var cells=this.model.getChildCells(parent,vertices,edges);var result=[];for(var i=0;i0||height>0){var right=x+width;var bottom=y+height;parent=parent||this.getDefaultParent();if(parent!=null){var childCount=this.model.getChildCount(parent);for(var i=0;i=x&&state.y>=y&&state.x+state.width<=right&&state.y+state.height<=bottom){result.push(cell);}else{this.getCells(x,y,width,height,cell,result);}}}}}return result;};mxGraph.prototype.getCellsBeyond=function(x0,y0,parent,rightHalfpane,bottomHalfpane){var result=[];if(rightHalfpane||bottomHalfpane){if(parent==null){parent=this.getDefaultParent();}if(parent!=null){var childCount=this.model.getChildCount(parent);for(var i=0;i=x0)&&(!bottomHalfpane||state.y>=y0)){result.push(child);}}}}}return result;};mxGraph.prototype.findTreeRoots=function(parent,isolate,invert){isolate=(isolate!=null)?isolate:false;invert=(invert!=null)?invert:false;var roots=[];if(parent!=null){var model=this.getModel();var childCount=model.getChildCount(parent);var best=null;var maxDiff=0;for(var i=0;i0)||(!invert&&fanIn==0&&fanOut>0)){roots.push(cell);}var diff=(invert)?fanIn-fanOut:fanOut-fanIn;if(diff>maxDiff){maxDiff=diff;best=cell;}}}if(roots.length==0&&best!=null){roots.push(best);}}return roots;};mxGraph.prototype.traverse=function(vertex,directed,func,edge,visited){if(func!=null&&vertex!=null){directed=(directed!=null)?directed:true;visited=visited||[];var id=mxCellPath.create(vertex);if(visited[id]==null){visited[id]=vertex;var result=func(vertex,edge);if(result==null||result){var edgeCount=this.model.getEdgeCount(vertex);if(edgeCount>0){for(var i=0;i0)?sel.cells[0]:null;if(sel.cells.length>1){sel.clear();}var parent=(cell!=null)?this.model.getParent(cell):this.getDefaultParent();var childCount=this.model.getChildCount(parent);if(cell==null&&childCount>0){var child=this.model.getChildAt(parent,0);this.setSelectionCell(child);}else if((cell==null||isParent)&&this.view.getState(parent)!=null&&this.model.getGeometry(parent)!=null){if(this.getCurrentRoot()!=parent){this.setSelectionCell(parent);}}else if(cell!=null&&isChild){var tmp=this.model.getChildCount(cell);if(tmp>0){var child=this.model.getChildAt(cell,0);this.setSelectionCell(child);}}else if(childCount>0){var i=parent.getIndex(cell);if(isNext){i++;var child=this.model.getChildAt(parent,i%childCount);this.setSelectionCell(child);}else{i--;var index=(i<0)?childCount-1:i;var child=this.model.getChildAt(parent,index);this.setSelectionCell(child);}}};mxGraph.prototype.selectAll=function(parent){parent=parent||this.getDefaultParent();var children=this.model.getChildren(parent);if(children!=null){this.setSelectionCells(children);}};mxGraph.prototype.selectVertices=function(parent){this.selectCells(true,false,parent);};mxGraph.prototype.selectEdges=function(parent){this.selectCells(false,true,parent);};mxGraph.prototype.selectCells=function(vertices,edges,parent){parent=parent||this.getDefaultParent();var filter=mxUtils.bind(this,function(cell){return this.view.getState(cell)!=null&&this.model.getChildCount(cell)==0&&((this.model.isVertex(cell)&&vertices)||(this.model.isEdge(cell)&&edges));});var cells=this.model.filterDescendants(filter,parent);this.setSelectionCells(cells);};mxGraph.prototype.selectCellForEvent=function(cell,evt){var isSelected=this.isCellSelected(cell);if(this.isToggleEvent(evt)){if(isSelected){this.removeSelectionCell(cell);}else{this.addSelectionCell(cell);}}else if(!isSelected||this.getSelectionCount()!=1){this.setSelectionCell(cell);}};mxGraph.prototype.selectCellsForEvent=function(cells,evt){if(this.isToggleEvent(evt)){this.addSelectionCells(cells);}else{this.setSelectionCells(cells);}};mxGraph.prototype.createHandler=function(state){var result=null;if(state!=null){if(this.model.isEdge(state.cell)){var style=this.view.getEdgeStyle(state);if(this.isLoop(state)||style==mxEdgeStyle.ElbowConnector||style==mxEdgeStyle.SideToSide||style==mxEdgeStyle.TopToBottom){result=new mxElbowEdgeHandler(state);}else if(style==mxEdgeStyle.SegmentConnector||style==mxEdgeStyle.OrthConnector){result=new mxEdgeSegmentHandler(state);}else{result=new mxEdgeHandler(state);}}else{result=new mxVertexHandler(state);}}return result;};mxGraph.prototype.addMouseListener=function(listener){if(this.mouseListeners==null){this.mouseListeners=[];}this.mouseListeners.push(listener);};mxGraph.prototype.removeMouseListener=function(listener){if(this.mouseListeners!=null){for(var i=0;ithis.doubleTapTolerance)||(this.lastMouseY!=null&&Math.abs(this.lastMouseY-me.getY())>this.doubleTapTolerance)){noDoubleClick=true;}if(evtName==mxEvent.MOUSE_UP){this.lastMouseX=me.getX();this.lastMouseY=me.getY();}}if((evtName!=mxEvent.MOUSE_UP||this.isMouseDown)&&noDoubleClick){if(evtName==mxEvent.MOUSE_UP){this.isMouseDown=false;}if(!this.isEditing()&&(mxClient.IS_OP||mxClient.IS_SF||mxClient.IS_GC||(mxClient.IS_IE&&mxClient.IS_SVG)||me.getEvent().target!=this.container)){if(evtName==mxEvent.MOUSE_MOVE&&this.isMouseDown&&this.autoScroll){this.scrollPointToVisible(me.getGraphX(),me.getGraphY(),this.autoExtend);}if(this.mouseListeners!=null){var args=[sender,me];me.getEvent().returnValue=true;for(var i=0;i0){if(this.outline.getView().scale!=scale){this.outline.getView().scale=scale;revalidate=true;}var navView=this.outline.getView();if(navView.currentRoot!=this.source.getView().currentRoot){navView.setCurrentRoot(this.source.getView().currentRoot);}var t=this.source.view.translate;var tx=t.x+this.source.panDx;var ty=t.y+this.source.panDy;if(unscaledGraphBounds.x<0){tx=tx-unscaledGraphBounds.x;}if(unscaledGraphBounds.y<0){ty=ty-unscaledGraphBounds.y;}if(navView.translate.x!=tx||navView.translate.y!=ty){navView.translate.x=tx;navView.translate.y=ty;revalidate=true;}var t2=navView.translate;var scale=this.source.getView().scale;var scale2=scale/navView.scale;var scale3=1.0/navView.scale;var container=this.source.container;this.bounds=new mxRectangle((t2.x-t.x-this.source.panDx)/scale3,(t2.y-t.y-this.source.panDy)/scale3,(container.clientWidth/scale2),(container.clientHeight/scale2));this.bounds.x+=this.source.container.scrollLeft*navView.scale/scale;this.bounds.y+=this.source.container.scrollTop*navView.scale/scale;var b=this.selectionBorder.bounds;if(b.x!=this.bounds.x||b.y!=this.bounds.y||b.width!=this.bounds.width||b.height!=this.bounds.height){this.selectionBorder.bounds=this.bounds;this.selectionBorder.redraw();}var b=this.sizer.bounds;var b2=new mxRectangle(this.bounds.x+this.bounds.width-b.width/2,this.bounds.y+this.bounds.height-b.height/2,b.width,b.height);if(b.x!=b2.x||b.y!=b2.y||b.width!=b2.width||b.height!=b2.height){this.sizer.bounds=b2;this.sizer.redraw();}if(revalidate){this.outline.view.revalidate();}}}};mxOutline.prototype.mouseDown=function(sender,me){if(this.enabled&&this.showViewport){this.zoom=me.isSource(this.sizer);this.startX=me.getX();this.startY=me.getY();this.active=true;if(this.source.useScrollbarsForPanning&&mxUtils.hasScrollbars(this.source.container)){this.dx0=this.source.container.scrollLeft;this.dy0=this.source.container.scrollTop;}else{this.dx0=0;this.dy0=0;}}me.consume();};mxOutline.prototype.mouseMove=function(sender,me){if(this.active){this.selectionBorder.node.style.display=(this.showViewport)?'':'none';this.sizer.node.style.display=this.selectionBorder.node.style.display;var dx=me.getX()-this.startX;var dy=me.getY()-this.startY;var bounds=null;if(!this.zoom){var scale=this.outline.getView().scale;bounds=new mxRectangle(this.bounds.x+dx,this.bounds.y+dy,this.bounds.width,this.bounds.height);this.selectionBorder.bounds=bounds;this.selectionBorder.redraw();dx/=scale;dx*=this.source.getView().scale;dy/=scale;dy*=this.source.getView().scale;this.source.panGraph(-dx-this.dx0,-dy-this.dy0);}else{var container=this.source.container;var viewRatio=container.clientWidth/container.clientHeight;dy=dx/viewRatio;bounds=new mxRectangle(this.bounds.x,this.bounds.y,Math.max(1,this.bounds.width+dx),Math.max(1,this.bounds.height+dy));this.selectionBorder.bounds=bounds;this.selectionBorder.redraw();}var b=this.sizer.bounds;this.sizer.bounds=new mxRectangle(bounds.x+bounds.width-b.width/2,bounds.y+bounds.height-b.height/2,b.width,b.height);this.sizer.redraw();me.consume();}};mxOutline.prototype.mouseUp=function(sender,me){if(this.active){var dx=me.getX()-this.startX;var dy=me.getY()-this.startY;if(Math.abs(dx)>0||Math.abs(dy)>0){if(!this.zoom){if(!this.source.useScrollbarsForPanning||!mxUtils.hasScrollbars(this.source.container)){this.source.panGraph(0,0);dx/=this.outline.getView().scale;dy/=this.outline.getView().scale;var t=this.source.getView().translate;this.source.getView().setTranslate(t.x-dx,t.y-dy);}}else{var w=this.selectionBorder.bounds.width;var scale=this.source.getView().scale;this.source.getView().setScale(scale-(dx*scale)/w);}this.update();me.consume();}this.index=null;this.active=false;}};mxOutline.prototype.destroy=function(){if(this.source!=null){this.source.removeListener(this.panHandler);this.source.removeListener(this.refreshHandler);this.source.getModel().removeListener(this.updateHandler);this.source.getView().removeListener(this.updateHandler);mxEvent.addListener(this.source.container,'scroll',this.updateHandler);this.source=null;}if(this.outline!=null){this.outline.removeMouseListener(this);this.outline.destroy();this.outline=null;}if(this.selectionBorder!=null){this.selectionBorder.destroy();this.selectionBorder=null;}if(this.sizer!=null){this.sizer.destroy();this.sizer=null;}};function mxMultiplicity(source,type,attr,value,min,max,validNeighbors,countError,typeError,validNeighborsAllowed){this.source=source;this.type=type;this.attr=attr;this.value=value;this.min=(min!=null)?min:0;this.max=(max!=null)?max:'n';this.validNeighbors=validNeighbors;this.countError=mxResources.get(countError)||countError;this.typeError=mxResources.get(typeError)||typeError;this.validNeighborsAllowed=(validNeighborsAllowed!=null)?validNeighborsAllowed:true;};mxMultiplicity.prototype.type=null;mxMultiplicity.prototype.attr=null;mxMultiplicity.prototype.value=null;mxMultiplicity.prototype.source=null;mxMultiplicity.prototype.min=null;mxMultiplicity.prototype.max=null;mxMultiplicity.prototype.validNeighbors=null;mxMultiplicity.prototype.validNeighborsAllowed=true;mxMultiplicity.prototype.countError=null;mxMultiplicity.prototype.typeError=null;mxMultiplicity.prototype.check=function(graph,edge,source,target,sourceOut,targetIn){var error='';if((this.source&&this.checkTerminal(graph,source,edge))||(!this.source&&this.checkTerminal(graph,target,edge))){if(this.countError!=null&&((this.source&&(this.max==0||(sourceOut>=this.max)))||(!this.source&&(this.max==0||(targetIn>=this.max))))){error+=this.countError+'\n';}if(this.validNeighbors!=null&&this.typeError!=null&&this.validNeighbors.length>0){var isValid=this.checkNeighbors(graph,edge,source,target);if(!isValid){error+=this.typeError+'\n';}}}return(error.length>0)?error:null;};mxMultiplicity.prototype.checkNeighbors=function(graph,edge,source,target){var sourceValue=graph.model.getValue(source);var targetValue=graph.model.getValue(target);var isValid=!this.validNeighborsAllowed;var valid=this.validNeighbors;for(var j=0;j0){cells=cells.concat(tmp);tmp=model.getParents(tmp);}}this.layoutCells(mxUtils.sortCells(cells,false));};mxLayoutManager.prototype.cellsMoved=function(cells,evt){if(cells!=null&&evt!=null){var point=mxUtils.convertPoint(this.getGraph().container,mxEvent.getClientX(evt),mxEvent.getClientY(evt));var model=this.getGraph().getModel();for(var i=0;i0){var model=this.getGraph().getModel();model.beginUpdate();try{var last=null;for(var i=0;i=right){geo=geo.clone();geo.translate(-dx,0);}else{var tmpDx=Math.max(0,state.x-x0);geo=geo.clone();geo.translate(-fx*tmpDx,0);}}if(this.isShiftDownwards()){if(state.y>=bottom){geo=geo.clone();geo.translate(0,-dy);}else{var tmpDy=Math.max(0,state.y-y0);geo=geo.clone();geo.translate(0,-fy*tmpDy);}}if(geo!=model.getGeometry(cell)){model.setGeometry(cell,geo);if(extendParent){graph.extendParent(cell);}}}finally{model.endUpdate();}}}};mxSpaceManager.prototype.getCellsToShift=function(state){var graph=this.getGraph();var parent=graph.getModel().getParent(state.cell);var down=this.isShiftDownwards();var right=this.isShiftRightwards();return graph.getCellsBeyond(state.x+((down)?0:state.width),state.y+((down&&right)?0:state.height),parent,right,down);};mxSpaceManager.prototype.destroy=function(){this.setGraph(null);};function mxSwimlaneManager(graph,horizontal,addEnabled,resizeEnabled){this.horizontal=(horizontal!=null)?horizontal:true;this.addEnabled=(addEnabled!=null)?addEnabled:true;this.resizeEnabled=(resizeEnabled!=null)?resizeEnabled:true;this.addHandler=mxUtils.bind(this,function(sender,evt){if(this.isEnabled()&&this.isAddEnabled()){this.cellsAdded(evt.getProperty('cells'));}});this.resizeHandler=mxUtils.bind(this,function(sender,evt){if(this.isEnabled()&&this.isResizeEnabled()){this.cellsResized(evt.getProperty('cells'));}});this.setGraph(graph);};mxSwimlaneManager.prototype=new mxEventSource();mxSwimlaneManager.prototype.constructor=mxSwimlaneManager;mxSwimlaneManager.prototype.graph=null;mxSwimlaneManager.prototype.enabled=true;mxSwimlaneManager.prototype.horizontal=true;mxSwimlaneManager.prototype.addEnabled=true;mxSwimlaneManager.prototype.resizeEnabled=true;mxSwimlaneManager.prototype.addHandler=null;mxSwimlaneManager.prototype.resizeHandler=null;mxSwimlaneManager.prototype.isEnabled=function(){return this.enabled;};mxSwimlaneManager.prototype.setEnabled=function(value){this.enabled=value;};mxSwimlaneManager.prototype.isHorizontal=function(){return this.horizontal;};mxSwimlaneManager.prototype.setHorizontal=function(value){this.horizontal=value;};mxSwimlaneManager.prototype.isAddEnabled=function(){return this.addEnabled;};mxSwimlaneManager.prototype.setAddEnabled=function(value){this.addEnabled=value;};mxSwimlaneManager.prototype.isResizeEnabled=function(){return this.resizeEnabled;};mxSwimlaneManager.prototype.setResizeEnabled=function(value){this.resizeEnabled=value;};mxSwimlaneManager.prototype.getGraph=function(){return this.graph;};mxSwimlaneManager.prototype.setGraph=function(graph){if(this.graph!=null){this.graph.removeListener(this.addHandler);this.graph.removeListener(this.resizeHandler);}this.graph=graph;if(this.graph!=null){this.graph.addListener(mxEvent.ADD_CELLS,this.addHandler);this.graph.addListener(mxEvent.CELLS_RESIZED,this.resizeHandler);}};mxSwimlaneManager.prototype.isSwimlaneIgnored=function(swimlane){return!this.getGraph().isSwimlane(swimlane);};mxSwimlaneManager.prototype.isCellHorizontal=function(cell){if(this.graph.isSwimlane(cell)){var state=this.graph.view.getState(cell);var style=(state!=null)?state.style:this.graph.getCellStyle(cell);return mxUtils.getValue(style,mxConstants.STYLE_HORIZONTAL,1)==1;}return!this.isHorizontal();};mxSwimlaneManager.prototype.cellsAdded=function(cells){if(cells!=null){var model=this.getGraph().getModel();model.beginUpdate();try{for(var i=0;i1||(geo.points!=null&&geo.points.length>0)||model.getTerminal(cell,true)==null||model.getTerminal(cell,false)==null)||this.graph.allowDanglingEdges||(this.graph.isCloneEvent(me.getEvent())&&this.graph.isCellsCloneable()))){this.start(cell,me.getX(),me.getY());}this.cellWasClicked=true;if((!mxClient.IS_SF&&!mxClient.IS_GC)||me.getSource().nodeName!='SELECT'){me.consume();}else if(mxClient.IS_SF&&me.getSource().nodeName=='SELECT'){this.cellWasClicked=false;this.first=null;}}}};mxGraphHandler.prototype.getGuideStates=function(){var parent=this.graph.getDefaultParent();var model=this.graph.getModel();var filter=mxUtils.bind(this,function(cell){return this.graph.view.getState(cell)!=null&&model.isVertex(cell)&&model.getGeometry(cell)!=null&&!model.getGeometry(cell).relative;});return this.graph.view.getCellStates(model.filterDescendants(filter,parent));};mxGraphHandler.prototype.getCells=function(initialCell){if(!this.delayedSelection&&this.graph.isCellMovable(initialCell)){return[initialCell];}else{return this.graph.getMovableCells(this.graph.getSelectionCells());}};mxGraphHandler.prototype.getPreviewBounds=function(cells){var bounds=this.graph.getView().getBounds(cells);if(bounds!=null){if(bounds.widthtol||Math.abs(dy)>tol){if(this.highlight==null){this.highlight=new mxCellHighlight(this.graph,mxConstants.DROP_TARGET_COLOR,3);}if(this.shape==null){this.shape=this.createPreviewShape(this.bounds);}var gridEnabled=graph.isGridEnabledEvent(me.getEvent());var hideGuide=true;if(this.guide!=null&&this.useGuidesForEvent(me)){var delta=this.guide.move(this.bounds,new mxPoint(dx,dy),gridEnabled);hideGuide=false;dx=delta.x;dy=delta.y;}else if(gridEnabled){var trx=graph.getView().translate;var scale=graph.getView().scale;var tx=this.bounds.x-(graph.snap(this.bounds.x/scale-trx.x)+trx.x)*scale;var ty=this.bounds.y-(graph.snap(this.bounds.y/scale-trx.y)+trx.y)*scale;var v=this.snap(new mxPoint(dx,dy));dx=v.x-tx;dy=v.y-ty;}if(this.guide!=null&&hideGuide){this.guide.hide();}if(graph.isConstrainedEvent(me.getEvent())){if(Math.abs(dx)>Math.abs(dy)){dy=0;}else{dx=0;}}this.currentDx=dx;this.currentDy=dy;this.updatePreviewShape();var target=null;var cell=me.getCell();if(graph.isDropEnabled()&&this.highlightEnabled){target=graph.getDropTarget(this.cells,me.getEvent(),cell);}var parent=target;var model=graph.getModel();while(parent!=null&&parent!=this.cells[0]){parent=model.getParent(parent);}var clone=graph.isCloneEvent(me.getEvent())&&graph.isCellsCloneable()&&this.isCloneEnabled();var state=graph.getView().getState(target);var highlight=false;if(state!=null&&parent==null&&(model.getParent(this.cell)!=target||clone)){if(this.target!=target){this.target=target;this.setHighlightColor(mxConstants.DROP_TARGET_COLOR);}highlight=true;}else{this.target=null;if(this.connectOnDrop&&cell!=null&&this.cells.length==1&&graph.getModel().isVertex(cell)&&graph.isCellConnectable(cell)){state=graph.getView().getState(cell);if(state!=null){var error=graph.getEdgeValidationError(null,this.cell,cell);var color=(error==null)?mxConstants.VALID_COLOR:mxConstants.INVALID_CONNECT_TARGET_COLOR;this.setHighlightColor(color);highlight=true;}}}if(state!=null&&highlight){this.highlight.highlight(state);}else{this.highlight.hide();}}me.consume();mxEvent.consume(me.getEvent());}else if((this.isMoveEnabled()||this.isCloneEnabled())&&this.updateCursor&&!me.isConsumed()&&me.getState()!=null&&!graph.isMouseDown){var cursor=graph.getCursorForCell(me.getCell());if(cursor==null&&graph.isEnabled()&&graph.isCellMovable(me.getCell())){if(graph.getModel().isEdge(me.getCell())){cursor=mxConstants.CURSOR_MOVABLE_EDGE;}else{cursor=mxConstants.CURSOR_MOVABLE_VERTEX;}}me.getState().setCursor(cursor);me.consume();}};mxGraphHandler.prototype.updatePreviewShape=function(){if(this.shape!=null){this.shape.bounds=new mxRectangle(this.bounds.x+this.currentDx-this.graph.panDx,this.bounds.y+this.currentDy-this.graph.panDy,this.bounds.width,this.bounds.height);this.shape.redraw();}};mxGraphHandler.prototype.setHighlightColor=function(color){if(this.highlight!=null){this.highlight.setHighlightColor(color);}};mxGraphHandler.prototype.mouseUp=function(sender,me){if(!me.isConsumed()){var graph=this.graph;if(this.cell!=null&&this.first!=null&&this.shape!=null&&this.currentDx!=null&&this.currentDy!=null){var scale=graph.getView().scale;var clone=graph.isCloneEvent(me.getEvent())&&graph.isCellsCloneable()&&this.isCloneEnabled();var dx=this.currentDx/scale;var dy=this.currentDy/scale;var cell=me.getCell();if(this.connectOnDrop&&this.target==null&&cell!=null&&graph.getModel().isVertex(cell)&&graph.isCellConnectable(cell)&&graph.isEdgeValid(null,this.cell,cell)){graph.connectionHandler.connect(this.cell,cell,me.getEvent());}else{var target=this.target;if(graph.isSplitEnabled()&&graph.isSplitTarget(target,this.cells,me.getEvent())){graph.splitEdge(target,this.cells,null,dx,dy);}else{this.moveCells(this.cells,dx,dy,clone,this.target,me.getEvent());}}}else if(this.isSelectEnabled()&&this.delayedSelection&&this.cell!=null){this.selectDelayed(me);}}if(this.cellWasClicked){me.consume();}this.reset();};mxGraphHandler.prototype.selectDelayed=function(me){this.graph.selectCellForEvent(this.cell,me.getEvent());};mxGraphHandler.prototype.reset=function(){this.destroyShapes();this.cellWasClicked=false;this.delayedSelection=false;this.currentDx=null;this.currentDy=null;this.guides=null;this.first=null;this.cell=null;this.target=null;};mxGraphHandler.prototype.shouldRemoveCellsFromParent=function(parent,cells,evt){if(this.graph.getModel().isVertex(parent)){var pState=this.graph.getView().getState(parent);var pt=mxUtils.convertPoint(this.graph.container,mxEvent.getClientX(evt),mxEvent.getClientY(evt));return pState!=null&&!mxUtils.contains(pState,pt.x,pt.y);}return false;};mxGraphHandler.prototype.moveCells=function(cells,dx,dy,clone,target,evt){if(clone){cells=this.graph.getCloneableCells(cells);}if(target==null&&this.isRemoveCellsFromParent()&&this.shouldRemoveCellsFromParent(this.graph.getModel().getParent(this.cell),cells,evt)){target=this.graph.getDefaultParent();}cells=this.graph.moveCells(cells,dx-this.graph.panDx/this.graph.view.scale,dy-this.graph.panDy/this.graph.view.scale,clone,target,evt);if(this.isSelectEnabled()&&this.scrollOnMove){this.graph.scrollCellToVisible(cells[0]);}if(clone){this.graph.setSelectionCells(cells);}};mxGraphHandler.prototype.destroyShapes=function(){if(this.shape!=null){this.shape.destroy();this.shape=null;}if(this.guide!=null){this.guide.destroy();this.guide=null;}if(this.highlight!=null){this.highlight.destroy();this.highlight=null;}};mxGraphHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.panHandler);this.destroyShapes();};function mxPanningHandler(graph,factoryMethod){if(graph!=null){this.graph=graph;this.factoryMethod=factoryMethod;this.graph.addMouseListener(this);this.init();}};mxPanningHandler.prototype=new mxPopupMenu();mxPanningHandler.prototype.constructor=mxPanningHandler;mxPanningHandler.prototype.graph=null;mxPanningHandler.prototype.usePopupTrigger=true;mxPanningHandler.prototype.useLeftButtonForPanning=false;mxPanningHandler.prototype.selectOnPopup=true;mxPanningHandler.prototype.clearSelectionOnBackground=true;mxPanningHandler.prototype.ignoreCell=false;mxPanningHandler.prototype.previewEnabled=true;mxPanningHandler.prototype.useGrid=false;mxPanningHandler.prototype.panningEnabled=true;mxPanningHandler.prototype.isPanningEnabled=function(){return this.panningEnabled;};mxPanningHandler.prototype.setPanningEnabled=function(value){this.panningEnabled=value;};mxPanningHandler.prototype.init=function(){mxPopupMenu.prototype.init.apply(this);mxEvent.addListener(this.div,(mxClient.IS_TOUCH)?'touchmove':'mousemove',mxUtils.bind(this,function(evt){this.graph.tooltipHandler.hide();}));};mxPanningHandler.prototype.isPanningTrigger=function(me){var evt=me.getEvent();return(this.useLeftButtonForPanning&&(this.ignoreCell||me.getState()==null)&&mxEvent.isLeftMouseButton(evt))||(mxEvent.isControlDown(evt)&&mxEvent.isShiftDown(evt))||(this.usePopupTrigger&&mxEvent.isPopupTrigger(evt));};mxPanningHandler.prototype.mouseDown=function(sender,me){if(!me.isConsumed()&&this.isEnabled()){this.hideMenu();this.dx0=-this.graph.container.scrollLeft;this.dy0=-this.graph.container.scrollTop;this.popupTrigger=this.isPopupTrigger(me);this.panningTrigger=this.isPanningEnabled()&&this.isPanningTrigger(me);this.startX=me.getX();this.startY=me.getY();if(this.panningTrigger){me.consume();}}};mxPanningHandler.prototype.mouseMove=function(sender,me){var dx=me.getX()-this.startX;var dy=me.getY()-this.startY;if(this.active){if(this.previewEnabled){if(this.useGrid){dx=this.graph.snap(dx);dy=this.graph.snap(dy);}this.graph.panGraph(dx+this.dx0,dy+this.dy0);}this.fireEvent(new mxEventObject(mxEvent.PAN,'event',me));me.consume();}else if(this.panningTrigger){var tmp=this.active;this.active=Math.abs(dx)>this.graph.tolerance||Math.abs(dy)>this.graph.tolerance;if(!tmp&&this.active){this.fireEvent(new mxEventObject(mxEvent.PAN_START,'event',me));}}};mxPanningHandler.prototype.mouseUp=function(sender,me){var dx=Math.abs(me.getX()-this.startX);var dy=Math.abs(me.getY()-this.startY);if(this.active){if(!this.graph.useScrollbarsForPanning||!mxUtils.hasScrollbars(this.graph.container)){dx=me.getX()-this.startX;dy=me.getY()-this.startY;if(this.useGrid){dx=this.graph.snap(dx);dy=this.graph.snap(dy);}var scale=this.graph.getView().scale;var t=this.graph.getView().translate;this.graph.panGraph(0,0);this.panGraph(t.x+dx/scale,t.y+dy/scale);}this.active=false;this.fireEvent(new mxEventObject(mxEvent.PAN_END,'event',me));me.consume();}else if(this.popupTrigger){if(dx0)?this.waypoints[0]:current;var tmp=this.getSourcePerimeterPoint(this.previous,next,me);if(tmp!=null){pt2=tmp;}}}if(this.currentState==null&&this.movePreviewAway){var dx=current.x-pt2.x;var dy=current.y-pt2.y;var len=Math.sqrt(dx*dx+dy*dy);current.x-=dx*4/len;current.y-=dy*4/len;}if(this.shape==null){var dx=Math.abs(point.x-this.first.x);var dy=Math.abs(point.y-this.first.y);if(dx>this.graph.tolerance||dy>this.graph.tolerance){this.shape=this.createShape();}}if(this.shape!=null){if(this.edgeState!=null){this.shape.points=this.edgeState.absolutePoints;}else{var pts=[pt2];if(this.waypoints!=null){pts=pts.concat(this.waypoints);}pts.push(current);this.shape.points=pts;}this.drawPreview();}mxEvent.consume(me.getEvent());me.consume();}else if(!this.isEnabled()||!this.graph.isEnabled()){this.constraintHandler.reset();}else if(this.previous!=this.currentState&&this.edgeState==null){this.destroyIcons(this.icons);this.icons=null;if(this.currentState!=null&&this.error==null){this.icons=this.createIcons(this.currentState);if(this.icons==null){this.currentState.setCursor(mxConstants.CURSOR_CONNECT);me.consume();}}this.previous=this.currentState;}else if(this.previous==this.currentState&&this.currentState!=null&&this.icons==null&&!this.graph.isMouseDown){me.consume();}if(this.constraintHandler.currentConstraint!=null){this.marker.reset();}if(!this.graph.isMouseDown&&this.currentState!=null&&this.icons!=null){var hitsIcon=false;var target=me.getSource();for(var i=0;i0)?this.waypoints[this.waypoints.length-1]:new mxPoint(this.previous.getCenterX(),this.previous.getCenterY());var tmp=targetPerimeter(view.getPerimeterBounds(state),this.edgeState,next,false);if(tmp!=null){result=tmp;}}else{result=new mxPoint(state.getCenterX(),state.getCenterY());}return result;};mxConnectionHandler.prototype.getSourcePerimeterPoint=function(state,next,me){var result=null;var view=state.view;var sourcePerimeter=view.getPerimeterFunction(state);if(sourcePerimeter!=null){var tmp=sourcePerimeter(view.getPerimeterBounds(state),state,next,false);if(tmp!=null){result=tmp;}}else{result=new mxPoint(state.getCenterX(),state.getCenterY());}return result;};mxConnectionHandler.prototype.updateIcons=function(state,icons,me){};mxConnectionHandler.prototype.isStopEvent=function(me){return me.getState()!=null;};mxConnectionHandler.prototype.addWaypointForEvent=function(me){var point=mxUtils.convertPoint(this.graph.container,me.getX(),me.getY());var dx=Math.abs(point.x-this.first.x);var dy=Math.abs(point.y-this.first.y);var addPoint=this.waypoints!=null||(this.mouseDownCounter>1&&(dx>this.graph.tolerance||dy>this.graph.tolerance));if(addPoint){if(this.waypoints==null){this.waypoints=[];}var scale=this.graph.view.scale;var point=new mxPoint(this.graph.snap(me.getGraphX()/scale)*scale,this.graph.snap(me.getGraphY()/scale)*scale);this.waypoints.push(point);}};mxConnectionHandler.prototype.mouseUp=function(sender,me){if(!me.isConsumed()&&this.isConnecting()){if(this.waypointsEnabled&&!this.isStopEvent(me)){this.addWaypointForEvent(me);me.consume();return;}if(this.error==null){var source=(this.previous!=null)?this.previous.cell:null;var target=null;if(this.constraintHandler.currentConstraint!=null&&this.constraintHandler.currentFocus!=null){target=this.constraintHandler.currentFocus.cell;}if(target==null&&this.marker.hasValidState()){target=this.marker.validState.cell;}this.connect(source,target,me.getEvent(),me.getCell());}else{if(this.previous!=null&&this.marker.validState!=null&&this.previous.cell==this.marker.validState.cell){this.graph.selectCellForEvent(this.marker.source,evt);}if(this.error.length>0){this.graph.validationAlert(this.error);}}this.destroyIcons(this.icons);me.consume();}if(this.first!=null){this.reset();}this.tapAndHoldInProgress=false;this.tapAndHoldValid=false;};mxConnectionHandler.prototype.reset=function(){if(this.shape!=null){this.shape.destroy();this.shape=null;}this.destroyIcons(this.icons);this.icons=null;this.marker.reset();this.constraintHandler.reset();this.selectedIcon=null;this.edgeState=null;this.previous=null;this.error=null;this.sourceConstraint=null;this.mouseDownCounter=0;this.first=null;this.icon=null;};mxConnectionHandler.prototype.drawPreview=function(){var valid=this.error==null;var color=this.getEdgeColor(valid);if(this.shape.dialect==mxConstants.DIALECT_SVG){this.shape.innerNode.setAttribute('stroke',color);}else{this.shape.node.strokecolor=color;}this.shape.strokewidth=this.getEdgeWidth(valid);this.shape.redraw();mxUtils.repaintGraph(this.graph,this.shape.points[1]);};mxConnectionHandler.prototype.getEdgeColor=function(valid){return(valid)?mxConstants.VALID_COLOR:mxConstants.INVALID_COLOR;};mxConnectionHandler.prototype.getEdgeWidth=function(valid){return(valid)?3:1;};mxConnectionHandler.prototype.connect=function(source,target,evt,dropTarget){if(target!=null||this.isCreateTarget()||this.graph.allowDanglingEdges){var model=this.graph.getModel();var edge=null;model.beginUpdate();try{if(source!=null&&target==null&&this.isCreateTarget()){target=this.createTargetVertex(evt,source);if(target!=null){dropTarget=this.graph.getDropTarget([target],evt,dropTarget);if(dropTarget==null||!this.graph.getModel().isEdge(dropTarget)){var pstate=this.graph.getView().getState(dropTarget);if(pstate!=null){var tmp=model.getGeometry(target);tmp.x-=pstate.origin.x;tmp.y-=pstate.origin.y;}}else{dropTarget=this.graph.getDefaultParent();}this.graph.addCell(target,dropTarget);}}var parent=this.graph.getDefaultParent();if(source!=null&&target!=null&&model.getParent(source)==model.getParent(target)&&model.getParent(model.getParent(source))!=model.getRoot()){parent=model.getParent(source);if((source.geometry!=null&&source.geometry.relative)&&(target.geometry!=null&&target.geometry.relative)){parent=model.getParent(parent);}}var value=null;var style=null;if(this.edgeState!=null){value=this.edgeState.cell.value;style=this.edgeState.cell.style;}edge=this.insertEdge(parent,null,value,source,target,style);if(edge!=null){this.graph.setConnectionConstraint(edge,source,true,this.sourceConstraint);this.graph.setConnectionConstraint(edge,target,false,this.constraintHandler.currentConstraint);if(this.edgeState!=null){model.setGeometry(edge,this.edgeState.cell.geometry);}var geo=model.getGeometry(edge);if(geo==null){geo=new mxGeometry();geo.relative=true;model.setGeometry(edge,geo);}if(this.waypoints!=null&&this.waypoints.length>0){var s=this.graph.view.scale;var tr=this.graph.view.translate;geo.points=[];for(var i=0;itol||Math.abs(dy)>tol){if(this.div==null){this.div=this.createShape();}mxUtils.clearSelection();this.update(x,y);me.consume();}}};mxRubberband.prototype.createShape=function(){if(this.sharedDiv==null){this.sharedDiv=document.createElement('div');this.sharedDiv.className='mxRubberband';mxUtils.setOpacity(this.sharedDiv,this.defaultOpacity);}this.graph.container.appendChild(this.sharedDiv);return this.sharedDiv;};mxRubberband.prototype.mouseUp=function(sender,me){var execute=this.div!=null;this.reset();if(execute){var rect=new mxRectangle(this.x,this.y,this.width,this.height);this.graph.selectRegion(rect,me.getEvent());me.consume();}};mxRubberband.prototype.reset=function(){if(this.div!=null){this.div.parentNode.removeChild(this.div);}if(this.dragHandler!=null){mxEvent.removeListener(document,'mousemove',this.dragHandler);this.dragHandler=null;}if(this.dropHandler!=null){mxEvent.removeListener(document,'mouseup',this.dropHandler);this.dropHandler=null;}this.currentX=0;this.currentY=0;this.first=null;this.div=null;};mxRubberband.prototype.update=function(x,y){this.currentX=x;this.currentY=y;this.repaint();};mxRubberband.prototype.repaint=function(){if(this.div!=null){var x=this.currentX-this.graph.panDx;var y=this.currentY-this.graph.panDy;this.x=Math.min(this.first.x,x);this.y=Math.min(this.first.y,y);this.width=Math.max(this.first.x,x)-this.x;this.height=Math.max(this.first.y,y)-this.y;var dx=(mxClient.IS_VML)?this.graph.panDx:0;var dy=(mxClient.IS_VML)?this.graph.panDy:0;this.div.style.left=(this.x+dx)+'px';this.div.style.top=(this.y+dy)+'px';this.div.style.width=Math.max(1,this.width)+'px';this.div.style.height=Math.max(1,this.height)+'px';}};mxRubberband.prototype.destroy=function(){if(!this.destroyed){this.destroyed=true;this.graph.removeMouseListener(this);this.graph.removeListener(this.panHandler);this.reset();if(this.sharedDiv!=null){this.sharedDiv=null;}}};function mxVertexHandler(state){if(state!=null){this.state=state;this.init();}};mxVertexHandler.prototype.graph=null;mxVertexHandler.prototype.state=null;mxVertexHandler.prototype.singleSizer=false;mxVertexHandler.prototype.index=null;mxVertexHandler.prototype.allowHandleBoundsCheck=true;mxVertexHandler.prototype.crisp=true;mxVertexHandler.prototype.handleImage=null;mxVertexHandler.prototype.tolerance=0;mxVertexHandler.prototype.init=function(){this.graph=this.state.view.graph;this.bounds=this.getSelectionBounds(this.state);this.selectionBorder=this.createSelectionShape(this.bounds);this.selectionBorder.dialect=(this.graph.dialect!=mxConstants.DIALECT_SVG)?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;this.selectionBorder.init(this.graph.getView().getOverlayPane());if(this.selectionBorder.dialect==mxConstants.DIALECT_SVG){this.selectionBorder.node.setAttribute('pointer-events','none');}else{this.selectionBorder.node.style.background='';}if(this.graph.isCellMovable(this.state.cell)){this.selectionBorder.node.style.cursor=mxConstants.CURSOR_MOVABLE_VERTEX;}mxEvent.redirectMouseEvents(this.selectionBorder.node,this.graph,this.state);if(mxGraphHandler.prototype.maxCells<=0||this.graph.getSelectionCount()=2&&this.state.height>=2)){var i=0;if(resizable){if(!this.singleSizer){this.sizers.push(this.createSizer('nw-resize',i++));this.sizers.push(this.createSizer('n-resize',i++));this.sizers.push(this.createSizer('ne-resize',i++));this.sizers.push(this.createSizer('w-resize',i++));this.sizers.push(this.createSizer('e-resize',i++));this.sizers.push(this.createSizer('sw-resize',i++));this.sizers.push(this.createSizer('s-resize',i++));}this.sizers.push(this.createSizer('se-resize',i++));}var geo=this.graph.model.getGeometry(this.state.cell);if(geo!=null&&!geo.relative&&!this.graph.isSwimlane(this.state.cell)&&this.graph.isLabelMovable(this.state.cell)){this.labelShape=this.createSizer(mxConstants.CURSOR_LABEL_HANDLE,mxEvent.LABEL_HANDLE,mxConstants.LABEL_HANDLE_SIZE,mxConstants.LABEL_HANDLE_FILLCOLOR);this.sizers.push(this.labelShape);}}else if(this.graph.isCellMovable(this.state.cell)&&!this.graph.isCellResizable(this.state.cell)&&this.state.width<2&&this.state.height<2){this.labelShape=this.createSizer(mxConstants.CURSOR_MOVABLE_VERTEX,null,null,mxConstants.LABEL_HANDLE_FILLCOLOR);this.sizers.push(this.labelShape);}}this.redraw();};mxVertexHandler.prototype.getSelectionBounds=function(state){return new mxRectangle(state.x,state.y,state.width,state.height);};mxVertexHandler.prototype.createSelectionShape=function(bounds){var shape=new mxRectangleShape(bounds,null,this.getSelectionColor());shape.strokewidth=this.getSelectionStrokeWidth();shape.isDashed=this.isSelectionDashed();shape.crisp=this.crisp;return shape;};mxVertexHandler.prototype.getSelectionColor=function(){return mxConstants.VERTEX_SELECTION_COLOR;};mxVertexHandler.prototype.getSelectionStrokeWidth=function(){return mxConstants.VERTEX_SELECTION_STROKEWIDTH;};mxVertexHandler.prototype.isSelectionDashed=function(){return mxConstants.VERTEX_SELECTION_DASHED;};mxVertexHandler.prototype.createSizer=function(cursor,index,size,fillColor){size=size||mxConstants.HANDLE_SIZE;var bounds=new mxRectangle(0,0,size,size);var sizer=this.createSizerShape(bounds,index,fillColor);if(this.state.text!=null&&this.state.text.node.parentNode==this.graph.container){sizer.bounds.height-=1;sizer.bounds.width-=1;sizer.dialect=mxConstants.DIALECT_STRICTHTML;sizer.init(this.graph.container);}else{sizer.dialect=(this.graph.dialect!=mxConstants.DIALECT_SVG)?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;sizer.init(this.graph.getView().getOverlayPane());}sizer.node.style.cursor=cursor;mxEvent.redirectMouseEvents(sizer.node,this.graph,this.state);if(!this.isSizerVisible(index)){sizer.node.style.visibility='hidden';}return sizer;};mxVertexHandler.prototype.isSizerVisible=function(index){return true;};mxVertexHandler.prototype.createSizerShape=function(bounds,index,fillColor){if(this.handleImage!=null){bounds.width=this.handleImage.width;bounds.height=this.handleImage.height;return new mxImageShape(bounds,this.handleImage.src);}else{var shape=new mxRectangleShape(bounds,fillColor||mxConstants.HANDLE_FILLCOLOR,mxConstants.HANDLE_STROKECOLOR);shape.crisp=this.crisp;return shape;}};mxVertexHandler.prototype.moveSizerTo=function(shape,x,y){if(shape!=null){shape.bounds.x=x-shape.bounds.width/2;shape.bounds.y=y-shape.bounds.height/2;shape.redraw();}};mxVertexHandler.prototype.getHandleForEvent=function(me){if(me.isSource(this.labelShape)){return mxEvent.LABEL_HANDLE;}if(this.sizers!=null){var tol=this.tolerance;var hit=(this.allowHandleBoundsCheck&&(mxClient.IS_IE||tol>0))?new mxRectangle(me.getGraphX()-tol,me.getGraphY()-tol,2*tol,2*tol):null;for(var i=0;i0||me.getState()==this.state)){var handle=this.getHandleForEvent(me);if(handle!=null){this.start(me.getX(),me.getY(),handle);me.consume();}}};mxVertexHandler.prototype.start=function(x,y,index){var pt=mxUtils.convertPoint(this.graph.container,x,y);this.startX=pt.x;this.startY=pt.y;this.index=index;this.selectionBorder.node.style.visibility='hidden';this.preview=this.createSelectionShape(this.bounds);if(this.state.text!=null&&this.state.text.node.parentNode==this.graph.container){this.preview.dialect=mxConstants.DIALECT_STRICTHTML;this.preview.init(this.graph.container);}else{this.preview.dialect=(this.graph.dialect!=mxConstants.DIALECT_SVG)?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;this.preview.init(this.graph.view.getOverlayPane());}};mxVertexHandler.prototype.mouseMove=function(sender,me){if(!me.isConsumed()&&this.index!=null){var point=new mxPoint(me.getGraphX(),me.getGraphY());var gridEnabled=this.graph.isGridEnabledEvent(me.getEvent());var scale=this.graph.getView().scale;if(this.index==mxEvent.LABEL_HANDLE){if(gridEnabled){point.x=this.graph.snap(point.x/scale)*scale;point.y=this.graph.snap(point.y/scale)*scale;}this.moveSizerTo(this.sizers[this.sizers.length-1],point.x,point.y);me.consume();}else if(this.index!=null){var dx=point.x-this.startX;var dy=point.y-this.startY;var tr=this.graph.view.translate;this.bounds=this.union(this.state,dx,dy,this.index,gridEnabled,scale,tr);this.drawPreview();me.consume();}}else if(this.getHandleForEvent(me)!=null){me.consume(false);}};mxVertexHandler.prototype.mouseUp=function(sender,me){if(!me.isConsumed()&&this.index!=null&&this.state!=null){var point=new mxPoint(me.getGraphX(),me.getGraphY());var scale=this.graph.getView().scale;var gridEnabled=this.graph.isGridEnabledEvent(me.getEvent());var dx=(point.x-this.startX)/scale;var dy=(point.y-this.startY)/scale;this.resizeCell(this.state.cell,dx,dy,this.index,gridEnabled);this.reset();me.consume();}};mxVertexHandler.prototype.reset=function(){this.index=null;if(this.preview!=null){this.preview.destroy();this.preview=null;}if(this.selectionBorder!=null){this.selectionBorder.node.style.visibility='visible';this.bounds=new mxRectangle(this.state.x,this.state.y,this.state.width,this.state.height);this.drawPreview();}};mxVertexHandler.prototype.resizeCell=function(cell,dx,dy,index,gridEnabled){var geo=this.graph.model.getGeometry(cell);if(index==mxEvent.LABEL_HANDLE){var scale=this.graph.view.scale;dx=(this.labelShape.bounds.getCenterX()-this.startX)/scale;dy=(this.labelShape.bounds.getCenterY()-this.startY)/scale;geo=geo.clone();if(geo.offset==null){geo.offset=new mxPoint(dx,dy);}else{geo.offset.x+=dx;geo.offset.y+=dy;}this.graph.model.setGeometry(cell,geo);}else{var bounds=this.union(geo,dx,dy,index,gridEnabled,1,new mxPoint(0,0));this.graph.resizeCell(cell,bounds);}};mxVertexHandler.prototype.union=function(bounds,dx,dy,index,gridEnabled,scale,tr){if(this.singleSizer){var x=bounds.x+bounds.width+dx;var y=bounds.y+bounds.height+dy;if(gridEnabled){x=this.graph.snap(x/scale)*scale;y=this.graph.snap(y/scale)*scale;}var rect=new mxRectangle(bounds.x,bounds.y,0,0);rect.add(new mxRectangle(x,y,0,0));return rect;}else{var left=bounds.x-tr.x*scale;var right=left+bounds.width;var top=bounds.y-tr.y*scale;var bottom=top+bounds.height;if(index>4 ){bottom=bottom+dy;if(gridEnabled){bottom=this.graph.snap(bottom/scale)*scale;}}else if(index<3 ){top=top+dy;if(gridEnabled){top=this.graph.snap(top/scale)*scale;}}if(index==0||index==3||index==5 ){left+=dx;if(gridEnabled){left=this.graph.snap(left/scale)*scale;}}else if(index==2||index==4||index==7 ){right+=dx;if(gridEnabled){right=this.graph.snap(right/scale)*scale;}}var width=right-left;var height=bottom-top;if(width<0){left+=width;width=Math.abs(width);}if(height<0){top+=height;height=Math.abs(height);}return new mxRectangle(left+tr.x*scale,top+tr.y*scale,width,height);}};mxVertexHandler.prototype.redraw=function(){this.bounds=new mxRectangle(this.state.x,this.state.y,this.state.width,this.state.height);if(this.sizers!=null){var s=this.state;var r=s.x+s.width;var b=s.y+s.height;if(this.singleSizer){this.moveSizerTo(this.sizers[0],r,b);}else{var cx=s.x+s.width/2;var cy=s.y+s.height/2;if(this.sizers.length>1){this.moveSizerTo(this.sizers[0],s.x,s.y);this.moveSizerTo(this.sizers[1],cx,s.y);this.moveSizerTo(this.sizers[2],r,s.y);this.moveSizerTo(this.sizers[3],s.x,cy);this.moveSizerTo(this.sizers[4],r,cy);this.moveSizerTo(this.sizers[5],s.x,b);this.moveSizerTo(this.sizers[6],cx,b);this.moveSizerTo(this.sizers[7],r,b);this.moveSizerTo(this.sizers[8],cx+s.absoluteOffset.x,cy+s.absoluteOffset.y);}else if(this.state.width>=2&&this.state.height>=2){this.moveSizerTo(this.sizers[0],cx+s.absoluteOffset.x,cy+s.absoluteOffset.y);}else{this.moveSizerTo(this.sizers[0],s.x,s.y);}}}this.drawPreview();};mxVertexHandler.prototype.drawPreview=function(){if(this.preview!=null){this.preview.bounds=this.bounds;if(this.preview.node.parentNode==this.graph.container){this.preview.bounds.width=Math.max(0,this.preview.bounds.width-1);this.preview.bounds.height=Math.max(0,this.preview.bounds.height-1);}this.preview.redraw();}this.selectionBorder.bounds=this.bounds;this.selectionBorder.redraw();};mxVertexHandler.prototype.destroy=function(){if(this.preview!=null){this.preview.destroy();this.preview=null;}this.selectionBorder.destroy();this.selectionBorder=null;this.labelShape=null;if(this.sizers!=null){for(var i=0;i0))?new mxRectangle(me.getGraphX()-tol,me.getGraphY()-tol,2*tol,2*tol):null;for(var i=0;i0){function snapToPoint(pt){if(pt!=null){var x=pt.x;if(Math.abs(point.x-x)0){this.graph.validationAlert(this.error);}}else if(this.isLabel){this.moveLabel(this.state,this.label.x,this.label.y);}else if(this.isSource||this.isTarget){var terminal=null;if(this.constraintHandler.currentConstraint!=null&&this.constraintHandler.currentFocus!=null){terminal=this.constraintHandler.currentFocus.cell;}if(terminal==null&&this.marker.hasValidState()){terminal=this.marker.validState.cell;}if(terminal!=null){edge=this.connect(edge,terminal,this.isSource,this.graph.isCloneEvent(me.getEvent())&&this.cloneEnabled&&this.graph.isCellsCloneable(),me);}else if(this.graph.isAllowDanglingEdges()){var pt=this.graph.getPointForEvent(me.getEvent(),false);var pstate=this.graph.getView().getState(this.graph.getModel().getParent(edge));if(pstate!=null){pt.x-=pstate.origin.x;pt.y-=pstate.origin.y;}pt.x-=this.graph.panDx/this.graph.view.scale;pt.y-=this.graph.panDy/this.graph.view.scale;this.changeTerminalPoint(edge,pt,this.isSource);}}else if(this.active){this.changePoints(edge,this.points);}else{this.graph.getView().invalidate(this.state.cell);this.graph.getView().revalidate(this.state.cell);}}if(this.marker!=null){this.reset();if(edge!=this.state.cell){this.graph.setSelectionCell(edge);}}me.consume();}};mxEdgeHandler.prototype.reset=function(){this.error=null;this.index=null;this.label=null;this.points=null;this.active=false;this.isLabel=false;this.isSource=false;this.isTarget=false;this.marker.reset();this.constraintHandler.reset();this.setPreviewColor(mxConstants.EDGE_SELECTION_COLOR);this.redraw();};mxEdgeHandler.prototype.setPreviewColor=function(color){if(this.shape!=null&&this.shape.node!=null){if(this.shape.dialect==mxConstants.DIALECT_SVG){this.shape.innerNode.setAttribute('stroke',color);}else{this.shape.node.setAttribute('strokecolor',color);}}};mxEdgeHandler.prototype.convertPoint=function(point,gridEnabled){var scale=this.graph.getView().getScale();var tr=this.graph.getView().getTranslate();if(gridEnabled){point.x=this.graph.snap(point.x);point.y=this.graph.snap(point.y);}point.x=Math.round(point.x/scale-tr.x);point.y=Math.round(point.y/scale-tr.y);var pstate=this.graph.getView().getState(this.graph.getModel().getParent(this.state.cell));if(pstate!=null){point.x-=pstate.origin.x;point.y-=pstate.origin.y;}return point;};mxEdgeHandler.prototype.moveLabel=function(edgeState,x,y){var model=this.graph.getModel();var geometry=model.getGeometry(edgeState.cell);if(geometry!=null){geometry=geometry.clone();var pt=this.graph.getView().getRelativePoint(edgeState,x,y);geometry.x=pt.x;geometry.y=pt.y;var scale=this.graph.getView().scale;geometry.offset=new mxPoint(0,0);var pt=this.graph.view.getPoint(edgeState,geometry);geometry.offset=new mxPoint((x-pt.x)/scale,(y-pt.y)/scale);model.setGeometry(edgeState.cell,geometry);}};mxEdgeHandler.prototype.connect=function(edge,terminal,isSource,isClone,me){var model=this.graph.getModel();var parent=model.getParent(edge);model.beginUpdate();try{if(isClone){var clone=edge.clone();model.add(parent,clone,model.getChildCount(parent));var other=model.getTerminal(edge,!isSource);this.graph.connectCell(clone,other,!isSource);edge=clone;}var constraint=this.constraintHandler.currentConstraint;if(constraint==null){constraint=new mxConnectionConstraint();}this.graph.connectCell(edge,terminal,isSource,constraint);}finally{model.endUpdate();}return edge;};mxEdgeHandler.prototype.changeTerminalPoint=function(edge,point,isSource){var model=this.graph.getModel();var geo=model.getGeometry(edge);if(geo!=null){model.beginUpdate();try{geo=geo.clone();geo.setTerminalPoint(point,isSource);model.setGeometry(edge,geo);this.graph.connectCell(edge,null,isSource,new mxConnectionConstraint());}finally{model.endUpdate();}}};mxEdgeHandler.prototype.changePoints=function(edge,points){var model=this.graph.getModel();var geo=model.getGeometry(edge);if(geo!=null){geo=geo.clone();geo.points=points;model.setGeometry(edge,geo);}};mxEdgeHandler.prototype.addPoint=function(state,evt){var geo=this.graph.getCellGeometry(state.cell);if(geo!=null){geo=geo.clone();var pt=mxUtils.convertPoint(this.graph.container,mxEvent.getClientX(evt),mxEvent.getClientY(evt));var index=mxUtils.findNearestSegment(state,pt.x,pt.y);var gridEnabled=this.graph.isGridEnabledEvent(evt);this.convertPoint(pt,gridEnabled);if(geo.points==null){geo.points=[pt];}else{geo.points.splice(index,0,pt);}this.graph.getModel().setGeometry(state.cell,geo);this.destroy();this.init();mxEvent.consume(evt);}};mxEdgeHandler.prototype.removePoint=function(state,index){if(index>0&&index0&&this.graph.isLabelMovable(cell)){this.labelShape.node.style.visibility='visible';}else{this.labelShape.node.style.visibility='hidden';}if(this.bends!=null&&this.bends.length>0){var n=this.abspoints.length-1;var p0=this.abspoints[0];var x0=this.abspoints[0].x;var y0=this.abspoints[0].y;var b=this.bends[0].bounds;this.bends[0].bounds=new mxRectangle(x0-b.width/2,y0-b.height/2,b.width,b.height);this.bends[0].fill=this.getHandleFillColor(0);this.bends[0].reconfigure();this.bends[0].redraw();var pe=this.abspoints[n];var xn=this.abspoints[n].x;var yn=this.abspoints[n].y;var bn=this.bends.length-1;b=this.bends[bn].bounds;this.bends[bn].bounds=new mxRectangle(xn-b.width/2,yn-b.height/2,b.width,b.height);this.bends[bn].fill=this.getHandleFillColor(bn);this.bends[bn].reconfigure();this.bends[bn].redraw();this.redrawInnerBends(p0,pe);}this.drawPreview();};mxEdgeHandler.prototype.redrawInnerBends=function(p0,pe){var g=this.graph.getModel().getGeometry(this.state.cell);var pts=g.points;if(pts!=null){if(this.points==null){this.points=[];}for(var i=1;i1){for(var i=0;i1){var pt0=pts[0];var pt1=pts[1];for(var i=2;i0){if(this.div==null){this.init();}var origin=mxUtils.getScrollOrigin();this.div.style.left=(x+origin.x)+'px';this.div.style.top=(y+mxConstants.TOOLTIP_VERTICAL_OFFSET+origin.y)+'px';if(!mxUtils.isNode(tip)){this.div.innerHTML=tip.replace(/\n/g,'
');}else{this.div.innerHTML='';this.div.appendChild(tip);}this.div.style.visibility='';mxUtils.fit(this.div);}};mxTooltipHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);mxEvent.release(this.div);if(this.div!=null&&this.div.parentNode!=null){this.div.parentNode.removeChild(this.div);}this.div=null;};function mxCellTracker(graph,color,funct){mxCellMarker.call(this,graph,color);this.graph.addMouseListener(this);if(funct!=null){this.getCell=funct;}if(mxClient.IS_IE){mxEvent.addListener(window,'unload',mxUtils.bind(this,function(){this.destroy();}));}};mxCellTracker.prototype=new mxCellMarker();mxCellTracker.prototype.constructor=mxCellTracker;mxCellTracker.prototype.mouseDown=function(sender,me){};mxCellTracker.prototype.mouseMove=function(sender,me){if(this.isEnabled()){this.process(me);}};mxCellTracker.prototype.mouseUp=function(sender,me){this.reset();};mxCellTracker.prototype.destroy=function(){if(!this.destroyed){this.destroyed=true;this.graph.removeMouseListener(this);mxCellMarker.prototype.destroy.apply(this);}};function mxCellHighlight(graph,highlightColor,strokeWidth){if(graph!=null){this.graph=graph;this.highlightColor=(highlightColor!=null)?highlightColor:mxConstants.DEFAULT_VALID_COLOR;this.strokeWidth=(strokeWidth!=null)?strokeWidth:mxConstants.HIGHLIGHT_STROKEWIDTH;this.resetHandler=mxUtils.bind(this,function(sender){this.hide();});this.graph.getView().addListener(mxEvent.SCALE,this.resetHandler);this.graph.getView().addListener(mxEvent.TRANSLATE,this.resetHandler);this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE,this.resetHandler);this.graph.getView().addListener(mxEvent.DOWN,this.resetHandler);this.graph.getView().addListener(mxEvent.UP,this.resetHandler);this.graph.getModel().addListener(mxEvent.CHANGE,this.resetHandler);}};mxCellHighlight.prototype.keepOnTop=false;mxCellHighlight.prototype.graph=true;mxCellHighlight.prototype.state=null;mxCellHighlight.prototype.spacing=2;mxCellHighlight.prototype.resetHandler=null;mxCellHighlight.prototype.setHighlightColor=function(color){this.highlightColor=color;if(this.shape!=null){if(this.shape.dialect==mxConstants.DIALECT_SVG){this.shape.innerNode.setAttribute('stroke',color);}else if(this.shape.dialect==mxConstants.DIALECT_VML){this.shape.node.setAttribute('strokecolor',color);}}};mxCellHighlight.prototype.drawHighlight=function(state){var shape=this.createShape(state);shape.redraw();if(!this.keepOnTop&&shape.node.parentNode.firstChild!=shape.node){shape.node.parentNode.insertBefore(shape.node,shape.node.parentNode.firstChild);}if(this.graph.model.isEdge(state.cell)){mxUtils.repaintGraph(this.graph,shape.points[0]);}return shape;};mxCellHighlight.prototype.createShape=function(state){var shape=null;if(this.graph.model.isEdge(state.cell)){shape=new mxPolyline(state.absolutePoints,this.highlightColor,this.strokeWidth);}else{shape=new mxRectangleShape(new mxRectangle(state.x-this.spacing,state.y-this.spacing,state.width+2*this.spacing,state.height+2*this.spacing),null,this.highlightColor,this.strokeWidth);}shape.dialect=(this.graph.dialect!=mxConstants.DIALECT_SVG)?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;shape.init(this.graph.getView().getOverlayPane());mxEvent.redirectMouseEvents(shape.node,this.graph,state);if(state.shape!=null){shape.setCursor(state.shape.getCursor());}if(shape.dialect==mxConstants.DIALECT_SVG){shape.node.setAttribute('style','pointer-events:none;');}else{shape.node.style.background='';}return shape;};mxCellHighlight.prototype.hide=function(){this.highlight(null);};mxCellHighlight.prototype.highlight=function(state){if(this.state!=state){if(this.shape!=null){this.shape.destroy();this.shape=null;}if(state!=null){this.shape=this.drawHighlight(state);}this.state=state;}};mxCellHighlight.prototype.destroy=function(){this.graph.getView().removeListener(this.resetHandler);this.graph.getModel().removeListener(this.resetHandler);if(this.shape!=null){this.shape.destroy();this.shape=null;}};function mxDefaultKeyHandler(editor){if(editor!=null){this.editor=editor;this.handler=new mxKeyHandler(editor.graph);var old=this.handler.escape;this.handler.escape=function(evt){old.apply(this,arguments);editor.hideProperties();editor.fireEvent(new mxEventObject(mxEvent.ESCAPE,'event',evt));};}};mxDefaultKeyHandler.prototype.editor=null;mxDefaultKeyHandler.prototype.handler=null;mxDefaultKeyHandler.prototype.bindAction=function(code,action,control){var keyHandler=mxUtils.bind(this,function(){this.editor.execute(action);});if(control){this.handler.bindControlKey(code,keyHandler);}else{this.handler.bindKey(code,keyHandler);}};mxDefaultKeyHandler.prototype.destroy=function(){this.handler.destroy();this.handler=null;};function mxDefaultPopupMenu(config){this.config=config;};mxDefaultPopupMenu.prototype.imageBasePath=null;mxDefaultPopupMenu.prototype.config=null;mxDefaultPopupMenu.prototype.createMenu=function(editor,menu,cell,evt){if(this.config!=null){var conditions=this.createConditions(editor,cell,evt);var item=this.config.firstChild;this.addItems(editor,menu,cell,evt,conditions,item,null);}};mxDefaultPopupMenu.prototype.addItems=function(editor,menu,cell,evt,conditions,item,parent){var addSeparator=false;while(item!=null){if(item.nodeName=='add'){var condition=item.getAttribute('if');if(condition==null||conditions[condition]){var as=item.getAttribute('as');as=mxResources.get(as)||as;var funct=mxUtils.eval(mxUtils.getTextContent(item));var action=item.getAttribute('action');var icon=item.getAttribute('icon');var iconCls=item.getAttribute('iconCls');if(addSeparator){menu.addSeparator(parent);addSeparator=false;}if(icon!=null&&this.imageBasePath){icon=this.imageBasePath+icon;}var row=this.addAction(menu,editor,as,icon,funct,action,cell,parent,iconCls);this.addItems(editor,menu,cell,evt,conditions,item.firstChild,row);}}else if(item.nodeName=='separator'){addSeparator=true;}item=item.nextSibling;}};mxDefaultPopupMenu.prototype.addAction=function(menu,editor,lab,icon,funct,action,cell,parent,iconCls){var clickHandler=function(evt){if(typeof(funct)=='function'){funct.call(editor,editor,cell,evt);}if(action!=null){editor.execute(action,cell,evt);}};return menu.addItem(lab,icon,clickHandler,parent,iconCls);};mxDefaultPopupMenu.prototype.createConditions=function(editor,cell,evt){var model=editor.graph.getModel();var childCount=model.getChildCount(cell);var conditions=[];conditions['nocell']=cell==null;conditions['ncells']=editor.graph.getSelectionCount()>1;conditions['notRoot']=model.getRoot()!=model.getParent(editor.graph.getDefaultParent());conditions['cell']=cell!=null;var isCell=cell!=null&&editor.graph.getSelectionCount()==1;conditions['nonEmpty']=isCell&&childCount>0;conditions['expandable']=isCell&&editor.graph.isCellFoldable(cell,false);conditions['collapsable']=isCell&&editor.graph.isCellFoldable(cell,true);conditions['validRoot']=isCell&&editor.graph.isValidRoot(cell);conditions['emptyValidRoot']=conditions['validRoot']&&childCount==0;conditions['swimlane']=isCell&&editor.graph.isSwimlane(cell);var condNodes=this.config.getElementsByTagName('condition');for(var i=0;i0){this.editor.execute(action);}});return this.toolbar.addItem(title,icon,clickHandler,pressed);};mxDefaultToolbar.prototype.addSeparator=function(icon){icon=icon||mxClient.imageBasePath+'/separator.gif';this.toolbar.addSeparator(icon);};mxDefaultToolbar.prototype.addCombo=function(){return this.toolbar.addCombo();};mxDefaultToolbar.prototype.addActionCombo=function(title){return this.toolbar.addActionCombo(title);};mxDefaultToolbar.prototype.addActionOption=function(combo,title,action){var clickHandler=mxUtils.bind(this,function(){this.editor.execute(action);});this.addOption(combo,title,clickHandler);};mxDefaultToolbar.prototype.addOption=function(combo,title,value){return this.toolbar.addOption(combo,title,value);};mxDefaultToolbar.prototype.addMode=function(title,icon,mode,pressed,funct){var clickHandler=mxUtils.bind(this,function(){this.editor.setMode(mode);if(funct!=null){funct(this.editor);}});return this.toolbar.addSwitchMode(title,icon,clickHandler,pressed);};mxDefaultToolbar.prototype.addPrototype=function(title,icon,ptype,pressed,insert,toggle){var factory=function(){if(typeof(ptype)=='function'){return ptype();}else if(ptype!=null){return ptype.clone();}return null;};var clickHandler=mxUtils.bind(this,function(evt,cell){if(typeof(insert)=='function'){insert(this.editor,factory(),evt,cell);}else{this.drop(factory(),evt,cell);}this.toolbar.resetMode();mxEvent.consume(evt);});var img=this.toolbar.addMode(title,icon,clickHandler,pressed,null,toggle);var dropHandler=function(graph,evt,cell){clickHandler(evt,cell);};this.installDropHandler(img,dropHandler);return img;};mxDefaultToolbar.prototype.drop=function(vertex,evt,target){var graph=this.editor.graph;var model=graph.getModel();if(target==null||model.isEdge(target)||!this.connectOnDrop||!graph.isCellConnectable(target)){while(target!=null&&!graph.isValidDropTarget(target,[vertex],evt)){target=model.getParent(target);}this.insert(vertex,evt,target);}else{this.connect(vertex,evt,target);}};mxDefaultToolbar.prototype.insert=function(vertex,evt,target){var graph=this.editor.graph;if(graph.canImportCell(vertex)){var x=mxEvent.getClientX(evt);var y=mxEvent.getClientY(evt);var pt=mxUtils.convertPoint(graph.container,x,y);if(graph.isSplitEnabled()&&graph.isSplitTarget(target,[vertex],evt)){return graph.splitEdge(target,[vertex],null,pt.x,pt.y);}else{return this.editor.addVertex(target,vertex,pt.x,pt.y);}}return null;};mxDefaultToolbar.prototype.connect=function(vertex,evt,source){var graph=this.editor.graph;var model=graph.getModel();if(source!=null&&graph.isCellConnectable(vertex)&&graph.isEdgeValid(null,source,vertex)){var edge=null;model.beginUpdate();try{var geo=model.getGeometry(source);var g=model.getGeometry(vertex).clone();g.x=geo.x+(geo.width-g.width)/2;g.y=geo.y+(geo.height-g.height)/2;var step=this.spacing*graph.gridSize;var dist=model.getDirectedEdgeCount(source,true)*20;if(this.editor.horizontalFlow){g.x+=(g.width+geo.width)/2+step+dist;}else{g.y+=(g.height+geo.height)/2+step+dist;}vertex.setGeometry(g);var parent=model.getParent(source);graph.addCell(vertex,parent);graph.constrainChild(vertex);edge=this.editor.createEdge(source,vertex);if(model.getGeometry(edge)==null){var edgeGeometry=new mxGeometry();edgeGeometry.relative=true;model.setGeometry(edge,edgeGeometry);}graph.addEdge(edge,parent,source,vertex);}finally{model.endUpdate();}graph.setSelectionCells([vertex,edge]);graph.scrollCellToVisible(vertex);}};mxDefaultToolbar.prototype.installDropHandler=function(img,dropHandler){var sprite=document.createElement('img');sprite.setAttribute('src',img.getAttribute('src'));var loader=mxUtils.bind(this,function(evt){sprite.style.width=(2*img.offsetWidth)+'px';sprite.style.height=(2*img.offsetHeight)+'px';mxUtils.makeDraggable(img,this.editor.graph,dropHandler,sprite);mxEvent.removeListener(sprite,'load',loader);});if(mxClient.IS_IE){loader();}else{mxEvent.addListener(sprite,'load',loader);}};mxDefaultToolbar.prototype.destroy=function(){if(this.resetHandler!=null){this.editor.graph.removeListener('dblclick',this.resetHandler);this.editor.removeListener('escape',this.resetHandler);this.resetHandler=null;}if(this.toolbar!=null){this.toolbar.destroy();this.toolbar=null;}};function mxEditor(config){this.actions=[];this.addActions();if(document.body!=null){this.cycleAttributeValues=[];this.popupHandler=new mxDefaultPopupMenu();this.undoManager=new mxUndoManager();this.graph=this.createGraph();this.toolbar=this.createToolbar();this.keyHandler=new mxDefaultKeyHandler(this);this.configure(config);this.graph.swimlaneIndicatorColorAttribute=this.cycleAttributeName;if(!mxClient.IS_LOCAL&&this.urlInit!=null){this.createSession();}if(this.onInit!=null){this.onInit();}if(mxClient.IS_IE){mxEvent.addListener(window,'unload',mxUtils.bind(this,function(){this.destroy();}));}}};if(mxLoadResources){mxResources.add(mxClient.basePath+'/resources/editor');}mxEditor.prototype=new mxEventSource();mxEditor.prototype.constructor=mxEditor;mxEditor.prototype.askZoomResource=(mxClient.language!='none')?'askZoom':'';mxEditor.prototype.lastSavedResource=(mxClient.language!='none')?'lastSaved':'';mxEditor.prototype.currentFileResource=(mxClient.language!='none')?'currentFile':'';mxEditor.prototype.propertiesResource=(mxClient.language!='none')?'properties':'';mxEditor.prototype.tasksResource=(mxClient.language!='none')?'tasks':'';mxEditor.prototype.helpResource=(mxClient.language!='none')?'help':'';mxEditor.prototype.outlineResource=(mxClient.language!='none')?'outline':'';mxEditor.prototype.outline=null;mxEditor.prototype.graph=null;mxEditor.prototype.graphRenderHint=null;mxEditor.prototype.toolbar=null;mxEditor.prototype.status=null;mxEditor.prototype.popupHandler=null;mxEditor.prototype.undoManager=null;mxEditor.prototype.keyHandler=null;mxEditor.prototype.actions=null;mxEditor.prototype.dblClickAction='edit';mxEditor.prototype.swimlaneRequired=false;mxEditor.prototype.disableContextMenu=true;mxEditor.prototype.insertFunction=null;mxEditor.prototype.forcedInserting=false;mxEditor.prototype.templates=null;mxEditor.prototype.defaultEdge=null;mxEditor.prototype.defaultEdgeStyle=null;mxEditor.prototype.defaultGroup=null;mxEditor.prototype.groupBorderSize=null;mxEditor.prototype.filename=null;mxEditor.prototype.linefeed=' ';mxEditor.prototype.postParameterName='xml';mxEditor.prototype.escapePostData=true;mxEditor.prototype.urlPost=null;mxEditor.prototype.urlImage=null;mxEditor.prototype.urlInit=null;mxEditor.prototype.urlNotify=null;mxEditor.prototype.urlPoll=null;mxEditor.prototype.horizontalFlow=false;mxEditor.prototype.layoutDiagram=false;mxEditor.prototype.swimlaneSpacing=0;mxEditor.prototype.maintainSwimlanes=false;mxEditor.prototype.layoutSwimlanes=false;mxEditor.prototype.cycleAttributeValues=null;mxEditor.prototype.cycleAttributeIndex=0;mxEditor.prototype.cycleAttributeName='fillColor';mxEditor.prototype.tasks=null;mxEditor.prototype.tasksWindowImage=null;mxEditor.prototype.tasksTop=20;mxEditor.prototype.help=null;mxEditor.prototype.helpWindowImage=null;mxEditor.prototype.urlHelp=null;mxEditor.prototype.helpWidth=300;mxEditor.prototype.helpHeight=260;mxEditor.prototype.propertiesWidth=240;mxEditor.prototype.propertiesHeight=null;mxEditor.prototype.movePropertiesDialog=false;mxEditor.prototype.validating=false;mxEditor.prototype.modified=false;mxEditor.prototype.isModified=function(){return this.modified;};mxEditor.prototype.setModified=function(value){this.modified=value;};mxEditor.prototype.addActions=function(){this.addAction('save',function(editor){editor.save();});this.addAction('print',function(editor){var preview=new mxPrintPreview(editor.graph,1);preview.open();});this.addAction('show',function(editor){mxUtils.show(editor.graph,null,10,10);});this.addAction('exportImage',function(editor){var url=editor.getUrlImage();if(url==null||mxClient.IS_LOCAL){editor.execute('show');}else{var node=mxUtils.getViewXml(editor.graph,1);var xml=mxUtils.getXml(node,'\n');mxUtils.submit(url,editor.postParameterName+'='+encodeURIComponent(xml),document,'_blank');}});this.addAction('refresh',function(editor){editor.graph.refresh();});this.addAction('cut',function(editor){if(editor.graph.isEnabled()){mxClipboard.cut(editor.graph);}});this.addAction('copy',function(editor){if(editor.graph.isEnabled()){mxClipboard.copy(editor.graph);}});this.addAction('paste',function(editor){if(editor.graph.isEnabled()){mxClipboard.paste(editor.graph);}});this.addAction('delete',function(editor){if(editor.graph.isEnabled()){editor.graph.removeCells();}});this.addAction('group',function(editor){if(editor.graph.isEnabled()){editor.graph.setSelectionCell(editor.groupCells());}});this.addAction('ungroup',function(editor){if(editor.graph.isEnabled()){editor.graph.setSelectionCells(editor.graph.ungroupCells());}});this.addAction('removeFromParent',function(editor){if(editor.graph.isEnabled()){editor.graph.removeCellsFromParent();}});this.addAction('undo',function(editor){if(editor.graph.isEnabled()){editor.undo();}});this.addAction('redo',function(editor){if(editor.graph.isEnabled()){editor.redo();}});this.addAction('zoomIn',function(editor){editor.graph.zoomIn();});this.addAction('zoomOut',function(editor){editor.graph.zoomOut();});this.addAction('actualSize',function(editor){editor.graph.zoomActual();});this.addAction('fit',function(editor){editor.graph.fit();});this.addAction('showProperties',function(editor,cell){editor.showProperties(cell);});this.addAction('selectAll',function(editor){if(editor.graph.isEnabled()){editor.graph.selectAll();}});this.addAction('selectNone',function(editor){if(editor.graph.isEnabled()){editor.graph.clearSelection();}});this.addAction('selectVertices',function(editor){if(editor.graph.isEnabled()){editor.graph.selectVertices();}});this.addAction('selectEdges',function(editor){if(editor.graph.isEnabled()){editor.graph.selectEdges();}});this.addAction('edit',function(editor,cell){if(editor.graph.isEnabled()&&editor.graph.isCellEditable(cell)){editor.graph.startEditingAtCell(cell);}});this.addAction('toBack',function(editor,cell){if(editor.graph.isEnabled()){editor.graph.orderCells(true);}});this.addAction('toFront',function(editor,cell){if(editor.graph.isEnabled()){editor.graph.orderCells(false);}});this.addAction('enterGroup',function(editor,cell){editor.graph.enterGroup(cell);});this.addAction('exitGroup',function(editor){editor.graph.exitGroup();});this.addAction('home',function(editor){editor.graph.home();});this.addAction('selectPrevious',function(editor){if(editor.graph.isEnabled()){editor.graph.selectPreviousCell();}});this.addAction('selectNext',function(editor){if(editor.graph.isEnabled()){editor.graph.selectNextCell();}});this.addAction('selectParent',function(editor){if(editor.graph.isEnabled()){editor.graph.selectParentCell();}});this.addAction('selectChild',function(editor){if(editor.graph.isEnabled()){editor.graph.selectChildCell();}});this.addAction('collapse',function(editor){if(editor.graph.isEnabled()){editor.graph.foldCells(true);}});this.addAction('collapseAll',function(editor){if(editor.graph.isEnabled()){var cells=editor.graph.getChildVertices();editor.graph.foldCells(true,false,cells);}});this.addAction('expand',function(editor){if(editor.graph.isEnabled()){editor.graph.foldCells(false);}});this.addAction('expandAll',function(editor){if(editor.graph.isEnabled()){var cells=editor.graph.getChildVertices();editor.graph.foldCells(false,false,cells);}});this.addAction('bold',function(editor){if(editor.graph.isEnabled()){editor.graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE,mxConstants.FONT_BOLD);}});this.addAction('italic',function(editor){if(editor.graph.isEnabled()){editor.graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE,mxConstants.FONT_ITALIC);}});this.addAction('underline',function(editor){if(editor.graph.isEnabled()){editor.graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE,mxConstants.FONT_UNDERLINE);}});this.addAction('shadow',function(editor){if(editor.graph.isEnabled()){editor.graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE,mxConstants.FONT_SHADOW);}});this.addAction('alignCellsLeft',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_LEFT);}});this.addAction('alignCellsCenter',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_CENTER);}});this.addAction('alignCellsRight',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_RIGHT);}});this.addAction('alignCellsTop',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_TOP);}});this.addAction('alignCellsMiddle',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_MIDDLE);}});this.addAction('alignCellsBottom',function(editor){if(editor.graph.isEnabled()){editor.graph.alignCells(mxConstants.ALIGN_BOTTOM);}});this.addAction('alignFontLeft',function(editor){editor.graph.setCellStyles(mxConstants.STYLE_ALIGN,mxConstants.ALIGN_LEFT);});this.addAction('alignFontCenter',function(editor){if(editor.graph.isEnabled()){editor.graph.setCellStyles(mxConstants.STYLE_ALIGN,mxConstants.ALIGN_CENTER);}});this.addAction('alignFontRight',function(editor){if(editor.graph.isEnabled()){editor.graph.setCellStyles(mxConstants.STYLE_ALIGN,mxConstants.ALIGN_RIGHT);}});this.addAction('alignFontTop',function(editor){if(editor.graph.isEnabled()){editor.graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN,mxConstants.ALIGN_TOP);}});this.addAction('alignFontMiddle',function(editor){if(editor.graph.isEnabled()){editor.graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN,mxConstants.ALIGN_MIDDLE);}});this.addAction('alignFontBottom',function(editor){if(editor.graph.isEnabled()){editor.graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN,mxConstants.ALIGN_BOTTOM);}});this.addAction('zoom',function(editor){var current=editor.graph.getView().scale*100;var scale=parseFloat(mxUtils.prompt(mxResources.get(editor.askZoomResource)||editor.askZoomResource,current))/100;if(!isNaN(scale)){editor.graph.getView().setScale(scale);}});this.addAction('toggleTasks',function(editor){if(editor.tasks!=null){editor.tasks.setVisible(!editor.tasks.isVisible());}else{editor.showTasks();}});this.addAction('toggleHelp',function(editor){if(editor.help!=null){editor.help.setVisible(!editor.help.isVisible());}else{editor.showHelp();}});this.addAction('toggleOutline',function(editor){if(editor.outline==null){editor.showOutline();}else{editor.outline.setVisible(!editor.outline.isVisible());}});this.addAction('toggleConsole',function(editor){mxLog.setVisible(!mxLog.isVisible());});};mxEditor.prototype.createSession=function(){var session=null;var sessionChanged=mxUtils.bind(this,function(session){this.fireEvent(new mxEventObject(mxEvent.SESSION,'session',session));});session=this.connect(this.urlInit,this.urlPoll,this.urlNotify,sessionChanged);};mxEditor.prototype.configure=function(node){if(node!=null){var dec=new mxCodec(node.ownerDocument);dec.decode(node,this);this.resetHistory();}};mxEditor.prototype.resetFirstTime=function(){document.cookie='mxgraph=seen; expires=Fri, 27 Jul 2001 02:47:11 UTC; path=/';};mxEditor.prototype.resetHistory=function(){this.lastSnapshot=new Date().getTime();this.undoManager.clear();this.ignoredChanges=0;this.setModified(false);};mxEditor.prototype.addAction=function(actionname,funct){this.actions[actionname]=funct;};mxEditor.prototype.execute=function(actionname,cell,evt){var action=this.actions[actionname];if(action!=null){try{var args=arguments;args[0]=this;action.apply(this,args);}catch(e){mxUtils.error('Cannot execute '+actionname+': '+e.message,280,true);throw e;}}else{mxUtils.error('Cannot find action '+actionname,280,true);}};mxEditor.prototype.addTemplate=function(name,template){this.templates[name]=template;};mxEditor.prototype.getTemplate=function(name){return this.templates[name];};mxEditor.prototype.createGraph=function(){var graph=new mxGraph(null,null,this.graphRenderHint);graph.setTooltips(true);graph.setPanning(true);this.installDblClickHandler(graph);this.installUndoHandler(graph);this.installDrillHandler(graph);this.installChangeHandler(graph);this.installInsertHandler(graph);graph.panningHandler.factoryMethod=mxUtils.bind(this,function(menu,cell,evt){return this.createPopupMenu(menu,cell,evt);});graph.connectionHandler.factoryMethod=mxUtils.bind(this,function(source,target){return this.createEdge(source,target);});this.createSwimlaneManager(graph);this.createLayoutManager(graph);return graph;};mxEditor.prototype.createSwimlaneManager=function(graph){var swimlaneMgr=new mxSwimlaneManager(graph,false);swimlaneMgr.isHorizontal=mxUtils.bind(this,function(){return this.horizontalFlow;});swimlaneMgr.isEnabled=mxUtils.bind(this,function(){return this.maintainSwimlanes;});return swimlaneMgr;};mxEditor.prototype.createLayoutManager=function(graph){var layoutMgr=new mxLayoutManager(graph);var self=this;layoutMgr.getLayout=function(cell){var layout=null;var model=self.graph.getModel();if(model.getParent(cell)!=null){if(self.layoutSwimlanes&&graph.isSwimlane(cell)){if(self.swimlaneLayout==null){self.swimlaneLayout=self.createSwimlaneLayout();}layout=self.swimlaneLayout;}else if(self.layoutDiagram&&(graph.isValidRoot(cell)||model.getParent(model.getParent(cell))==null)){if(self.diagramLayout==null){self.diagramLayout=self.createDiagramLayout();}layout=self.diagramLayout;}}return layout;};return layoutMgr;};mxEditor.prototype.setGraphContainer=function(container){if(this.graph.container==null){this.graph.init(container);this.rubberband=new mxRubberband(this.graph);if(this.disableContextMenu){mxEvent.disableContextMenu(container);}if(mxClient.IS_IE){new mxDivResizer(container);}}};mxEditor.prototype.installDblClickHandler=function(graph){graph.addListener(mxEvent.DOUBLE_CLICK,mxUtils.bind(this,function(sender,evt){var cell=evt.getProperty('cell');if(cell!=null&&graph.isEnabled()&&this.dblClickAction!=null){this.execute(this.dblClickAction,cell);evt.consume();}}));};mxEditor.prototype.installUndoHandler=function(graph){var listener=mxUtils.bind(this,function(sender,evt){var edit=evt.getProperty('edit');this.undoManager.undoableEditHappened(edit);});graph.getModel().addListener(mxEvent.UNDO,listener);graph.getView().addListener(mxEvent.UNDO,listener);var undoHandler=function(sender,evt){var changes=evt.getProperty('edit').changes;graph.setSelectionCells(graph.getSelectionCellsForChanges(changes));};this.undoManager.addListener(mxEvent.UNDO,undoHandler);this.undoManager.addListener(mxEvent.REDO,undoHandler);};mxEditor.prototype.installDrillHandler=function(graph){var listener=mxUtils.bind(this,function(sender){this.fireEvent(new mxEventObject(mxEvent.ROOT));});graph.getView().addListener(mxEvent.DOWN,listener);graph.getView().addListener(mxEvent.UP,listener);};mxEditor.prototype.installChangeHandler=function(graph){var listener=mxUtils.bind(this,function(sender,evt){this.setModified(true);if(this.validating==true){graph.validateGraph();}var changes=evt.getProperty('edit').changes;for(var i=0;i '+graph.convertValueToString(cell)+title;}cell=graph.getModel().getParent(cell);}var prefix=this.getRootTitle();return prefix+title;};mxEditor.prototype.getRootTitle=function(){var root=this.graph.getModel().getRoot();return this.graph.convertValueToString(root);};mxEditor.prototype.undo=function(){this.undoManager.undo();};mxEditor.prototype.redo=function(){this.undoManager.redo();};mxEditor.prototype.groupCells=function(){var border=(this.groupBorderSize!=null)?this.groupBorderSize:this.graph.gridSize;return this.graph.groupCells(this.createGroup(),border);};mxEditor.prototype.createGroup=function(){var model=this.graph.getModel();return model.cloneCell(this.defaultGroup);};mxEditor.prototype.open=function(filename){if(filename!=null){var xml=mxUtils.load(filename).getXml();this.readGraphModel(xml.documentElement);this.filename=filename;this.fireEvent(new mxEventObject(mxEvent.OPEN,'filename',filename));}};mxEditor.prototype.readGraphModel=function(node){var dec=new mxCodec(node.ownerDocument);dec.decode(node,this.graph.getModel());this.resetHistory();};mxEditor.prototype.save=function(url,linefeed){url=url||this.getUrlPost();if(url!=null&&url.length>0){var data=this.writeGraphModel(linefeed);this.postDiagram(url,data);this.setModified(false);}this.fireEvent(new mxEventObject(mxEvent.SAVE,'url',url));};mxEditor.prototype.postDiagram=function(url,data){if(this.escapePostData){data=encodeURIComponent(data);}mxUtils.post(url,this.postParameterName+'='+data,mxUtils.bind(this,function(req){this.fireEvent(new mxEventObject(mxEvent.POST,'request',req,'url',url,'data',data));}));};mxEditor.prototype.writeGraphModel=function(linefeed){linefeed=(linefeed!=null)?linefeed:this.linefeed;var enc=new mxCodec();var node=enc.encode(this.graph.getModel());return mxUtils.getXml(node,linefeed);};mxEditor.prototype.getUrlPost=function(){return this.urlPost;};mxEditor.prototype.getUrlImage=function(){return this.urlImage;};mxEditor.prototype.connect=function(urlInit,urlPoll,urlNotify,onChange){var session=null;if(!mxClient.IS_LOCAL){var session=new mxSession(this.graph.getModel(),urlInit,urlPoll,urlNotify);session.addListener(mxEvent.RECEIVE,mxUtils.bind(this,function(sender,evt){var node=evt.getProperty('node');if(node.getAttribute('namespace')!=null){this.resetHistory();}}));session.addListener(mxEvent.DISCONNECT,onChange);session.addListener(mxEvent.CONNECT,onChange);session.addListener(mxEvent.NOTIFY,onChange);session.addListener(mxEvent.GET,onChange);session.start();}return session;};mxEditor.prototype.swapStyles=function(first,second){var style=this.graph.getStylesheet().styles[second];this.graph.getView().getStylesheet().putCellStyle(second,this.graph.getStylesheet().styles[first]);this.graph.getStylesheet().putCellStyle(first,style);this.graph.refresh();};mxEditor.prototype.showProperties=function(cell){cell=cell||this.graph.getSelectionCell();if(cell==null){cell=this.graph.getCurrentRoot();if(cell==null){cell=this.graph.getModel().getRoot();}}if(cell!=null){this.graph.stopEditing(true);var offset=mxUtils.getOffset(this.graph.container);var x=offset.x+10;var y=offset.y;if(this.properties!=null&&!this.movePropertiesDialog){x=this.properties.getX();y=this.properties.getY();}else{var bounds=this.graph.getCellBounds(cell);if(bounds!=null){x+=bounds.x+Math.min(200,bounds.width);y+=bounds.y;}}this.hideProperties();var node=this.createProperties(cell);if(node!=null){this.properties=new mxWindow(mxResources.get(this.propertiesResource)||this.propertiesResource,node,x,y,this.propertiesWidth,this.propertiesHeight,false);this.properties.setVisible(true);}}};mxEditor.prototype.isPropertiesVisible=function(){return this.properties!=null;};mxEditor.prototype.createProperties=function(cell){var model=this.graph.getModel();var value=model.getValue(cell);if(mxUtils.isNode(value)){var form=new mxForm('properties');var id=form.addText('ID',cell.getId());id.setAttribute('readonly','true');var geo=null;var yField=null;var xField=null;var widthField=null;var heightField=null;if(model.isVertex(cell)){geo=model.getGeometry(cell);if(geo!=null){yField=form.addText('top',geo.y);xField=form.addText('left',geo.x);widthField=form.addText('width',geo.width);heightField=form.addText('height',geo.height);}}var tmp=model.getStyle(cell);var style=form.addText('Style',tmp||'');var attrs=value.attributes;var texts=[];for(var i=0;i0){model.setStyle(cell,style.value);}else{model.setStyle(cell,null);}for(var i=0;i0&&this.graph.isSwimlane(cell))?this.cycleAttributeValues[this.cycleAttributeIndex++%this.cycleAttributeValues.length]:null;};mxEditor.prototype.cycleAttribute=function(cell){if(this.cycleAttributeName!=null){var value=this.consumeCycleAttribute(cell);if(value!=null){cell.setStyle(cell.getStyle()+';'+this.cycleAttributeName+'='+value);}}};mxEditor.prototype.addVertex=function(parent,vertex,x,y){var model=this.graph.getModel();while(parent!=null&&!this.graph.isValidDropTarget(parent)){parent=model.getParent(parent);}parent=(parent!=null)?parent:this.graph.getSwimlaneAt(x,y);var scale=this.graph.getView().scale;var geo=model.getGeometry(vertex);var pgeo=model.getGeometry(parent);if(this.graph.isSwimlane(vertex)&&!this.graph.swimlaneNesting){parent=null;}else if(parent==null&&this.swimlaneRequired){return null;}else if(parent!=null&&pgeo!=null){var state=this.graph.getView().getState(parent);if(state!=null){x-=state.origin.x*scale;y-=state.origin.y*scale;if(this.graph.isConstrainedMoving){var width=geo.width;var height=geo.height;var tmp=state.x+state.width;if(x+width>tmp){x-=x+width-tmp;}tmp=state.y+state.height;if(y+height>tmp){y-=y+height-tmp;}}}else if(pgeo!=null){x-=pgeo.x*scale;y-=pgeo.y*scale;}}geo=geo.clone();geo.x=this.graph.snap(x/scale-this.graph.getView().translate.x-this.graph.gridSize/2);geo.y=this.graph.snap(y/scale-this.graph.getView().translate.y-this.graph.gridSize/2);vertex.setGeometry(geo);if(parent==null){parent=this.graph.getDefaultParent();}this.cycleAttribute(vertex);this.fireEvent(new mxEventObject(mxEvent.BEFORE_ADD_VERTEX,'vertex',vertex,'parent',parent));model.beginUpdate();try{vertex=this.graph.addCell(vertex,parent);if(vertex!=null){this.graph.constrainChild(vertex);this.fireEvent(new mxEventObject(mxEvent.ADD_VERTEX,'vertex',vertex));}}finally{model.endUpdate();}if(vertex!=null){this.graph.setSelectionCell(vertex);this.graph.scrollCellToVisible(vertex);this.fireEvent(new mxEventObject(mxEvent.AFTER_ADD_VERTEX,'vertex',vertex));}return vertex;};mxEditor.prototype.destroy=function(){if(!this.destroyed){this.destroyed=true;if(this.tasks!=null){this.tasks.destroy();}if(this.outline!=null){this.outline.destroy();}if(this.properties!=null){this.properties.destroy();}if(this.keyHandler!=null){this.keyHandler.destroy();}if(this.rubberband!=null){this.rubberband.destroy();}if(this.toolbar!=null){this.toolbar.destroy();}if(this.graph!=null){this.graph.destroy();}this.status=null;this.templates=null;}};var mxCodecRegistry={codecs:[],aliases:[],register:function(codec){if(codec!=null){var name=codec.getName();mxCodecRegistry.codecs[name]=codec;var classname=mxUtils.getFunctionName(codec.template.constructor);if(classname!=name){mxCodecRegistry.addAlias(classname,name);}}return codec;},addAlias:function(classname,codecname){mxCodecRegistry.aliases[classname]=codecname;},getCodec:function(ctor){var codec=null;if(ctor!=null){var name=mxUtils.getFunctionName(ctor);var tmp=mxCodecRegistry.aliases[name];if(tmp!=null){name=tmp;}codec=mxCodecRegistry.codecs[name];if(codec==null){try{codec=new mxObjectCodec(new ctor());mxCodecRegistry.register(codec);}catch(e){}}}return codec;}};function mxCodec(document){this.document=document||mxUtils.createXmlDocument();this.objects=[];};mxCodec.prototype.document=null;mxCodec.prototype.objects=null;mxCodec.prototype.encodeDefaults=false;mxCodec.prototype.putObject=function(id,obj){this.objects[id]=obj;return obj;};mxCodec.prototype.getObject=function(id){var obj=null;if(id!=null){obj=this.objects[id];if(obj==null){obj=this.lookup(id);if(obj==null){var node=this.getElementById(id);if(node!=null){obj=this.decode(node);}}}}return obj;};mxCodec.prototype.lookup=function(id){return null;};mxCodec.prototype.getElementById=function(id,attr){attr=(attr!=null)?attr:'id';return mxUtils.findNodeByAttribute(this.document.documentElement,attr,id);};mxCodec.prototype.getId=function(obj){var id=null;if(obj!=null){id=this.reference(obj);if(id==null&&obj instanceof mxCell){id=obj.getId();if(id==null){id=mxCellPath.create(obj);if(id.length==0){id='root';}}}}return id;};mxCodec.prototype.reference=function(obj){return null;};mxCodec.prototype.encode=function(obj){var node=null;if(obj!=null&&obj.constructor!=null){var enc=mxCodecRegistry.getCodec(obj.constructor);if(enc!=null){node=enc.encode(this,obj);}else{if(mxUtils.isNode(obj)){node=(mxClient.IS_IE)?obj.cloneNode(true):this.document.importNode(obj,true);}else{mxLog.warn('mxCodec.encode: No codec for '+mxUtils.getFunctionName(obj.constructor));}}}return node;};mxCodec.prototype.decode=function(node,into){var obj=null;if(node!=null&&node.nodeType==mxConstants.NODETYPE_ELEMENT){var ctor=null;try{ctor=eval(node.nodeName);}catch(err){}try{var dec=mxCodecRegistry.getCodec(ctor);if(dec!=null){obj=dec.decode(this,node,into);}else{obj=node.cloneNode(true);obj.removeAttribute('as');}}catch(err){mxLog.debug('Cannot decode '+node.nodeName+': '+err.message);}}return obj;};mxCodec.prototype.encodeCell=function(cell,node,includeChildren){node.appendChild(this.encode(cell));if(includeChildren==null||includeChildren){var childCount=cell.getChildCount();for(var i=0;i=0;};mxObjectCodec.prototype.isReference=function(obj,attr,value,write){return mxUtils.indexOf(this.idrefs,attr)>=0;};mxObjectCodec.prototype.encode=function(enc,obj){var node=enc.document.createElement(this.getName());obj=this.beforeEncode(enc,obj,node);this.encodeObject(enc,obj,node);return this.afterEncode(enc,obj,node);};mxObjectCodec.prototype.encodeObject=function(enc,obj,node){enc.setAttribute(node,'id',enc.getId(obj));for(var i in obj){var name=i;var value=obj[name];if(value!=null&&!this.isExcluded(obj,name,value,true)){if(mxUtils.isNumeric(name)){name=null;}this.encodeValue(enc,obj,name,value,node);}}};mxObjectCodec.prototype.encodeValue=function(enc,obj,name,value,node){if(value!=null){if(this.isReference(obj,name,value,true)){var tmp=enc.getId(value);if(tmp==null){mxLog.warn('mxObjectCodec.encode: No ID for '+this.getName()+'.'+name+'='+value);return;}value=tmp;}var defaultValue=this.template[name];if(name==null||enc.encodeDefaults||defaultValue!=value){name=this.getAttributeName(name);this.writeAttribute(enc,obj,name,value,node);}}};mxObjectCodec.prototype.writeAttribute=function(enc,obj,attr,value,node){if(typeof(value)!='object' ){this.writePrimitiveAttribute(enc,obj,attr,value,node);}else {this.writeComplexAttribute(enc,obj,attr,value,node);}};mxObjectCodec.prototype.writePrimitiveAttribute=function(enc,obj,attr,value,node){value=this.convertValueToXml(value);if(attr==null){var child=enc.document.createElement('add');if(typeof(value)=='function'){child.appendChild(enc.document.createTextNode(value));}else{enc.setAttribute(child,'value',value);}node.appendChild(child);}else if(typeof(value)!='function'){enc.setAttribute(node,attr,value);}};mxObjectCodec.prototype.writeComplexAttribute=function(enc,obj,attr,value,node){var child=enc.encode(value);if(child!=null){if(attr!=null){child.setAttribute('as',attr);}node.appendChild(child);}else{mxLog.warn('mxObjectCodec.encode: No node for '+this.getName()+'.'+attr+': '+value);}};mxObjectCodec.prototype.convertValueToXml=function(value){if(typeof(value.length)=='undefined'&&(value==true||value==false)){value=(value==true)?'1':'0';}return value;};mxObjectCodec.prototype.convertValueFromXml=function(value){if(mxUtils.isNumeric(value)){value=parseFloat(value);}return value;};mxObjectCodec.prototype.beforeEncode=function(enc,obj,node){return obj;};mxObjectCodec.prototype.afterEncode=function(enc,obj,node){return node;};mxObjectCodec.prototype.decode=function(dec,node,into){var id=node.getAttribute('id');var obj=dec.objects[id];if(obj==null){obj=into||this.cloneTemplate();if(id!=null){dec.putObject(id,obj);}}node=this.beforeDecode(dec,node,obj);this.decodeNode(dec,node,obj);return this.afterDecode(dec,node,obj);};mxObjectCodec.prototype.decodeNode=function(dec,node,obj){if(node!=null){this.decodeAttributes(dec,node,obj);this.decodeChildren(dec,node,obj);}};mxObjectCodec.prototype.decodeAttributes=function(dec,node,obj){var attrs=node.attributes;if(attrs!=null){for(var i=0;i0){template=null;}return template;};mxObjectCodec.prototype.addObjectValue=function(obj,fieldname,value,template){if(value!=null&&value!=template){if(fieldname!=null&&fieldname.length>0){obj[fieldname]=value;}else{obj.push(value);}}};mxObjectCodec.prototype.processInclude=function(dec,node,into){if(node.nodeName=='include'){var name=node.getAttribute('name');if(name!=null){try{var xml=mxUtils.load(name).getDocumentElement();if(xml!=null){dec.decode(xml,into);}}catch(e){}}return true;}return false;};mxObjectCodec.prototype.beforeDecode=function(dec,node,obj){return node;};mxObjectCodec.prototype.afterDecode=function(dec,node,obj){return obj;};mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxCell(),['children','edges','overlays','mxTransient'],['parent','source','target']);codec.isCellCodec=function(){return true;};codec.isExcluded=function(obj,attr,value,isWrite){return mxObjectCodec.prototype.isExcluded.apply(this,arguments)||(isWrite&&attr=='value'&&value.nodeType==mxConstants.NODETYPE_ELEMENT);};codec.afterEncode=function(enc,obj,node){if(obj.value!=null&&obj.value.nodeType==mxConstants.NODETYPE_ELEMENT){var tmp=node;node=(mxClient.IS_IE)?obj.value.cloneNode(true):enc.document.importNode(obj.value,true);node.appendChild(tmp);var id=tmp.getAttribute('id');node.setAttribute('id',id);tmp.removeAttribute('id');}return node;};codec.beforeDecode=function(dec,node,obj){var inner=node;var classname=this.getName();if(node.nodeName!=classname){var tmp=node.getElementsByTagName(classname)[0];if(tmp!=null&&tmp.parentNode==node){mxUtils.removeWhitespace(tmp,true);mxUtils.removeWhitespace(tmp,false);tmp.parentNode.removeChild(tmp);inner=tmp;}else{inner=null;}obj.value=node.cloneNode(true);var id=obj.value.getAttribute('id');if(id!=null){obj.setId(id);obj.value.removeAttribute('id');}}else{obj.setId(node.getAttribute('id'));}if(inner!=null){for(var i=0;i=0;};codec.afterEncode=function(enc,obj,node){if(this.isReference(obj,'child',obj.child,true)){node.setAttribute('child',enc.getId(obj.child));}else{enc.encodeCell(obj.child,node);}return node;};codec.beforeDecode=function(dec,node,obj){if(node.firstChild!=null&&node.firstChild.nodeType==mxConstants.NODETYPE_ELEMENT){node=node.cloneNode(true);var tmp=node.firstChild;obj.child=dec.decodeCell(tmp,false);var tmp2=tmp.nextSibling;tmp.parentNode.removeChild(tmp);tmp=tmp2;while(tmp!=null){tmp2=tmp.nextSibling;if(tmp.nodeType==mxConstants.NODETYPE_ELEMENT){var id=tmp.getAttribute('id');if(dec.lookup(id)==null){dec.decodeCell(tmp);}}tmp.parentNode.removeChild(tmp);tmp=tmp2;}}else{var childRef=node.getAttribute('child');obj.child=dec.getObject(childRef);}return node;};codec.afterDecode=function(dec,node,obj){obj.child.parent=obj.previous;obj.previous=obj.parent;obj.previousIndex=obj.index;return obj;};return codec;}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxTerminalChange(),['model','previous'],['cell','terminal']);codec.afterDecode=function(dec,node,obj){obj.previous=obj.terminal;return obj;};return codec;}());var mxGenericChangeCodec=function(obj,variable){var codec=new mxObjectCodec(obj,['model','previous'],['cell']);codec.afterDecode=function(dec,node,obj){if(mxUtils.isNode(obj.cell)){obj.cell=dec.decodeCell(obj.cell,false);}obj.previous=obj[variable];return obj;};return codec;};mxCodecRegistry.register(mxGenericChangeCodec(new mxValueChange(),'value'));mxCodecRegistry.register(mxGenericChangeCodec(new mxStyleChange(),'style'));mxCodecRegistry.register(mxGenericChangeCodec(new mxGeometryChange(),'geometry'));mxCodecRegistry.register(mxGenericChangeCodec(new mxCollapseChange(),'collapsed'));mxCodecRegistry.register(mxGenericChangeCodec(new mxVisibleChange(),'visible'));mxCodecRegistry.register(mxGenericChangeCodec(new mxCellAttributeChange(),'value'));mxCodecRegistry.register(function(){return new mxObjectCodec(new mxGraph(),['graphListeners','eventListeners','view','container','cellRenderer','editor','selection']);}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxGraphView());codec.encode=function(enc,view){return this.encodeCell(enc,view,view.graph.getModel().getRoot());};codec.encodeCell=function(enc,view,cell){var model=view.graph.getModel();var state=view.getState(cell);var parent=model.getParent(cell);if(parent==null||state!=null){var childCount=model.getChildCount(cell);var geo=view.graph.getCellGeometry(cell);var name=null;if(parent==model.getRoot()){name='layer';}else if(parent==null){name='graph';}else if(model.isEdge(cell)){name='edge';}else if(childCount>0&&geo!=null){name='group';}else if(model.isVertex(cell)){name='vertex';}if(name!=null){var node=enc.document.createElement(name);var lab=view.graph.getLabel(cell);if(lab!=null){node.setAttribute('label',view.graph.getLabel(cell));if(view.graph.isHtmlLabel(cell)){node.setAttribute('html',true);}}if(parent==null){var bounds=view.getGraphBounds();if(bounds!=null){node.setAttribute('x',Math.round(bounds.x));node.setAttribute('y',Math.round(bounds.y));node.setAttribute('width',Math.round(bounds.width));node.setAttribute('height',Math.round(bounds.height));}node.setAttribute('scale',view.scale);}else if(state!=null&&geo!=null){for(var i in state.style){var value=state.style[i];if(typeof(value)=='function'&&typeof(value)=='object'){value=mxStyleRegistry.getName(value);}if(value!=null&&typeof(value)!='function'&&typeof(value)!='object'){node.setAttribute(i,value);}}var abs=state.absolutePoints;if(abs!=null&&abs.length>0){var pts=Math.round(abs[0].x)+','+Math.round(abs[0].y);for(var i=1;i0){node.appendChild(styleNode);}}}return node;};codec.getStringValue=function(key,value){var type=typeof(value);if(type=='function'){value=mxStyleRegistry.getName(style[j]);}else if(type=='object'){value=null;}return value;};codec.decode=function(dec,node,into){var obj=into||new this.template.constructor();var id=node.getAttribute('id');if(id!=null){dec.objects[id]=obj;}node=node.firstChild;while(node!=null){if(!this.processInclude(dec,node,obj)&&node.nodeName=='add'){var as=node.getAttribute('as');if(as!=null){var extend=node.getAttribute('extend');var style=(extend!=null)?mxUtils.clone(obj.styles[extend]):null;if(style==null){if(extend!=null){mxLog.warn('mxStylesheetCodec.decode: stylesheet '+extend+' not found to extend');}style=new Object();}var entry=node.firstChild;while(entry!=null){if(entry.nodeType==mxConstants.NODETYPE_ELEMENT){var key=entry.getAttribute('as');if(entry.nodeName=='add'){var text=mxUtils.getTextContent(entry);var value=null;if(text!=null&&text.length>0){value=mxUtils.eval(text);}else{value=entry.getAttribute('value');if(mxUtils.isNumeric(value)){value=parseFloat(value);}}if(value!=null){style[key]=value;}}else if(entry.nodeName=='remove'){delete style[key];}}entry=entry.nextSibling;}obj.putCellStyle(as,style);}}node=node.nextSibling;}return obj;};return codec;}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxDefaultKeyHandler());codec.encode=function(enc,obj){return null;};codec.decode=function(dec,node,into){if(into!=null){var editor=into.editor;node=node.firstChild;while(node!=null){if(!this.processInclude(dec,node,into)&&node.nodeName=='add'){var as=node.getAttribute('as');var action=node.getAttribute('action');var control=node.getAttribute('control');into.bindAction(as,action,control);}node=node.nextSibling;}}return into;};return codec;}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxDefaultToolbar());codec.encode=function(enc,obj){return null;};codec.decode=function(dec,node,into){if(into!=null){var editor=into.editor;node=node.firstChild;while(node!=null){if(node.nodeType==mxConstants.NODETYPE_ELEMENT){if(!this.processInclude(dec,node,into)){if(node.nodeName=='separator'){into.addSeparator();}else if(node.nodeName=='br'){into.toolbar.addBreak();}else if(node.nodeName=='hr'){into.toolbar.addLine();}else if(node.nodeName=='add'){var as=node.getAttribute('as');as=mxResources.get(as)||as;var icon=node.getAttribute('icon');var pressedIcon=node.getAttribute('pressedIcon');var action=node.getAttribute('action');var mode=node.getAttribute('mode');var template=node.getAttribute('template');var toggle=node.getAttribute('toggle')!='0';var text=mxUtils.getTextContent(node);var elt=null;if(action!=null){elt=into.addItem(as,icon,action,pressedIcon);}else if(mode!=null){var funct=mxUtils.eval(text);elt=into.addMode(as,icon,mode,pressedIcon,funct);}else if(template!=null||(text!=null&&text.length>0)){var cell=editor.templates[template];var style=node.getAttribute('style');if(cell!=null&&style!=null){cell=cell.clone();cell.setStyle(style);}var insertFunction=null;if(text!=null&&text.length>0){insertFunction=mxUtils.eval(text);}elt=into.addPrototype(as,icon,cell,pressedIcon,insertFunction,toggle);}else{var children=mxUtils.getChildNodes(node);if(children.length>0){if(icon==null){var combo=into.addActionCombo(as);for(var i=0;i0){elt.setAttribute('id',id);}}}}}node=node.nextSibling;}}return into;};return codec;}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxDefaultPopupMenu());codec.encode=function(enc,obj){return null;};codec.decode=function(dec,node,into){var inc=node.getElementsByTagName('include')[0];if(inc!=null){this.processInclude(dec,inc,into);}else if(into!=null){into.config=node;}return into;};return codec;}());mxCodecRegistry.register(function(){var codec=new mxObjectCodec(new mxEditor(),['modified','lastSnapshot','ignoredChanges','undoManager','graphContainer','toolbarContainer']);codec.afterDecode=function(dec,node,obj){var defaultEdge=node.getAttribute('defaultEdge');if(defaultEdge!=null){node.removeAttribute('defaultEdge');obj.defaultEdge=obj.templates[defaultEdge];}var defaultGroup=node.getAttribute('defaultGroup');if(defaultGroup!=null){node.removeAttribute('defaultGroup');obj.defaultGroup=obj.templates[defaultGroup];}return obj;};codec.decodeChild=function(dec,child,obj){if(child.nodeName=='Array'){var role=child.getAttribute('as');if(role=='templates'){this.decodeTemplates(dec,child,obj);return;}}else if(child.nodeName=='ui'){this.decodeUi(dec,child,obj);return;}mxObjectCodec.prototype.decodeChild.apply(this,arguments);};codec.decodeUi=function(dec,node,editor){var tmp=node.firstChild;while(tmp!=null){if(tmp.nodeName=='add'){var as=tmp.getAttribute('as');var elt=tmp.getAttribute('element');var style=tmp.getAttribute('style');var element=null;if(elt!=null){element=document.getElementById(elt);if(element!=null&&style!=null){element.style.cssText+=';'+style;}}else{var x=parseInt(tmp.getAttribute('x'));var y=parseInt(tmp.getAttribute('y'));var width=tmp.getAttribute('width');var height=tmp.getAttribute('height');element=document.createElement('div');element.style.cssText=style;var wnd=new mxWindow(mxResources.get(as)||as,element,x,y,width,height,false,true);wnd.setVisible(true);}if(as=='graph'){editor.setGraphContainer(element);}else if(as=='toolbar'){editor.setToolbarContainer(element);}else if(as=='title'){editor.setTitleContainer(element);}else if(as=='status'){editor.setStatusContainer(element);}else if(as=='map'){editor.setMapContainer(element);}}else if(tmp.nodeName=='resource'){mxResources.add(tmp.getAttribute('basename'));}else if(tmp.nodeName=='stylesheet'){mxClient.link('stylesheet',tmp.getAttribute('name'));}tmp=tmp.nextSibling;}};codec.decodeTemplates=function(dec,node,editor){if(editor.templates==null){editor.templates=[];}var children=mxUtils.getChildNodes(node);for(var j=0;j= 0, + + /** + * Variable: IS_IE6 + * + * True if the current browser is Internet Explorer 6.x. + */ + IS_IE6: navigator.userAgent.indexOf('MSIE 6') >= 0, + + /** + * Variable: IS_NS + * + * True if the current browser is Netscape (including Firefox). + */ + IS_NS: navigator.userAgent.indexOf('Mozilla/') >= 0 && + navigator.userAgent.indexOf('MSIE') < 0, + + /** + * Variable: IS_OP + * + * True if the current browser is Opera. + */ + IS_OP: navigator.userAgent.indexOf('Opera/') >= 0, + + /** + * Variable: IS_OT + * + * True if -o-transform is available as a CSS style. This is the case + * for Opera browsers that use Presto/2.5 and later. + */ + IS_OT: navigator.userAgent.indexOf('Presto/2.4.') < 0 && + navigator.userAgent.indexOf('Presto/2.3.') < 0 && + navigator.userAgent.indexOf('Presto/2.2.') < 0 && + navigator.userAgent.indexOf('Presto/2.1.') < 0 && + navigator.userAgent.indexOf('Presto/2.0.') < 0 && + navigator.userAgent.indexOf('Presto/1.') < 0, + + /** + * Variable: IS_SF + * + * True if the current browser is Safari. + */ + IS_SF: navigator.userAgent.indexOf('AppleWebKit/') >= 0 && + navigator.userAgent.indexOf('Chrome/') < 0, + + /** + * Variable: IS_GC + * + * True if the current browser is Google Chrome. + */ + IS_GC: navigator.userAgent.indexOf('Chrome/') >= 0, + + /** + * Variable: IS_MT + * + * True if -moz-transform is available as a CSS style. This is the case + * for all Firefox-based browsers newer than or equal 3, such as Camino, + * Iceweasel, Seamonkey and Iceape. + */ + IS_MT: (navigator.userAgent.indexOf('Firefox/') >= 0 && + navigator.userAgent.indexOf('Firefox/1.') < 0 && + navigator.userAgent.indexOf('Firefox/2.') < 0) || + (navigator.userAgent.indexOf('Iceweasel/') >= 0 && + navigator.userAgent.indexOf('Iceweasel/1.') < 0 && + navigator.userAgent.indexOf('Iceweasel/2.') < 0) || + (navigator.userAgent.indexOf('SeaMonkey/') >= 0 && + navigator.userAgent.indexOf('SeaMonkey/1.') < 0) || + (navigator.userAgent.indexOf('Iceape/') >= 0 && + navigator.userAgent.indexOf('Iceape/1.') < 0), + + /** + * Variable: IS_SVG + * + * True if the browser supports SVG. + */ + IS_SVG: navigator.userAgent.indexOf('Firefox/') >= 0 || // FF and Camino + navigator.userAgent.indexOf('Iceweasel/') >= 0 || // Firefox on Debian + navigator.userAgent.indexOf('Seamonkey/') >= 0 || // Firefox-based + navigator.userAgent.indexOf('Iceape/') >= 0 || // Seamonkey on Debian + navigator.userAgent.indexOf('Galeon/') >= 0 || // Gnome Browser (old) + navigator.userAgent.indexOf('Epiphany/') >= 0 || // Gnome Browser (new) + navigator.userAgent.indexOf('AppleWebKit/') >= 0 || // Safari/Google Chrome + navigator.userAgent.indexOf('Gecko/') >= 0 || // Netscape/Gecko + navigator.userAgent.indexOf('Opera/') >= 0, + + + /** + * Variable: NO_FO + * + * True if foreignObject support is not available. This is the case for + * Opera and older SVG-based browsers. IE does not require this type + * of tag. + */ + NO_FO: navigator.userAgent.indexOf('Firefox/1.') >= 0 || + navigator.userAgent.indexOf('Iceweasel/1.') >= 0 || + navigator.userAgent.indexOf('Firefox/2.') >= 0 || + navigator.userAgent.indexOf('Iceweasel/2.') >= 0 || + navigator.userAgent.indexOf('SeaMonkey/1.') >= 0 || + navigator.userAgent.indexOf('Iceape/1.') >= 0 || + navigator.userAgent.indexOf('Camino/1.') >= 0 || + navigator.userAgent.indexOf('Epiphany/2.') >= 0 || + navigator.userAgent.indexOf('Opera/') >= 0 || + navigator.userAgent.indexOf('MSIE') >= 0 || + navigator.userAgent.indexOf('Mozilla/2.') >= 0, // Safari/Google Chrome + + /** + * Variable: IS_VML + * + * True if the browser supports VML. + */ + IS_VML: navigator.appName.toUpperCase() == 'MICROSOFT INTERNET EXPLORER', + + /** + * Variable: IS_MAC + * + * True if the client is a Mac. + */ + IS_MAC: navigator.userAgent.toUpperCase().indexOf('MACINTOSH') > 0, + + /** + * Variable: IS_TOUCH + * + * True if this client uses a touch interface (no mouse). Currently this + * detects IPads, IPods, IPhones and Android devices. + */ + IS_TOUCH: navigator.userAgent.toUpperCase().indexOf('IPAD') > 0 || + navigator.userAgent.toUpperCase().indexOf('IPOD') > 0 || + navigator.userAgent.toUpperCase().indexOf('IPHONE') > 0 || + navigator.userAgent.toUpperCase().indexOf('ANDROID') > 0, + + /** + * Variable: IS_LOCAL + * + * True if the documents location does not start with http:// or https://. + */ + IS_LOCAL: document.location.href.indexOf('http://') < 0 && + document.location.href.indexOf('https://') < 0, + + /** + * Function: isBrowserSupported + * + * Returns true if the current browser is supported, that is, if + * or is true. + * + * Example: + * + * (code) + * if (!mxClient.isBrowserSupported()) + * { + * mxUtils.error('Browser is not supported!', 200, false); + * } + * (end) + */ + isBrowserSupported: function() + { + return mxClient.IS_VML || mxClient.IS_SVG; + }, + + /** + * Function: link + * + * Adds a link node to the head of the document. Use this + * to add a stylesheet to the page as follows: + * + * (code) + * mxClient.link('stylesheet', filename); + * (end) + * + * where filename is the (relative) URL of the stylesheet. The charset + * is hardcoded to ISO-8859-1 and the type is text/css. + * + * Parameters: + * + * rel - String that represents the rel attribute of the link node. + * href - String that represents the href attribute of the link node. + * doc - Optional parent document of the link node. + */ + link: function(rel, href, doc) + { + doc = doc || document; + + // Workaround for Operation Aborted in IE6 if base tag is used in head + if (mxClient.IS_IE6) + { + doc.write(''); + } + else + { + var link = doc.createElement('link'); + + link.setAttribute('rel', rel); + link.setAttribute('href', href); + link.setAttribute('charset', 'ISO-8859-1'); + link.setAttribute('type', 'text/css'); + + var head = doc.getElementsByTagName('head')[0]; + head.appendChild(link); + } + }, + + /** + * Function: include + * + * Dynamically adds a script node to the document header. + * + * In production environments, the includes are resolved in the mxClient.js + * file to reduce the number of requests required for client startup. This + * function should only be used in development environments, but not in + * production systems. + */ + include: function(src) + { + document.write(''); + }, + + /** + * Function: dispose + * + * Frees up memory in IE by resolving cyclic dependencies between the DOM + * and the JavaScript objects. This is always invoked in IE when the page + * unloads. + */ + dispose: function() + { + // Cleans all objects where listeners have been added + for (var i = 0; i < mxEvent.objects.length; i++) + { + if (mxEvent.objects[i].mxListenerList != null) + { + mxEvent.removeAllListeners(mxEvent.objects[i]); + } + } + } + +}; + +/** + * Variable: mxLoadResources + * + * Optional global config variable to toggle loading of the two resource files + * in and . Default is true. NOTE: This is a global variable, + * not a variable of mxClient. + * + * (code) + * + * + * (end) + */ +if (typeof(mxLoadResources) == 'undefined') +{ + mxLoadResources = true; +} + +/** + * Variable: mxLoadStylesheets + * + * Optional global config variable to toggle loading of the CSS files when + * the library is initialized. Default is true. NOTE: This is a global variable, + * not a variable of mxClient. + * + * (code) + * + * + * (end) + */ +if (typeof(mxLoadStylesheets) == 'undefined') +{ + mxLoadStylesheets = true; +} + +/** + * Variable: basePath + * + * Basepath for all URLs in the core without trailing slash. Default is '.'. + * Set mxBasePath prior to loading the mxClient library as follows to override + * this setting: + * + * (code) + * + * + * (end) + * + * When using a relative path, the path is relative to the URL of the page that + * contains the assignment. Trailing slashes are automatically removed. + */ +if (typeof(mxBasePath) != 'undefined' && mxBasePath.length > 0) +{ + // Adds a trailing slash if required + if (mxBasePath.substring(mxBasePath.length - 1) == '/') + { + mxBasePath = mxBasePath.substring(0, mxBasePath.length - 1); + } + + mxClient.basePath = mxBasePath; +} +else +{ + mxClient.basePath = '.'; +} + +/** + * Variable: imageBasePath + * + * Basepath for all images URLs in the core without trailing slash. Default is + * + '/images'. Set mxImageBasePath prior to loading the + * mxClient library as follows to override this setting: + * + * (code) + * + * + * (end) + * + * When using a relative path, the path is relative to the URL of the page that + * contains the assignment. Trailing slashes are automatically removed. + */ +if (typeof(mxImageBasePath) != 'undefined' && mxImageBasePath.length > 0) +{ + // Adds a trailing slash if required + if (mxImageBasePath.substring(mxImageBasePath.length - 1) == '/') + { + mxImageBasePath = mxImageBasePath.substring(0, mxImageBasePath.length - 1); + } + + mxClient.imageBasePath = mxImageBasePath; +} +else +{ + mxClient.imageBasePath = mxClient.basePath + '/images'; +} + +/** + * Variable: language + * + * Defines the language of the client, eg. en for english, de for german etc. + * The special value 'none' will disable all built-in internationalization and + * resource loading. See for handling identifiers + * with and without a dash. + * + * Set mxLanguage prior to loading the mxClient library as follows to override + * this setting: + * + * (code) + * + * + * (end) + * + * If internationalization is disabled, then the following variables should be + * overridden to reflect the current language of the system. These variables are + * cleared when i18n is disabled. + * , , + * , , + * , , , + * , , + * , , + * , , + * , , + * and + * . + */ +if (typeof(mxLanguage) != 'undefined') +{ + mxClient.language = mxLanguage; +} +else +{ + mxClient.language = (mxClient.IS_IE) ? navigator.userLanguage : navigator.language; +} + +/** + * Variable: defaultLanguage + * + * Defines the default language which is used in the common resource files. Any + * resources for this language will only load the common resource file, but not + * the language-specific resource file. Default is 'en'. + * + * Set mxDefaultLanguage prior to loading the mxClient library as follows to override + * this setting: + * + * (code) + * + * + * (end) + */ +if (typeof(mxDefaultLanguage) != 'undefined') +{ + mxClient.defaultLanguage = mxDefaultLanguage; +} +else +{ + mxClient.defaultLanguage = 'en'; +} + +// Adds all required stylesheets and namespaces +if (mxLoadStylesheets) +{ + mxClient.link('stylesheet', mxClient.basePath + '/css/common.css'); +} + +/** + * Variable: languages + * + * Defines the optional array of all supported language extensions. The default + * language does not have to be part of this list. See + * . + * + * (code) + * + * + * (end) + * + * This is used to avoid unnecessary requests to language files, ie. if a 404 + * will be returned. + */ +if (typeof(mxLanguages) != 'undefined') +{ + mxClient.languages = mxLanguages; +} + +if (mxClient.IS_IE) +{ + // IE9/10 standards mode uses SVG (VML is broken) + if (document.documentMode >= 9) + { + mxClient.IS_VML = false; + mxClient.IS_SVG = true; + } + else + { + // Enables support for IE8 standards mode. Note that this requires all attributes for VML + // elements to be set using direct notation, ie. node.attr = value. The use of setAttribute + // is not possible. See mxShape.init for more code to handle this specific document mode. + if (document.documentMode == 8) + { + document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML'); + document.namespaces.add('o', 'urn:schemas-microsoft-com:office:office', '#default#VML'); + } + else + { + document.namespaces.add('v', 'urn:schemas-microsoft-com:vml'); + document.namespaces.add('o', 'urn:schemas-microsoft-com:office:office'); + } + + var ss = document.createStyleSheet(); + ss.cssText = 'v\\:*{behavior:url(#default#VML)}o\\:*{behavior:url(#default#VML)}'; + + if (mxLoadStylesheets) + { + mxClient.link('stylesheet', mxClient.basePath + '/css/explorer.css'); + } + } + + // Cleans up resources when the application terminates + window.attachEvent('onunload', mxClient.dispose); +} + +/** + * $Id: mxLog.js,v 1.31 2011-07-29 08:15:50 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxLog = +{ + /** + * Class: mxLog + * + * A singleton class that implements a simple console. + * + * Variable: consoleName + * + * Specifies the name of the console window. Default is 'Console'. + */ + consoleName: 'Console', + + /** + * Variable: TRACE + * + * Specified if the output for and should be visible in the + * console. Default is false. + */ + TRACE: false, + + /** + * Variable: DEBUG + * + * Specifies if the output for should be visible in the console. + * Default is true. + */ + DEBUG: true, + + /** + * Variable: WARN + * + * Specifies if the output for should be visible in the console. + * Default is true. + */ + WARN: true, + + /** + * Variable: buffer + * + * Buffer for pre-initialized content. + */ + buffer: '', + + /** + * Function: init + * + * Initializes the DOM node for the console. This requires document.body to + * point to a non-null value. This is called from within if the + * log has not yet been initialized. + */ + init: function() + { + if (mxLog.window == null && document.body != null) + { + var title = mxLog.consoleName + ' - mxGraph ' + mxClient.VERSION; + + // Creates a table that maintains the layout + var table = document.createElement('table'); + table.setAttribute('width', '100%'); + table.setAttribute('height', '100%'); + + var tbody = document.createElement('tbody'); + var tr = document.createElement('tr'); + var td = document.createElement('td'); + td.style.verticalAlign = 'top'; + + // Adds the actual console as a textarea + mxLog.textarea = document.createElement('textarea'); + mxLog.textarea.setAttribute('readOnly', 'true'); + mxLog.textarea.style.height = '100%'; + mxLog.textarea.style.resize = 'none'; + mxLog.textarea.value = mxLog.buffer; + + // Workaround for wrong width in standards mode + if (mxClient.IS_NS && document.compatMode != 'BackCompat') + { + mxLog.textarea.style.width = '99%'; + } + else + { + mxLog.textarea.style.width = '100%'; + } + + td.appendChild(mxLog.textarea); + tr.appendChild(td); + tbody.appendChild(tr); + + // Creates the container div + tr = document.createElement('tr'); + mxLog.td = document.createElement('td'); + mxLog.td.style.verticalAlign = 'top'; + mxLog.td.setAttribute('height', '30px'); + + tr.appendChild(mxLog.td); + tbody.appendChild(tr); + table.appendChild(tbody); + + // Adds various debugging buttons + mxLog.addButton('Info', function (evt) + { + mxLog.info(); + }); + + mxLog.addButton('DOM', function (evt) + { + var content = mxUtils.getInnerHtml(document.body); + mxLog.debug(content); + }); + + mxLog.addButton('Trace', function (evt) + { + mxLog.TRACE = !mxLog.TRACE; + + if (mxLog.TRACE) + { + mxLog.debug('Tracing enabled'); + } + else + { + mxLog.debug('Tracing disabled'); + } + }); + + mxLog.addButton('Copy', function (evt) + { + try + { + mxUtils.copy(mxLog.textarea.value); + } + catch (err) + { + mxUtils.alert(err); + } + }); + + mxLog.addButton('Show', function (evt) + { + try + { + mxUtils.popup(mxLog.textarea.value); + } + catch (err) + { + mxUtils.alert(err); + } + }); + + mxLog.addButton('Clear', function (evt) + { + mxLog.textarea.value = ''; + }); + + // Workaround for clientHeight in body = 0 if doctype in FF + var h = (document.body.clientHeight || document.documentElement.clientHeight); + var w = document.body.clientWidth; + + mxLog.window = new mxWindow(title, table, Math.max(0, w-320), Math.max(0, h-210), 300, 160); + mxLog.window.setMaximizable(true); + mxLog.window.setScrollable(false); + mxLog.window.setResizable(true); + mxLog.window.setClosable(true); + mxLog.window.destroyOnClose = false; + + // Workaround for ignored textarea height in various setups + if ((mxClient.IS_NS || mxClient.IS_IE) && !mxClient.IS_GC && + !mxClient.IS_SF && document.compatMode != 'BackCompat') + { + var elt = mxLog.window.getElement(); + + var resizeHandler = function(sender, evt) + { + mxLog.textarea.style.height = Math.max(0, elt.offsetHeight - 70)+'px'; + }; + + mxLog.window.addListener(mxEvent.RESIZE_END, resizeHandler); + mxLog.window.addListener(mxEvent.MAXIMIZE, resizeHandler); + mxLog.window.addListener(mxEvent.NORMALIZE, resizeHandler); + + mxLog.textarea.style.height = '92px'; + } + } + }, + + /** + * Function: info + * + * Writes the current navigator information to the console. + */ + info: function() + { + mxLog.writeln(mxUtils.toString(navigator)); + }, + + /** + * Function: addButton + * + * Adds a button to the console using the given label and function. + */ + addButton: function(lab, funct) + { + var button = document.createElement('button'); + mxUtils.write(button, lab); + mxEvent.addListener(button, 'click', funct); + mxLog.td.appendChild(button); + }, + + /** + * Function: isVisible + * + * Returns true if the console is visible. + */ + isVisible: function() + { + if (mxLog.window != null) + { + return mxLog.window.isVisible(); + } + return false; + }, + + + /** + * Function: show + * + * Shows the console. + */ + show: function() + { + mxLog.setVisible(true); + }, + + /** + * Function: setVisible + * + * Shows or hides the console. + */ + setVisible: function(visible) + { + if (mxLog.window == null) + { + mxLog.init(); + } + + if (mxLog.window != null) + { + mxLog.window.setVisible(visible); + } + }, + + /** + * Function: enter + * + * Writes the specified string to the console + * if is true and returns the current + * time in milliseconds. + * + * Example: + * + * (code) + * mxLog.show(); + * var t0 = mxLog.enter('Hello'); + * // Do something + * mxLog.leave('World!', t0); + * (end) + */ + enter: function(string) + { + if (mxLog.TRACE) + { + mxLog.writeln('Entering '+string); + + return new Date().getTime(); + } + }, + + /** + * Function: leave + * + * Writes the specified string to the console + * if is true and computes the difference + * between the current time and t0 in milliseconds. + * See for an example. + */ + leave: function(string, t0) + { + if (mxLog.TRACE) + { + var dt = (t0 != 0) ? ' ('+(new Date().getTime() - t0)+' ms)' : ''; + mxLog.writeln('Leaving '+string+dt); + } + }, + + /** + * Function: debug + * + * Adds all arguments to the console if is enabled. + * + * Example: + * + * (code) + * mxLog.show(); + * mxLog.debug('Hello, World!'); + * (end) + */ + debug: function() + { + if (mxLog.DEBUG) + { + mxLog.writeln.apply(this, arguments); + } + }, + + /** + * Function: warn + * + * Adds all arguments to the console if is enabled. + * + * Example: + * + * (code) + * mxLog.show(); + * mxLog.warn('Hello, World!'); + * (end) + */ + warn: function() + { + if (mxLog.WARN) + { + mxLog.writeln.apply(this, arguments); + } + }, + + /** + * Function: write + * + * Adds the specified strings to the console. + */ + write: function() + { + var string = ''; + + for (var i = 0; i < arguments.length; i++) + { + string += arguments[i]; + + if (i < arguments.length - 1) + { + string += ' '; + } + } + + if (mxLog.textarea != null) + { + mxLog.textarea.value = mxLog.textarea.value + string; + + // Workaround for no update in Presto 2.5.22 (Opera 10.5) + if (navigator.userAgent.indexOf('Presto/2.5') >= 0) + { + mxLog.textarea.style.visibility = 'hidden'; + mxLog.textarea.style.visibility = 'visible'; + } + + mxLog.textarea.scrollTop = mxLog.textarea.scrollHeight; + } + else + { + mxLog.buffer += string; + } + }, + + /** + * Function: writeln + * + * Adds the specified strings to the console, appending a linefeed at the + * end of each string. + */ + writeln: function() + { + var string = ''; + + for (var i = 0; i < arguments.length; i++) + { + string += arguments[i]; + + if (i < arguments.length - 1) + { + string += ' '; + } + } + + mxLog.write(string + '\n'); + } + +}; +/** + * $Id: mxObjectIdentity.js,v 1.8 2010-01-02 09:45:14 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxObjectIdentity = +{ + /** + * Class: mxObjectIdentity + * + * Identity for JavaScript objects. This is implemented using a simple + * incremeting counter which is stored in each object under . + * + * The identity for an object does not change during its lifecycle. + * + * Variable: FIELD_NAME + * + * Name of the field to be used to store the object ID. Default is + * '_mxObjectId'. + */ + FIELD_NAME: 'mxObjectId', + + /** + * Variable: counter + * + * Current counter for objects. + */ + counter: 0, + + /** + * Function: get + * + * Returns the object id for the given object. + */ + get: function(obj) + { + if (typeof(obj) == 'object' && + obj[mxObjectIdentity.FIELD_NAME] == null) + { + var ctor = mxUtils.getFunctionName(obj.constructor); + obj[mxObjectIdentity.FIELD_NAME] = ctor+'#'+mxObjectIdentity.counter++; + } + + return obj[mxObjectIdentity.FIELD_NAME]; + }, + + /** + * Function: clear + * + * Removes the object id from the given object. + */ + clear: function(obj) + { + if (typeof(obj) == 'object') + { + delete obj[mxObjectIdentity.FIELD_NAME]; + } + } + +}; +/** + * $Id: mxDictionary.js,v 1.12 2012-04-26 08:08:54 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxDictionary + * + * A wrapper class for an associative array with object keys. Note: This + * implementation uses to turn object keys into strings. + * + * Constructor: mxEventSource + * + * Constructs a new dictionary which allows object to be used as keys. + */ +function mxDictionary() +{ + this.clear(); +}; + +/** + * Function: map + * + * Stores the (key, value) pairs in this dictionary. + */ +mxDictionary.prototype.map = null; + +/** + * Function: clear + * + * Clears the dictionary. + */ +mxDictionary.prototype.clear = function() +{ + this.map = {}; +}; + +/** + * Function: get + * + * Returns the value for the given key. + */ +mxDictionary.prototype.get = function(key) +{ + var id = mxObjectIdentity.get(key); + + return this.map[id]; +}; + +/** + * Function: put + * + * Stores the value under the given key and returns the previous + * value for that key. + */ +mxDictionary.prototype.put = function(key, value) +{ + var id = mxObjectIdentity.get(key); + var previous = this.map[id]; + this.map[id] = value; + + return previous; +}; + +/** + * Function: remove + * + * Removes the value for the given key and returns the value that + * has been removed. + */ +mxDictionary.prototype.remove = function(key) +{ + var id = mxObjectIdentity.get(key); + var previous = this.map[id]; + delete this.map[id]; + + return previous; +}; + +/** + * Function: getKeys + * + * Returns all keys as an array. + */ +mxDictionary.prototype.getKeys = function() +{ + var result = []; + + for (var key in this.map) + { + result.push(key); + } + + return result; +}; + +/** + * Function: getValues + * + * Returns all values as an array. + */ +mxDictionary.prototype.getValues = function() +{ + var result = []; + + for (var key in this.map) + { + result.push(this.map[key]); + } + + return result; +}; + +/** + * Function: visit + * + * Visits all entries in the dictionary using the given function with the + * following signature: function(key, value) where key is a string and + * value is an object. + * + * Parameters: + * + * visitor - A function that takes the key and value as arguments. + */ +mxDictionary.prototype.visit = function(visitor) +{ + for (var key in this.map) + { + visitor(key, this.map[key]); + } +}; +/** + * $Id: mxResources.js,v 1.27 2012-05-28 17:09:03 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxResources = +{ + /** + * Class: mxResources + * + * Implements internationalization. You can provide any number of + * resource files on the server using the following format for the + * filename: name[-en].properties. The en stands for any lowercase + * 2-character language shortcut (eg. de for german, fr for french). + * + * If the optional language extension is omitted, then the file is used as a + * default resource which is loaded in all cases. If a properties file for a + * specific language exists, then it is used to override the settings in the + * default resource. All entries in the file are of the form key=value. The + * values may then be accessed in code via . Lines without + * equal signs in the properties files are ignored. + * + * Resource files may either be added programmatically using + * or via a resource tag in the UI section of the + * editor configuration file, eg: + * + * (code) + * + * + * + * (end) + * + * The above element will load examples/resources/mxWorkflow.properties as well + * as the language specific file for the current language, if it exists. + * + * Values may contain placeholders of the form {1}...{n} where each placeholder + * is replaced with the value of the corresponding array element in the params + * argument passed to . The placeholder {1} maps to the first + * element in the array (at index 0). + * + * See for more information on specifying the default + * language or disabling all loading of resources. + * + * Special characters + * + * To use unicode characters use %u as a prefix, eg. %u20AC will display a + * Euro sign. For normal hex encoded strings, use % as a prefix, eg. %F6 will + * display a ö (ö). + * + * Variable: resources + * + * Associative array that maps from keys to values. + */ + resources: [], + + /** + * Variable: loadDefaultBundle + * + * Specifies if the default file for a given basename should be loaded. + * Default is true. + */ + loadDefaultBundle: true, + + /** + * Variable: loadDefaultBundle + * + * Specifies if the specific language file file for a given basename should + * be loaded. Default is true. + */ + loadSpecialBundle: true, + + /** + * Function: isBundleSupported + * + * Hook for subclassers to disable support for a given language. This + * implementation always returns true. + * + * Parameters: + * + * basename - The basename for which the file should be loaded. + * lan - The current language. + */ + isLanguageSupported: function(lan) + { + if (mxClient.languages != null) + { + return mxUtils.indexOf(mxClient.languages, lan) >= 0; + } + + return true; + }, + + /** + * Function: getDefaultBundle + * + * Hook for subclassers to return the URL for the special bundle. This + * implementation returns basename + '.properties' or null if + * is false. + * + * Parameters: + * + * basename - The basename for which the file should be loaded. + * lan - The current language. + */ + getDefaultBundle: function(basename, lan) + { + if (mxResources.loadDefaultBundle || !mxResources.isLanguageSupported(lan)) + { + return basename + '.properties'; + } + else + { + return null; + } + }, + + /** + * Function: getSpecialBundle + * + * Hook for subclassers to return the URL for the special bundle. This + * implementation returns basename + '_' + lan + '.properties' or null if + * is false or lan equals . + * + * If is not null and contains + * a dash, then this method checks if returns true + * for the full language (including the dash). If that returns false the + * first part of the language (up to the dash) will be tried as an extension. + * + * If is null then the first part of the language is + * used to maintain backwards compatibility. + * + * Parameters: + * + * basename - The basename for which the file should be loaded. + * lan - The language for which the file should be loaded. + */ + getSpecialBundle: function(basename, lan) + { + if (mxClient.languages == null || !this.isLanguageSupported(lan)) + { + var dash = lan.indexOf('-'); + + if (dash > 0) + { + lan = lan.substring(0, dash); + } + } + + if (mxResources.loadSpecialBundle && mxResources.isLanguageSupported(lan) && lan != mxClient.defaultLanguage) + { + return basename + '_' + lan + '.properties'; + } + else + { + return null; + } + }, + + /** + * Function: add + * + * Adds the default and current language properties + * file for the specified basename. Existing keys + * are overridden as new files are added. + * + * Example: + * + * At application startup, additional resources may be + * added using the following code: + * + * (code) + * mxResources.add('resources/editor'); + * (end) + */ + add: function(basename, lan) + { + lan = (lan != null) ? lan : mxClient.language.toLowerCase(); + + if (lan != mxConstants.NONE) + { + // Loads the common language file (no extension) + var defaultBundle = mxResources.getDefaultBundle(basename, lan); + + if (defaultBundle != null) + { + try + { + var req = mxUtils.load(defaultBundle); + + if (req.isReady()) + { + mxResources.parse(req.getText()); + } + } + catch (e) + { + // ignore + } + } + + // Overlays the language specific file (_lan-extension) + var specialBundle = mxResources.getSpecialBundle(basename, lan); + + if (specialBundle != null) + { + try + { + var req = mxUtils.load(specialBundle); + + if (req.isReady()) + { + mxResources.parse(req.getText()); + } + } + catch (e) + { + // ignore + } + } + } + }, + + /** + * Function: parse + * + * Parses the key, value pairs in the specified + * text and stores them as local resources. + */ + parse: function(text) + { + if (text != null) + { + var lines = text.split('\n'); + + for (var i = 0; i < lines.length; i++) + { + var index = lines[i].indexOf('='); + + if (index > 0) + { + var key = lines[i].substring(0, index); + var idx = lines[i].length; + + if (lines[i].charCodeAt(idx - 1) == 13) + { + idx--; + } + + var value = lines[i].substring(index + 1, idx); + mxResources.resources[key] = unescape(value); + } + } + } + }, + + /** + * Function: get + * + * Returns the value for the specified resource key. + * + * Example: + * To read the value for 'welomeMessage', use the following: + * (code) + * var result = mxResources.get('welcomeMessage') || ''; + * (end) + * + * This would require an entry of the following form in + * one of the English language resource files: + * (code) + * welcomeMessage=Welcome to mxGraph! + * (end) + * + * The part behind the || is the string value to be used if the given + * resource is not available. + * + * Parameters: + * + * key - String that represents the key of the resource to be returned. + * params - Array of the values for the placeholders of the form {1}...{n} + * to be replaced with in the resulting string. + * defaultValue - Optional string that specifies the default return value. + */ + get: function(key, params, defaultValue) + { + var value = mxResources.resources[key]; + + // Applies the default value if no resource was found + if (value == null) + { + value = defaultValue; + } + + // Replaces the placeholders with the values in the array + if (value != null && + params != null) + { + var result = []; + var index = null; + + for (var i = 0; i < value.length; i++) + { + var c = value.charAt(i); + + if (c == '{') + { + index = ''; + } + else if (index != null && c == '}') + { + index = parseInt(index)-1; + + if (index >= 0 && index < params.length) + { + result.push(params[index]); + } + + index = null; + } + else if (index != null) + { + index += c; + } + else + { + result.push(c); + } + } + + value = result.join(''); + } + + return value; + } + +}; +/** + * $Id: mxPoint.js,v 1.12 2010-01-02 09:45:14 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxPoint + * + * Implements a 2-dimensional vector with double precision coordinates. + * + * Constructor: mxPoint + * + * Constructs a new point for the optional x and y coordinates. If no + * coordinates are given, then the default values for and are used. + */ +function mxPoint(x, y) +{ + this.x = (x != null) ? x : 0; + this.y = (y != null) ? y : 0; +}; + +/** + * Variable: x + * + * Holds the x-coordinate of the point. Default is 0. + */ +mxPoint.prototype.x = null; + +/** + * Variable: y + * + * Holds the y-coordinate of the point. Default is 0. + */ +mxPoint.prototype.y = null; + +/** + * Function: equals + * + * Returns true if the given object equals this rectangle. + */ +mxPoint.prototype.equals = function(obj) +{ + return obj.x == this.x && + obj.y == this.y; +}; + +/** + * Function: clone + * + * Returns a clone of this . + */ +mxPoint.prototype.clone = function() +{ + // Handles subclasses as well + return mxUtils.clone(this); +}; +/** + * $Id: mxRectangle.js,v 1.17 2010-12-08 12:46:03 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxRectangle + * + * Extends to implement a 2-dimensional rectangle with double + * precision coordinates. + * + * Constructor: mxRectangle + * + * Constructs a new rectangle for the optional parameters. If no parameters + * are given then the respective default values are used. + */ +function mxRectangle(x, y, width, height) +{ + mxPoint.call(this, x, y); + + this.width = (width != null) ? width : 0; + this.height = (height != null) ? height : 0; +}; + +/** + * Extends mxPoint. + */ +mxRectangle.prototype = new mxPoint(); +mxRectangle.prototype.constructor = mxRectangle; + +/** + * Variable: width + * + * Holds the width of the rectangle. Default is 0. + */ +mxRectangle.prototype.width = null; + +/** + * Variable: height + * + * Holds the height of the rectangle. Default is 0. + */ +mxRectangle.prototype.height = null; + +/** + * Function: setRect + * + * Sets this rectangle to the specified values + */ +mxRectangle.prototype.setRect = function(x, y, w, h) +{ + this.x = x; + this.y = y; + this.width = w; + this.height = h; +}; + +/** + * Function: getCenterX + * + * Returns the x-coordinate of the center point. + */ +mxRectangle.prototype.getCenterX = function () +{ + return this.x + this.width/2; +}; + +/** + * Function: getCenterY + * + * Returns the y-coordinate of the center point. + */ +mxRectangle.prototype.getCenterY = function () +{ + return this.y + this.height/2; +}; + +/** + * Function: add + * + * Adds the given rectangle to this rectangle. + */ +mxRectangle.prototype.add = function(rect) +{ + if (rect != null) + { + var minX = Math.min(this.x, rect.x); + var minY = Math.min(this.y, rect.y); + var maxX = Math.max(this.x + this.width, rect.x + rect.width); + var maxY = Math.max(this.y + this.height, rect.y + rect.height); + + this.x = minX; + this.y = minY; + this.width = maxX - minX; + this.height = maxY - minY; + } +}; + +/** + * Function: grow + * + * Grows the rectangle by the given amount, that is, this method subtracts + * the given amount from the x- and y-coordinates and adds twice the amount + * to the width and height. + */ +mxRectangle.prototype.grow = function(amount) +{ + this.x -= amount; + this.y -= amount; + this.width += 2 * amount; + this.height += 2 * amount; +}; + +/** + * Function: getPoint + * + * Returns the top, left corner as a new . + */ +mxRectangle.prototype.getPoint = function() +{ + return new mxPoint(this.x, this.y); +}; + +/** + * Function: equals + * + * Returns true if the given object equals this rectangle. + */ +mxRectangle.prototype.equals = function(obj) +{ + return obj.x == this.x && + obj.y == this.y && + obj.width == this.width && + obj.height == this.height; +}; +/** + * $Id: mxEffects.js,v 1.6 2012-01-04 10:01:16 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxEffects = +{ + + /** + * Class: mxEffects + * + * Provides animation effects. + */ + + /** + * Function: animateChanges + * + * Asynchronous animated move operation. See also: . + * + * Example: + * + * (code) + * graph.model.addListener(mxEvent.CHANGE, function(sender, evt) + * { + * var changes = evt.getProperty('edit').changes; + * + * if (changes.length < 10) + * { + * mxEffects.animateChanges(graph, changes); + * } + * }); + * (end) + * + * Parameters: + * + * graph - that received the changes. + * changes - Array of changes to be animated. + * done - Optional function argument that is invoked after the + * last step of the animation. + */ + animateChanges: function(graph, changes, done) + { + var maxStep = 10; + var step = 0; + + var animate = function() + { + var isRequired = false; + + for (var i = 0; i < changes.length; i++) + { + var change = changes[i]; + + if (change instanceof mxGeometryChange || + change instanceof mxTerminalChange || + change instanceof mxValueChange || + change instanceof mxChildChange || + change instanceof mxStyleChange) + { + var state = graph.getView().getState(change.cell || change.child, false); + + if (state != null) + { + isRequired = true; + + if (change.constructor != mxGeometryChange || graph.model.isEdge(change.cell)) + { + mxUtils.setOpacity(state.shape.node, 100 * step / maxStep); + } + else + { + var scale = graph.getView().scale; + + var dx = (change.geometry.x - change.previous.x) * scale; + var dy = (change.geometry.y - change.previous.y) * scale; + + var sx = (change.geometry.width - change.previous.width) * scale; + var sy = (change.geometry.height - change.previous.height) * scale; + + if (step == 0) + { + state.x -= dx; + state.y -= dy; + state.width -= sx; + state.height -= sy; + } + else + { + state.x += dx / maxStep; + state.y += dy / maxStep; + state.width += sx / maxStep; + state.height += sy / maxStep; + } + + graph.cellRenderer.redraw(state); + + // Fades all connected edges and children + mxEffects.cascadeOpacity(graph, change.cell, 100 * step / maxStep); + } + } + } + } + + // Workaround to force a repaint in AppleWebKit + mxUtils.repaintGraph(graph, new mxPoint(1, 1)); + + if (step < maxStep && isRequired) + { + step++; + window.setTimeout(animate, delay); + } + else if (done != null) + { + done(); + } + }; + + var delay = 30; + animate(); + }, + + /** + * Function: cascadeOpacity + * + * Sets the opacity on the given cell and its descendants. + * + * Parameters: + * + * graph - that contains the cells. + * cell - to set the opacity for. + * opacity - New value for the opacity in %. + */ + cascadeOpacity: function(graph, cell, opacity) + { + // Fades all children + var childCount = graph.model.getChildCount(cell); + + for (var i=0; i 0) + { + window.setTimeout(f, delay); + } + else + { + node.style.visibility = 'hidden'; + + if (remove && node.parentNode) + { + node.parentNode.removeChild(node); + } + } + }; + window.setTimeout(f, delay); + } + else + { + node.style.visibility = 'hidden'; + + if (remove && node.parentNode) + { + node.parentNode.removeChild(node); + } + } + } + +}; +/** + * $Id: mxUtils.js,v 1.291 2012-05-29 14:30:24 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +var mxUtils = +{ + /** + * Class: mxUtils + * + * A singleton class that provides cross-browser helper methods. + * This is a global functionality. To access the functions in this + * class, use the global classname appended by the functionname. + * You may have to load chrome://global/content/contentAreaUtils.js + * to disable certain security restrictions in Mozilla for the , + * , and function. + * + * For example, the following code displays an error message: + * + * (code) + * mxUtils.error('Browser is not supported!', 200, false); + * (end) + * + * Variable: errorResource + * + * Specifies the resource key for the title of the error window. If the + * resource for this key does not exist then the value is used as + * the title. Default is 'error'. + */ + errorResource: (mxClient.language != 'none') ? 'error' : '', + + /** + * Variable: closeResource + * + * Specifies the resource key for the label of the close button. If the + * resource for this key does not exist then the value is used as + * the label. Default is 'close'. + */ + closeResource: (mxClient.language != 'none') ? 'close' : '', + + /** + * Variable: errorImage + * + * Defines the image used for error dialogs. + */ + errorImage: mxClient.imageBasePath + '/error.gif', + + /** + * Function: removeCursors + * + * Removes the cursors from the style of the given DOM node and its + * descendants. + * + * Parameters: + * + * element - DOM node to remove the cursor style from. + */ + removeCursors: function(element) + { + if (element.style != null) + { + element.style.cursor = ''; + } + + var children = element.childNodes; + + if (children != null) + { + var childCount = children.length; + + for (var i = 0; i < childCount; i += 1) + { + mxUtils.removeCursors(children[i]); + } + } + }, + + /** + * Function: repaintGraph + * + * Normally not required, this contains the code to workaround a repaint + * issue and force a repaint of the graph container in AppleWebKit. + * + * Parameters: + * + * graph - to be repainted. + * pt - where the dummy element should be placed. + */ + repaintGraph: function(graph, pt) + { + if (mxClient.IS_GC || mxClient.IS_SF || mxClient.IS_OP) + { + var c = graph.container; + + if (c != null && pt != null && (c.scrollLeft > 0 || c.scrollTop > 0)) + { + var dummy = document.createElement('div'); + dummy.style.position = 'absolute'; + dummy.style.left = pt.x + 'px'; + dummy.style.top = pt.y + 'px'; + dummy.style.width = '1px'; + dummy.style.height = '1px'; + + c.appendChild(dummy); + c.removeChild(dummy); + } + } + }, + + /** + * Function: getCurrentStyle + * + * Returns the current style of the specified element. + * + * Parameters: + * + * element - DOM node whose current style should be returned. + */ + getCurrentStyle: function() + { + if (mxClient.IS_IE) + { + return function(element) + { + return (element != null) ? element.currentStyle : null; + }; + } + else + { + return function(element) + { + return (element != null) ? + window.getComputedStyle(element, '') : + null; + }; + } + }(), + + /** + * Function: hasScrollbars + * + * Returns true if the overflow CSS property of the given node is either + * scroll or auto. + * + * Parameters: + * + * node - DOM node whose style should be checked for scrollbars. + */ + hasScrollbars: function(node) + { + var style = mxUtils.getCurrentStyle(node); + + return style != null && (style.overflow == 'scroll' || style.overflow == 'auto'); + }, + + /** + * Function: bind + * + * Returns a wrapper function that locks the execution scope of the given + * function to the specified scope. Inside funct, the "this" keyword + * becomes a reference to that scope. + */ + bind: function(scope, funct) + { + return function() + { + return funct.apply(scope, arguments); + }; + }, + + /** + * Function: eval + * + * Evaluates the given expression using eval and returns the JavaScript + * object that represents the expression result. Supports evaluation of + * expressions that define functions and returns the function object for + * these expressions. + * + * Parameters: + * + * expr - A string that represents a JavaScript expression. + */ + eval: function(expr) + { + var result = null; + + if (expr.indexOf('function') >= 0) + { + try + { + eval('var _mxJavaScriptExpression='+expr); + result = _mxJavaScriptExpression; + // TODO: Use delete here? + _mxJavaScriptExpression = null; + } + catch (e) + { + mxLog.warn(e.message + ' while evaluating ' + expr); + } + } + else + { + try + { + result = eval(expr); + } + catch (e) + { + mxLog.warn(e.message + ' while evaluating ' + expr); + } + } + + return result; + }, + + /** + * Function: findNode + * + * Returns the first node where attr equals value. + * This implementation does not use XPath. + */ + findNode: function(node, attr, value) + { + var tmp = node.getAttribute(attr); + + if (tmp != null && tmp == value) + { + return node; + } + + node = node.firstChild; + + while (node != null) + { + var result = mxUtils.findNode(node, attr, value); + + if (result != null) + { + return result; + } + + node = node.nextSibling; + } + + return null; + }, + + /** + * Function: findNodeByAttribute + * + * Returns the first node where the given attribute matches the given value. + * + * Parameters: + * + * node - Root node where the search should start. + * attr - Name of the attribute to be checked. + * value - Value of the attribute to match. + */ + findNodeByAttribute: function() + { + // Workaround for missing XPath support in IE9 + if (document.documentMode >= 9) + { + return function(node, attr, value) + { + var result = null; + + if (node.nodeType == mxConstants.NODETYPE_ELEMENT && node.getAttribute(attr) == value) + { + result = node; + } + else + { + var child = node.firstChild; + + while (child != null && result == null) + { + result = mxUtils.findNodeByAttribute(child, attr, value); + child = child.nextSibling; + } + } + + return result; + }; + } + else if (mxClient.IS_IE) + { + return function(node, attr, value) + { + var expr = '//*[@' + attr + '=\'' + value + '\']'; + + return node.ownerDocument.selectSingleNode(expr); + }; + } + else + { + return function(node, attr, value) + { + var result = node.ownerDocument.evaluate( + '//*[@' + attr + '=\'' + value + '\']', + node.ownerDocument, null, + XPathResult.ANY_TYPE, null); + + return result.iterateNext(); + }; + } + }(), + + /** + * Function: getFunctionName + * + * Returns the name for the given function. + * + * Parameters: + * + * f - JavaScript object that represents a function. + */ + getFunctionName: function(f) + { + var str = null; + + if (f != null) + { + if (f.name != null) + { + str = f.name; + } + else + { + var tmp = f.toString(); + var idx1 = 9; + + while (tmp.charAt(idx1) == ' ') + { + idx1++; + } + + var idx2 = tmp.indexOf('(', idx1); + str = tmp.substring(idx1, idx2); + } + } + + return str; + }, + + /** + * Function: indexOf + * + * Returns the index of obj in array or -1 if the array does not contains + * the given object. + * + * Parameters: + * + * array - Array to check for the given obj. + * obj - Object to find in the given array. + */ + indexOf: function(array, obj) + { + if (array != null && obj != null) + { + for (var i = 0; i < array.length; i++) + { + if (array[i] == obj) + { + return i; + } + } + } + + return -1; + }, + + /** + * Function: remove + * + * Removes all occurrences of the given object in the given array or + * object. If there are multiple occurrences of the object, be they + * associative or as an array entry, all occurrences are removed from + * the array or deleted from the object. By removing the object from + * the array, all elements following the removed element are shifted + * by one step towards the beginning of the array. + * + * The length of arrays is not modified inside this function. + * + * Parameters: + * + * obj - Object to find in the given array. + * array - Array to check for the given obj. + */ + remove: function(obj, array) + { + var result = null; + + if (typeof(array) == 'object') + { + var index = mxUtils.indexOf(array, obj); + + while (index >= 0) + { + array.splice(index, 1); + result = obj; + index = mxUtils.indexOf(array, obj); + } + } + + for (var key in array) + { + if (array[key] == obj) + { + delete array[key]; + result = obj; + } + } + + return result; + }, + + /** + * Function: isNode + * + * Returns true if the given value is an XML node with the node name + * and if the optional attribute has the specified value. + * + * This implementation assumes that the given value is a DOM node if the + * nodeType property is numeric, that is, if isNaN returns false for + * value.nodeType. + * + * Parameters: + * + * value - Object that should be examined as a node. + * nodeName - String that specifies the node name. + * attributeName - Optional attribute name to check. + * attributeValue - Optional attribute value to check. + */ + isNode: function(value, nodeName, attributeName, attributeValue) + { + if (value != null && !isNaN(value.nodeType) && (nodeName == null || + value.nodeName.toLowerCase() == nodeName.toLowerCase())) + { + return attributeName == null || + value.getAttribute(attributeName) == attributeValue; + } + + return false; + }, + + /** + * Function: getChildNodes + * + * Returns an array of child nodes that are of the given node type. + * + * Parameters: + * + * node - Parent DOM node to return the children from. + * nodeType - Optional node type to return. Default is + * . + */ + getChildNodes: function(node, nodeType) + { + nodeType = nodeType || mxConstants.NODETYPE_ELEMENT; + + var children = []; + var tmp = node.firstChild; + + while (tmp != null) + { + if (tmp.nodeType == nodeType) + { + children.push(tmp); + } + + tmp = tmp.nextSibling; + } + + return children; + }, + + /** + * Function: createXmlDocument + * + * Returns a new, empty XML document. + */ + createXmlDocument: function() + { + var doc = null; + + if (document.implementation && document.implementation.createDocument) + { + doc = document.implementation.createDocument('', '', null); + } + else if (window.ActiveXObject) + { + doc = new ActiveXObject('Microsoft.XMLDOM'); + } + + return doc; + }, + + /** + * Function: parseXml + * + * Parses the specified XML string into a new XML document and returns the + * new document. + * + * Example: + * + * (code) + * var doc = mxUtils.parseXml( + * ''+ + * ''+ + * ''+ + * ''+ + * ''); + * (end) + * + * Parameters: + * + * xml - String that contains the XML data. + */ + parseXml: function() + { + if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) + { + return function(xml) + { + var result = mxUtils.createXmlDocument(); + + result.async = 'false'; + result.loadXML(xml); + + return result; + }; + } + else + { + return function(xml) + { + var parser = new DOMParser(); + + return parser.parseFromString(xml, 'text/xml'); + }; + } + }(), + + /** + * Function: clearSelection + * + * Clears the current selection in the page. + */ + clearSelection: function() + { + if (document.selection) + { + return function() + { + document.selection.empty(); + }; + } + else if (window.getSelection) + { + return function() + { + window.getSelection().removeAllRanges(); + }; + } + }(), + + /** + * Function: getPrettyXML + * + * Returns a pretty printed string that represents the XML tree for the + * given node. This method should only be used to print XML for reading, + * use instead to obtain a string for processing. + * + * Parameters: + * + * node - DOM node to return the XML for. + * tab - Optional string that specifies the indentation for one level. + * Default is two spaces. + * indent - Optional string that represents the current indentation. + * Default is an empty string. + */ + getPrettyXml: function(node, tab, indent) + { + var result = []; + + if (node != null) + { + tab = tab || ' '; + indent = indent || ''; + + if (node.nodeType == mxConstants.NODETYPE_TEXT) + { + result.push(node.nodeValue); + } + else + { + result.push(indent + '<'+node.nodeName); + + // Creates the string with the node attributes + // and converts all HTML entities in the values + var attrs = node.attributes; + + if (attrs != null) + { + for (var i = 0; i < attrs.length; i++) + { + var val = mxUtils.htmlEntities(attrs[i].nodeValue); + result.push(' ' + attrs[i].nodeName + + '="' + val + '"'); + } + } + + // Recursively creates the XML string for each + // child nodes and appends it here with an + // indentation + var tmp = node.firstChild; + + if (tmp != null) + { + result.push('>\n'); + + while (tmp != null) + { + result.push(mxUtils.getPrettyXml( + tmp, tab, indent + tab)); + tmp = tmp.nextSibling; + } + + result.push(indent + '\n'); + } + else + { + result.push('/>\n'); + } + } + } + + return result.join(''); + }, + + /** + * Function: removeWhitespace + * + * Removes the sibling text nodes for the given node that only consists + * of tabs, newlines and spaces. + * + * Parameters: + * + * node - DOM node whose siblings should be removed. + * before - Optional boolean that specifies the direction of the traversal. + */ + removeWhitespace: function(node, before) + { + var tmp = (before) ? node.previousSibling : node.nextSibling; + + while (tmp != null && tmp.nodeType == mxConstants.NODETYPE_TEXT) + { + var next = (before) ? tmp.previousSibling : tmp.nextSibling; + var text = mxUtils.getTextContent(tmp); + + if (mxUtils.trim(text).length == 0) + { + tmp.parentNode.removeChild(tmp); + } + + tmp = next; + } + }, + + /** + * Function: htmlEntities + * + * Replaces characters (less than, greater than, newlines and quotes) with + * their HTML entities in the given string and returns the result. + * + * Parameters: + * + * s - String that contains the characters to be converted. + * newline - If newlines should be replaced. Default is true. + */ + htmlEntities: function(s, newline) + { + s = s || ''; + + s = s.replace(/&/g,'&'); // 38 26 + s = s.replace(/"/g,'"'); // 34 22 + s = s.replace(/\'/g,'''); // 39 27 + s = s.replace(//g,'>'); // 62 3E + + if (newline == null || newline) + { + s = s.replace(/\n/g, ' '); + } + + return s; + }, + + /** + * Function: isVml + * + * Returns true if the given node is in the VML namespace. + * + * Parameters: + * + * node - DOM node whose tag urn should be checked. + */ + isVml: function(node) + { + return node != null && node.tagUrn == 'urn:schemas-microsoft-com:vml'; + }, + + /** + * Function: getXml + * + * Returns the XML content of the specified node. For Internet Explorer, + * all \r\n\t[\t]* are removed from the XML string and the remaining \r\n + * are replaced by \n. All \n are then replaced with linefeed, or if + * no linefeed is defined. + * + * Parameters: + * + * node - DOM node to return the XML for. + * linefeed - Optional string that linefeeds are converted into. Default is + * + */ + getXml: function(node, linefeed) + { + var xml = ''; + + if (node != null) + { + xml = node.xml; + + if (xml == null) + { + if (node.innerHTML) + { + xml = node.innerHTML; + } + else + { + var xmlSerializer = new XMLSerializer(); + xml = xmlSerializer.serializeToString(node); + } + } + else + { + xml = xml.replace(/\r\n\t[\t]*/g, ''). + replace(/>\r\n/g, '>'). + replace(/\r\n/g, '\n'); + } + } + + // Replaces linefeeds with HTML Entities. + linefeed = linefeed || ' '; + xml = xml.replace(/\n/g, linefeed); + + return xml; + }, + + /** + * Function: getTextContent + * + * Returns the text content of the specified node. + * + * Parameters: + * + * node - DOM node to return the text content for. + */ + getTextContent: function(node) + { + var result = ''; + + if (node != null) + { + if (node.firstChild != null) + { + node = node.firstChild; + } + + result = node.nodeValue || ''; + } + + return result; + }, + + /** + * Function: getInnerHtml + * + * Returns the inner HTML for the given node as a string or an empty string + * if no node was specified. The inner HTML is the text representing all + * children of the node, but not the node itself. + * + * Parameters: + * + * node - DOM node to return the inner HTML for. + */ + getInnerHtml: function() + { + if (mxClient.IS_IE) + { + return function(node) + { + if (node != null) + { + return node.innerHTML; + } + + return ''; + }; + } + else + { + return function(node) + { + if (node != null) + { + var serializer = new XMLSerializer(); + return serializer.serializeToString(node); + } + + return ''; + }; + } + }(), + + /** + * Function: getOuterHtml + * + * Returns the outer HTML for the given node as a string or an empty + * string if no node was specified. The outer HTML is the text representing + * all children of the node including the node itself. + * + * Parameters: + * + * node - DOM node to return the outer HTML for. + */ + getOuterHtml: function() + { + if (mxClient.IS_IE) + { + return function(node) + { + if (node != null) + { + if (node.outerHTML != null) + { + return node.outerHTML; + } + else + { + var tmp = []; + tmp.push('<'+node.nodeName); + + var attrs = node.attributes; + + if (attrs != null) + { + for (var i = 0; i < attrs.length; i++) + { + var value = attrs[i].nodeValue; + + if (value != null && value.length > 0) + { + tmp.push(' '); + tmp.push(attrs[i].nodeName); + tmp.push('="'); + tmp.push(value); + tmp.push('"'); + } + } + } + + if (node.innerHTML.length == 0) + { + tmp.push('/>'); + } + else + { + tmp.push('>'); + tmp.push(node.innerHTML); + tmp.push(''); + } + + return tmp.join(''); + } + } + + return ''; + }; + } + else + { + return function(node) + { + if (node != null) + { + var serializer = new XMLSerializer(); + return serializer.serializeToString(node); + } + + return ''; + }; + } + }(), + + /** + * Function: write + * + * Creates a text node for the given string and appends it to the given + * parent. Returns the text node. + * + * Parameters: + * + * parent - DOM node to append the text node to. + * text - String representing the text to be added. + */ + write: function(parent, text) + { + doc = parent.ownerDocument; + var node = doc.createTextNode(text); + + if (parent != null) + { + parent.appendChild(node); + } + + return node; + }, + + /** + * Function: writeln + * + * Creates a text node for the given string and appends it to the given + * parent with an additional linefeed. Returns the text node. + * + * Parameters: + * + * parent - DOM node to append the text node to. + * text - String representing the text to be added. + */ + writeln: function(parent, text) + { + doc = parent.ownerDocument; + var node = doc.createTextNode(text); + + if (parent != null) + { + parent.appendChild(node); + parent.appendChild(document.createElement('br')); + } + + return node; + }, + + /** + * Function: br + * + * Appends a linebreak to the given parent and returns the linebreak. + * + * Parameters: + * + * parent - DOM node to append the linebreak to. + */ + br: function(parent, count) + { + count = count || 1; + var br = null; + + for (var i = 0; i < count; i++) + { + if (parent != null) + { + br = parent.ownerDocument.createElement('br'); + parent.appendChild(br); + } + } + + return br; + }, + + /** + * Function: button + * + * Returns a new button with the given level and function as an onclick + * event handler. + * + * (code) + * document.body.appendChild(mxUtils.button('Test', function(evt) + * { + * alert('Hello, World!'); + * })); + * (end) + * + * Parameters: + * + * label - String that represents the label of the button. + * funct - Function to be called if the button is pressed. + * doc - Optional document to be used for creating the button. Default is the + * current document. + */ + button: function(label, funct, doc) + { + doc = (doc != null) ? doc : document; + + var button = doc.createElement('button'); + mxUtils.write(button, label); + + mxEvent.addListener(button, 'click', function(evt) + { + funct(evt); + }); + + return button; + }, + + /** + * Function: para + * + * Appends a new paragraph with the given text to the specified parent and + * returns the paragraph. + * + * Parameters: + * + * parent - DOM node to append the text node to. + * text - String representing the text for the new paragraph. + */ + para: function(parent, text) + { + var p = document.createElement('p'); + mxUtils.write(p, text); + + if (parent != null) + { + parent.appendChild(p); + } + + return p; + }, + + /** + * Function: linkAction + * + * Adds a hyperlink to the specified parent that invokes action on the + * specified editor. + * + * Parameters: + * + * parent - DOM node to contain the new link. + * text - String that is used as the link label. + * editor - that will execute the action. + * action - String that defines the name of the action to be executed. + * pad - Optional left-padding for the link. Default is 0. + */ + linkAction: function(parent, text, editor, action, pad) + { + return mxUtils.link(parent, text, function() + { + editor.execute(action); + }, pad); + }, + + /** + * Function: linkInvoke + * + * Adds a hyperlink to the specified parent that invokes the specified + * function on the editor passing along the specified argument. The + * function name is the name of a function of the editor instance, + * not an action name. + * + * Parameters: + * + * parent - DOM node to contain the new link. + * text - String that is used as the link label. + * editor - instance to execute the function on. + * functName - String that represents the name of the function. + * arg - Object that represents the argument to the function. + * pad - Optional left-padding for the link. Default is 0. + */ + linkInvoke: function(parent, text, editor, functName, arg, pad) + { + return mxUtils.link(parent, text, function() + { + editor[functName](arg); + }, pad); + }, + + /** + * Function: link + * + * Adds a hyperlink to the specified parent and invokes the given function + * when the link is clicked. + * + * Parameters: + * + * parent - DOM node to contain the new link. + * text - String that is used as the link label. + * funct - Function to execute when the link is clicked. + * pad - Optional left-padding for the link. Default is 0. + */ + link: function(parent, text, funct, pad) + { + var a = document.createElement('span'); + + a.style.color = 'blue'; + a.style.textDecoration = 'underline'; + a.style.cursor = 'pointer'; + + if (pad != null) + { + a.style.paddingLeft = pad+'px'; + } + + mxEvent.addListener(a, 'click', funct); + mxUtils.write(a, text); + + if (parent != null) + { + parent.appendChild(a); + } + + return a; + }, + + /** + * Function: fit + * + * Makes sure the given node is inside the visible area of the window. This + * is done by setting the left and top in the style. + */ + fit: function(node) + { + var left = parseInt(node.offsetLeft); + var width = parseInt(node.offsetWidth); + + var b = document.body; + var d = document.documentElement; + + var right = (b.scrollLeft || d.scrollLeft) + + (b.clientWidth || d.clientWidth); + + if (left + width > right) + { + node.style.left = Math.max((b.scrollLeft || d.scrollLeft), + right - width)+'px'; + } + + var top = parseInt(node.offsetTop); + var height = parseInt(node.offsetHeight); + + var bottom = (b.scrollTop || d.scrollTop) + + Math.max(b.clientHeight || 0, d.clientHeight); + + if (top + height > bottom) + { + node.style.top = Math.max((b.scrollTop || d.scrollTop), + bottom - height)+'px'; + } + }, + + /** + * Function: open + * + * Opens the specified file from the local filesystem and returns the + * contents of the file as a string. This implementation requires an + * ActiveX object in IE and special privileges in Firefox. Relative + * filenames are only supported in IE and will go onto the users' + * Desktop. You may have to load + * chrome://global/content/contentAreaUtils.js to disable certain + * security restrictions in Mozilla for this to work. + * + * See known-issues before using this function. + * + * Example: + * (code) + * var data = mxUtils.open('C:\\temp\\test.txt'); + * mxUtils.alert('Data: '+data); + * (end) + * + * Parameters: + * + * filename - String representing the local file name. + */ + open: function(filename) + { + // Requests required privileges in Firefox + if (mxClient.IS_NS) + { + try + { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + } + catch (e) + { + mxUtils.alert('Permission to read file denied.'); + + return ''; + } + + var file = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(filename); + + if (!file.exists()) + { + mxUtils.alert('File not found.'); + return ''; + } + + var is = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream); + is.init(file,0x01, 00004, null); + + var sis = Components.classes['@mozilla.org/scriptableinputstream;1'].createInstance(Components.interfaces.nsIScriptableInputStream); + sis.init(is); + + var output = sis.read(sis.available()); + + return output; + } + else + { + var activeXObject = new ActiveXObject('Scripting.FileSystemObject'); + + var newStream = activeXObject.OpenTextFile(filename, 1); + var text = newStream.readAll(); + newStream.close(); + + return text; + } + }, + + /** + * Function: save + * + * Saves the specified content in the given file on the local file system. + * This implementation requires an ActiveX object in IE and special + * privileges in Firefox. Relative filenames are only supported in IE and + * will be loaded from the users' Desktop. You may have to load + * chrome://global/content/contentAreaUtils.js to disable certain + * security restrictions in Mozilla for this to work. + * + * See known-issues before using this function. + * + * Example: + * + * (code) + * var data = 'Hello, World!'; + * mxUtils.save('C:\\test.txt', data); + * (end) + * + * Parameters: + * + * filename - String representing the local file name. + */ + save: function(filename, content) + { + if (mxClient.IS_NS) + { + try + { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + } + catch (e) + { + mxUtils.alert('Permission to write file denied.'); + return; + } + + var file = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(filename); + + if (!file.exists()) + { + file.create(0x00, 0644); + } + + var outputStream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream); + + outputStream.init(file, 0x20 | 0x02,00004, null); + outputStream.write(content, content.length); + outputStream.flush(); + outputStream.close(); + } + else + { + var fso = new ActiveXObject('Scripting.FileSystemObject'); + + var file = fso.CreateTextFile(filename, true); + file.Write(content); + file.Close(); + } + }, + + /** + * Function: saveAs + * + * Saves the specified content by displaying a dialog to save the content + * as a file on the local filesystem. This implementation does not use an + * ActiveX object in IE, however, it does require special privileges in + * Firefox. You may have to load + * chrome://global/content/contentAreaUtils.js to disable certain + * security restrictions in Mozilla for this to work. + * + * See known-issues before using this function. It is not recommended using + * this function in production environment as access to the filesystem + * cannot be guaranteed in Firefox. The following code is used in + * Firefox to try and enable saving to the filesystem. + * + * (code) + * netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + * (end) + * + * Example: + * + * (code) + * mxUtils.saveAs('Hello, World!'); + * (end) + * + * Parameters: + * + * content - String representing the file's content. + */ + saveAs: function(content) + { + var iframe = document.createElement('iframe'); + iframe.setAttribute('src', ''); + iframe.style.visibility = 'hidden'; + document.body.appendChild(iframe); + + try + { + if (mxClient.IS_NS) + { + var doc = iframe.contentDocument; + + doc.open(); + doc.write(content); + doc.close(); + + try + { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + // LATER: Remove existing HTML markup in file + iframe.focus(); + saveDocument(doc); + } + catch (e) + { + mxUtils.alert('Permission to save document denied.'); + } + } + else + { + var doc = iframe.contentWindow.document; + doc.write(content); + doc.execCommand('SaveAs', false, document.location); + } + } + finally + { + document.body.removeChild(iframe); + } + }, + + /** + * Function: copy + * + * Copies the specified content to the local clipboard. This implementation + * requires special privileges in Firefox. You may have to load + * chrome://global/content/contentAreaUtils.js to disable certain + * security restrictions in Mozilla for this to work. + * + * Parameters: + * + * content - String to be copied to the clipboard. + */ + copy: function(content) + { + if (window.clipboardData) + { + window.clipboardData.setData('Text', content); + } + else + { + netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + + var clip = Components.classes['@mozilla.org/widget/clipboard;1'] + .createInstance(Components.interfaces.nsIClipboard); + + if (!clip) + { + return; + } + + var trans = Components.classes['@mozilla.org/widget/transferable;1'] + .createInstance(Components.interfaces.nsITransferable); + + if (!trans) + { + return; + } + + trans.addDataFlavor('text/unicode'); + var str = Components.classes['@mozilla.org/supports-string;1'] + .createInstance(Components.interfaces.nsISupportsString); + + var copytext=content; + str.data=copytext; + trans.setTransferData('text/unicode', str, copytext.length*2); + var clipid=Components.interfaces.nsIClipboard; + + clip.setData(trans,null,clipid.kGlobalClipboard); + } + }, + + /** + * Function: load + * + * Loads the specified URL *synchronously* and returns the . + * Throws an exception if the file cannot be loaded. See for + * an asynchronous implementation. + * + * Example: + * + * (code) + * try + * { + * var req = mxUtils.load(filename); + * var root = req.getDocumentElement(); + * // Process XML DOM... + * } + * catch (ex) + * { + * mxUtils.alert('Cannot load '+filename+': '+ex); + * } + * (end) + * + * Parameters: + * + * url - URL to get the data from. + */ + load: function(url) + { + var req = new mxXmlRequest(url, null, 'GET', false); + req.send(); + + return req; + }, + + /** + * Function: get + * + * Loads the specified URL *asynchronously* and invokes the given functions + * depending on the request status. Returns the in use. Both + * functions take the as the only parameter. See + * for a synchronous implementation. + * + * Example: + * + * (code) + * mxUtils.get(url, function(req) + * { + * var node = req.getDocumentElement(); + * // Process XML DOM... + * }); + * (end) + * + * So for example, to load a diagram into an existing graph model, the + * following code is used. + * + * (code) + * mxUtils.get(url, function(req) + * { + * var node = req.getDocumentElement(); + * var dec = new mxCodec(node.ownerDocument); + * dec.decode(node, graph.getModel()); + * }); + * (end) + * + * Parameters: + * + * url - URL to get the data from. + * onload - Optional function to execute for a successful response. + * onerror - Optional function to execute on error. + */ + get: function(url, onload, onerror) + { + return new mxXmlRequest(url, null, 'GET').send(onload, onerror); + }, + + /** + * Function: post + * + * Posts the specified params to the given URL *asynchronously* and invokes + * the given functions depending on the request status. Returns the + * in use. Both functions take the as the + * only parameter. Make sure to use encodeURIComponent for the parameter + * values. + * + * Example: + * + * (code) + * mxUtils.post(url, 'key=value', function(req) + * { + * mxUtils.alert('Ready: '+req.isReady()+' Status: '+req.getStatus()); + * // Process req.getDocumentElement() using DOM API if OK... + * }); + * (end) + * + * Parameters: + * + * url - URL to get the data from. + * params - Parameters for the post request. + * onload - Optional function to execute for a successful response. + * onerror - Optional function to execute on error. + */ + post: function(url, params, onload, onerror) + { + return new mxXmlRequest(url, params).send(onload, onerror); + }, + + /** + * Function: submit + * + * Submits the given parameters to the specified URL using + * and returns the . + * Make sure to use encodeURIComponent for the parameter + * values. + * + * Parameters: + * + * url - URL to get the data from. + * params - Parameters for the form. + * doc - Document to create the form in. + * target - Target to send the form result to. + */ + submit: function(url, params, doc, target) + { + return new mxXmlRequest(url, params).simulate(doc, target); + }, + + /** + * Function: loadInto + * + * Loads the specified URL *asynchronously* into the specified document, + * invoking onload after the document has been loaded. This implementation + * does not use , but the document.load method. + * + * Parameters: + * + * url - URL to get the data from. + * doc - The document to load the URL into. + * onload - Function to execute when the URL has been loaded. + */ + loadInto: function(url, doc, onload) + { + if (mxClient.IS_IE) + { + doc.onreadystatechange = function () + { + if (doc.readyState == 4) + { + onload(); + } + }; + } + else + { + doc.addEventListener('load', onload, false); + } + + doc.load(url); + }, + + /** + * Function: getValue + * + * Returns the value for the given key in the given associative array or + * the given default value if the value is null. + * + * Parameters: + * + * array - Associative array that contains the value for the key. + * key - Key whose value should be returned. + * defaultValue - Value to be returned if the value for the given + * key is null. + */ + getValue: function(array, key, defaultValue) + { + var value = (array != null) ? array[key] : null; + + if (value == null) + { + value = defaultValue; + } + + return value; + }, + + /** + * Function: getNumber + * + * Returns the numeric value for the given key in the given associative + * array or the given default value (or 0) if the value is null. The value + * is converted to a numeric value using the Number function. + * + * Parameters: + * + * array - Associative array that contains the value for the key. + * key - Key whose value should be returned. + * defaultValue - Value to be returned if the value for the given + * key is null. Default is 0. + */ + getNumber: function(array, key, defaultValue) + { + var value = (array != null) ? array[key] : null; + + if (value == null) + { + value = defaultValue || 0; + } + + return Number(value); + }, + + /** + * Function: getColor + * + * Returns the color value for the given key in the given associative + * array or the given default value if the value is null. If the value + * is then null is returned. + * + * Parameters: + * + * array - Associative array that contains the value for the key. + * key - Key whose value should be returned. + * defaultValue - Value to be returned if the value for the given + * key is null. Default is null. + */ + getColor: function(array, key, defaultValue) + { + var value = (array != null) ? array[key] : null; + + if (value == null) + { + value = defaultValue; + } + else if (value == mxConstants.NONE) + { + value = null; + } + + return value; + }, + + /** + * Function: clone + * + * Recursively clones the specified object ignoring all fieldnames in the + * given array of transient fields. is always + * ignored by this function. + * + * Parameters: + * + * obj - Object to be cloned. + * transients - Optional array of strings representing the fieldname to be + * ignored. + * shallow - Optional boolean argument to specify if a shallow clone should + * be created, that is, one where all object references are not cloned or, + * in other words, one where only atomic (strings, numbers) values are + * cloned. Default is false. + */ + clone: function(obj, transients, shallow) + { + shallow = (shallow != null) ? shallow : false; + var clone = null; + + if (obj != null && typeof(obj.constructor) == 'function') + { + clone = new obj.constructor(); + + for (var i in obj) + { + if (i != mxObjectIdentity.FIELD_NAME && (transients == null || + mxUtils.indexOf(transients, i) < 0)) + { + if (!shallow && typeof(obj[i]) == 'object') + { + clone[i] = mxUtils.clone(obj[i]); + } + else + { + clone[i] = obj[i]; + } + } + } + } + + return clone; + }, + + /** + * Function: equalPoints + * + * Compares all mxPoints in the given lists. + * + * Parameters: + * + * a - Array of to be compared. + * b - Array of to be compared. + */ + equalPoints: function(a, b) + { + if ((a == null && b != null) || (a != null && b == null) || + (a != null && b != null && a.length != b.length)) + { + return false; + } + else if (a != null && b != null) + { + for (var i = 0; i < a.length; i++) + { + if (a[i] == b[i] || (a[i] != null && !a[i].equals(b[i]))) + { + return false; + } + } + } + + return true; + }, + + /** + * Function: equalEntries + * + * Compares all entries in the given dictionaries. + * + * Parameters: + * + * a - to be compared. + * b - to be compared. + */ + equalEntries: function(a, b) + { + if ((a == null && b != null) || (a != null && b == null) || + (a != null && b != null && a.length != b.length)) + { + return false; + } + else if (a != null && b != null) + { + for (var key in a) + { + if (a[key] != b[key]) + { + return false; + } + } + } + + return true; + }, + + /** + * Function: extend + * + * Assigns a copy of the superclass prototype to the subclass prototype. + * Note that this does not call the constructor of the superclass at this + * point, the superclass constructor should be called explicitely in the + * subclass constructor. Below is an example. + * + * (code) + * MyGraph = function(container, model, renderHint, stylesheet) + * { + * mxGraph.call(this, container, model, renderHint, stylesheet); + * } + * + * mxUtils.extend(MyGraph, mxGraph); + * (end) + * + * Parameters: + * + * ctor - Constructor of the subclass. + * superCtor - Constructor of the superclass. + */ + extend: function(ctor, superCtor) + { + var f = function() {}; + f.prototype = superCtor.prototype; + + ctor.prototype = new f(); + ctor.prototype.constructor = ctor; + }, + + /** + * Function: toString + * + * Returns a textual representation of the specified object. + * + * Parameters: + * + * obj - Object to return the string representation for. + */ + toString: function(obj) + { + var output = ''; + + for (var i in obj) + { + try + { + if (obj[i] == null) + { + output += i + ' = [null]\n'; + } + else if (typeof(obj[i]) == 'function') + { + output += i + ' => [Function]\n'; + } + else if (typeof(obj[i]) == 'object') + { + var ctor = mxUtils.getFunctionName(obj[i].constructor); + output += i + ' => [' + ctor + ']\n'; + } + else + { + output += i + ' = ' + obj[i] + '\n'; + } + } + catch (e) + { + output += i + '=' + e.message; + } + } + + return output; + }, + + /** + * Function: toRadians + * + * Converts the given degree to radians. + */ + toRadians: function(deg) + { + return Math.PI * deg / 180; + }, + + /** + * Function: arcToCurves + * + * Converts the given arc to a series of curves. + */ + arcToCurves: function(x0, y0, r1, r2, angle, largeArcFlag, sweepFlag, x, y) + { + x -= x0; + y -= y0; + + if (r1 === 0 || r2 === 0) + { + return result; + } + + var fS = sweepFlag; + var psai = angle; + r1 = Math.abs(r1); + r2 = Math.abs(r2); + var ctx = -x / 2; + var cty = -y / 2; + var cpsi = Math.cos(psai * Math.PI / 180); + var spsi = Math.sin(psai * Math.PI / 180); + var rxd = cpsi * ctx + spsi * cty; + var ryd = -1 * spsi * ctx + cpsi * cty; + var rxdd = rxd * rxd; + var rydd = ryd * ryd; + var r1x = r1 * r1; + var r2y = r2 * r2; + var lamda = rxdd / r1x + rydd / r2y; + var sds; + + if (lamda > 1) + { + r1 = Math.sqrt(lamda) * r1; + r2 = Math.sqrt(lamda) * r2; + sds = 0; + } + else + { + var seif = 1; + + if (largeArcFlag === fS) + { + seif = -1; + } + + sds = seif * Math.sqrt((r1x * r2y - r1x * rydd - r2y * rxdd) / (r1x * rydd + r2y * rxdd)); + } + + var txd = sds * r1 * ryd / r2; + var tyd = -1 * sds * r2 * rxd / r1; + var tx = cpsi * txd - spsi * tyd + x / 2; + var ty = spsi * txd + cpsi * tyd + y / 2; + var rad = Math.atan2((ryd - tyd) / r2, (rxd - txd) / r1) - Math.atan2(0, 1); + var s1 = (rad >= 0) ? rad : 2 * Math.PI + rad; + rad = Math.atan2((-ryd - tyd) / r2, (-rxd - txd) / r1) - Math.atan2((ryd - tyd) / r2, (rxd - txd) / r1); + var dr = (rad >= 0) ? rad : 2 * Math.PI + rad; + + if (fS == 0 && dr > 0) + { + dr -= 2 * Math.PI; + } + else if (fS != 0 && dr < 0) + { + dr += 2 * Math.PI; + } + + var sse = dr * 2 / Math.PI; + var seg = Math.ceil(sse < 0 ? -1 * sse : sse); + var segr = dr / seg; + var t = 8/3 * Math.sin(segr / 4) * Math.sin(segr / 4) / Math.sin(segr / 2); + var cpsir1 = cpsi * r1; + var cpsir2 = cpsi * r2; + var spsir1 = spsi * r1; + var spsir2 = spsi * r2; + var mc = Math.cos(s1); + var ms = Math.sin(s1); + var x2 = -t * (cpsir1 * ms + spsir2 * mc); + var y2 = -t * (spsir1 * ms - cpsir2 * mc); + var x3 = 0; + var y3 = 0; + + var result = []; + + for (var n = 0; n < seg; ++n) + { + s1 += segr; + mc = Math.cos(s1); + ms = Math.sin(s1); + + x3 = cpsir1 * mc - spsir2 * ms + tx; + y3 = spsir1 * mc + cpsir2 * ms + ty; + var dx = -t * (cpsir1 * ms + spsir2 * mc); + var dy = -t * (spsir1 * ms - cpsir2 * mc); + + // CurveTo updates x0, y0 so need to restore it + var index = n * 6; + result[index] = Number(x2 + x0); + result[index + 1] = Number(y2 + y0); + result[index + 2] = Number(x3 - dx + x0); + result[index + 3] = Number(y3 - dy + y0); + result[index + 4] = Number(x3 + x0); + result[index + 5] = Number(y3 + y0); + + x2 = x3 + dx; + y2 = y3 + dy; + } + + return result; + }, + + /** + * Function: getBoundingBox + * + * Returns the bounding box for the rotated rectangle. + */ + getBoundingBox: function(rect, rotation) + { + var result = null; + + if (rect != null && rotation != null && rotation != 0) + { + var rad = mxUtils.toRadians(rotation); + var cos = Math.cos(rad); + var sin = Math.sin(rad); + + var cx = new mxPoint( + rect.x + rect.width / 2, + rect.y + rect.height / 2); + + var p1 = new mxPoint(rect.x, rect.y); + var p2 = new mxPoint(rect.x + rect.width, rect.y); + var p3 = new mxPoint(p2.x, rect.y + rect.height); + var p4 = new mxPoint(rect.x, p3.y); + + p1 = mxUtils.getRotatedPoint(p1, cos, sin, cx); + p2 = mxUtils.getRotatedPoint(p2, cos, sin, cx); + p3 = mxUtils.getRotatedPoint(p3, cos, sin, cx); + p4 = mxUtils.getRotatedPoint(p4, cos, sin, cx); + + result = new mxRectangle(p1.x, p1.y, 0, 0); + result.add(new mxRectangle(p2.x, p2.y, 0, 0)); + result.add(new mxRectangle(p3.x, p3.y, 0, 0)); + result.add(new mxRectangle(p4.x, p4.Y, 0, 0)); + } + + return result; + }, + + /** + * Function: getRotatedPoint + * + * Rotates the given point by the given cos and sin. + */ + getRotatedPoint: function(pt, cos, sin, c) + { + c = (c != null) ? c : new mxPoint(); + var x = pt.x - c.x; + var y = pt.y - c.y; + + var x1 = x * cos - y * sin; + var y1 = y * cos + x * sin; + + return new mxPoint(x1 + c.x, y1 + c.y); + }, + + /** + * Returns an integer mask of the port constraints of the given map + * @param dict the style map to determine the port constraints for + * @param defaultValue Default value to return if the key is undefined. + * @return the mask of port constraint directions + * + * Parameters: + * + * terminal - that represents the terminal. + * edge - that represents the edge. + * source - Boolean that specifies if the terminal is the source terminal. + * defaultValue - Default value to be returned. + */ + getPortConstraints: function(terminal, edge, source, defaultValue) + { + var value = mxUtils.getValue(terminal.style, mxConstants.STYLE_PORT_CONSTRAINT, null); + + if (value == null) + { + return defaultValue; + } + else + { + var directions = value.toString(); + var returnValue = mxConstants.DIRECTION_MASK_NONE; + + if (directions.indexOf(mxConstants.DIRECTION_NORTH) >= 0) + { + returnValue |= mxConstants.DIRECTION_MASK_NORTH; + } + if (directions.indexOf(mxConstants.DIRECTION_WEST) >= 0) + { + returnValue |= mxConstants.DIRECTION_MASK_WEST; + } + if (directions.indexOf(mxConstants.DIRECTION_SOUTH) >= 0) + { + returnValue |= mxConstants.DIRECTION_MASK_SOUTH; + } + if (directions.indexOf(mxConstants.DIRECTION_EAST) >= 0) + { + returnValue |= mxConstants.DIRECTION_MASK_EAST; + } + + return returnValue; + } + }, + + /** + * Function: reversePortConstraints + * + * Reverse the port constraint bitmask. For example, north | east + * becomes south | west + */ + reversePortConstraints: function(constraint) + { + var result = 0; + + result = (constraint & mxConstants.DIRECTION_MASK_WEST) << 3; + result |= (constraint & mxConstants.DIRECTION_MASK_NORTH) << 1; + result |= (constraint & mxConstants.DIRECTION_MASK_SOUTH) >> 1; + result |= (constraint & mxConstants.DIRECTION_MASK_EAST) >> 3; + + return result; + }, + + /** + * Function: findNearestSegment + * + * Finds the index of the nearest segment on the given cell state for + * the specified coordinate pair. + */ + findNearestSegment: function(state, x, y) + { + var index = -1; + + if (state.absolutePoints.length > 0) + { + var last = state.absolutePoints[0]; + var min = null; + + for (var i = 1; i < state.absolutePoints.length; i++) + { + var current = state.absolutePoints[i]; + var dist = mxUtils.ptSegDistSq(last.x, last.y, + current.x, current.y, x, y); + + if (min == null || dist < min) + { + min = dist; + index = i - 1; + } + + last = current; + } + } + + return index; + }, + + /** + * Function: rectangleIntersectsSegment + * + * Returns true if the given rectangle intersects the given segment. + * + * Parameters: + * + * bounds - that represents the rectangle. + * p1 - that represents the first point of the segment. + * p2 - that represents the second point of the segment. + */ + rectangleIntersectsSegment: function(bounds, p1, p2) + { + var top = bounds.y; + var left = bounds.x; + var bottom = top + bounds.height; + var right = left + bounds.width; + + // Find min and max X for the segment + var minX = p1.x; + var maxX = p2.x; + + if (p1.x > p2.x) + { + minX = p2.x; + maxX = p1.x; + } + + // Find the intersection of the segment's and rectangle's x-projections + if (maxX > right) + { + maxX = right; + } + + if (minX < left) + { + minX = left; + } + + if (minX > maxX) // If their projections do not intersect return false + { + return false; + } + + // Find corresponding min and max Y for min and max X we found before + var minY = p1.y; + var maxY = p2.y; + var dx = p2.x - p1.x; + + if (Math.abs(dx) > 0.0000001) + { + var a = (p2.y - p1.y) / dx; + var b = p1.y - a * p1.x; + minY = a * minX + b; + maxY = a * maxX + b; + } + + if (minY > maxY) + { + var tmp = maxY; + maxY = minY; + minY = tmp; + } + + // Find the intersection of the segment's and rectangle's y-projections + if (maxY > bottom) + { + maxY = bottom; + } + + if (minY < top) + { + minY = top; + } + + if (minY > maxY) // If Y-projections do not intersect return false + { + return false; + } + + return true; + }, + + /** + * Function: contains + * + * Returns true if the specified point (x, y) is contained in the given rectangle. + * + * Parameters: + * + * bounds - that represents the area. + * x - X-coordinate of the point. + * y - Y-coordinate of the point. + */ + contains: function(bounds, x, y) + { + return (bounds.x <= x && bounds.x + bounds.width >= x && + bounds.y <= y && bounds.y + bounds.height >= y); + }, + + /** + * Function: intersects + * + * Returns true if the two rectangles intersect. + * + * Parameters: + * + * a - to be checked for intersection. + * b - to be checked for intersection. + */ + intersects: function(a, b) + { + var tw = a.width; + var th = a.height; + var rw = b.width; + var rh = b.height; + + if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) + { + return false; + } + + var tx = a.x; + var ty = a.y; + var rx = b.x; + var ry = b.y; + + rw += rx; + rh += ry; + tw += tx; + th += ty; + + return ((rw < rx || rw > tx) && + (rh < ry || rh > ty) && + (tw < tx || tw > rx) && + (th < ty || th > ry)); + }, + + /** + * Function: intersects + * + * Returns true if the two rectangles intersect. + * + * Parameters: + * + * a - to be checked for intersection. + * b - to be checked for intersection. + */ + intersectsHotspot: function(state, x, y, hotspot, min, max) + { + hotspot = (hotspot != null) ? hotspot : 1; + min = (min != null) ? min : 0; + max = (max != null) ? max : 0; + + if (hotspot > 0) + { + var cx = state.getCenterX(); + var cy = state.getCenterY(); + var w = state.width; + var h = state.height; + + var start = mxUtils.getValue(state.style, + mxConstants.STYLE_STARTSIZE); + + if (start > 0) + { + if (mxUtils.getValue(state.style, + mxConstants.STYLE_HORIZONTAL, true)) + { + cy = state.y + start / 2; + h = start; + } + else + { + cx = state.x + start / 2; + w = start; + } + } + + w = Math.max(min, w * hotspot); + h = Math.max(min, h * hotspot); + + if (max > 0) + { + w = Math.min(w, max); + h = Math.min(h, max); + } + + var rect = new mxRectangle(cx - w / 2, cy - h / 2, w, h); + + return mxUtils.contains(rect, x, y); + } + + return true; + }, + + /** + * Function: getOffset + * + * Returns the offset for the specified container as an . The + * offset is the distance from the top left corner of the container to the + * top left corner of the document. + * + * Parameters: + * + * container - DOM node to return the offset for. + */ + getOffset: function(container) + { + // TODO: Take scrollbar into account + var offsetLeft = 0; + var offsetTop = 0; + + while (container.offsetParent) + { + offsetLeft += container.offsetLeft; + offsetTop += container.offsetTop; + + container = container.offsetParent; + } + + return new mxPoint(offsetLeft, offsetTop); + }, + + /** + * Function: getScrollOrigin + * + * Returns the top, left corner of the viewrect as an . + */ + getScrollOrigin: function(node) + { + var b = document.body; + var d = document.documentElement; + var sl = (b.scrollLeft || d.scrollLeft); + var st = (b.scrollTop || d.scrollTop); + + var result = new mxPoint(sl, st); + + while (node != null && node != b && node != d) + { + if (!isNaN(node.scrollLeft) && !isNaN(node.scrollTop)) + { + result.x += node.scrollLeft; + result.y += node.scrollTop; + } + + node = node.parentNode; + } + + return result; + }, + + /** + * Function: convertPoint + * + * Converts the specified point (x, y) using the offset of the specified + * container and returns a new with the result. + * + * Parameters: + * + * container - DOM node to use for the offset. + * x - X-coordinate of the point to be converted. + * y - Y-coordinate of the point to be converted. + */ + convertPoint: function(container, x, y) + { + var origin = mxUtils.getScrollOrigin(container); + var offset = mxUtils.getOffset(container); + + offset.x -= origin.x; + offset.y -= origin.y; + + return new mxPoint(x - offset.x, y - offset.y); + }, + + /** + * Function: ltrim + * + * Strips all whitespaces from the beginning of the string. + * Without the second parameter, Javascript function will trim these + * characters: + * + * - " " (ASCII 32 (0x20)), an ordinary space + * - "\t" (ASCII 9 (0x09)), a tab + * - "\n" (ASCII 10 (0x0A)), a new line (line feed) + * - "\r" (ASCII 13 (0x0D)), a carriage return + * - "\0" (ASCII 0 (0x00)), the NUL-byte + * - "\x0B" (ASCII 11 (0x0B)), a vertical tab + */ + ltrim: function(str, chars) + { + chars = chars || "\\s"; + + return str.replace(new RegExp("^[" + chars + "]+", "g"), ""); + }, + + /** + * Function: rtrim + * + * Strips all whitespaces from the end of the string. + * Without the second parameter, Javascript function will trim these + * characters: + * + * - " " (ASCII 32 (0x20)), an ordinary space + * - "\t" (ASCII 9 (0x09)), a tab + * - "\n" (ASCII 10 (0x0A)), a new line (line feed) + * - "\r" (ASCII 13 (0x0D)), a carriage return + * - "\0" (ASCII 0 (0x00)), the NUL-byte + * - "\x0B" (ASCII 11 (0x0B)), a vertical tab + */ + rtrim: function(str, chars) + { + chars = chars || "\\s"; + + return str.replace(new RegExp("[" + chars + "]+$", "g"), ""); + }, + + /** + * Function: trim + * + * Strips all whitespaces from both end of the string. + * Without the second parameter, Javascript function will trim these + * characters: + * + * - " " (ASCII 32 (0x20)), an ordinary space + * - "\t" (ASCII 9 (0x09)), a tab + * - "\n" (ASCII 10 (0x0A)), a new line (line feed) + * - "\r" (ASCII 13 (0x0D)), a carriage return + * - "\0" (ASCII 0 (0x00)), the NUL-byte + * - "\x0B" (ASCII 11 (0x0B)), a vertical tab + */ + trim: function(str, chars) + { + return mxUtils.ltrim(mxUtils.rtrim(str, chars), chars); + }, + + /** + * Function: isNumeric + * + * Returns true if the specified value is numeric, that is, if it is not + * null, not an empty string, not a HEX number and isNaN returns false. + * + * Parameters: + * + * str - String representing the possibly numeric value. + */ + isNumeric: function(str) + { + return str != null && (str.length == null || (str.length > 0 && + str.indexOf('0x') < 0) && str.indexOf('0X') < 0) && !isNaN(str); + }, + + /** + * Function: mod + * + * Returns the remainder of division of n by m. You should use this instead + * of the built-in operation as the built-in operation does not properly + * handle negative numbers. + */ + mod: function(n, m) + { + return ((n % m) + m) % m; + }, + + /** + * Function: intersection + * + * Returns the intersection of two lines as an . + * + * Parameters: + * + * x0 - X-coordinate of the first line's startpoint. + * y0 - X-coordinate of the first line's startpoint. + * x1 - X-coordinate of the first line's endpoint. + * y1 - Y-coordinate of the first line's endpoint. + * x2 - X-coordinate of the second line's startpoint. + * y2 - Y-coordinate of the second line's startpoint. + * x3 - X-coordinate of the second line's endpoint. + * y3 - Y-coordinate of the second line's endpoint. + */ + intersection: function (x0, y0, x1, y1, x2, y2, x3, y3) + { + var denom = ((y3 - y2)*(x1 - x0)) - ((x3 - x2)*(y1 - y0)); + var nume_a = ((x3 - x2)*(y0 - y2)) - ((y3 - y2)*(x0 - x2)); + var nume_b = ((x1 - x0)*(y0 - y2)) - ((y1 - y0)*(x0 - x2)); + + var ua = nume_a / denom; + var ub = nume_b / denom; + + if(ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0) + { + // Get the intersection point + var intersectionX = x0 + ua*(x1 - x0); + var intersectionY = y0 + ua*(y1 - y0); + + return new mxPoint(intersectionX, intersectionY); + } + + // No intersection + return null; + }, + + /** + * Function: ptSeqDistSq + * + * Returns the square distance between a segment and a point. + * + * Parameters: + * + * x1 - X-coordinate of the startpoint of the segment. + * y1 - Y-coordinate of the startpoint of the segment. + * x2 - X-coordinate of the endpoint of the segment. + * y2 - Y-coordinate of the endpoint of the segment. + * px - X-coordinate of the point. + * py - Y-coordinate of the point. + */ + ptSegDistSq: function(x1, y1, x2, y2, px, py) + { + x2 -= x1; + y2 -= y1; + + px -= x1; + py -= y1; + + var dotprod = px * x2 + py * y2; + var projlenSq; + + if (dotprod <= 0.0) + { + projlenSq = 0.0; + } + else + { + px = x2 - px; + py = y2 - py; + dotprod = px * x2 + py * y2; + + if (dotprod <= 0.0) + { + projlenSq = 0.0; + } + else + { + projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2); + } + } + + var lenSq = px * px + py * py - projlenSq; + + if (lenSq < 0) + { + lenSq = 0; + } + + return lenSq; + }, + + /** + * Function: relativeCcw + * + * Returns 1 if the given point on the right side of the segment, 0 if its + * on the segment, and -1 if the point is on the left side of the segment. + * + * Parameters: + * + * x1 - X-coordinate of the startpoint of the segment. + * y1 - Y-coordinate of the startpoint of the segment. + * x2 - X-coordinate of the endpoint of the segment. + * y2 - Y-coordinate of the endpoint of the segment. + * px - X-coordinate of the point. + * py - Y-coordinate of the point. + */ + relativeCcw: function(x1, y1, x2, y2, px, py) + { + x2 -= x1; + y2 -= y1; + px -= x1; + py -= y1; + var ccw = px * y2 - py * x2; + + if (ccw == 0.0) + { + ccw = px * x2 + py * y2; + + if (ccw > 0.0) + { + px -= x2; + py -= y2; + ccw = px * x2 + py * y2; + + if (ccw < 0.0) + { + ccw = 0.0; + } + } + } + + return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); + }, + + /** + * Function: animateChanges + * + * See . This is for backwards compatibility and + * will be removed later. + */ + animateChanges: function(graph, changes) + { + // LATER: Deprecated, remove this function + mxEffects.animateChanges.apply(this, arguments); + }, + + /** + * Function: cascadeOpacity + * + * See . This is for backwards compatibility and + * will be removed later. + */ + cascadeOpacity: function(graph, cell, opacity) + { + mxEffects.cascadeOpacity.apply(this, arguments); + }, + + /** + * Function: fadeOut + * + * See . This is for backwards compatibility and + * will be removed later. + */ + fadeOut: function(node, from, remove, step, delay, isEnabled) + { + mxEffects.fadeOut.apply(this, arguments); + }, + + /** + * Function: setOpacity + * + * Sets the opacity of the specified DOM node to the given value in %. + * + * Parameters: + * + * node - DOM node to set the opacity for. + * value - Opacity in %. Possible values are between 0 and 100. + */ + setOpacity: function(node, value) + { + if (mxUtils.isVml(node)) + { + if (value >= 100) + { + node.style.filter = null; + } + else + { + // TODO: Why is the division by 5 needed in VML? + node.style.filter = 'alpha(opacity=' + (value/5) + ')'; + } + } + else if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) + { + if (value >= 100) + { + node.style.filter = null; + } + else + { + node.style.filter = 'alpha(opacity=' + value + ')'; + } + } + else + { + node.style.opacity = (value / 100); + } + }, + + /** + * Function: createImage + * + * Creates and returns an image (IMG node) or VML image (v:image) in IE6 in + * quirs mode. + * + * Parameters: + * + * src - URL that points to the image to be displayed. + */ + createImage: function(src) + { + var imageNode = null; + + if (mxClient.IS_IE6 && document.compatMode != 'CSS1Compat') + { + imageNode = document.createElement('v:image'); + imageNode.setAttribute('src', src); + imageNode.style.borderStyle = 'none'; + } + else + { + imageNode = document.createElement('img'); + imageNode.setAttribute('src', src); + imageNode.setAttribute('border', '0'); + } + + return imageNode; + }, + + /** + * Function: sortCells + * + * Sorts the given cells according to the order in the cell hierarchy. + * Ascending is optional and defaults to true. + */ + sortCells: function(cells, ascending) + { + ascending = (ascending != null) ? ascending : true; + var lookup = new mxDictionary(); + cells.sort(function(o1, o2) + { + var p1 = lookup.get(o1); + + if (p1 == null) + { + p1 = mxCellPath.create(o1).split(mxCellPath.PATH_SEPARATOR); + lookup.put(o1, p1); + } + + var p2 = lookup.get(o2); + + if (p2 == null) + { + p2 = mxCellPath.create(o2).split(mxCellPath.PATH_SEPARATOR); + lookup.put(o2, p2); + } + + var comp = mxCellPath.compare(p1, p2); + + return (comp == 0) ? 0 : (((comp > 0) == ascending) ? 1 : -1); + }); + + return cells; + }, + + /** + * Function: getStylename + * + * Returns the stylename in a style of the form [(stylename|key=value);] or + * an empty string if the given style does not contain a stylename. + * + * Parameters: + * + * style - String of the form [(stylename|key=value);]. + */ + getStylename: function(style) + { + if (style != null) + { + var pairs = style.split(';'); + var stylename = pairs[0]; + + if (stylename.indexOf('=') < 0) + { + return stylename; + } + } + + return ''; + }, + + /** + * Function: getStylenames + * + * Returns the stylenames in a style of the form [(stylename|key=value);] + * or an empty array if the given style does not contain any stylenames. + * + * Parameters: + * + * style - String of the form [(stylename|key=value);]. + */ + getStylenames: function(style) + { + var result = []; + + if (style != null) + { + var pairs = style.split(';'); + + for (var i = 0; i < pairs.length; i++) + { + if (pairs[i].indexOf('=') < 0) + { + result.push(pairs[i]); + } + } + } + + return result; + }, + + /** + * Function: indexOfStylename + * + * Returns the index of the given stylename in the given style. This + * returns -1 if the given stylename does not occur (as a stylename) in the + * given style, otherwise it returns the index of the first character. + */ + indexOfStylename: function(style, stylename) + { + if (style != null && stylename != null) + { + var tokens = style.split(';'); + var pos = 0; + + for (var i = 0; i < tokens.length; i++) + { + if (tokens[i] == stylename) + { + return pos; + } + + pos += tokens[i].length + 1; + } + } + + return -1; + }, + + /** + * Function: addStylename + * + * Adds the specified stylename to the given style if it does not already + * contain the stylename. + */ + addStylename: function(style, stylename) + { + if (mxUtils.indexOfStylename(style, stylename) < 0) + { + if (style == null) + { + style = ''; + } + else if (style.length > 0 && style.charAt(style.length - 1) != ';') + { + style += ';'; + } + + style += stylename; + } + + return style; + }, + + /** + * Function: removeStylename + * + * Removes all occurrences of the specified stylename in the given style + * and returns the updated style. Trailing semicolons are not preserved. + */ + removeStylename: function(style, stylename) + { + var result = []; + + if (style != null) + { + var tokens = style.split(';'); + + for (var i = 0; i < tokens.length; i++) + { + if (tokens[i] != stylename) + { + result.push(tokens[i]); + } + } + } + + return result.join(';'); + }, + + /** + * Function: removeAllStylenames + * + * Removes all stylenames from the given style and returns the updated + * style. + */ + removeAllStylenames: function(style) + { + var result = []; + + if (style != null) + { + var tokens = style.split(';'); + + for (var i = 0; i < tokens.length; i++) + { + // Keeps the key, value assignments + if (tokens[i].indexOf('=') >= 0) + { + result.push(tokens[i]); + } + } + } + + return result.join(';'); + }, + + /** + * Function: setCellStyles + * + * Assigns the value for the given key in the styles of the given cells, or + * removes the key from the styles if the value is null. + * + * Parameters: + * + * model - to execute the transaction in. + * cells - Array of to be updated. + * key - Key of the style to be changed. + * value - New value for the given key. + */ + setCellStyles: function(model, cells, key, value) + { + if (cells != null && cells.length > 0) + { + model.beginUpdate(); + try + { + for (var i = 0; i < cells.length; i++) + { + if (cells[i] != null) + { + var style = mxUtils.setStyle( + model.getStyle(cells[i]), + key, value); + model.setStyle(cells[i], style); + } + } + } + finally + { + model.endUpdate(); + } + } + }, + + /** + * Function: setStyle + * + * Adds or removes the given key, value pair to the style and returns the + * new style. If value is null or zero length then the key is removed from + * the style. This is for cell styles, not for CSS styles. + * + * Parameters: + * + * style - String of the form [(stylename|key=value);]. + * key - Key of the style to be changed. + * value - New value for the given key. + */ + setStyle: function(style, key, value) + { + var isValue = value != null && (typeof(value.length) == 'undefined' || value.length > 0); + + if (style == null || style.length == 0) + { + if (isValue) + { + style = key+'='+value; + } + } + else + { + var index = style.indexOf(key+'='); + + if (index < 0) + { + if (isValue) + { + var sep = (style.charAt(style.length-1) == ';') ? '' : ';'; + style = style + sep + key+'='+value; + } + } + else + { + var tmp = (isValue) ? (key + '=' + value) : ''; + var cont = style.indexOf(';', index); + + if (!isValue) + { + cont++; + } + + style = style.substring(0, index) + tmp + + ((cont > index) ? style.substring(cont) : ''); + } + } + + return style; + }, + + /** + * Function: setCellStyleFlags + * + * Sets or toggles the flag bit for the given key in the cell's styles. + * If value is null then the flag is toggled. + * + * Example: + * + * (code) + * var cells = graph.getSelectionCells(); + * mxUtils.setCellStyleFlags(graph.model, + * cells, + * mxConstants.STYLE_FONTSTYLE, + * mxConstants.FONT_BOLD); + * (end) + * + * Toggles the bold font style. + * + * Parameters: + * + * model - that contains the cells. + * cells - Array of to change the style for. + * key - Key of the style to be changed. + * flag - Integer for the bit to be changed. + * value - Optional boolean value for the flag. + */ + setCellStyleFlags: function(model, cells, key, flag, value) + { + if (cells != null && cells.length > 0) + { + model.beginUpdate(); + try + { + for (var i = 0; i < cells.length; i++) + { + if (cells[i] != null) + { + var style = mxUtils.setStyleFlag( + model.getStyle(cells[i]), + key, flag, value); + model.setStyle(cells[i], style); + } + } + } + finally + { + model.endUpdate(); + } + } + }, + + /** + * Function: setStyleFlag + * + * Sets or removes the given key from the specified style and returns the + * new style. If value is null then the flag is toggled. + * + * Parameters: + * + * style - String of the form [(stylename|key=value);]. + * key - Key of the style to be changed. + * flag - Integer for the bit to be changed. + * value - Optional boolean value for the given flag. + */ + setStyleFlag: function(style, key, flag, value) + { + if (style == null || style.length == 0) + { + if (value || value == null) + { + style = key+'='+flag; + } + else + { + style = key+'=0'; + } + } + else + { + var index = style.indexOf(key+'='); + + if (index < 0) + { + var sep = (style.charAt(style.length-1) == ';') ? '' : ';'; + + if (value || value == null) + { + style = style + sep + key + '=' + flag; + } + else + { + style = style + sep + key + '=0'; + } + } + else + { + var cont = style.indexOf(';', index); + var tmp = ''; + + if (cont < 0) + { + tmp = style.substring(index+key.length+1); + } + else + { + tmp = style.substring(index+key.length+1, cont); + } + + if (value == null) + { + tmp = parseInt(tmp) ^ flag; + } + else if (value) + { + tmp = parseInt(tmp) | flag; + } + else + { + tmp = parseInt(tmp) & ~flag; + } + + style = style.substring(0, index) + key + '=' + tmp + + ((cont >= 0) ? style.substring(cont) : ''); + } + } + + return style; + }, + + /** + * Function: getSizeForString + * + * Returns an with the size (width and height in pixels) of + * the given string. The string may contain HTML markup. Newlines should be + * converted to
before calling this method. + * + * Example: + * + * (code) + * var label = graph.getLabel(cell).replace(/\n/g, "
"); + * var size = graph.getSizeForString(label); + * (end) + * + * Parameters: + * + * text - String whose size should be returned. + * fontSize - Integer that specifies the font size in pixels. Default is + * . + * fontFamily - String that specifies the name of the font family. Default + * is . + */ + getSizeForString: function(text, fontSize, fontFamily) + { + var div = document.createElement('div'); + + // Sets the font size and family if non-default + div.style.fontSize = fontSize || mxConstants.DEFAULT_FONTSIZE; + div.style.fontFamily = fontFamily || mxConstants.DEFAULT_FONTFAMILY; + + // Disables block layout and outside wrapping and hides the div + div.style.position = 'absolute'; + div.style.display = 'inline'; + div.style.visibility = 'hidden'; + + // Adds the text and inserts into DOM for updating of size + div.innerHTML = text; + document.body.appendChild(div); + + // Gets the size and removes from DOM + var size = new mxRectangle(0, 0, div.offsetWidth, div.offsetHeight); + document.body.removeChild(div); + + return size; + }, + + /** + * Function: getViewXml + */ + getViewXml: function(graph, scale, cells, x0, y0) + { + x0 = (x0 != null) ? x0 : 0; + y0 = (y0 != null) ? y0 : 0; + scale = (scale != null) ? scale : 1; + + if (cells == null) + { + var model = graph.getModel(); + cells = [model.getRoot()]; + } + + var view = graph.getView(); + var result = null; + + // Disables events on the view + var eventsEnabled = view.isEventsEnabled(); + view.setEventsEnabled(false); + + // Workaround for label bounds not taken into account for image export. + // Creates a temporary draw pane which is used for rendering the text. + // Text rendering is required for finding the bounds of the labels. + var drawPane = view.drawPane; + var overlayPane = view.overlayPane; + + if (graph.dialect == mxConstants.DIALECT_SVG) + { + view.drawPane = document.createElementNS(mxConstants.NS_SVG, 'g'); + view.canvas.appendChild(view.drawPane); + + // Redirects cell overlays into temporary container + view.overlayPane = document.createElementNS(mxConstants.NS_SVG, 'g'); + view.canvas.appendChild(view.overlayPane); + } + else + { + view.drawPane = view.drawPane.cloneNode(false); + view.canvas.appendChild(view.drawPane); + + // Redirects cell overlays into temporary container + view.overlayPane = view.overlayPane.cloneNode(false); + view.canvas.appendChild(view.overlayPane); + } + + // Resets the translation + var translate = view.getTranslate(); + view.translate = new mxPoint(x0, y0); + + // Creates the temporary cell states in the view + var temp = new mxTemporaryCellStates(graph.getView(), scale, cells); + + try + { + var enc = new mxCodec(); + result = enc.encode(graph.getView()); + } + finally + { + temp.destroy(); + view.translate = translate; + view.canvas.removeChild(view.drawPane); + view.canvas.removeChild(view.overlayPane); + view.drawPane = drawPane; + view.overlayPane = overlayPane; + view.setEventsEnabled(eventsEnabled); + } + + return result; + }, + + /** + * Function: getScaleForPageCount + * + * Returns the scale to be used for printing the graph with the given + * bounds across the specifies number of pages with the given format. The + * scale is always computed such that it given the given amount or fewer + * pages in the print output. See for an example. + * + * Parameters: + * + * pageCount - Specifies the number of pages in the print output. + * graph - that should be printed. + * pageFormat - Optional that specifies the page format. + * Default is . + * border - The border along each side of every page. + */ + getScaleForPageCount: function(pageCount, graph, pageFormat, border) + { + if (pageCount < 1) + { + // We can't work with less than 1 page, return no scale + // change + return 1; + } + + pageFormat = (pageFormat != null) ? pageFormat : mxConstants.PAGE_FORMAT_A4_PORTRAIT; + border = (border != null) ? border : 0; + + var availablePageWidth = pageFormat.width - (border * 2); + var availablePageHeight = pageFormat.height - (border * 2); + + // Work out the number of pages required if the + // graph is not scaled. + var graphBounds = graph.getGraphBounds().clone(); + var sc = graph.getView().getScale(); + graphBounds.width /= sc; + graphBounds.height /= sc; + var graphWidth = graphBounds.width; + var graphHeight = graphBounds.height; + + var scale = 1; + + // The ratio of the width/height for each printer page + var pageFormatAspectRatio = availablePageWidth / availablePageHeight; + // The ratio of the width/height for the graph to be printer + var graphAspectRatio = graphWidth / graphHeight; + + // The ratio of horizontal pages / vertical pages for this + // graph to maintain its aspect ratio on this page format + var pagesAspectRatio = graphAspectRatio / pageFormatAspectRatio; + + // Factor the square root of the page count up and down + // by the pages aspect ratio to obtain a horizontal and + // vertical page count that adds up to the page count + // and has the correct aspect ratio + var pageRoot = Math.sqrt(pageCount); + var pagesAspectRatioSqrt = Math.sqrt(pagesAspectRatio); + var numRowPages = pageRoot * pagesAspectRatioSqrt; + var numColumnPages = pageRoot / pagesAspectRatioSqrt; + + // These value are rarely more than 2 rounding downs away from + // a total that meets the page count. In cases of one being less + // than 1 page, the other value can be too high and take more iterations + // In this case, just change that value to be the page count, since + // we know the other value is 1 + if (numRowPages < 1 && numColumnPages > pageCount) + { + var scaleChange = numColumnPages / pageCount; + numColumnPages = pageCount; + numRowPages /= scaleChange; + } + + if (numColumnPages < 1 && numRowPages > pageCount) + { + var scaleChange = numRowPages / pageCount; + numRowPages = pageCount; + numColumnPages /= scaleChange; + } + + var currentTotalPages = Math.ceil(numRowPages) * Math.ceil(numColumnPages); + + var numLoops = 0; + + // Iterate through while the rounded up number of pages comes to + // a total greater than the required number + while (currentTotalPages > pageCount) + { + // Round down the page count (rows or columns) that is + // closest to its next integer down in percentage terms. + // i.e. Reduce the page total by reducing the total + // page area by the least possible amount + + var roundRowDownProportion = Math.floor(numRowPages) / numRowPages; + var roundColumnDownProportion = Math.floor(numColumnPages) / numColumnPages; + + // If the round down proportion is, work out the proportion to + // round down to 1 page less + if (roundRowDownProportion == 1) + { + roundRowDownProportion = Math.floor(numRowPages-1) / numRowPages; + } + if (roundColumnDownProportion == 1) + { + roundColumnDownProportion = Math.floor(numColumnPages-1) / numColumnPages; + } + + // Check which rounding down is smaller, but in the case of very small roundings + // try the other dimension instead + var scaleChange = 1; + + // Use the higher of the two values + if (roundRowDownProportion > roundColumnDownProportion) + { + scaleChange = roundRowDownProportion; + } + else + { + scaleChange = roundColumnDownProportion; + } + + numRowPages = numRowPages * scaleChange; + numColumnPages = numColumnPages * scaleChange; + currentTotalPages = Math.ceil(numRowPages) * Math.ceil(numColumnPages); + + numLoops++; + + if (numLoops > 10) + { + break; + } + } + + // Work out the scale from the number of row pages required + // The column pages will give the same value + var posterWidth = availablePageWidth * numRowPages; + scale = posterWidth / graphWidth; + + // Allow for rounding errors + return scale * 0.99999; + }, + + /** + * Function: show + * + * Copies the styles and the markup from the graph's container into the + * given document and removes all cursor styles. The document is returned. + * + * This function should be called from within the document with the graph. + * If you experience problems with missing stylesheets in IE then try adding + * the domain to the trusted sites. + * + * Parameters: + * + * graph - to be copied. + * doc - Document where the new graph is created. + * x0 - X-coordinate of the graph view origin. Default is 0. + * y0 - Y-coordinate of the graph view origin. Default is 0. + */ + show: function(graph, doc, x0, y0) + { + x0 = (x0 != null) ? x0 : 0; + y0 = (y0 != null) ? y0 : 0; + + if (doc == null) + { + var wnd = window.open(); + doc = wnd.document; + } + else + { + doc.open(); + } + + var bounds = graph.getGraphBounds(); + var dx = -bounds.x + x0; + var dy = -bounds.y + y0; + + // Needs a special way of creating the page so that no click is required + // to refresh the contents after the external CSS styles have been loaded. + // To avoid a click or programmatic refresh, the styleSheets[].cssText + // property is copied over from the original document. + if (mxClient.IS_IE) + { + var html = ''; + html += ''; + + var base = document.getElementsByTagName('base'); + + for (var i = 0; i < base.length; i++) + { + html += base[i].outerHTML; + } + + html += ''; + + html += ''; + html += ''; + + // Copies the contents of the graph container + html += graph.container.innerHTML; + + html += ''; + html += ''; + + doc.writeln(html); + doc.close(); + + // Makes sure the inner container is on the top, left + var node = doc.body.getElementsByTagName('DIV')[0]; + + if (node != null) + { + node.style.position = 'absolute'; + node.style.left = dx + 'px'; + node.style.top = dy + 'px'; + } + } + else + { + doc.writeln(''); + + var base = document.getElementsByTagName('base'); + + for (var i=0; i'); + doc.writeln(''); + doc.close(); + + // Workaround for FF2 which has no body element in a document where + // the body has been added using document.write. + if (doc.body == null) + { + doc.documentElement.appendChild(doc.createElement('body')); + } + + // Workaround for missing scrollbars in FF + doc.body.style.overflow = 'auto'; + + var node = graph.container.firstChild; + + while (node != null) + { + var clone = node.cloneNode(true); + doc.body.appendChild(clone); + node = node.nextSibling; + } + + // Shifts negative coordinates into visible space + var node = doc.getElementsByTagName('g')[0]; + + if (node != null) + { + node.setAttribute('transform', 'translate(' + dx + ',' + dy + ')'); + + // Updates the size of the SVG container + var root = node.ownerSVGElement; + root.setAttribute('width', bounds.width + Math.max(bounds.x, 0) + 3); + root.setAttribute('height', bounds.height + Math.max(bounds.y, 0) + 3); + } + } + + mxUtils.removeCursors(doc.body); + + return doc; + }, + + /** + * Function: printScreen + * + * Prints the specified graph using a new window and the built-in print + * dialog. + * + * This function should be called from within the document with the graph. + * + * Parameters: + * + * graph - to be printed. + */ + printScreen: function(graph) + { + var wnd = window.open(); + mxUtils.show(graph, wnd.document); + + var print = function() + { + wnd.focus(); + wnd.print(); + wnd.close(); + }; + + // Workaround for Google Chrome which needs a bit of a + // delay in order to render the SVG contents + if (mxClient.IS_GC) + { + wnd.setTimeout(print, 500); + } + else + { + print(); + } + }, + + /** + * Function: popup + * + * Shows the specified text content in a new or a new browser + * window if isInternalWindow is false. + * + * Parameters: + * + * content - String that specifies the text to be displayed. + * isInternalWindow - Optional boolean indicating if an mxWindow should be + * used instead of a new browser window. Default is false. + */ + popup: function(content, isInternalWindow) + { + if (isInternalWindow) + { + var div = document.createElement('div'); + + div.style.overflow = 'scroll'; + div.style.width = '636px'; + div.style.height = '460px'; + + var pre = document.createElement('pre'); + pre.innerHTML = mxUtils.htmlEntities(content, false). + replace(/\n/g,'
').replace(/ /g, ' '); + + div.appendChild(pre); + + var w = document.body.clientWidth; + var h = (document.body.clientHeight || document.documentElement.clientHeight); + var wnd = new mxWindow('Popup Window', div, + w/2-320, h/2-240, 640, 480, false, true); + + wnd.setClosable(true); + wnd.setVisible(true); + } + else + { + // Wraps up the XML content in a textarea + if (mxClient.IS_NS) + { + var wnd = window.open(); + wnd.document.writeln('
'+mxUtils.htmlEntities(content)+'').replace(/ /g, ' ');
+			   	wnd.document.body.appendChild(pre);
+			}
+	   	}
+	},
+	
+	/**
+	 * Function: alert
+	 * 
+	 * Displayss the given alert in a new dialog. This implementation uses the
+	 * built-in alert function. This is used to display validation errors when
+	 * connections cannot be changed or created.
+	 * 
+	 * Parameters:
+	 * 
+	 * message - String specifying the message to be displayed.
+	 */
+	alert: function(message)
+	{
+		alert(message);
+	},
+	
+	/**
+	 * Function: prompt
+	 * 
+	 * Displays the given message in a prompt dialog. This implementation uses
+	 * the built-in prompt function.
+	 * 
+	 * Parameters:
+	 * 
+	 * message - String specifying the message to be displayed.
+	 * defaultValue - Optional string specifying the default value.
+	 */
+	prompt: function(message, defaultValue)
+	{
+		return prompt(message, defaultValue);
+	},
+	
+	/**
+	 * Function: confirm
+	 * 
+	 * Displays the given message in a confirm dialog. This implementation uses
+	 * the built-in confirm function.
+	 * 
+	 * Parameters:
+	 * 
+	 * message - String specifying the message to be displayed.
+	 */
+	confirm: function(message)
+	{
+		return confirm(message);
+	},
+
+	/**
+	 * Function: error
+	 * 
+	 * Displays the given error message in a new  of the given width.
+	 * If close is true then an additional close button is added to the window.
+	 * The optional icon specifies the icon to be used for the window. Default
+	 * is .
+	 * 
+	 * Parameters:
+	 * 
+	 * message - String specifying the message to be displayed.
+	 * width - Integer specifying the width of the window.
+	 * close - Optional boolean indicating whether to add a close button.
+	 * icon - Optional icon for the window decoration.
+	 */
+	error: function(message, width, close, icon)
+	{
+		var div = document.createElement('div');
+		div.style.padding = '20px';
+
+		var img = document.createElement('img');
+		img.setAttribute('src', icon || mxUtils.errorImage);
+		img.setAttribute('valign', 'bottom');
+		img.style.verticalAlign = 'middle';
+		div.appendChild(img);
+
+		div.appendChild(document.createTextNode('\u00a0')); //  
+		div.appendChild(document.createTextNode('\u00a0')); //  
+		div.appendChild(document.createTextNode('\u00a0')); //  
+		mxUtils.write(div, message);
+
+		var w = document.body.clientWidth;
+		var h = (document.body.clientHeight || document.documentElement.clientHeight);
+		var warn = new mxWindow(mxResources.get(mxUtils.errorResource) ||
+			mxUtils.errorResource, div, (w-width)/2, h/4, width, null,
+			false, true);
+
+		if (close)
+		{
+			mxUtils.br(div);
+			
+			var tmp = document.createElement('p');
+			var button = document.createElement('button');
+
+			if (mxClient.IS_IE)
+			{
+				button.style.cssText = 'float:right';
+			}
+			else
+			{
+				button.setAttribute('style', 'float:right');
+			}
+
+			mxEvent.addListener(button, 'click', function(evt)
+			{
+				warn.destroy();
+			});
+
+			mxUtils.write(button, mxResources.get(mxUtils.closeResource) ||
+				mxUtils.closeResource);
+			
+			tmp.appendChild(button);
+			div.appendChild(tmp);
+			
+			mxUtils.br(div);
+			
+			warn.setClosable(true);
+		}
+		
+		warn.setVisible(true);
+		
+		return warn;
+	},
+
+	/**
+	 * Function: makeDraggable
+	 * 
+	 * Configures the given DOM element to act as a drag source for the
+	 * specified graph. Returns a a new . If
+	 *  is enabled then the x and y arguments must
+	 * be used in funct to match the preview location.
+	 * 
+	 * Example:
+	 * 
+	 * (code)
+	 * var funct = function(graph, evt, cell, x, y)
+	 * {
+	 *   if (graph.canImportCell(cell))
+	 *   {
+	 *     var parent = graph.getDefaultParent();
+	 *     var vertex = null;
+	 *     
+	 *     graph.getModel().beginUpdate();
+	 *     try
+	 *     {
+	 * 	     vertex = graph.insertVertex(parent, null, 'Hello', x, y, 80, 30);
+	 *     }
+	 *     finally
+	 *     {
+	 *       graph.getModel().endUpdate();
+	 *     }
+	 *
+	 *     graph.setSelectionCell(vertex);
+	 *   }
+	 * }
+	 * 
+	 * var img = document.createElement('img');
+	 * img.setAttribute('src', 'editors/images/rectangle.gif');
+	 * img.style.position = 'absolute';
+	 * img.style.left = '0px';
+	 * img.style.top = '0px';
+	 * img.style.width = '16px';
+	 * img.style.height = '16px';
+	 * 
+	 * var dragImage = img.cloneNode(true);
+	 * dragImage.style.width = '32px';
+	 * dragImage.style.height = '32px';
+	 * mxUtils.makeDraggable(img, graph, funct, dragImage);
+	 * document.body.appendChild(img);
+	 * (end)
+	 * 
+	 * Parameters:
+	 * 
+	 * element - DOM element to make draggable.
+	 * graphF -  that acts as the drop target or a function that takes a
+	 * mouse event and returns the current .
+	 * funct - Function to execute on a successful drop.
+	 * dragElement - Optional DOM node to be used for the drag preview.
+	 * dx - Optional horizontal offset between the cursor and the drag
+	 * preview.
+	 * dy - Optional vertical offset between the cursor and the drag
+	 * preview.
+	 * autoscroll - Optional boolean that specifies if autoscroll should be
+	 * used. Default is mxGraph.autoscroll.
+	 * scalePreview - Optional boolean that specifies if the preview element
+	 * should be scaled according to the graph scale. If this is true, then
+	 * the offsets will also be scaled. Default is false.
+	 * highlightDropTargets - Optional boolean that specifies if dropTargets
+	 * should be highlighted. Default is true.
+	 * getDropTarget - Optional function to return the drop target for a given
+	 * location (x, y). Default is mxGraph.getCellAt.
+	 */
+	makeDraggable: function(element, graphF, funct, dragElement, dx, dy, autoscroll,
+			scalePreview, highlightDropTargets, getDropTarget)
+	{
+		var dragSource = new mxDragSource(element, funct);
+		dragSource.dragOffset = new mxPoint((dx != null) ? dx : 0,
+			(dy != null) ? dy : mxConstants.TOOLTIP_VERTICAL_OFFSET);
+		dragSource.autoscroll = autoscroll;
+		
+		// Cannot enable this by default. This needs to be enabled in the caller
+		// if the funct argument uses the new x- and y-arguments.
+		dragSource.setGuidesEnabled(false);
+		
+		if (highlightDropTargets != null)
+		{
+			dragSource.highlightDropTargets = highlightDropTargets;
+		}
+		
+		// Overrides function to find drop target cell
+		if (getDropTarget != null)
+		{
+			dragSource.getDropTarget = getDropTarget;
+		}
+		
+		// Overrides function to get current graph
+		dragSource.getGraphForEvent = function(evt)
+		{
+			return (typeof(graphF) == 'function') ? graphF(evt) : graphF;
+		};
+		
+		// Translates switches into dragSource customizations
+		if (dragElement != null)
+		{
+			dragSource.createDragElement = function()
+			{
+				return dragElement.cloneNode(true);
+			};
+			
+			if (scalePreview)
+			{
+				dragSource.createPreviewElement = function(graph)
+				{
+					var elt = dragElement.cloneNode(true);
+
+					var w = parseInt(elt.style.width);
+					var h = parseInt(elt.style.height);
+					elt.style.width = Math.round(w * graph.view.scale) + 'px';
+					elt.style.height = Math.round(h * graph.view.scale) + 'px';
+					
+					return elt;
+				};
+			}
+		}
+		
+		return dragSource;
+	}
+
+};
+/**
+ * $Id: mxConstants.js,v 1.124 2012-05-24 06:39:54 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+ var mxConstants =
+ {
+	/**
+	 * Class: mxConstants
+	 * 
+	 * Defines various global constants.
+	 * 
+	 * Variable: DEFAULT_HOTSPOT
+	 * 
+	 * Defines the portion of the cell which is to be used as a connectable
+	 * region. Default is 0.3. Possible values are 0 < x <= 1. 
+	 */
+	DEFAULT_HOTSPOT: 0.3,
+
+	/**
+	 * Variable: MIN_HOTSPOT_SIZE
+	 * 
+	 * Defines the minimum size in pixels of the portion of the cell which is
+	 * to be used as a connectable region. Default is 8.
+	 */
+	MIN_HOTSPOT_SIZE: 8,
+
+	/**
+	 * Variable: MAX_HOTSPOT_SIZE
+	 * 
+	 * Defines the maximum size in pixels of the portion of the cell which is
+	 * to be used as a connectable region. Use 0 for no maximum. Default is 0.
+	 */
+	MAX_HOTSPOT_SIZE: 0,
+
+	/**
+	 * Variable: RENDERING_HINT_EXACT
+	 * 
+	 * Defines the exact rendering hint.
+	 */
+	RENDERING_HINT_EXACT: 'exact',
+
+	/**
+	 * Variable: RENDERING_HINT_FASTER
+	 * 
+	 * Defines the faster rendering hint.
+	 */
+	RENDERING_HINT_FASTER: 'faster',
+
+	/**
+	 * Variable: RENDERING_HINT_FASTEST
+	 * 
+	 * Defines the fastest rendering hint.
+	 */
+	RENDERING_HINT_FASTEST: 'fastest',
+
+	/**
+	 * Variable: DIALECT_SVG
+	 * 
+	 * Defines the SVG display dialect name.
+	 */
+	DIALECT_SVG: 'svg',
+
+	/**
+	 * Variable: DIALECT_VML
+	 * 
+	 * Defines the VML display dialect name.
+	 */
+	DIALECT_VML: 'vml',
+
+	/**
+	 * Variable: DIALECT_MIXEDHTML
+	 * 
+	 * Defines the mixed HTML display dialect name.
+	 */
+	DIALECT_MIXEDHTML: 'mixedHtml',
+
+	/**
+	 * Variable: DIALECT_PREFERHTML
+	 * 
+	 * Defines the preferred HTML display dialect name.
+	 */
+	DIALECT_PREFERHTML: 'preferHtml',
+
+	/**
+	 * Variable: DIALECT_STRICTHTML
+	 * 
+	 * Defines the strict HTML display dialect.
+	 */
+	DIALECT_STRICTHTML: 'strictHtml',
+
+	/**
+	 * Variable: NS_SVG
+	 * 
+	 * Defines the SVG namespace.
+	 */
+	NS_SVG: 'http://www.w3.org/2000/svg',
+
+	/**
+	 * Variable: NS_XHTML
+	 * 
+	 * Defines the XHTML namespace.
+	 */
+	NS_XHTML: 'http://www.w3.org/1999/xhtml',
+
+	/**
+	 * Variable: NS_XLINK
+	 * 
+	 * Defines the XLink namespace.
+	 */
+	NS_XLINK: 'http://www.w3.org/1999/xlink',
+
+	/**
+	 * Variable: SHADOWCOLOR
+	 * 
+	 * Defines the color to be used to draw shadows in shapes and windows.
+	 * Default is gray.
+	 */
+	SHADOWCOLOR: 'gray',
+
+	/**
+	 * Variable: SHADOW_OFFSET_X
+	 * 
+	 * Specifies the x-offset of the shadow. Default is 2.
+	 */
+	SHADOW_OFFSET_X: 2,
+
+	/**
+	 * Variable: SHADOW_OFFSET_Y
+	 * 
+	 * Specifies the y-offset of the shadow. Default is 3.
+	 */
+	SHADOW_OFFSET_Y: 3,
+	
+	/**
+	 * Variable: SHADOW_OPACITY
+	 * 
+	 * Defines the opacity for shadows. Default is 1.
+	 */
+	SHADOW_OPACITY: 1,
+ 
+	/**
+	 * Variable: NODETYPE_ELEMENT
+	 * 
+	 * DOM node of type ELEMENT.
+	 */
+	NODETYPE_ELEMENT: 1,
+
+	/**
+	 * Variable: NODETYPE_ATTRIBUTE
+	 * 
+	 * DOM node of type ATTRIBUTE.
+	 */
+	NODETYPE_ATTRIBUTE: 2,
+
+	/**
+	 * Variable: NODETYPE_TEXT
+	 * 
+	 * DOM node of type TEXT.
+	 */
+	NODETYPE_TEXT: 3,
+
+	/**
+	 * Variable: NODETYPE_CDATA
+	 * 
+	 * DOM node of type CDATA.
+	 */
+	NODETYPE_CDATA: 4,
+	
+	/**
+	 * Variable: NODETYPE_ENTITY_REFERENCE
+	 * 
+	 * DOM node of type ENTITY_REFERENCE.
+	 */
+	NODETYPE_ENTITY_REFERENCE: 5,
+
+	/**
+	 * Variable: NODETYPE_ENTITY
+	 * 
+	 * DOM node of type ENTITY.
+	 */
+	NODETYPE_ENTITY: 6,
+
+	/**
+	 * Variable: NODETYPE_PROCESSING_INSTRUCTION
+	 * 
+	 * DOM node of type PROCESSING_INSTRUCTION.
+	 */
+	NODETYPE_PROCESSING_INSTRUCTION: 7,
+
+	/**
+	 * Variable: NODETYPE_COMMENT
+	 * 
+	 * DOM node of type COMMENT.
+	 */
+	NODETYPE_COMMENT: 8,
+		
+	/**
+	 * Variable: NODETYPE_DOCUMENT
+	 * 
+	 * DOM node of type DOCUMENT.
+	 */
+	NODETYPE_DOCUMENT: 9,
+
+	/**
+	 * Variable: NODETYPE_DOCUMENTTYPE
+	 * 
+	 * DOM node of type DOCUMENTTYPE.
+	 */
+	NODETYPE_DOCUMENTTYPE: 10,
+
+	/**
+	 * Variable: NODETYPE_DOCUMENT_FRAGMENT
+	 * 
+	 * DOM node of type DOCUMENT_FRAGMENT.
+	 */
+	NODETYPE_DOCUMENT_FRAGMENT: 11,
+
+	/**
+	 * Variable: NODETYPE_NOTATION
+	 * 
+	 * DOM node of type NOTATION.
+	 */
+	NODETYPE_NOTATION: 12,
+	
+	/**
+	 * Variable: TOOLTIP_VERTICAL_OFFSET
+	 * 
+	 * Defines the vertical offset for the tooltip.
+	 * Default is 16.
+	 */
+	TOOLTIP_VERTICAL_OFFSET: 16,
+
+	/**
+	 * Variable: DEFAULT_VALID_COLOR
+	 * 
+	 * Specifies the default valid colorr. Default is #0000FF.
+	 */
+	DEFAULT_VALID_COLOR: '#00FF00',
+
+	/**
+	 * Variable: DEFAULT_INVALID_COLOR
+	 * 
+	 * Specifies the default invalid color. Default is #FF0000.
+	 */
+	DEFAULT_INVALID_COLOR: '#FF0000',
+
+	/**
+	 * Variable: HIGHLIGHT_STROKEWIDTH
+	 * 
+	 * Defines the strokewidth to be used for the highlights.
+	 * Default is 3.
+	 */
+	HIGHLIGHT_STROKEWIDTH: 3,
+	
+	/**
+	 * Variable: CURSOR_MOVABLE_VERTEX
+	 * 
+	 * Defines the cursor for a movable vertex. Default is 'move'.
+	 */
+	CURSOR_MOVABLE_VERTEX: 'move',
+	
+	/**
+	 * Variable: CURSOR_MOVABLE_EDGE
+	 * 
+	 * Defines the cursor for a movable edge. Default is 'move'.
+	 */
+	CURSOR_MOVABLE_EDGE: 'move',
+	
+	/**
+	 * Variable: CURSOR_LABEL_HANDLE
+	 * 
+	 * Defines the cursor for a movable label. Default is 'default'.
+	 */
+	CURSOR_LABEL_HANDLE: 'default',
+	
+	/**
+	 * Variable: CURSOR_BEND_HANDLE
+	 * 
+	 * Defines the cursor for a movable bend. Default is 'pointer'.
+	 */
+	CURSOR_BEND_HANDLE: 'pointer',
+	
+	/**
+	 * Variable: CURSOR_CONNECT
+	 * 
+	 * Defines the cursor for a connectable state. Default is 'pointer'.
+	 */
+	CURSOR_CONNECT: 'pointer',
+
+	/**
+	 * Variable: HIGHLIGHT_COLOR
+	 * 
+	 * Defines the color to be used for the cell highlighting.
+	 * Use 'none' for no color. Default is #00FF00.
+	 */
+	HIGHLIGHT_COLOR: '#00FF00',
+
+	/**
+	 * Variable: TARGET_HIGHLIGHT_COLOR
+	 * 
+	 * Defines the color to be used for highlighting a target cell for a new
+	 * or changed connection. Note that this may be either a source or
+	 * target terminal in the graph. Use 'none' for no color.
+	 * Default is #0000FF.
+	 */
+	CONNECT_TARGET_COLOR: '#0000FF',
+
+	/**
+	 * Variable: INVALID_CONNECT_TARGET_COLOR
+	 * 
+	 * Defines the color to be used for highlighting a invalid target cells
+	 * for a new or changed connections. Note that this may be either a source
+	 * or target terminal in the graph. Use 'none' for no color. Default is
+	 * #FF0000.
+	 */
+	INVALID_CONNECT_TARGET_COLOR: '#FF0000',
+
+	/**
+	 * Variable: DROP_TARGET_COLOR
+	 * 
+	 * Defines the color to be used for the highlighting target parent cells
+	 * (for drag and drop). Use 'none' for no color. Default is #0000FF.
+	 */
+	DROP_TARGET_COLOR: '#0000FF',
+
+	/**
+	 * Variable: VALID_COLOR
+	 * 
+	 * Defines the color to be used for the coloring valid connection
+	 * previews. Use 'none' for no color. Default is #FF0000.
+	 */
+	VALID_COLOR: '#00FF00',
+
+	/**
+	 * Variable: INVALID_COLOR
+	 * 
+	 * Defines the color to be used for the coloring invalid connection
+	 * previews. Use 'none' for no color. Default is #FF0000.
+	 */
+	INVALID_COLOR: '#FF0000',
+
+	/**
+	 * Variable: EDGE_SELECTION_COLOR
+	 * 
+	 * Defines the color to be used for the selection border of edges. Use
+	 * 'none' for no color. Default is #00FF00.
+	 */
+	EDGE_SELECTION_COLOR: '#00FF00',
+
+	/**
+	 * Variable: VERTEX_SELECTION_COLOR
+	 * 
+	 * Defines the color to be used for the selection border of vertices. Use
+	 * 'none' for no color. Default is #00FF00.
+	 */
+	VERTEX_SELECTION_COLOR: '#00FF00',
+
+	/**
+	 * Variable: VERTEX_SELECTION_STROKEWIDTH
+	 * 
+	 * Defines the strokewidth to be used for vertex selections.
+	 * Default is 1.
+	 */
+	VERTEX_SELECTION_STROKEWIDTH: 1,
+
+	/**
+	 * Variable: EDGE_SELECTION_STROKEWIDTH
+	 * 
+	 * Defines the strokewidth to be used for edge selections.
+	 * Default is 1.
+	 */
+	EDGE_SELECTION_STROKEWIDTH: 1,
+
+	/**
+	 * Variable: SELECTION_DASHED
+	 * 
+	 * Defines the dashed state to be used for the vertex selection
+	 * border. Default is true.
+	 */
+	VERTEX_SELECTION_DASHED: true,
+
+	/**
+	 * Variable: SELECTION_DASHED
+	 * 
+	 * Defines the dashed state to be used for the edge selection
+	 * border. Default is true.
+	 */
+	EDGE_SELECTION_DASHED: true,
+
+	/**
+	 * Variable: GUIDE_COLOR
+	 * 
+	 * Defines the color to be used for the guidelines in mxGraphHandler.
+	 * Default is #FF0000.
+	 */
+	GUIDE_COLOR: '#FF0000',
+
+	/**
+	 * Variable: GUIDE_STROKEWIDTH
+	 * 
+	 * Defines the strokewidth to be used for the guidelines in mxGraphHandler.
+	 * Default is 1.
+	 */
+	GUIDE_STROKEWIDTH: 1,
+
+	/**
+	 * Variable: OUTLINE_COLOR
+	 * 
+	 * Defines the color to be used for the outline rectangle
+	 * border.  Use 'none' for no color. Default is #0099FF.
+	 */
+	OUTLINE_COLOR: '#0099FF',
+
+	/**
+	 * Variable: OUTLINE_STROKEWIDTH
+	 * 
+	 * Defines the strokewidth to be used for the outline rectangle
+	 * stroke width. Default is 3.
+	 */
+	OUTLINE_STROKEWIDTH: (mxClient.IS_IE) ? 2 : 3,
+
+	/**
+	 * Variable: HANDLE_SIZE
+	 * 
+	 * Defines the default size for handles. Default is 7.
+	 */
+	HANDLE_SIZE: 7,
+
+	/**
+	 * Variable: LABEL_HANDLE_SIZE
+	 * 
+	 * Defines the default size for label handles. Default is 4.
+	 */
+	LABEL_HANDLE_SIZE: 4,
+
+	/**
+	 * Variable: HANDLE_FILLCOLOR
+	 * 
+	 * Defines the color to be used for the handle fill color. Use 'none' for
+	 * no color. Default is #00FF00 (green).
+	 */
+	HANDLE_FILLCOLOR: '#00FF00',
+
+	/**
+	 * Variable: HANDLE_STROKECOLOR
+	 * 
+	 * Defines the color to be used for the handle stroke color. Use 'none' for
+	 * no color. Default is black.
+	 */
+	HANDLE_STROKECOLOR: 'black',
+
+	/**
+	 * Variable: LABEL_HANDLE_FILLCOLOR
+	 * 
+	 * Defines the color to be used for the label handle fill color. Use 'none'
+	 * for no color. Default is yellow.
+	 */
+	LABEL_HANDLE_FILLCOLOR: 'yellow',
+
+	/**
+	 * Variable: CONNECT_HANDLE_FILLCOLOR
+	 * 
+	 * Defines the color to be used for the connect handle fill color. Use
+	 * 'none' for no color. Default is #0000FF (blue).
+	 */
+	CONNECT_HANDLE_FILLCOLOR: '#0000FF',
+
+	/**
+	 * Variable: LOCKED_HANDLE_FILLCOLOR
+	 * 
+	 * Defines the color to be used for the locked handle fill color. Use
+	 * 'none' for no color. Default is #FF0000 (red).
+	 */
+	LOCKED_HANDLE_FILLCOLOR: '#FF0000',
+
+	/**
+	 * Variable: OUTLINE_HANDLE_FILLCOLOR
+	 * 
+	 * Defines the color to be used for the outline sizer fill color. Use
+	 * 'none' for no color. Default is #00FFFF.
+	 */
+	OUTLINE_HANDLE_FILLCOLOR: '#00FFFF',
+
+	/**
+	 * Variable: OUTLINE_HANDLE_STROKECOLOR
+	 * 
+	 * Defines the color to be used for the outline sizer stroke color. Use
+	 * 'none' for no color. Default is #0033FF.
+	 */
+	OUTLINE_HANDLE_STROKECOLOR: '#0033FF',
+
+	/**
+	 * Variable: DEFAULT_FONTFAMILY
+	 * 
+	 * Defines the default family for all fonts in points. Default is
+	 * Arial,Helvetica.
+	 */
+	DEFAULT_FONTFAMILY: 'Arial,Helvetica',
+
+	/**
+	 * Variable: DEFAULT_FONTSIZE
+	 * 
+	 * Defines the default size for all fonts in points. Default is 11.
+	 */
+	DEFAULT_FONTSIZE: 11,
+
+	/**
+	 * Variable: DEFAULT_STARTSIZE
+	 * 
+	 * Defines the default start size for swimlanes. Default is 40.
+	 */
+	DEFAULT_STARTSIZE: 40,
+
+	/**
+	 * Variable: DEFAULT_MARKERSIZE
+	 * 
+	 * Defines the default size for all markers. Default is 6.
+	 */
+	DEFAULT_MARKERSIZE: 6,
+
+	/**
+	 * Variable: DEFAULT_IMAGESIZE
+	 * 
+	 * Defines the default width and height for images used in the
+	 * label shape. Default is 24.
+	 */
+	DEFAULT_IMAGESIZE: 24,
+
+	/**
+	 * Variable: ENTITY_SEGMENT
+	 * 
+	 * Defines the length of the horizontal segment of an Entity Relation.
+	 * This can be overridden using  style.
+	 * Default is 30.
+	 */
+	ENTITY_SEGMENT: 30,
+
+	/**
+	 * Variable: RECTANGLE_ROUNDING_FACTOR
+	 * 
+	 * Defines the rounding factor for rounded rectangles in percent between
+	 * 0 and 1. Values should be smaller than 0.5. Default is 0.15.
+	 */
+	RECTANGLE_ROUNDING_FACTOR: 0.15,
+
+	/**
+	 * Variable: LINE_ARCSIZE
+	 * 
+	 * Defines the size of the arcs for rounded edges. Default is 20.
+	 */
+	LINE_ARCSIZE: 20,
+
+	/**
+	 * Variable: ARROW_SPACING
+	 * 
+	 * Defines the spacing between the arrow shape and its terminals. Default
+	 * is 10.
+	 */
+	ARROW_SPACING: 10,
+
+	/**
+	 * Variable: ARROW_WIDTH
+	 * 
+	 * Defines the width of the arrow shape. Default is 30.
+	 */
+	ARROW_WIDTH: 30,
+
+	/**
+	 * Variable: ARROW_SIZE
+	 * 
+	 * Defines the size of the arrowhead in the arrow shape. Default is 30.
+	 */
+	ARROW_SIZE: 30,
+
+	/**
+	 * Variable: PAGE_FORMAT_A4_PORTRAIT
+	 * 
+	 * Defines the rectangle for the A4 portrait page format. The dimensions
+	 * of this page format are 826x1169 pixels.
+	 */
+	PAGE_FORMAT_A4_PORTRAIT: new mxRectangle(0, 0, 826, 1169),
+
+	/**
+	 * Variable: PAGE_FORMAT_A4_PORTRAIT
+	 * 
+	 * Defines the rectangle for the A4 portrait page format. The dimensions
+	 * of this page format are 826x1169 pixels.
+	 */
+	PAGE_FORMAT_A4_LANDSCAPE: new mxRectangle(0, 0, 1169, 826),
+
+	/**
+	 * Variable: PAGE_FORMAT_LETTER_PORTRAIT
+	 * 
+	 * Defines the rectangle for the Letter portrait page format. The
+	 * dimensions of this page format are 850x1100 pixels.
+	 */
+	PAGE_FORMAT_LETTER_PORTRAIT: new mxRectangle(0, 0, 850, 1100),
+
+	/**
+	 * Variable: PAGE_FORMAT_LETTER_PORTRAIT
+	 * 
+	 * Defines the rectangle for the Letter portrait page format. The dimensions
+	 * of this page format are 850x1100 pixels.
+	 */
+	PAGE_FORMAT_LETTER_LANDSCAPE: new mxRectangle(0, 0, 1100, 850),
+
+	/**
+	 * Variable: NONE
+	 * 
+	 * Defines the value for none. Default is "none".
+	 */
+	NONE: 'none',
+
+	/**
+	 * Variable: STYLE_PERIMETER
+	 * 
+	 * Defines the key for the perimeter style. This is a function that defines
+	 * the perimeter around a particular shape. Possible values are the
+	 * functions defined in . Alternatively, the constants in this
+	 * class that start with PERIMETER_ may be used to access
+	 * perimeter styles in .
+	 */
+	STYLE_PERIMETER: 'perimeter',
+	
+	/**
+	 * Variable: STYLE_SOURCE_PORT
+	 * 
+	 * Defines the ID of the cell that should be used for computing the
+	 * perimeter point of the source for an edge. This allows for graphically
+	 * connecting to a cell while keeping the actual terminal of the edge.
+	 */
+	STYLE_SOURCE_PORT: 'sourcePort',
+	
+	/**
+	 * Variable: STYLE_TARGET_PORT
+	 * 
+	 * Defines the ID of the cell that should be used for computing the
+	 * perimeter point of the target for an edge. This allows for graphically
+	 * connecting to a cell while keeping the actual terminal of the edge.
+	 */
+	STYLE_TARGET_PORT: 'targetPort',
+
+	/**
+	 * Variable: STYLE_PORT_CONSTRAINT
+	 * 
+	 * Defines the direction(s) that edges are allowed to connect to cells in.
+	 * Possible values are DIRECTION_NORTH, DIRECTION_SOUTH, 
+	 * DIRECTION_EAST and DIRECTION_WEST.
+	 */
+	STYLE_PORT_CONSTRAINT: 'portConstraint',
+
+	/**
+	 * Variable: STYLE_OPACITY
+	 * 
+	 * Defines the key for the opacity style. The type of the value is 
+	 * numeric and the possible range is 0-100.
+	 */
+	STYLE_OPACITY: 'opacity',
+
+	/**
+	 * Variable: STYLE_TEXT_OPACITY
+	 * 
+	 * Defines the key for the text opacity style. The type of the value is 
+	 * numeric and the possible range is 0-100.
+	 */
+	STYLE_TEXT_OPACITY: 'textOpacity',
+
+	/**
+	 * Variable: STYLE_OVERFLOW
+	 * 
+	 * Defines the key for the overflow style. Possible values are 'visible',
+	 * 'hidden' and 'fill'. The default value is 'visible'. This value
+	 * specifies how overlapping vertex labels are handled. A value of
+	 * 'visible' will show the complete label. A value of 'hidden' will clip
+	 * the label so that it does not overlap the vertex bounds. A value of
+	 * 'fill' will use the vertex bounds for the label. See
+	 * .
+	 */
+	STYLE_OVERFLOW: 'overflow',
+
+	/**
+	 * Variable: STYLE_ORTHOGONAL
+	 * 
+	 * Defines if the connection points on either end of the edge should be
+	 * computed so that the edge is vertical or horizontal if possible and
+	 * if the point is not at a fixed location. Default is false. This is
+	 * used in , which also returns true if the edgeStyle
+	 * of the edge is an elbow or entity.
+	 */
+	STYLE_ORTHOGONAL: 'orthogonal',
+
+	/**
+	 * Variable: STYLE_EXIT_X
+	 * 
+	 * Defines the key for the horizontal relative coordinate connection point
+	 * of an edge with its source terminal.
+	 */
+	STYLE_EXIT_X: 'exitX',
+
+	/**
+	 * Variable: STYLE_EXIT_Y
+	 * 
+	 * Defines the key for the vertical relative coordinate connection point
+	 * of an edge with its source terminal.
+	 */
+	STYLE_EXIT_Y: 'exitY',
+
+	/**
+	 * Variable: STYLE_EXIT_PERIMETER
+	 * 
+	 * Defines if the perimeter should be used to find the exact entry point
+	 * along the perimeter of the source. Possible values are 0 (false) and
+	 * 1 (true). Default is 1 (true).
+	 */
+	STYLE_EXIT_PERIMETER: 'exitPerimeter',
+
+	/**
+	 * Variable: STYLE_ENTRY_X
+	 * 
+	 * Defines the key for the horizontal relative coordinate connection point
+	 * of an edge with its target terminal.
+	 */
+	STYLE_ENTRY_X: 'entryX',
+
+	/**
+	 * Variable: STYLE_ENTRY_Y
+	 * 
+	 * Defines the key for the vertical relative coordinate connection point
+	 * of an edge with its target terminal.
+	 */
+	STYLE_ENTRY_Y: 'entryY',
+
+	/**
+	 * Variable: STYLE_ENTRY_PERIMETER
+	 * 
+	 * Defines if the perimeter should be used to find the exact entry point
+	 * along the perimeter of the target. Possible values are 0 (false) and
+	 * 1 (true). Default is 1 (true).
+	 */
+	STYLE_ENTRY_PERIMETER: 'entryPerimeter',
+
+	/**
+	 * Variable: STYLE_WHITE_SPACE
+	 * 
+	 * Defines the key for the white-space style. Possible values are 'nowrap'
+	 * and 'wrap'. The default value is 'nowrap'. This value specifies how
+	 * white-space inside a HTML vertex label should be handled. A value of
+	 * 'nowrap' means the text will never wrap to the next line until a
+	 * linefeed is encountered. A value of 'wrap' means text will wrap when
+	 * necessary. This style is only used for HTML labels.
+	 * See .
+	 */
+	STYLE_WHITE_SPACE: 'whiteSpace',
+
+	/**
+	 * Variable: STYLE_ROTATION
+	 * 
+	 * Defines the key for the rotation style. The type of the value is 
+	 * numeric and the possible range is 0-360.
+	 */
+	STYLE_ROTATION: 'rotation',
+
+	/**
+	 * Variable: STYLE_FILLCOLOR
+	 * 
+	 * Defines the key for the fill color. Possible values are all HTML color
+	 * names or HEX codes, as well as special keywords such as 'swimlane,
+	 * 'inherit' or 'indicated' to use the color code of a related cell or the
+	 * indicator shape.
+	 */
+	STYLE_FILLCOLOR: 'fillColor',
+
+	/**
+	 * Variable: STYLE_GRADIENTCOLOR
+	 * 
+	 * Defines the key for the gradient color. Possible values are all HTML color
+	 * names or HEX codes, as well as special keywords such as 'swimlane,
+	 * 'inherit' or 'indicated' to use the color code of a related cell or the
+	 * indicator shape. This is ignored if no fill color is defined.
+	 */
+	STYLE_GRADIENTCOLOR: 'gradientColor',
+
+	/**
+	 * Variable: STYLE_GRADIENT_DIRECTION
+	 * 
+	 * Defines the key for the gradient direction. Possible values are
+	 * , ,  and
+	 * . Default is . Generally, and by
+	 * default in mxGraph, gradient painting is done from the value of
+	 *  to the value of . Taking the
+	 * example of , this means  color at the 
+	 * bottom of paint pattern and  at top, with a
+	 * gradient in-between.
+	 */
+	STYLE_GRADIENT_DIRECTION: 'gradientDirection',
+
+	/**
+	 * Variable: STYLE_STROKECOLOR
+	 * 
+	 * Defines the key for the strokeColor style. Possible values are all HTML
+	 * color names or HEX codes, as well as special keywords such as 'swimlane,
+	 * 'inherit', 'indicated' to use the color code of a related cell or the
+	 * indicator shape or 'none' for no color.
+	 */
+	STYLE_STROKECOLOR: 'strokeColor',
+
+	/**
+	 * Variable: STYLE_SEPARATORCOLOR
+	 * 
+	 * Defines the key for the separatorColor style. Possible values are all
+	 * HTML color names or HEX codes. This style is only used for
+	 *  shapes.
+	 */
+	STYLE_SEPARATORCOLOR: 'separatorColor',
+
+	/**
+	 * Variable: STYLE_STROKEWIDTH
+	 * 
+	 * Defines the key for the strokeWidth style. The type of the value is 
+	 * numeric and the possible range is any non-negative value larger or equal
+	 * to 1. The value defines the stroke width in pixels. Note: To hide a
+	 * stroke use strokeColor none.
+	 */
+	STYLE_STROKEWIDTH: 'strokeWidth',
+
+	/**
+	 * Variable: STYLE_ALIGN
+	 * 
+	 * Defines the key for the align style. Possible values are ,
+	 *  and . This value defines how the lines of
+	 * the label are horizontally aligned.  mean label text lines
+	 * are aligned to left of the label bounds,  to the right of
+	 * the label bounds and  means the center of the text lines
+	 * are aligned in the center of the label bounds. Note this value doesn't
+	 * affect the positioning of the overall label bounds relative to the
+	 * vertex, to move the label bounds horizontally, use
+	 * .
+	 */
+	STYLE_ALIGN: 'align',
+
+	/**
+	 * Variable: STYLE_VERTICAL_ALIGN
+	 * 
+	 * Defines the key for the verticalAlign style. Possible values are
+	 * ,  and . This value defines how
+	 * the lines of the label are vertically aligned.  means the
+	 * topmost label text line is aligned against the top of the label bounds,
+	 *  means the bottom-most label text line is aligned against
+	 * the bottom of the label bounds and  means there is equal
+	 * spacing between the topmost text label line and the top of the label
+	 * bounds and the bottom-most text label line and the bottom of the label
+	 * bounds. Note this value doesn't affect the positioning of the overall
+	 * label bounds relative to the vertex, to move the label bounds
+	 * vertically, use .
+	 */
+	STYLE_VERTICAL_ALIGN: 'verticalAlign',
+
+	/**
+	 * Variable: STYLE_LABEL_POSITION
+	 * 
+	 * Defines the key for the horizontal label position of vertices. Possible
+	 * values are ,  and . Default is
+	 * . The label align defines the position of the label
+	 * relative to the cell.  means the entire label bounds is
+	 * placed completely just to the left of the vertex,  means
+	 * adjust to the right and  means the label bounds are
+	 * vertically aligned with the bounds of the vertex. Note this value
+	 * doesn't affect the positioning of label within the label bounds, to move
+	 * the label horizontally within the label bounds, use .
+	 */
+	STYLE_LABEL_POSITION: 'labelPosition',
+
+	/**
+	 * Variable: STYLE_VERTICAL_LABEL_POSITION
+	 * 
+	 * Defines the key for the vertical label position of vertices. Possible
+	 * values are ,  and . Default is
+	 * . The label align defines the position of the label
+	 * relative to the cell.  means the entire label bounds is
+	 * placed completely just on the top of the vertex,  means
+	 * adjust on the bottom and  means the label bounds are
+	 * horizontally aligned with the bounds of the vertex. Note this value
+	 * doesn't affect the positioning of label within the label bounds, to move
+	 * the label vertically within the label bounds, use
+	 * .
+	 */
+	STYLE_VERTICAL_LABEL_POSITION: 'verticalLabelPosition',
+	
+	/**
+	 * Variable: STYLE_IMAGE_ASPECT
+	 * 
+	 * Defines the key for the image aspect style. Possible values are 0 (do
+	 * not preserve aspect) or 1 (keep aspect). This is only used in
+	 * . Default is 1.
+	 */
+	STYLE_IMAGE_ASPECT: 'imageAspect',
+
+	/**
+	 * Variable: STYLE_IMAGE_ALIGN
+	 * 
+	 * Defines the key for the align style. Possible values are ,
+	 *  and . The value defines how any image in the
+	 * vertex label is aligned horizontally within the label bounds of a
+	 *  shape.
+	 */
+	STYLE_IMAGE_ALIGN: 'imageAlign',
+
+	/**
+	 * Variable: STYLE_IMAGE_VERTICAL_ALIGN
+	 * 
+	 * Defines the key for the verticalAlign style. Possible values are
+	 * ,  and . The value defines how
+	 * any image in the vertex label is aligned vertically within the label
+	 * bounds of a  shape.
+	 */
+	STYLE_IMAGE_VERTICAL_ALIGN: 'imageVerticalAlign',
+
+	/**
+	 * Variable: STYLE_GLASS
+	 * 
+	 * Defines the key for the glass style. Possible values are 0 (disabled) and
+	 * 1(enabled). The default value is 0. This is used in .
+	 */
+	STYLE_GLASS: 'glass',
+
+	/**
+	 * Variable: STYLE_IMAGE
+	 * 
+	 * Defines the key for the image style. Possible values are any image URL,
+	 * the type of the value is String. This is the path to the image to image
+	 * that is to be displayed within the label of a vertex.
+	 */
+	STYLE_IMAGE: 'image',
+
+	/**
+	 * Variable: STYLE_IMAGE_WIDTH
+	 * 
+	 * Defines the key for the imageWidth style. The type of this value is
+	 * int, the value is the image width in pixels and must be greater than 0.
+	 */
+	STYLE_IMAGE_WIDTH: 'imageWidth',
+
+	/**
+	 * Variable: STYLE_IMAGE_HEIGHT
+	 * 
+	 * Defines the key for the imageHeight style. The type of this value is
+	 * int, the value is the image height in pixels and must be greater than 0.
+	 */
+	STYLE_IMAGE_HEIGHT: 'imageHeight',
+
+	/**
+	 * Variable: STYLE_IMAGE_BACKGROUND
+	 * 
+	 * Defines the key for the image background color. This style is only used
+	 * in . Possible values are all HTML color names or HEX
+	 * codes.
+	 */
+	STYLE_IMAGE_BACKGROUND: 'imageBackground',
+
+	/**
+	 * Variable: STYLE_IMAGE_BORDER
+	 * 
+	 * Defines the key for the image border color. This style is only used in
+	 * . Possible values are all HTML color names or HEX codes.
+	 */
+	STYLE_IMAGE_BORDER: 'imageBorder',
+
+	/**
+	 * Variable: STYLE_IMAGE_FLIPH
+	 * 
+	 * Defines the key for the horizontal image flip. This style is only used
+	 * in . Possible values are 0 and 1. Default is 0.
+	 */
+	STYLE_IMAGE_FLIPH: 'imageFlipH',
+
+	/**
+	 * Variable: STYLE_IMAGE_FLIPV
+	 * 
+	 * Defines the key for the vertical image flip. This style is only used
+	 * in . Possible values are 0 and 1. Default is 0.
+	 */
+	STYLE_IMAGE_FLIPV: 'imageFlipV',
+
+	/**
+	 * Variable: STYLE_STENCIL_FLIPH
+	 * 
+	 * Defines the key for the horizontal stencil flip. This style is only used
+	 * for . Possible values are 0 and 1. Default is 0.
+	 */
+	STYLE_STENCIL_FLIPH: 'stencilFlipH',
+
+	/**
+	 * Variable: STYLE_STENCIL_FLIPV
+	 * 
+	 * Defines the key for the vertical stencil flip. This style is only used
+	 * for . Possible values are 0 and 1. Default is 0.
+	 */
+	STYLE_STENCIL_FLIPV: 'stencilFlipV',
+
+	/**
+	 * Variable: STYLE_NOLABEL
+	 * 
+	 * Defines the key for the noLabel style. If this is
+	 * true then no label is visible for a given cell.
+	 * Possible values are true or false (1 or 0).
+	 * Default is false.
+	 */
+	STYLE_NOLABEL: 'noLabel',
+
+	/**
+	 * Variable: STYLE_NOEDGESTYLE
+	 * 
+	 * Defines the key for the noEdgeStyle style. If this is
+	 * true then no edge style is applied for a given edge.
+	 * Possible values are true or false (1 or 0).
+	 * Default is false.
+	 */
+	STYLE_NOEDGESTYLE: 'noEdgeStyle',
+
+	/**
+	 * Variable: STYLE_LABEL_BACKGROUNDCOLOR
+	 * 
+	 * Defines the key for the label background color. Possible values are all
+	 * HTML color names or HEX codes.
+	 */
+	STYLE_LABEL_BACKGROUNDCOLOR: 'labelBackgroundColor',
+
+	/**
+	 * Variable: STYLE_LABEL_BORDERCOLOR
+	 * 
+	 * Defines the key for the label border color. Possible values are all
+	 * HTML color names or HEX codes.
+	 */
+	STYLE_LABEL_BORDERCOLOR: 'labelBorderColor',
+
+	/**
+	 * Variable: STYLE_LABEL_PADDING
+	 * 
+	 * Defines the key for the label padding, ie. the space between the label
+	 * border and the label.
+	 */
+	STYLE_LABEL_PADDING: 'labelPadding',
+
+	/**
+	 * Variable: STYLE_INDICATOR_SHAPE
+	 * 
+	 * Defines the key for the indicator shape used within an .
+	 * Possible values are all SHAPE_* constants or the names of any new
+	 * shapes.
+	 */
+	STYLE_INDICATOR_SHAPE: 'indicatorShape',
+
+	/**
+	 * Variable: STYLE_INDICATOR_IMAGE
+	 * 
+	 * Defines the key for the indicator image used within an .
+	 * Possible values are all image URLs.
+	 */
+	STYLE_INDICATOR_IMAGE: 'indicatorImage',
+
+	/**
+	 * Variable: STYLE_INDICATOR_COLOR
+	 * 
+	 * Defines the key for the indicatorColor style. Possible values are all
+	 * HTML color names or HEX codes, as well as the special 'swimlane' keyword
+	 * to refer to the color of the parent swimlane if one exists.
+	 */
+	STYLE_INDICATOR_COLOR: 'indicatorColor',
+
+	/**
+	 * Variable: STYLE_INDICATOR_STROKECOLOR
+	 * 
+	 * Defines the key for the indicator stroke color in .
+	 * Possible values are all color codes.
+	 */
+	STYLE_INDICATOR_STROKECOLOR: 'indicatorStrokeColor',
+
+	/**
+	 * Variable: STYLE_INDICATOR_GRADIENTCOLOR
+	 * 
+	 * Defines the key for the indicatorGradientColor style. Possible values
+	 * are all HTML color names or HEX codes. This style is only supported in
+	 *  shapes.
+	 */
+	STYLE_INDICATOR_GRADIENTCOLOR: 'indicatorGradientColor',
+
+	/**
+	 * Variable: STYLE_INDICATOR_SPACING
+	 * 
+	 * The defines the key for the spacing between the label and the
+	 * indicator in . Possible values are in pixels.
+	 */
+	STYLE_INDICATOR_SPACING: 'indicatorSpacing',
+
+	/**
+	 * Variable: STYLE_INDICATOR_WIDTH
+	 * 
+	 * Defines the key for the indicator width.
+	 * Possible values start at 0 (in pixels).
+	 */
+	STYLE_INDICATOR_WIDTH: 'indicatorWidth',
+
+	/**
+	 * Variable: STYLE_INDICATOR_HEIGHT
+	 * 
+	 * Defines the key for the indicator height.
+	 * Possible values start at 0 (in pixels).
+	 */
+	STYLE_INDICATOR_HEIGHT: 'indicatorHeight',
+
+	/**
+	 * Variable: STYLE_INDICATOR_DIRECTION
+	 * 
+	 * Defines the key for the indicatorDirection style. The direction style is
+	 * used to specify the direction of certain shapes (eg. ).
+	 * Possible values are  (default), ,
+	 *  and .
+	 */
+	STYLE_INDICATOR_DIRECTION: 'indicatorDirection',
+
+	/**
+	 * Variable: STYLE_SHADOW
+	 * 
+	 * Defines the key for the shadow style. The type of the value is Boolean.
+	 */
+	STYLE_SHADOW: 'shadow',
+	
+	/**
+	 * Variable: STYLE_SEGMENT
+	 * 
+	 * Defines the key for the segment style. The type of this value is
+	 * float and the value represents the size of the horizontal
+	 * segment of the entity relation style. Default is ENTITY_SEGMENT.
+	 */
+	STYLE_SEGMENT: 'segment',
+	
+	/**
+	 * Variable: STYLE_ENDARROW
+	 *
+	 * Defines the key for the end arrow marker.
+	 * Possible values are all constants with an ARROW-prefix.
+	 * This is only used in .
+	 *
+	 * Example:
+	 * (code)
+	 * style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
+	 * (end)
+	 */
+	STYLE_ENDARROW: 'endArrow',
+
+	/**
+	 * Variable: STYLE_STARTARROW
+	 * 
+	 * Defines the key for the start arrow marker.
+	 * Possible values are all constants with an ARROW-prefix.
+	 * This is only used in .
+	 * See .
+	 */
+	STYLE_STARTARROW: 'startArrow',
+
+	/**
+	 * Variable: STYLE_ENDSIZE
+	 * 
+	 * Defines the key for the endSize style. The type of this value is numeric
+	 * and the value represents the size of the end marker in pixels.
+	 */
+	STYLE_ENDSIZE: 'endSize',
+
+	/**
+	 * Variable: STYLE_STARTSIZE
+	 * 
+	 * Defines the key for the startSize style. The type of this value is
+	 * numeric and the value represents the size of the start marker or the
+	 * size of the swimlane title region depending on the shape it is used for.
+	 */
+	STYLE_STARTSIZE: 'startSize',
+
+	/**
+	 * Variable: STYLE_ENDFILL
+	 * 
+	 * Defines the key for the endFill style. Use 0 for no fill or 1
+	 * (default) for fill. (This style is only exported via .)
+	 */
+	STYLE_ENDFILL: 'endFill',
+
+	/**
+	 * Variable: STYLE_STARTFILL
+	 * 
+	 * Defines the key for the startFill style. Use 0 for no fill or 1
+	 * (default) for fill. (This style is only exported via .)
+	 */
+	STYLE_STARTFILL: 'startFill',
+
+	/**
+	 * Variable: STYLE_DASHED
+	 * 
+	 * Defines the key for the endSize style. The type of this value is numeric
+	 * and the value represents the size of the end marker in pixels.
+	 */
+	STYLE_DASHED: 'dashed',
+
+	/**
+	 * Defines the key for the dashed pattern style in SVG and image exports.
+	 * The type of this value is a space separated list of numbers that specify
+	 * a custom-defined dash pattern. Dash styles are defined in terms of the
+	 * length of the dash (the drawn part of the stroke) and the length of the
+	 * space between the dashes. The lengths are relative to the line width: a
+	 * length of "1" is equal to the line width. VML ignores this style and
+	 * uses dashStyle instead as defined in the VML specification. This style
+	 * is only used in the  shape.
+	 */
+	STYLE_DASH_PATTERN: 'dashPattern',
+
+	/**
+	 * Variable: STYLE_ROUNDED
+	 * 
+	 * Defines the key for the rounded style. The type of this value is
+	 * Boolean. For edges this determines whether or not joins between edges
+	 * segments are smoothed to a rounded finish. For vertices that have the
+	 * rectangle shape, this determines whether or not the rectangle is
+	 * rounded.
+	 */
+	STYLE_ROUNDED: 'rounded',
+
+	/**
+	 * Variable: STYLE_ARCSIZE
+	 * 
+	 * Defines the rounding factor for a rounded rectangle in percent (without
+	 * the percent sign). Possible values are between 0 and 100. If this value
+	 * is not specified then RECTANGLE_ROUNDING_FACTOR * 100 is used.
+	 * (This style is only exported via .)
+	 */
+	STYLE_ARCSIZE: 'arcSize',
+
+	/**
+	 * Variable: STYLE_SMOOTH
+	 * 
+	 * An experimental style for edges. This style is currently not available
+	 * in the backends and is implemented differently for VML and SVG. The use
+	 * of this style is currently only recommended for VML.
+	 */
+	STYLE_SMOOTH: 'smooth',
+
+	/**
+	 * Variable: STYLE_SOURCE_PERIMETER_SPACING
+	 * 
+	 * Defines the key for the source perimeter spacing. The type of this value
+	 * is numeric. This is the distance between the source connection point of
+	 * an edge and the perimeter of the source vertex in pixels. This style
+	 * only applies to edges.
+	 */
+	STYLE_SOURCE_PERIMETER_SPACING: 'sourcePerimeterSpacing',
+
+	/**
+	 * Variable: STYLE_TARGET_PERIMETER_SPACING
+	 * 
+	 * Defines the key for the target perimeter spacing. The type of this value
+	 * is numeric. This is the distance between the target connection point of
+	 * an edge and the perimeter of the target vertex in pixels. This style
+	 * only applies to edges.
+	 */
+	STYLE_TARGET_PERIMETER_SPACING: 'targetPerimeterSpacing',
+
+	/**
+	 * Variable: STYLE_PERIMETER_SPACING
+	 * 
+	 * Defines the key for the perimeter spacing. This is the distance between
+	 * the connection point and the perimeter in pixels. When used in a vertex
+	 * style, this applies to all incoming edges to floating ports (edges that
+	 * terminate on the perimeter of the vertex). When used in an edge style,
+	 * this spacing applies to the source and target separately, if they
+	 * terminate in floating ports (on the perimeter of the vertex).
+	 */
+	STYLE_PERIMETER_SPACING: 'perimeterSpacing',
+
+	/**
+	 * Variable: STYLE_SPACING
+	 * 
+	 * Defines the key for the spacing. The value represents the spacing, in
+	 * pixels, added to each side of a label in a vertex (style applies to
+	 * vertices only).
+	 */
+	STYLE_SPACING: 'spacing',
+
+	/**
+	 * Variable: STYLE_SPACING_TOP
+	 * 
+	 * Defines the key for the spacingTop style. The value represents the
+	 * spacing, in pixels, added to the top side of a label in a vertex (style
+	 * applies to vertices only).
+	 */
+	STYLE_SPACING_TOP: 'spacingTop',
+
+	/**
+	 * Variable: STYLE_SPACING_LEFT
+	 * 
+	 * Defines the key for the spacingLeft style. The value represents the
+	 * spacing, in pixels, added to the left side of a label in a vertex (style
+	 * applies to vertices only).
+	 */
+	STYLE_SPACING_LEFT: 'spacingLeft',
+
+	/**
+	 * Variable: STYLE_SPACING_BOTTOM
+	 * 
+	 * Defines the key for the spacingBottom style The value represents the
+	 * spacing, in pixels, added to the bottom side of a label in a vertex
+	 * (style applies to vertices only).
+	 */
+	STYLE_SPACING_BOTTOM: 'spacingBottom',
+
+	/**
+	 * Variable: STYLE_SPACING_RIGHT
+	 * 
+	 * Defines the key for the spacingRight style The value represents the
+	 * spacing, in pixels, added to the right side of a label in a vertex (style
+	 * applies to vertices only).
+	 */
+	STYLE_SPACING_RIGHT: 'spacingRight',
+
+	/**
+	 * Variable: STYLE_HORIZONTAL
+	 * 
+	 * Defines the key for the horizontal style. Possible values are
+	 * true or false. This value only applies to vertices. If the 
+	 * is SHAPE_SWIMLANE a value of false indicates that the
+	 * swimlane should be drawn vertically, true indicates to draw it
+	 * horizontally. If the shape style does not indicate that this vertex is a
+	 * swimlane, this value affects only whether the label is drawn
+	 * horizontally or vertically.
+	 */
+	STYLE_HORIZONTAL: 'horizontal',
+
+	/**
+	 * Variable: STYLE_DIRECTION
+	 * 
+	 * Defines the key for the direction style. The direction style is used
+	 * to specify the direction of certain shapes (eg. ).
+	 * Possible values are  (default), ,
+	 *  and .
+	 */
+	STYLE_DIRECTION: 'direction',
+
+	/**
+	 * Variable: STYLE_ELBOW
+	 * 
+	 * Defines the key for the elbow style. Possible values are
+	 *  and . Default is .
+	 * This defines how the three segment orthogonal edge style leaves its
+	 * terminal vertices. The vertical style leaves the terminal vertices at
+	 * the top and bottom sides.
+	 */
+	STYLE_ELBOW: 'elbow',
+
+	/**
+	 * Variable: STYLE_FONTCOLOR
+	 * 
+	 * Defines the key for the fontColor style. Possible values are all HTML
+	 * color names or HEX codes.
+	 */
+	STYLE_FONTCOLOR: 'fontColor',
+
+	/**
+	 * Variable: STYLE_FONTFAMILY
+	 * 
+	 * Defines the key for the fontFamily style. Possible values are names such
+	 * as Arial; Dialog; Verdana; Times New Roman. The value is of type String.
+	 */
+	STYLE_FONTFAMILY: 'fontFamily',
+
+	/**
+	 * Variable: STYLE_FONTSIZE
+	 * 
+	 * Defines the key for the fontSize style (in points). The type of the value
+	 * is int.
+	 */
+	STYLE_FONTSIZE: 'fontSize',
+
+	/**
+	 * Variable: STYLE_FONTSTYLE
+	 * 
+	 * Defines the key for the fontStyle style. Values may be any logical AND
+	 * (sum) of , ,  and .
+	 * The type of the value is int.
+	 */
+	STYLE_FONTSTYLE: 'fontStyle',
+
+	/**
+	 * Variable: STYLE_AUTOSIZE
+	 * 
+	 * Defines the key for the autosize style. This specifies if a cell should be
+	 * resized automatically if the value has changed. Possible values are 0 or 1.
+	 * Default is 0. See . This is normally combined with
+	 *  to disable manual sizing.
+	 */
+	STYLE_AUTOSIZE: 'autosize',
+
+	/**
+	 * Variable: STYLE_FOLDABLE
+	 * 
+	 * Defines the key for the foldable style. This specifies if a cell is foldable
+	 * using a folding icon. Possible values are 0 or 1. Default is 1. See
+	 * .
+	 */
+	STYLE_FOLDABLE: 'foldable',
+
+	/**
+	 * Variable: STYLE_EDITABLE
+	 * 
+	 * Defines the key for the editable style. This specifies if the value of
+	 * a cell can be edited using the in-place editor. Possible values are 0 or
+	 * 1. Default is 1. See .
+	 */
+	STYLE_EDITABLE: 'editable',
+
+	/**
+	 * Variable: STYLE_BENDABLE
+	 * 
+	 * Defines the key for the bendable style. This specifies if the control
+	 * points of an edge can be moved. Possible values are 0 or 1. Default is
+	 * 1. See .
+	 */
+	STYLE_BENDABLE: 'bendable',
+
+	/**
+	 * Variable: STYLE_MOVABLE
+	 * 
+	 * Defines the key for the movable style. This specifies if a cell can
+	 * be moved. Possible values are 0 or 1. Default is 1. See
+	 * .
+	 */
+	STYLE_MOVABLE: 'movable',
+
+	/**
+	 * Variable: STYLE_RESIZABLE
+	 * 
+	 * Defines the key for the resizable style. This specifies if a cell can
+	 * be resized. Possible values are 0 or 1. Default is 1. See
+	 * .
+	 */
+	STYLE_RESIZABLE: 'resizable',
+
+	/**
+	 * Variable: STYLE_CLONEABLE
+	 * 
+	 * Defines the key for the cloneable style. This specifies if a cell can
+	 * be cloned. Possible values are 0 or 1. Default is 1. See
+	 * .
+	 */
+	STYLE_CLONEABLE: 'cloneable',
+
+	/**
+	 * Variable: STYLE_DELETABLE
+	 * 
+	 * Defines the key for the deletable style. This specifies if a cell can be
+	 * deleted. Possible values are 0 or 1. Default is 1. See
+	 * .
+	 */
+	STYLE_DELETABLE: 'deletable',
+
+	/**
+	 * Variable: STYLE_SHAPE
+	 * 
+	 * Defines the key for the shape. Possible values are all constants
+	 * with a SHAPE-prefix or any newly defined shape names.
+	 */
+	STYLE_SHAPE: 'shape',
+
+	/**
+	 * Variable: STYLE_EDGE
+	 * 
+	 * Defines the key for the edge style. Possible values are the functions
+	 * defined in .
+	 */
+	STYLE_EDGE: 'edgeStyle',
+
+	/**
+	 * Variable: STYLE_LOOP
+	 * 
+	 * Defines the key for the loop style. Possible values are the functions
+	 * defined in .
+	 */
+	STYLE_LOOP: 'loopStyle',
+
+	/**
+	 * Variable: STYLE_ROUTING_CENTER_X
+	 * 
+	 * Defines the key for the horizontal routing center. Possible values are
+	 * between -0.5 and 0.5. This is the relative offset from the center used
+	 * for connecting edges. The type of this value is numeric.
+	 */
+	STYLE_ROUTING_CENTER_X: 'routingCenterX',
+
+	/**
+	 * Variable: STYLE_ROUTING_CENTER_Y
+	 * 
+	 * Defines the key for the vertical routing center. Possible values are
+	 * between -0.5 and 0.5. This is the relative offset from the center used
+	 * for connecting edges. The type of this value is numeric.
+	 */
+	STYLE_ROUTING_CENTER_Y: 'routingCenterY',
+
+	/**
+	 * Variable: FONT_BOLD
+	 * 
+	 * Constant for bold fonts. Default is 1.
+	 */
+	FONT_BOLD: 1,
+
+	/**
+	 * Variable: FONT_ITALIC
+	 * 
+	 * Constant for italic fonts. Default is 2.
+	 */
+	FONT_ITALIC: 2,
+
+	/**
+	 * Variable: FONT_UNDERLINE
+	 * 
+	 * Constant for underlined fonts. Default is 4.
+	 */
+	FONT_UNDERLINE: 4,
+
+	/**
+	 * Variable: FONT_SHADOW
+	 * 
+	 * Constant for fonts with a shadow. Default is 8.
+	 */
+	FONT_SHADOW: 8,
+
+	/**
+	 * Variable: SHAPE_RECTANGLE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is rectangle.
+	 */
+	SHAPE_RECTANGLE: 'rectangle',
+
+	/**
+	 * Variable: SHAPE_ELLIPSE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is ellipse.
+	 */
+	SHAPE_ELLIPSE: 'ellipse',
+
+	/**
+	 * Variable: SHAPE_DOUBLE_ELLIPSE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is doubleEllipse.
+	 */
+	SHAPE_DOUBLE_ELLIPSE: 'doubleEllipse',
+
+	/**
+	 * Variable: SHAPE_RHOMBUS
+	 * 
+	 * Name under which  is registered
+	 * in . Default is rhombus.
+	 */
+	SHAPE_RHOMBUS: 'rhombus',
+
+	/**
+	 * Variable: SHAPE_LINE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is line.
+	 */
+	SHAPE_LINE: 'line',
+
+	/**
+	 * Variable: SHAPE_IMAGE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is image.
+	 */
+	SHAPE_IMAGE: 'image',
+	
+	/**
+	 * Variable: SHAPE_ARROW
+	 * 
+	 * Name under which  is registered
+	 * in . Default is arrow.
+	 */
+	SHAPE_ARROW: 'arrow',
+	
+	/**
+	 * Variable: SHAPE_LABEL
+	 * 
+	 * Name under which  is registered
+	 * in . Default is label.
+	 */
+	SHAPE_LABEL: 'label',
+	
+	/**
+	 * Variable: SHAPE_CYLINDER
+	 * 
+	 * Name under which  is registered
+	 * in . Default is cylinder.
+	 */
+	SHAPE_CYLINDER: 'cylinder',
+	
+	/**
+	 * Variable: SHAPE_SWIMLANE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is swimlane.
+	 */
+	SHAPE_SWIMLANE: 'swimlane',
+		
+	/**
+	 * Variable: SHAPE_CONNECTOR
+	 * 
+	 * Name under which  is registered
+	 * in . Default is connector.
+	 */
+	SHAPE_CONNECTOR: 'connector',
+		
+	/**
+	 * Variable: SHAPE_ACTOR
+	 * 
+	 * Name under which  is registered
+	 * in . Default is actor.
+	 */
+	SHAPE_ACTOR: 'actor',
+		
+	/**
+	 * Variable: SHAPE_CLOUD
+	 * 
+	 * Name under which  is registered
+	 * in . Default is cloud.
+	 */
+	SHAPE_CLOUD: 'cloud',
+		
+	/**
+	 * Variable: SHAPE_TRIANGLE
+	 * 
+	 * Name under which  is registered
+	 * in . Default is triangle.
+	 */
+	SHAPE_TRIANGLE: 'triangle',
+		
+	/**
+	 * Variable: SHAPE_HEXAGON
+	 * 
+	 * Name under which  is registered
+	 * in . Default is hexagon.
+	 */
+	SHAPE_HEXAGON: 'hexagon',
+
+	/**
+	 * Variable: ARROW_CLASSIC
+	 * 
+	 * Constant for classic arrow markers.
+	 */
+	ARROW_CLASSIC: 'classic',
+
+	/**
+	 * Variable: ARROW_BLOCK
+	 * 
+	 * Constant for block arrow markers.
+	 */
+	ARROW_BLOCK: 'block',
+
+	/**
+	 * Variable: ARROW_OPEN
+	 * 
+	 * Constant for open arrow markers.
+	 */
+	ARROW_OPEN: 'open',
+
+	/**
+	 * Variable: ARROW_OVAL
+	 * 
+	 * Constant for oval arrow markers.
+	 */
+	ARROW_OVAL: 'oval',
+
+	/**
+	 * Variable: ARROW_DIAMOND
+	 * 
+	 * Constant for diamond arrow markers.
+	 */
+	ARROW_DIAMOND: 'diamond',
+
+	/**
+	 * Variable: ARROW_DIAMOND
+	 * 
+	 * Constant for diamond arrow markers.
+	 */
+	ARROW_DIAMOND_THIN: 'diamondThin',
+
+	/**
+	 * Variable: ALIGN_LEFT
+	 * 
+	 * Constant for left horizontal alignment. Default is left.
+	 */
+	ALIGN_LEFT: 'left',
+
+	/**
+	 * Variable: ALIGN_CENTER
+	 * 
+	 * Constant for center horizontal alignment. Default is center.
+	 */
+	ALIGN_CENTER: 'center',
+
+	/**
+	 * Variable: ALIGN_RIGHT
+	 * 
+	 * Constant for right horizontal alignment. Default is right.
+	 */
+	ALIGN_RIGHT: 'right',
+
+	/**
+	 * Variable: ALIGN_TOP
+	 * 
+	 * Constant for top vertical alignment. Default is top.
+	 */
+	ALIGN_TOP: 'top',
+
+	/**
+	 * Variable: ALIGN_MIDDLE
+	 * 
+	 * Constant for middle vertical alignment. Default is middle.
+	 */
+	ALIGN_MIDDLE: 'middle',
+
+	/**
+	 * Variable: ALIGN_BOTTOM
+	 * 
+	 * Constant for bottom vertical alignment. Default is bottom.
+	 */
+	ALIGN_BOTTOM: 'bottom',
+
+	/**
+	 * Variable: DIRECTION_NORTH
+	 * 
+	 * Constant for direction north. Default is north.
+	 */
+	DIRECTION_NORTH: 'north',
+
+	/**
+	 * Variable: DIRECTION_SOUTH
+	 * 
+	 * Constant for direction south. Default is south.
+	 */
+	DIRECTION_SOUTH: 'south',
+
+	/**
+	 * Variable: DIRECTION_EAST
+	 * 
+	 * Constant for direction east. Default is east.
+	 */
+	DIRECTION_EAST: 'east',
+
+	/**
+	 * Variable: DIRECTION_WEST
+	 * 
+	 * Constant for direction west. Default is west.
+	 */
+	DIRECTION_WEST: 'west',
+
+	/**
+	 * Variable: DIRECTION_MASK_NONE
+	 * 
+	 * Constant for no direction.
+	 */
+	DIRECTION_MASK_NONE: 0,
+
+	/**
+	 * Variable: DIRECTION_MASK_WEST
+	 * 
+	 * Bitwise mask for west direction.
+	 */
+	DIRECTION_MASK_WEST: 1,
+	
+	/**
+	 * Variable: DIRECTION_MASK_NORTH
+	 * 
+	 * Bitwise mask for north direction.
+	 */
+	DIRECTION_MASK_NORTH: 2,
+
+	/**
+	 * Variable: DIRECTION_MASK_SOUTH
+	 * 
+	 * Bitwise mask for south direction.
+	 */
+	DIRECTION_MASK_SOUTH: 4,
+
+	/**
+	 * Variable: DIRECTION_MASK_EAST
+	 * 
+	 * Bitwise mask for east direction.
+	 */
+	DIRECTION_MASK_EAST: 8,
+	
+	/**
+	 * Variable: DIRECTION_MASK_ALL
+	 * 
+	 * Bitwise mask for all directions.
+	 */
+	DIRECTION_MASK_ALL: 15,
+
+	/**
+	 * Variable: ELBOW_VERTICAL
+	 * 
+	 * Constant for elbow vertical. Default is horizontal.
+	 */
+	ELBOW_VERTICAL: 'vertical',
+
+	/**
+	 * Variable: ELBOW_HORIZONTAL
+	 * 
+	 * Constant for elbow horizontal. Default is horizontal.
+	 */
+	ELBOW_HORIZONTAL: 'horizontal',
+
+	/**
+	 * Variable: EDGESTYLE_ELBOW
+	 * 
+	 * Name of the elbow edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_ELBOW: 'elbowEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_ENTITY_RELATION
+	 * 
+	 * Name of the entity relation edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_ENTITY_RELATION: 'entityRelationEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_LOOP
+	 * 
+	 * Name of the loop edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_LOOP: 'loopEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_SIDETOSIDE
+	 * 
+	 * Name of the side to side edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_SIDETOSIDE: 'sideToSideEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_TOPTOBOTTOM
+	 * 
+	 * Name of the top to bottom edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_TOPTOBOTTOM: 'topToBottomEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_ORTHOGONAL
+	 * 
+	 * Name of the generic orthogonal edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_ORTHOGONAL: 'orthogonalEdgeStyle',
+
+	/**
+	 * Variable: EDGESTYLE_SEGMENT
+	 * 
+	 * Name of the generic segment edge style. Can be used as a string value
+	 * for the STYLE_EDGE style.
+	 */
+	EDGESTYLE_SEGMENT: 'segmentEdgeStyle',
+ 
+	/**
+	 * Variable: PERIMETER_ELLIPSE
+	 * 
+	 * Name of the ellipse perimeter. Can be used as a string value
+	 * for the STYLE_PERIMETER style.
+	 */
+	PERIMETER_ELLIPSE: 'ellipsePerimeter',
+
+	/**
+	 * Variable: PERIMETER_RECTANGLE
+	 *
+	 * Name of the rectangle perimeter. Can be used as a string value
+	 * for the STYLE_PERIMETER style.
+	 */
+	PERIMETER_RECTANGLE: 'rectanglePerimeter',
+
+	/**
+	 * Variable: PERIMETER_RHOMBUS
+	 * 
+	 * Name of the rhombus perimeter. Can be used as a string value
+	 * for the STYLE_PERIMETER style.
+	 */
+	PERIMETER_RHOMBUS: 'rhombusPerimeter',
+
+	/**
+	 * Variable: PERIMETER_TRIANGLE
+	 * 
+	 * Name of the triangle perimeter. Can be used as a string value
+	 * for the STYLE_PERIMETER style.
+	 */
+	PERIMETER_TRIANGLE: 'trianglePerimeter'
+
+};
+/**
+ * $Id: mxEventObject.js,v 1.11 2011-09-09 10:29:05 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxEventObject
+ * 
+ * The mxEventObject is a wrapper for all properties of a single event.
+ * Additionally, it also offers functions to consume the event and check if it
+ * was consumed as follows:
+ * 
+ * (code)
+ * evt.consume();
+ * INV: evt.isConsumed() == true
+ * (end)
+ * 
+ * Constructor: mxEventObject
+ *
+ * Constructs a new event object with the specified name. An optional
+ * sequence of key, value pairs can be appended to define properties.
+ * 
+ * Example:
+ *
+ * (code)
+ * new mxEventObject("eventName", key1, val1, .., keyN, valN)
+ * (end)
+ */
+function mxEventObject(name)
+{
+	this.name = name;
+	this.properties = [];
+	
+	for (var i = 1; i < arguments.length; i += 2)
+	{
+		if (arguments[i + 1] != null)
+		{
+			this.properties[arguments[i]] = arguments[i + 1];
+		}
+	}
+};
+
+/**
+ * Variable: name
+ *
+ * Holds the name.
+ */
+mxEventObject.prototype.name = null;
+
+/**
+ * Variable: properties
+ *
+ * Holds the properties as an associative array.
+ */
+mxEventObject.prototype.properties = null;
+
+/**
+ * Variable: consumed
+ *
+ * Holds the consumed state. Default is false.
+ */
+mxEventObject.prototype.consumed = false;
+
+/**
+ * Function: getName
+ * 
+ * Returns .
+ */
+mxEventObject.prototype.getName = function()
+{
+	return this.name;
+};
+
+/**
+ * Function: getProperties
+ * 
+ * Returns .
+ */
+mxEventObject.prototype.getProperties = function()
+{
+	return this.properties;
+};
+
+/**
+ * Function: getProperty
+ * 
+ * Returns the property for the given key.
+ */
+mxEventObject.prototype.getProperty = function(key)
+{
+	return this.properties[key];
+};
+
+/**
+ * Function: isConsumed
+ *
+ * Returns true if the event has been consumed.
+ */
+mxEventObject.prototype.isConsumed = function()
+{
+	return this.consumed;
+};
+
+/**
+ * Function: consume
+ *
+ * Consumes the event.
+ */
+mxEventObject.prototype.consume = function()
+{
+	this.consumed = true;
+};
+/**
+ * $Id: mxMouseEvent.js,v 1.20 2011-03-02 17:24:39 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxMouseEvent
+ * 
+ * Base class for all mouse events in mxGraph. A listener for this event should
+ * implement the following methods:
+ * 
+ * (code)
+ * graph.addMouseListener(
+ * {
+ *   mouseDown: function(sender, evt)
+ *   {
+ *     mxLog.debug('mouseDown');
+ *   },
+ *   mouseMove: function(sender, evt)
+ *   {
+ *     mxLog.debug('mouseMove');
+ *   },
+ *   mouseUp: function(sender, evt)
+ *   {
+ *     mxLog.debug('mouseUp');
+ *   }
+ * });
+ * (end)
+ * 
+ * Constructor: mxMouseEvent
+ *
+ * Constructs a new event object for the given arguments.
+ * 
+ * Parameters:
+ * 
+ * evt - Native mouse event.
+ * state - Optional  under the mouse.
+ * 
+ */
+function mxMouseEvent(evt, state)
+{
+	this.evt = evt;
+	this.state = state;
+};
+
+/**
+ * Variable: consumed
+ *
+ * Holds the consumed state of this event.
+ */
+mxMouseEvent.prototype.consumed = false;
+
+/**
+ * Variable: evt
+ *
+ * Holds the inner event object.
+ */
+mxMouseEvent.prototype.evt = null;
+
+/**
+ * Variable: graphX
+ *
+ * Holds the x-coordinate of the event in the graph. This value is set in
+ * .
+ */
+mxMouseEvent.prototype.graphX = null;
+
+/**
+ * Variable: graphY
+ *
+ * Holds the y-coordinate of the event in the graph. This value is set in
+ * .
+ */
+mxMouseEvent.prototype.graphY = null;
+
+/**
+ * Variable: state
+ *
+ * Holds the optional  associated with this event.
+ */
+mxMouseEvent.prototype.state = null;
+
+/**
+ * Function: getEvent
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getEvent = function()
+{
+	return this.evt;
+};
+
+/**
+ * Function: getSource
+ * 
+ * Returns the target DOM element using  for .
+ */
+mxMouseEvent.prototype.getSource = function()
+{
+	return mxEvent.getSource(this.evt);
+};
+
+/**
+ * Function: isSource
+ * 
+ * Returns true if the given  is the source of .
+ */
+mxMouseEvent.prototype.isSource = function(shape)
+{
+	if (shape != null)
+	{
+		var source = this.getSource();
+		
+		while (source != null)
+		{
+			if (source == shape.node)
+			{
+				return true;
+			}
+	
+			source = source.parentNode;
+		}
+	}
+	
+	return false;
+};
+
+/**
+ * Function: getX
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getX = function()
+{
+	return mxEvent.getClientX(this.getEvent());
+};
+
+/**
+ * Function: getY
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getY = function()
+{
+	return mxEvent.getClientY(this.getEvent());
+};
+
+/**
+ * Function: getGraphX
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getGraphX = function()
+{
+	return this.graphX;
+};
+
+/**
+ * Function: getGraphY
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getGraphY = function()
+{
+	return this.graphY;
+};
+
+/**
+ * Function: getState
+ * 
+ * Returns .
+ */
+mxMouseEvent.prototype.getState = function()
+{
+	return this.state;
+};
+
+/**
+ * Function: getCell
+ * 
+ * Returns the  in  is not null.
+ */
+mxMouseEvent.prototype.getCell = function()
+{
+	var state = this.getState();
+	
+	if (state != null)
+	{
+		return state.cell;
+	}
+	
+	return null;
+};
+
+/**
+ * Function: isPopupTrigger
+ *
+ * Returns true if the event is a popup trigger.
+ */
+mxMouseEvent.prototype.isPopupTrigger = function()
+{
+	return mxEvent.isPopupTrigger(this.getEvent());
+};
+
+/**
+ * Function: isConsumed
+ *
+ * Returns .
+ */
+mxMouseEvent.prototype.isConsumed = function()
+{
+	return this.consumed;
+};
+
+/**
+ * Function: consume
+ *
+ * Sets  to true and invokes preventDefault on the native event
+ * if such a method is defined. This is used mainly to avoid the cursor from
+ * being changed to a text cursor in Webkit. You can use the preventDefault
+ * flag to disable this functionality.
+ * 
+ * Parameters:
+ * 
+ * preventDefault - Specifies if the native event should be canceled. Default
+ * is true.
+ */
+mxMouseEvent.prototype.consume = function(preventDefault)
+{
+	preventDefault = (preventDefault != null) ? preventDefault : true;
+	
+	if (preventDefault && this.evt.preventDefault)
+	{
+		this.evt.preventDefault();
+	}
+
+	// Workaround for images being dragged in IE
+	this.evt.returnValue = false;
+	
+	// Sets local consumed state
+	this.consumed = true;
+};
+/**
+ * $Id: mxEventSource.js,v 1.25 2012-04-16 10:54:20 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxEventSource
+ *
+ * Base class for objects that dispatch named events. To create a subclass that
+ * inherits from mxEventSource, the following code is used.
+ *
+ * (code)
+ * function MyClass() { };
+ *
+ * MyClass.prototype = new mxEventSource();
+ * MyClass.prototype.constructor = MyClass;
+ * (end)
+ *
+ * Known Subclasses:
+ *
+ * , , , , ,
+ * , 
+ * 
+ * Constructor: mxEventSource
+ *
+ * Constructs a new event source.
+ */
+function mxEventSource(eventSource)
+{
+	this.setEventSource(eventSource);
+};
+
+/**
+ * Variable: eventListeners
+ *
+ * Holds the event names and associated listeners in an array. The array
+ * contains the event name followed by the respective listener for each
+ * registered listener.
+ */
+mxEventSource.prototype.eventListeners = null;
+
+/**
+ * Variable: eventsEnabled
+ *
+ * Specifies if events can be fired. Default is true.
+ */
+mxEventSource.prototype.eventsEnabled = true;
+
+/**
+ * Variable: eventSource
+ *
+ * Optional source for events. Default is null.
+ */
+mxEventSource.prototype.eventSource = null;
+
+/**
+ * Function: isEventsEnabled
+ * 
+ * Returns .
+ */
+mxEventSource.prototype.isEventsEnabled = function()
+{
+	return this.eventsEnabled;
+};
+
+/**
+ * Function: setEventsEnabled
+ * 
+ * Sets .
+ */
+mxEventSource.prototype.setEventsEnabled = function(value)
+{
+	this.eventsEnabled = value;
+};
+
+/**
+ * Function: getEventSource
+ * 
+ * Returns .
+ */
+mxEventSource.prototype.getEventSource = function()
+{
+	return this.eventSource;
+};
+
+/**
+ * Function: setEventSource
+ * 
+ * Sets .
+ */
+mxEventSource.prototype.setEventSource = function(value)
+{
+	this.eventSource = value;
+};
+
+/**
+ * Function: addListener
+ *
+ * Binds the specified function to the given event name. If no event name
+ * is given, then the listener is registered for all events.
+ * 
+ * The parameters of the listener are the sender and an .
+ */
+mxEventSource.prototype.addListener = function(name, funct)
+{
+	if (this.eventListeners == null)
+	{
+		this.eventListeners = [];
+	}
+	
+	this.eventListeners.push(name);
+	this.eventListeners.push(funct);
+};
+
+/**
+ * Function: removeListener
+ *
+ * Removes all occurrences of the given listener from .
+ */
+mxEventSource.prototype.removeListener = function(funct)
+{
+	if (this.eventListeners != null)
+	{
+		var i = 0;
+		
+		while (i < this.eventListeners.length)
+		{
+			if (this.eventListeners[i+1] == funct)
+			{
+				this.eventListeners.splice(i, 2);
+			}
+			else
+			{
+				i += 2;
+			}
+		}
+	}
+};
+
+/**
+ * Function: fireEvent
+ *
+ * Dispatches the given event to the listeners which are registered for
+ * the event. The sender argument is optional. The current execution scope
+ * ("this") is used for the listener invocation (see ).
+ *
+ * Example:
+ *
+ * (code)
+ * fireEvent(new mxEventObject("eventName", key1, val1, .., keyN, valN))
+ * (end)
+ * 
+ * Parameters:
+ *
+ * evt -  that represents the event.
+ * sender - Optional sender to be passed to the listener. Default value is
+ * the return value of .
+ */
+mxEventSource.prototype.fireEvent = function(evt, sender)
+{
+	if (this.eventListeners != null &&
+		this.isEventsEnabled())
+	{
+		if (evt == null)
+		{
+			evt = new mxEventObject();
+		}
+		
+		if (sender == null)
+		{
+			sender = this.getEventSource();
+		}
+
+		if (sender == null)
+		{
+			sender = this;
+		}
+
+		var args = [sender, evt];
+		
+		for (var i = 0; i < this.eventListeners.length; i += 2)
+		{
+			var listen = this.eventListeners[i];
+			
+			if (listen == null ||
+				listen == evt.getName())
+			{
+				this.eventListeners[i+1].apply(this, args);
+			}
+		}
+	}
+};
+/**
+ * $Id: mxEvent.js,v 1.72 2012-05-03 13:28:03 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+var mxEvent =
+{
+
+	/**
+	 * Class: mxEvent
+	 * 
+	 * Cross-browser DOM event support. For internal event handling,
+	 *  and the graph event dispatch loop in  are used.
+	 * 
+	 * Memory Leaks:
+	 * 
+	 * Use this class for adding and removing listeners to/from DOM nodes. The
+	 *  function is provided to remove all listeners that
+	 * have been added using . The function should be invoked when
+	 * the last reference is removed in the JavaScript code, typically when the
+	 * referenced DOM node is removed from the DOM, and helps to reduce memory
+	 * leaks in IE6.
+	 * 
+	 * Variable: objects
+	 * 
+	 * Contains all objects where any listener was added using .
+	 * This is used to reduce memory leaks in IE, see .
+	 */
+	objects: [],
+
+	 /**
+	  * Function: addListener
+	  * 
+	  * Binds the function to the specified event on the given element. Use
+	  *  in order to bind the "this" keyword inside the function
+	  * to a given execution scope.
+	  */
+	addListener: function()
+	{
+		var updateListenerList = function(element, eventName, funct)
+		{
+			if (element.mxListenerList == null)
+			{
+				element.mxListenerList = [];
+				mxEvent.objects.push(element);
+			}
+			
+			var entry = {name: eventName, f: funct};
+			element.mxListenerList.push(entry);
+		};
+		
+		if (window.addEventListener)
+		{
+			return function(element, eventName, funct)
+			{
+				element.addEventListener(eventName, funct, false);
+				updateListenerList(element, eventName, funct);
+			};
+		}
+		else
+		{
+			return function(element, eventName, funct)
+			{
+				element.attachEvent("on" + eventName, funct);
+				updateListenerList(element, eventName, funct);				
+			};
+		}
+	}(),
+
+	/**
+	 * Function: removeListener
+	 *
+	 * Removes the specified listener from the given element.
+	 */
+	removeListener: function()
+	{
+		var updateListener = function(element, eventName, funct)
+		{
+			if (element.mxListenerList != null)
+			{
+				var listenerCount = element.mxListenerList.length;
+				
+				for (var i=0; i 0)
+			{
+				var entry = list[0];
+				mxEvent.removeListener(element, entry.name, entry.f);
+			}
+		}
+	},
+	
+	/**
+	 * Function: redirectMouseEvents
+	 *
+	 * Redirects the mouse events from the given DOM node to the graph dispatch
+	 * loop using the event and given state as event arguments. State can
+	 * either be an instance of  or a function that returns an
+	 * . The down, move, up and dblClick arguments are optional
+	 * functions that take the trigger event as arguments and replace the
+	 * default behaviour.
+	 */
+	redirectMouseEvents: function(node, graph, state, down, move, up, dblClick)
+	{
+		var getState = function(evt)
+		{
+			return (typeof(state) == 'function') ? state(evt) : state;
+		};
+		
+		var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+		var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+		var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+		
+		mxEvent.addListener(node, md, function (evt)
+		{
+			if (down != null)
+			{
+				down(evt);
+			}
+			else if (!mxEvent.isConsumed(evt))
+			{
+				graph.fireMouseEvent(mxEvent.MOUSE_DOWN,
+					new mxMouseEvent(evt, getState(evt)));
+			}
+		});
+		
+		mxEvent.addListener(node, mm, function (evt)
+		{
+			if (move != null)
+			{
+				move(evt);
+			}
+			else if (!mxEvent.isConsumed(evt))
+			{
+				graph.fireMouseEvent(mxEvent.MOUSE_MOVE,
+						new mxMouseEvent(evt, getState(evt)));
+			}
+		});
+		
+		mxEvent.addListener(node, mu, function (evt)
+		{
+			if (up != null)
+			{
+				up(evt);
+			}
+			else if (!mxEvent.isConsumed(evt))
+			{
+				graph.fireMouseEvent(mxEvent.MOUSE_UP,
+						new mxMouseEvent(evt, getState(evt)));
+			}
+		});
+
+		mxEvent.addListener(node, 'dblclick', function (evt)
+		{
+			if (dblClick != null)
+			{
+				dblClick(evt);
+			}
+			else if (!mxEvent.isConsumed(evt))
+			{
+				var tmp = getState(evt);
+				graph.dblClick(evt, (tmp != null) ? tmp.cell : null);
+			}
+		});
+	},
+
+	/**
+	 * Function: release
+	 * 
+	 * Removes the known listeners from the given DOM node and its descendants.
+	 * 
+	 * Parameters:
+	 * 
+	 * element - DOM node to remove the listeners from.
+	 */
+	release: function(element)
+	{
+		if (element != null)
+		{
+			mxEvent.removeAllListeners(element);
+			
+			var children = element.childNodes;
+			
+			if (children != null)
+			{
+		        var childCount = children.length;
+		        
+		        for (var i = 0; i < childCount; i += 1)
+		        {
+		        	mxEvent.release(children[i]);
+		        }
+		    }
+		}
+	},
+
+	/**
+	 * Function: addMouseWheelListener
+	 * 
+	 * Installs the given function as a handler for mouse wheel events. The
+	 * function has two arguments: the mouse event and a boolean that specifies
+	 * if the wheel was moved up or down.
+	 * 
+	 * This has been tested with IE 6 and 7, Firefox (all versions), Opera and
+	 * Safari. It does currently not work on Safari for Mac.
+	 * 
+	 * Example:
+	 * 
+	 * (code)
+	 * mxEvent.addMouseWheelListener(function (evt, up)
+	 * {
+	 *   mxLog.show();
+	 *   mxLog.debug('mouseWheel: up='+up);
+	 * });
+	 *(end)
+	 * 
+	 * Parameters:
+	 * 
+	 * funct - Handler function that takes the event argument and a boolean up
+	 * argument for the mousewheel direction.
+	 */
+	addMouseWheelListener: function(funct)
+	{
+		if (funct != null)
+		{
+			var wheelHandler = function(evt)
+			{
+				// IE does not give an event object but the
+				// global event object is the mousewheel event
+				// at this point in time.
+				if (evt == null)
+				{
+					evt = window.event;
+				}
+			
+				var delta = 0;
+				
+				if (mxClient.IS_NS && !mxClient.IS_SF && !mxClient.IS_GC)
+				{
+					delta = -evt.detail/2;
+				}
+				else
+				{
+					delta = evt.wheelDelta/120;
+				}
+				
+				// Handles the event using the given function
+				if (delta != 0)
+				{
+					funct(evt, delta > 0);
+				}
+			};
+	
+			// Webkit has NS event API, but IE event name and details 
+			if (mxClient.IS_NS)
+			{
+				var eventName = (mxClient.IS_SF || 	mxClient.IS_GC) ?
+						'mousewheel' : 'DOMMouseScroll';
+				mxEvent.addListener(window, eventName, wheelHandler);
+			}
+			else
+			{
+				// TODO: Does not work with Safari and Chrome but it should be
+				// working as tested in etc/markup/wheel.html
+				mxEvent.addListener(document, 'mousewheel', wheelHandler);
+			}
+		}
+	},
+	
+	/**
+	 * Function: disableContextMenu
+	 *
+	 * Disables the context menu for the given element.
+	 */
+	disableContextMenu: function()
+	{
+		if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9))
+		{
+			return function(element)
+			{
+				mxEvent.addListener(element, 'contextmenu', function()
+				{
+					return false;
+				});
+			};
+		}
+		else
+		{
+			return function(element)
+			{
+				element.setAttribute('oncontextmenu', 'return false;');
+			};		
+		}
+	}(),
+	
+	/**
+	 * Function: getSource
+	 * 
+	 * Returns the event's target or srcElement depending on the browser.
+	 */
+	getSource: function(evt)
+	{
+		return (evt.srcElement != null) ? evt.srcElement : evt.target;
+	},
+
+	/**
+	 * Function: isConsumed
+	 * 
+	 * Returns true if the event has been consumed using .
+	 */
+	isConsumed: function(evt)
+	{
+		return evt.isConsumed != null &&
+			evt.isConsumed; // Opera
+	},
+
+	/**
+	 * Function: isLeftMouseButton
+	 * 
+	 * Returns true if the left mouse button is pressed for the given event.
+	 * To check if a button is pressed during a mouseMove you should use the
+	 *  property.
+	 */
+	isLeftMouseButton: function(evt)
+	{
+		return evt.button == ((mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) ? 1 : 0);
+	},
+	
+	/**
+	 * Function: isRightMouseButton
+	 * 
+	 * Returns true if the right mouse button was pressed. Note that this
+	 * button might not be available on some systems. For handling a popup
+	 * trigger  should be used.
+	 */
+	isRightMouseButton: function(evt)
+	{
+		return evt.button == 2;
+	},
+
+	/**
+	 * Function: isPopupTrigger
+	 * 
+	 * Returns true if the event is a popup trigger. This implementation
+	 * returns true if the right mouse button or shift was pressed.
+	 */
+	isPopupTrigger: function(evt)
+	{
+		return mxEvent.isRightMouseButton(evt) ||
+			(mxEvent.isShiftDown(evt) &&
+			!mxEvent.isControlDown(evt));
+	},
+
+	/**
+	 * Function: isShiftDown
+	 * 
+	 * Returns true if the shift key is pressed for the given event.
+	 */
+	isShiftDown: function(evt)
+	{
+		return (evt != null) ? evt.shiftKey : false;
+	},
+
+	/**
+	 * Function: isAltDown
+	 * 
+	 * Returns true if the alt key is pressed for the given event.
+	 */
+	isAltDown: function(evt)
+	{
+		return (evt != null) ? evt.altKey : false;
+	},
+
+	/**
+	 * Function: isControlDown
+	 * 
+	 * Returns true if the control key is pressed for the given event.
+	 */
+	isControlDown: function(evt)
+	{
+		return (evt != null) ? evt.ctrlKey : false;
+	},
+
+	/**
+	 * Function: isMetaDown
+	 * 
+	 * Returns true if the meta key is pressed for the given event.
+	 */
+	isMetaDown: function(evt)
+	{
+		return (evt != null) ? evt.metaKey : false;
+	},
+
+	/**
+	 * Function: getMainEvent
+	 * 
+	 * Returns the touch or mouse event that contains the mouse coordinates.
+	 */
+	getMainEvent: function(e)
+	{
+		if ((e.type == 'touchstart' || e.type == 'touchmove') &&
+			e.touches != null && e.touches[0] != null)
+		{
+			e = e.touches[0];
+		}
+		else if (e.type == 'touchend' && e.changedTouches != null &&
+			e.changedTouches[0] != null)
+		{
+			e = e.changedTouches[0];
+		}
+		
+		return e;
+	},
+	
+	/**
+	 * Function: getClientX
+	 * 
+	 * Returns true if the meta key is pressed for the given event.
+	 */
+	getClientX: function(e)
+	{
+		return mxEvent.getMainEvent(e).clientX;
+	},
+
+	/**
+	 * Function: getClientY
+	 * 
+	 * Returns true if the meta key is pressed for the given event.
+	 */
+	getClientY: function(e)
+	{
+		return mxEvent.getMainEvent(e).clientY;
+	},
+
+	/**
+	 * Function: consume
+	 * 
+	 * Consumes the given event.
+	 * 
+	 * Parameters:
+	 * 
+	 * evt - Native event to be consumed.
+	 * preventDefault - Optional boolean to prevent the default for the event.
+	 * Default is true.
+	 * stopPropagation - Option boolean to stop event propagation. Default is
+	 * true.
+	 */
+	consume: function(evt, preventDefault, stopPropagation)
+	{
+		preventDefault = (preventDefault != null) ? preventDefault : true;
+		stopPropagation = (stopPropagation != null) ? stopPropagation : true;
+		
+		if (preventDefault)
+		{
+			if (evt.preventDefault)
+			{
+				if (stopPropagation)
+				{
+					evt.stopPropagation();
+				}
+				
+				evt.preventDefault();
+			}
+			else if (stopPropagation)
+			{
+				evt.cancelBubble = true;
+			}
+		}
+
+		// Opera
+		evt.isConsumed = true;
+
+		// Other browsers
+		evt.returnValue = false;
+	},
+	
+	//
+	// Special handles in mouse events
+	//
+	
+	/**
+	 * Variable: LABEL_HANDLE
+	 * 
+	 * Index for the label handle in an mxMouseEvent. This should be a negative
+	 * value that does not interfere with any possible handle indices. Default
+	 * is -1.
+	 */
+	LABEL_HANDLE: -1,
+	
+	//
+	// Event names
+	//
+	
+	/**
+	 * Variable: MOUSE_DOWN
+	 *
+	 * Specifies the event name for mouseDown.
+	 */
+	MOUSE_DOWN: 'mouseDown',
+	
+	/**
+	 * Variable: MOUSE_MOVE
+	 *
+	 * Specifies the event name for mouseMove. 
+	 */
+	MOUSE_MOVE: 'mouseMove',
+	
+	/**
+	 * Variable: MOUSE_UP
+	 *
+	 * Specifies the event name for mouseUp. 
+	 */
+	MOUSE_UP: 'mouseUp',
+
+	/**
+	 * Variable: ACTIVATE
+	 *
+	 * Specifies the event name for activate.
+	 */
+	ACTIVATE: 'activate',
+
+	/**
+	 * Variable: RESIZE_START
+	 *
+	 * Specifies the event name for resizeStart.
+	 */
+	RESIZE_START: 'resizeStart',
+
+	/**
+	 * Variable: RESIZE
+	 *
+	 * Specifies the event name for resize.
+	 */
+	RESIZE: 'resize',
+
+	/**
+	 * Variable: RESIZE_END
+	 *
+	 * Specifies the event name for resizeEnd.
+	 */
+	RESIZE_END: 'resizeEnd',
+
+	/**
+	 * Variable: MOVE_START
+	 *
+	 * Specifies the event name for moveStart.
+	 */
+	MOVE_START: 'moveStart',
+
+	/**
+	 * Variable: MOVE
+	 *
+	 * Specifies the event name for move.
+	 */
+	MOVE: 'move',
+
+	/**
+	 * Variable: MOVE_END
+	 *
+	 * Specifies the event name for moveEnd.
+	 */
+	MOVE_END: 'moveEnd',
+
+	/**
+	 * Variable: PAN_START
+	 *
+	 * Specifies the event name for panStart.
+	 */
+	PAN_START: 'panStart',
+
+	/**
+	 * Variable: PAN
+	 *
+	 * Specifies the event name for pan.
+	 */
+	PAN: 'pan',
+
+	/**
+	 * Variable: PAN_END
+	 *
+	 * Specifies the event name for panEnd.
+	 */
+	PAN_END: 'panEnd',
+
+	/**
+	 * Variable: MINIMIZE
+	 *
+	 * Specifies the event name for minimize.
+	 */
+	MINIMIZE: 'minimize',
+
+	/**
+	 * Variable: NORMALIZE
+	 *
+	 * Specifies the event name for normalize.
+	 */
+	NORMALIZE: 'normalize',
+
+	/**
+	 * Variable: MAXIMIZE
+	 *
+	 * Specifies the event name for maximize.
+	 */
+	MAXIMIZE: 'maximize',
+
+	/**
+	 * Variable: HIDE
+	 *
+	 * Specifies the event name for hide.
+	 */
+	HIDE: 'hide',
+
+	/**
+	 * Variable: SHOW
+	 *
+	 * Specifies the event name for show.
+	 */
+	SHOW: 'show',
+
+	/**
+	 * Variable: CLOSE
+	 *
+	 * Specifies the event name for close.
+	 */
+	CLOSE: 'close',
+
+	/**
+	 * Variable: DESTROY
+	 *
+	 * Specifies the event name for destroy.
+	 */
+	DESTROY: 'destroy',
+
+	/**
+	 * Variable: REFRESH
+	 *
+	 * Specifies the event name for refresh.
+	 */
+	REFRESH: 'refresh',
+
+	/**
+	 * Variable: SIZE
+	 *
+	 * Specifies the event name for size.
+	 */
+	SIZE: 'size',
+	
+	/**
+	 * Variable: SELECT
+	 *
+	 * Specifies the event name for select.
+	 */
+	SELECT: 'select',
+
+	/**
+	 * Variable: FIRED
+	 *
+	 * Specifies the event name for fired.
+	 */
+	FIRED: 'fired',
+
+	/**
+	 * Variable: GET
+	 *
+	 * Specifies the event name for get.
+	 */
+	GET: 'get',
+
+	/**
+	 * Variable: RECEIVE
+	 *
+	 * Specifies the event name for receive.
+	 */
+	RECEIVE: 'receive',
+
+	/**
+	 * Variable: CONNECT
+	 *
+	 * Specifies the event name for connect.
+	 */
+	CONNECT: 'connect',
+
+	/**
+	 * Variable: DISCONNECT
+	 *
+	 * Specifies the event name for disconnect.
+	 */
+	DISCONNECT: 'disconnect',
+
+	/**
+	 * Variable: SUSPEND
+	 *
+	 * Specifies the event name for suspend.
+	 */
+	SUSPEND: 'suspend',
+
+	/**
+	 * Variable: RESUME
+	 *
+	 * Specifies the event name for suspend.
+	 */
+	RESUME: 'resume',
+
+	/**
+	 * Variable: MARK
+	 *
+	 * Specifies the event name for mark.
+	 */
+	MARK: 'mark',
+
+	/**
+	 * Variable: SESSION
+	 *
+	 * Specifies the event name for session.
+	 */
+	SESSION: 'session',
+
+	/**
+	 * Variable: ROOT
+	 *
+	 * Specifies the event name for root.
+	 */
+	ROOT: 'root',
+
+	/**
+	 * Variable: POST
+	 *
+	 * Specifies the event name for post.
+	 */
+	POST: 'post',
+
+	/**
+	 * Variable: OPEN
+	 *
+	 * Specifies the event name for open.
+	 */
+	OPEN: 'open',
+
+	/**
+	 * Variable: SAVE
+	 *
+	 * Specifies the event name for open.
+	 */
+	SAVE: 'save',
+
+	/**
+	 * Variable: BEFORE_ADD_VERTEX
+	 *
+	 * Specifies the event name for beforeAddVertex.
+	 */
+	BEFORE_ADD_VERTEX: 'beforeAddVertex',
+
+	/**
+	 * Variable: ADD_VERTEX
+	 *
+	 * Specifies the event name for addVertex.
+	 */
+	ADD_VERTEX: 'addVertex',
+
+	/**
+	 * Variable: AFTER_ADD_VERTEX
+	 *
+	 * Specifies the event name for afterAddVertex.
+	 */
+	AFTER_ADD_VERTEX: 'afterAddVertex',
+
+	/**
+	 * Variable: DONE
+	 *
+	 * Specifies the event name for done.
+	 */
+	DONE: 'done',
+
+	/**
+	 * Variable: EXECUTE
+	 *
+	 * Specifies the event name for execute.
+	 */
+	EXECUTE: 'execute',
+
+	/**
+	 * Variable: BEGIN_UPDATE
+	 *
+	 * Specifies the event name for beginUpdate.
+	 */
+	BEGIN_UPDATE: 'beginUpdate',
+
+	/**
+	 * Variable: END_UPDATE
+	 *
+	 * Specifies the event name for endUpdate.
+	 */
+	END_UPDATE: 'endUpdate',
+
+	/**
+	 * Variable: BEFORE_UNDO
+	 *
+	 * Specifies the event name for beforeUndo.
+	 */
+	BEFORE_UNDO: 'beforeUndo',
+
+	/**
+	 * Variable: UNDO
+	 *
+	 * Specifies the event name for undo.
+	 */
+	UNDO: 'undo',
+
+	/**
+	 * Variable: REDO
+	 *
+	 * Specifies the event name for redo.
+	 */
+	REDO: 'redo',
+
+	/**
+	 * Variable: CHANGE
+	 *
+	 * Specifies the event name for change.
+	 */
+	CHANGE: 'change',
+
+	/**
+	 * Variable: NOTIFY
+	 *
+	 * Specifies the event name for notify.
+	 */
+	NOTIFY: 'notify',
+
+	/**
+	 * Variable: LAYOUT_CELLS
+	 *
+	 * Specifies the event name for layoutCells.
+	 */
+	LAYOUT_CELLS: 'layoutCells',
+
+	/**
+	 * Variable: CLICK
+	 *
+	 * Specifies the event name for click.
+	 */
+	CLICK: 'click',
+
+	/**
+	 * Variable: SCALE
+	 *
+	 * Specifies the event name for scale.
+	 */
+	SCALE: 'scale',
+
+	/**
+	 * Variable: TRANSLATE
+	 *
+	 * Specifies the event name for translate.
+	 */
+	TRANSLATE: 'translate',
+
+	/**
+	 * Variable: SCALE_AND_TRANSLATE
+	 *
+	 * Specifies the event name for scaleAndTranslate.
+	 */
+	SCALE_AND_TRANSLATE: 'scaleAndTranslate',
+
+	/**
+	 * Variable: UP
+	 *
+	 * Specifies the event name for up.
+	 */
+	UP: 'up',
+
+	/**
+	 * Variable: DOWN
+	 *
+	 * Specifies the event name for down.
+	 */
+	DOWN: 'down',
+
+	/**
+	 * Variable: ADD
+	 *
+	 * Specifies the event name for add.
+	 */
+	ADD: 'add',
+
+	/**
+	 * Variable: CLEAR
+	 *
+	 * Specifies the event name for clear.
+	 */
+	CLEAR: 'clear',
+
+	/**
+	 * Variable: ADD_CELLS
+	 *
+	 * Specifies the event name for addCells.
+	 */
+	ADD_CELLS: 'addCells',
+
+	/**
+	 * Variable: CELLS_ADDED
+	 *
+	 * Specifies the event name for cellsAdded.
+	 */
+	CELLS_ADDED: 'cellsAdded',
+
+	/**
+	 * Variable: MOVE_CELLS
+	 *
+	 * Specifies the event name for moveCells.
+	 */
+	MOVE_CELLS: 'moveCells',
+
+	/**
+	 * Variable: CELLS_MOVED
+	 *
+	 * Specifies the event name for cellsMoved.
+	 */
+	CELLS_MOVED: 'cellsMoved',
+
+	/**
+	 * Variable: RESIZE_CELLS
+	 *
+	 * Specifies the event name for resizeCells.
+	 */
+	RESIZE_CELLS: 'resizeCells',
+
+	/**
+	 * Variable: CELLS_RESIZED
+	 *
+	 * Specifies the event name for cellsResized.
+	 */
+	CELLS_RESIZED: 'cellsResized',
+
+	/**
+	 * Variable: TOGGLE_CELLS
+	 *
+	 * Specifies the event name for toggleCells.
+	 */
+	TOGGLE_CELLS: 'toggleCells',
+
+	/**
+	 * Variable: CELLS_TOGGLED
+	 *
+	 * Specifies the event name for cellsToggled.
+	 */
+	CELLS_TOGGLED: 'cellsToggled',
+
+	/**
+	 * Variable: ORDER_CELLS
+	 *
+	 * Specifies the event name for orderCells.
+	 */
+	ORDER_CELLS: 'orderCells',
+
+	/**
+	 * Variable: CELLS_ORDERED
+	 *
+	 * Specifies the event name for cellsOrdered.
+	 */
+	CELLS_ORDERED: 'cellsOrdered',
+
+	/**
+	 * Variable: REMOVE_CELLS
+	 *
+	 * Specifies the event name for removeCells.
+	 */
+	REMOVE_CELLS: 'removeCells',
+
+	/**
+	 * Variable: CELLS_REMOVED
+	 *
+	 * Specifies the event name for cellsRemoved.
+	 */
+	CELLS_REMOVED: 'cellsRemoved',
+
+	/**
+	 * Variable: GROUP_CELLS
+	 *
+	 * Specifies the event name for groupCells.
+	 */
+	GROUP_CELLS: 'groupCells',
+
+	/**
+	 * Variable: UNGROUP_CELLS
+	 *
+	 * Specifies the event name for ungroupCells.
+	 */
+	UNGROUP_CELLS: 'ungroupCells',
+
+	/**
+	 * Variable: REMOVE_CELLS_FROM_PARENT
+	 *
+	 * Specifies the event name for removeCellsFromParent.
+	 */
+	REMOVE_CELLS_FROM_PARENT: 'removeCellsFromParent',
+
+	/**
+	 * Variable: FOLD_CELLS
+	 *
+	 * Specifies the event name for foldCells.
+	 */
+	FOLD_CELLS: 'foldCells',
+
+	/**
+	 * Variable: CELLS_FOLDED
+	 *
+	 * Specifies the event name for cellsFolded.
+	 */
+	CELLS_FOLDED: 'cellsFolded',
+
+	/**
+	 * Variable: ALIGN_CELLS
+	 *
+	 * Specifies the event name for alignCells.
+	 */
+	ALIGN_CELLS: 'alignCells',
+
+	/**
+	 * Variable: LABEL_CHANGED
+	 *
+	 * Specifies the event name for labelChanged.
+	 */
+	LABEL_CHANGED: 'labelChanged',
+
+	/**
+	 * Variable: CONNECT_CELL
+	 *
+	 * Specifies the event name for connectCell.
+	 */
+	CONNECT_CELL: 'connectCell',
+
+	/**
+	 * Variable: CELL_CONNECTED
+	 *
+	 * Specifies the event name for cellConnected.
+	 */
+	CELL_CONNECTED: 'cellConnected',
+
+	/**
+	 * Variable: SPLIT_EDGE
+	 *
+	 * Specifies the event name for splitEdge.
+	 */
+	SPLIT_EDGE: 'splitEdge',
+
+	/**
+	 * Variable: FLIP_EDGE
+	 *
+	 * Specifies the event name for flipEdge.
+	 */
+	FLIP_EDGE: 'flipEdge',
+
+	/**
+	 * Variable: START_EDITING
+	 *
+	 * Specifies the event name for startEditing.
+	 */
+	START_EDITING: 'startEditing',
+
+	/**
+	 * Variable: ADD_OVERLAY
+	 *
+	 * Specifies the event name for addOverlay.
+	 */
+	ADD_OVERLAY: 'addOverlay',
+
+	/**
+	 * Variable: REMOVE_OVERLAY
+	 *
+	 * Specifies the event name for removeOverlay.
+	 */
+	REMOVE_OVERLAY: 'removeOverlay',
+
+	/**
+	 * Variable: UPDATE_CELL_SIZE
+	 *
+	 * Specifies the event name for updateCellSize.
+	 */
+	UPDATE_CELL_SIZE: 'updateCellSize',
+
+	/**
+	 * Variable: ESCAPE
+	 *
+	 * Specifies the event name for escape.
+	 */
+	ESCAPE: 'escape',
+
+	/**
+	 * Variable: CLICK
+	 *
+	 * Specifies the event name for click.
+	 */
+	CLICK: 'click',
+
+	/**
+	 * Variable: DOUBLE_CLICK
+	 *
+	 * Specifies the event name for doubleClick.
+	 */
+	DOUBLE_CLICK: 'doubleClick'
+
+};
+/**
+ * $Id: mxXmlRequest.js,v 1.38 2012-04-22 10:16:23 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxXmlRequest
+ * 
+ * XML HTTP request wrapper. See also: ,  and
+ * . This class provides a cross-browser abstraction for Ajax
+ * requests.
+ * 
+ * Encoding:
+ * 
+ * For encoding parameter values, the built-in encodeURIComponent JavaScript
+ * method must be used. For automatic encoding of post data in  the
+ *  switch can be set to true (default). The encoding
+ * will be carried out using the conte type of the page. That is, the page
+ * containting the editor should contain a meta tag in the header, eg.
+ * 
+ * 
+ * Example:
+ * 
+ * (code)
+ * var onload = function(req)
+ * {
+ *   mxUtils.alert(req.getDocumentElement());
+ * }
+ * 
+ * var onerror = function(req)
+ * {
+ *   mxUtils.alert(req.getStatus());
+ * }
+ * new mxXmlRequest(url, 'key=value').send(onload, onerror);
+ * (end)
+ * 
+ * Sends an asynchronous POST request to the specified URL.
+ * 
+ * Example:
+ * 
+ * (code)
+ * var req = new mxXmlRequest(url, 'key=value', 'POST', false);
+ * req.send();
+ * mxUtils.alert(req.getDocumentElement());
+ * (end)
+ * 
+ * Sends a synchronous POST request to the specified URL.
+ * 
+ * Example:
+ * 
+ * (code)
+ * var encoder = new mxCodec();
+ * var result = encoder.encode(graph.getModel());
+ * var xml = encodeURIComponent(mxUtils.getXml(result));
+ * new mxXmlRequest(url, 'xml='+xml).send();
+ * (end)
+ * 
+ * Sends an encoded graph model to the specified URL using xml as the
+ * parameter name. The parameter can then be retrieved in C# as follows:
+ * 
+ * (code)
+ * string xml = HttpUtility.UrlDecode(context.Request.Params["xml"]);
+ * (end)
+ * 
+ * Or in Java as follows:
+ * 
+ * (code)
+ * String xml = URLDecoder.decode(request.getParameter("xml"), "UTF-8").replace("\n", "
");
+ * (end)
+ *
+ * Note that the linefeeds should only be replaced if the XML is
+ * processed in Java, for example when creating an image.
+ * 
+ * Constructor: mxXmlRequest
+ * 
+ * Constructs an XML HTTP request.
+ * 
+ * Parameters:
+ * 
+ * url - Target URL of the request.
+ * params - Form encoded parameters to send with a POST request.
+ * method - String that specifies the request method. Possible values are
+ * POST and GET. Default is POST.
+ * async - Boolean specifying if an asynchronous request should be used.
+ * Default is true.
+ * username - String specifying the username to be used for the request.
+ * password - String specifying the password to be used for the request.
+ */
+function mxXmlRequest(url, params, method, async, username, password)
+{
+	this.url = url;
+	this.params = params;
+	this.method = method || 'POST';
+	this.async = (async != null) ? async : true;
+	this.username = username;
+	this.password = password;
+};
+
+/**
+ * Variable: url
+ * 
+ * Holds the target URL of the request.
+ */
+mxXmlRequest.prototype.url = null;
+
+/**
+ * Variable: params
+ * 
+ * Holds the form encoded data for the POST request.
+ */
+mxXmlRequest.prototype.params = null;
+
+/**
+ * Variable: method
+ * 
+ * Specifies the request method. Possible values are POST and GET. Default
+ * is POST.
+ */
+mxXmlRequest.prototype.method = null;
+
+/**
+ * Variable: async
+ * 
+ * Boolean indicating if the request is asynchronous.
+ */
+mxXmlRequest.prototype.async = null;
+
+/**
+ * Variable: binary
+ * 
+ * Boolean indicating if the request is binary. This option is ignored in IE.
+ * In all other browsers the requested mime type is set to
+ * text/plain; charset=x-user-defined. Default is false.
+ */
+mxXmlRequest.prototype.binary = false;
+
+/**
+ * Variable: username
+ * 
+ * Specifies the username to be used for authentication.
+ */
+mxXmlRequest.prototype.username = null;
+
+/**
+ * Variable: password
+ * 
+ * Specifies the password to be used for authentication.
+ */
+mxXmlRequest.prototype.password = null;
+
+/**
+ * Variable: request
+ * 
+ * Holds the inner, browser-specific request object.
+ */
+mxXmlRequest.prototype.request = null;
+
+/**
+ * Function: isBinary
+ * 
+ * Returns .
+ */
+mxXmlRequest.prototype.isBinary = function()
+{
+	return this.binary;
+};
+
+/**
+ * Function: setBinary
+ * 
+ * Sets .
+ */
+mxXmlRequest.prototype.setBinary = function(value)
+{
+	this.binary = value;
+};
+
+/**
+ * Function: getText
+ * 
+ * Returns the response as a string.
+ */
+mxXmlRequest.prototype.getText = function()
+{
+	return this.request.responseText;
+};
+
+/**
+ * Function: isReady
+ * 
+ * Returns true if the response is ready.
+ */
+mxXmlRequest.prototype.isReady = function()
+{
+	return this.request.readyState == 4;
+};
+
+/**
+ * Function: getDocumentElement
+ * 
+ * Returns the document element of the response XML document.
+ */
+mxXmlRequest.prototype.getDocumentElement = function()
+{
+	var doc = this.getXml();
+	
+	if (doc != null)
+	{
+		return doc.documentElement;
+	}
+	
+	return null;
+};
+
+/**
+ * Function: getXml
+ * 
+ * Returns the response as an XML document. Use  to get
+ * the document element of the XML document.
+ */
+mxXmlRequest.prototype.getXml = function()
+{
+	var xml = this.request.responseXML;
+	
+	// Handles missing response headers in IE, the first condition handles
+	// the case where responseXML is there, but using its nodes leads to
+	// type errors in the mxCellCodec when putting the nodes into a new
+	// document. This happens in IE9 standards mode and with XML user
+	// objects only, as they are used directly as values in cells.
+	if (document.documentMode >= 9 || xml == null || xml.documentElement == null)
+	{
+		xml = mxUtils.parseXml(this.request.responseText);
+	}
+	
+	return xml;
+};
+
+/**
+ * Function: getText
+ * 
+ * Returns the response as a string.
+ */
+mxXmlRequest.prototype.getText = function()
+{
+	return this.request.responseText;
+};
+
+/**
+ * Function: getStatus
+ * 
+ * Returns the status as a number, eg. 404 for "Not found" or 200 for "OK".
+ * Note: The NS_ERROR_NOT_AVAILABLE for invalid responses cannot be cought.
+ */
+mxXmlRequest.prototype.getStatus = function()
+{
+	return this.request.status;
+};
+
+/**
+ * Function: create
+ * 
+ * Creates and returns the inner  object.
+ */
+mxXmlRequest.prototype.create = function()
+{
+	if (window.XMLHttpRequest)
+	{
+		return function()
+		{
+			var req = new XMLHttpRequest();
+			
+			// TODO: Check for overrideMimeType required here?
+			if (this.isBinary() && req.overrideMimeType)
+			{
+				req.overrideMimeType('text/plain; charset=x-user-defined');
+			}
+
+			return req;
+		};
+	}
+	else if (typeof(ActiveXObject) != "undefined")
+	{
+		return function()
+		{
+			// TODO: Implement binary option
+			return new ActiveXObject("Microsoft.XMLHTTP");
+		};
+	}
+}();
+
+/**
+ * Function: send
+ * 
+ * Send the  to the target URL using the specified functions to
+ * process the response asychronously.
+ * 
+ * Parameters:
+ * 
+ * onload - Function to be invoked if a successful response was received.
+ * onerror - Function to be called on any error.
+ */
+mxXmlRequest.prototype.send = function(onload, onerror)
+{
+	this.request = this.create();
+	
+	if (this.request != null)
+	{
+		if (onload != null)
+		{
+			this.request.onreadystatechange = mxUtils.bind(this, function()
+			{
+				if (this.isReady())
+				{
+					onload(this);
+					this.onreadystatechaange = null;
+				}
+			});
+		}
+
+		this.request.open(this.method, this.url, this.async,
+			this.username, this.password);
+		this.setRequestHeaders(this.request, this.params);
+		this.request.send(this.params);
+	}
+};
+
+/**
+ * Function: setRequestHeaders
+ * 
+ * Sets the headers for the given request and parameters. This sets the
+ * content-type to application/x-www-form-urlencoded if any params exist.
+ * 
+ * Example:
+ * 
+ * (code)
+ * request.setRequestHeaders = function(request, params)
+ * {
+ *   if (params != null)
+ *   {
+ *     request.setRequestHeader('Content-Type',
+ *             'multipart/form-data');
+ *     request.setRequestHeader('Content-Length',
+ *             params.length);
+ *   }
+ * };
+ * (end)
+ * 
+ * Use the code above before calling  if you require a
+ * multipart/form-data request.   
+ */
+mxXmlRequest.prototype.setRequestHeaders = function(request, params)
+{
+	if (params != null)
+	{
+		request.setRequestHeader('Content-Type',
+			'application/x-www-form-urlencoded');
+	}
+};
+
+/**
+ * Function: simulate
+ * 
+ * Creates and posts a request to the given target URL using a dynamically
+ * created form inside the given document.
+ * 
+ * Parameters:
+ * 
+ * docs - Document that contains the form element.
+ * target - Target to send the form result to.
+ */
+mxXmlRequest.prototype.simulate = function(doc, target)
+{
+	doc = doc || document;
+	var old = null;
+
+	if (doc == document)
+	{
+		old = window.onbeforeunload;		
+		window.onbeforeunload = null;
+	}
+			
+	var form = doc.createElement('form');
+	form.setAttribute('method', this.method);
+	form.setAttribute('action', this.url);
+
+	if (target != null)
+	{
+		form.setAttribute('target', target);
+	}
+
+	form.style.display = 'none';
+	form.style.visibility = 'hidden';
+
+	var pars = (this.params.indexOf('&') > 0) ?
+		this.params.split('&') :
+		this.params.split();
+
+	// Adds the parameters as textareas to the form
+	for (var i=0; i 0)
+		{
+			var name = pars[i].substring(0, pos);
+			var value = pars[i].substring(pos+1);
+			
+			var textarea = doc.createElement('textarea');
+			textarea.setAttribute('name', name);
+			value = value.replace(/\n/g, '
');
+			
+			var content = doc.createTextNode(value);
+			textarea.appendChild(content);
+			form.appendChild(textarea);
+		}
+	}
+	
+	doc.body.appendChild(form);
+	form.submit();
+	doc.body.removeChild(form);
+
+	if (old != null)
+	{		
+		window.onbeforeunload = old;
+	}
+};
+/**
+ * $Id: mxClipboard.js,v 1.29 2010-01-02 09:45:14 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+var mxClipboard =
+{
+	/**
+	 * Class: mxClipboard
+	 * 
+	 * Singleton that implements a clipboard for graph cells.
+	 *
+	 * Example:
+	 * 
+	 * (code)
+	 * mxClipboard.copy(graph);
+	 * mxClipboard.paste(graph2);
+	 * (end)
+	 *
+	 * This copies the selection cells from the graph to the
+	 * clipboard and pastes them into graph2.
+	 * 
+	 * For fine-grained control of the clipboard data the 
+	 * and  functions can be overridden.
+	 * 
+	 * Variable: STEPSIZE
+	 * 
+	 * Defines the step size to offset the cells
+	 * after each paste operation. Default is 10.
+	 */
+	STEPSIZE: 10,
+
+	/**
+	 * Variable: insertCount
+	 * 
+	 * Counts the number of times the clipboard data has been inserted.
+	 */
+	insertCount: 1,
+
+	/**
+	 * Variable: cells
+	 * 
+	 * Holds the array of  currently in the clipboard.
+	 */
+	cells: null,
+	
+	/**
+	 * Function: isEmpty
+	 * 
+	 * Returns true if the clipboard currently has not data stored.
+	 */
+	isEmpty: function()
+	{
+		return mxClipboard.cells == null;
+	},
+
+	/**
+	 * Function: cut
+	 * 
+	 * Cuts the given array of  from the specified graph.
+	 * If cells is null then the selection cells of the graph will
+	 * be used. Returns the cells that have been cut from the graph.
+	 *
+	 * Parameters:
+	 * 
+	 * graph -  that contains the cells to be cut.
+	 * cells - Optional array of  to be cut.
+	 */
+	cut: function(graph, cells)
+	{
+		cells = mxClipboard.copy(graph, cells);
+		mxClipboard.insertCount = 0;
+		mxClipboard.removeCells(graph, cells);
+		
+		return cells;
+	},
+
+	/**
+	 * Function: removeCells
+	 * 
+	 * Hook to remove the given cells from the given graph after
+	 * a cut operation.
+	 *
+	 * Parameters:
+	 * 
+	 * graph -  that contains the cells to be cut.
+	 * cells - Array of  to be cut.
+	 */
+	removeCells: function(graph, cells)
+	{
+		graph.removeCells(cells);
+	},
+
+	/**
+	 * Function: copy
+	 * 
+	 * Copies the given array of  from the specified
+	 * graph to .Returns the original array of cells that has
+	 * been cloned.
+	 * 
+	 * Parameters:
+	 * 
+	 * graph -  that contains the cells to be copied.
+	 * cells - Optional array of  to be copied.
+	 */
+	copy: function(graph, cells)
+	{
+		cells = cells || graph.getSelectionCells();
+		var result = graph.getExportableCells(cells);
+		mxClipboard.insertCount = 1;
+		mxClipboard.cells = graph.cloneCells(result);
+
+		return result;
+	},
+
+	/**
+	 * Function: paste
+	 * 
+	 * Pastes the  into the specified graph restoring
+	 * the relation to , if possible. If the parents
+	 * are no longer in the graph or invisible then the
+	 * cells are added to the graph's default or into the
+	 * swimlane under the cell's new location if one exists.
+	 * The cells are added to the graph using .
+	 * 
+	 * Parameters:
+	 * 
+	 * graph -  to paste the  into.
+	 */
+	paste: function(graph)
+	{
+		if (mxClipboard.cells != null)
+		{
+			var cells = graph.getImportableCells(mxClipboard.cells);
+			var delta = mxClipboard.insertCount * mxClipboard.STEPSIZE;
+			var parent = graph.getDefaultParent();
+			cells = graph.importCells(cells, delta, delta, parent);
+			
+			// Increments the counter and selects the inserted cells
+			mxClipboard.insertCount++;
+			graph.setSelectionCells(cells);
+		}
+	}
+
+};
+/**
+ * $Id: mxWindow.js,v 1.65 2011-09-29 08:17:38 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxWindow
+ * 
+ * Basic window inside a document.
+ * 
+ * Examples:
+ * 
+ * Creating a simple window.
+ *
+ * (code)
+ * var tb = document.createElement('div');
+ * var wnd = new mxWindow('Title', tb, 100, 100, 200, 200, true, true);
+ * wnd.setVisible(true); 
+ * (end)
+ *
+ * Creating a window that contains an iframe. 
+ * 
+ * (code)
+ * var frame = document.createElement('iframe');
+ * frame.setAttribute('width', '192px');
+ * frame.setAttribute('height', '172px');
+ * frame.setAttribute('src', 'http://www.example.com/');
+ * frame.style.backgroundColor = 'white';
+ * 
+ * var w = document.body.clientWidth;
+ * var h = (document.body.clientHeight || document.documentElement.clientHeight);
+ * var wnd = new mxWindow('Title', frame, (w-200)/2, (h-200)/3, 200, 200);
+ * wnd.setVisible(true);
+ * (end);
+ *
+ * Event: mxEvent.MOVE_START
+ *
+ * Fires before the window is moved. The event property contains
+ * the corresponding mouse event.
+ *
+ * Event: mxEvent.MOVE
+ *
+ * Fires while the window is being moved. The event property
+ * contains the corresponding mouse event.
+ *
+ * Event: mxEvent.MOVE_END
+ *
+ * Fires after the window is moved. The event property contains
+ * the corresponding mouse event.
+ *
+ * Event: mxEvent.RESIZE_START
+ *
+ * Fires before the window is resized. The event property contains
+ * the corresponding mouse event.
+ *
+ * Event: mxEvent.RESIZE
+ *
+ * Fires while the window is being resized. The event property
+ * contains the corresponding mouse event.
+ *
+ * Event: mxEvent.RESIZE_END
+ *
+ * Fires after the window is resized. The event property contains
+ * the corresponding mouse event.
+ *
+ * Event: mxEvent.MAXIMIZE
+ * 
+ * Fires after the window is maximized. The event property
+ * contains the corresponding mouse event.
+ * 
+ * Event: mxEvent.MINIMIZE
+ * 
+ * Fires after the window is minimized. The event property
+ * contains the corresponding mouse event.
+ * 
+ * Event: mxEvent.NORMALIZE
+ * 
+ * Fires after the window is normalized, that is, it returned from
+ * maximized or minimized state. The event property contains the
+ * corresponding mouse event.
+ *  
+ * Event: mxEvent.ACTIVATE
+ * 
+ * Fires after a window is activated. The previousWindow property
+ * contains the previous window. The event sender is the active window.
+ * 
+ * Event: mxEvent.SHOW
+ * 
+ * Fires after the window is shown. This event has no properties.
+ * 
+ * Event: mxEvent.HIDE
+ * 
+ * Fires after the window is hidden. This event has no properties.
+ * 
+ * Event: mxEvent.CLOSE
+ * 
+ * Fires before the window is closed. The event property contains
+ * the corresponding mouse event.
+ * 
+ * Event: mxEvent.DESTROY
+ * 
+ * Fires before the window is destroyed. This event has no properties.
+ * 
+ * Constructor: mxWindow
+ * 
+ * Constructs a new window with the given dimension and title to display
+ * the specified content. The window elements use the given style as a
+ * prefix for the classnames of the respective window elements, namely,
+ * the window title and window pane. The respective postfixes are appended
+ * to the given stylename as follows:
+ * 
+ *   style - Base style for the window.
+ *   style+Title - Style for the window title.
+ *   style+Pane - Style for the window pane.
+ * 
+ * The default value for style is mxWindow, resulting in the following
+ * classnames for the window elements: mxWindow, mxWindowTitle and
+ * mxWindowPane.
+ * 
+ * If replaceNode is given then the window replaces the given DOM node in
+ * the document.
+ * 
+ * Parameters:
+ * 
+ * title - String that represents the title of the new window.
+ * content - DOM node that is used as the window content.
+ * x - X-coordinate of the window location.
+ * y - Y-coordinate of the window location.
+ * width - Width of the window.
+ * height - Optional height of the window. Default is to match the height
+ * of the content at the specified width.
+ * minimizable - Optional boolean indicating if the window is minimizable.
+ * Default is true.
+ * movable - Optional boolean indicating if the window is movable. Default
+ * is true.
+ * replaceNode - Optional DOM node that the window should replace.
+ * style - Optional base classname for the window elements. Default is
+ * mxWindow.
+ */
+function mxWindow(title, content, x, y, width, height, minimizable, movable, replaceNode, style)
+{
+	if (content != null)
+	{
+		minimizable = (minimizable != null) ? minimizable : true;
+		this.content = content;
+		this.init(x, y, width, height, style);
+		
+		this.installMaximizeHandler();
+		this.installMinimizeHandler();
+		this.installCloseHandler();
+		this.setMinimizable(minimizable);
+		this.setTitle(title);
+		
+		if (movable == null || movable)
+		{
+			this.installMoveHandler();
+		}
+
+		if (replaceNode != null && replaceNode.parentNode != null)
+		{
+			replaceNode.parentNode.replaceChild(this.div, replaceNode);
+		}
+		else
+		{
+			document.body.appendChild(this.div);
+		}
+	}
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxWindow.prototype = new mxEventSource();
+mxWindow.prototype.constructor = mxWindow;
+
+/**
+ * Variable: closeImage
+ * 
+ * URL of the image to be used for the close icon in the titlebar.
+ */
+mxWindow.prototype.closeImage = mxClient.imageBasePath + '/close.gif';
+
+/**
+ * Variable: minimizeImage
+ * 
+ * URL of the image to be used for the minimize icon in the titlebar.
+ */
+mxWindow.prototype.minimizeImage = mxClient.imageBasePath + '/minimize.gif';
+	
+/**
+ * Variable: normalizeImage
+ * 
+ * URL of the image to be used for the normalize icon in the titlebar.
+ */
+mxWindow.prototype.normalizeImage = mxClient.imageBasePath + '/normalize.gif';
+	
+/**
+ * Variable: maximizeImage
+ * 
+ * URL of the image to be used for the maximize icon in the titlebar.
+ */
+mxWindow.prototype.maximizeImage = mxClient.imageBasePath + '/maximize.gif';
+
+/**
+ * Variable: normalizeImage
+ * 
+ * URL of the image to be used for the resize icon.
+ */
+mxWindow.prototype.resizeImage = mxClient.imageBasePath + '/resize.gif';
+
+/**
+ * Variable: visible
+ * 
+ * Boolean flag that represents the visible state of the window.
+ */
+mxWindow.prototype.visible = false;
+	
+/**
+ * Variable: content
+ * 
+ * Reference to the DOM node that represents the window content.
+ */
+mxWindow.prototype.content = false;
+	
+/**
+ * Variable: minimumSize
+ * 
+ *  that specifies the minimum width and height of the window.
+ * Default is (50, 40).
+ */
+mxWindow.prototype.minimumSize = new mxRectangle(0, 0, 50, 40);
+
+/**
+ * Variable: title
+ * 
+ * Reference to the DOM node (TD) that contains the title.
+ */
+mxWindow.prototype.title = false;
+
+/**
+ * Variable: content
+ * 
+ * Reference to the DOM node that represents the window content.
+ */
+mxWindow.prototype.content = false;
+
+/**
+ * Variable: destroyOnClose
+ * 
+ * Specifies if the window should be destroyed when it is closed. If this
+ * is false then the window is hidden using . Default is true.
+ */
+mxWindow.prototype.destroyOnClose = true;
+
+/**
+ * Function: init
+ * 
+ * Initializes the DOM tree that represents the window.
+ */
+mxWindow.prototype.init = function(x, y, width, height, style)
+{
+	style = (style != null) ? style : 'mxWindow';
+	
+	this.div = document.createElement('div');
+	this.div.className = style; 
+	this.div.style.left = x+'px';
+	this.div.style.top = y+'px';
+	this.table = document.createElement('table');
+	this.table.className = style;
+	
+	// Workaround for table size problems in FF
+	if (width != null)
+	{
+		if (!mxClient.IS_IE)
+		{
+			this.div.style.width = width+'px'; 
+		}
+		
+		this.table.style.width = width+'px';
+	} 
+	
+	if (height != null)
+	{
+		if (!mxClient.IS_IE)
+		{
+			this.div.style.height = height+'px';
+		}
+		
+		this.table.style.height = height+'px';
+	}		
+	
+	// Creates title row
+	var tbody = document.createElement('tbody');
+	var tr = document.createElement('tr');
+	
+	this.title = document.createElement('td');
+	this.title.className = style+'Title';
+	tr.appendChild(this.title);
+	tbody.appendChild(tr);
+	
+	// Creates content row and table cell
+	tr = document.createElement('tr');
+	this.td = document.createElement('td');
+	this.td.className = style+'Pane';
+
+	this.contentWrapper = document.createElement('div');
+	this.contentWrapper.className = style+'Pane';
+	this.contentWrapper.style.width = '100%';
+	this.contentWrapper.appendChild(this.content);
+
+	// Workaround for div around div restricts height
+	// of inner div if outerdiv has hidden overflow
+	if (mxClient.IS_IE || this.content.nodeName.toUpperCase() != 'DIV')
+	{
+		this.contentWrapper.style.height = '100%';
+	}
+
+	// Puts all content into the DOM
+	this.td.appendChild(this.contentWrapper);
+	tr.appendChild(this.td);
+	tbody.appendChild(tr);
+	this.table.appendChild(tbody);
+	this.div.appendChild(this.table);
+	
+	// Puts the window on top of other windows when clicked
+	var activator = mxUtils.bind(this, function(evt)
+	{
+		this.activate();
+	});
+	
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	mxEvent.addListener(this.title, md, activator);
+	mxEvent.addListener(this.table, md, activator);
+
+	this.hide();
+};
+
+/**
+ * Function: setTitle
+ * 
+ * Sets the window title to the given string. HTML markup inside the title
+ * will be escaped.
+ */
+mxWindow.prototype.setTitle = function(title)
+{
+	// Removes all text content nodes (normally just one)
+	var child = this.title.firstChild;
+	
+	while (child != null)
+	{
+		var next = child.nextSibling;
+		
+		if (child.nodeType == mxConstants.NODETYPE_TEXT)
+		{
+			child.parentNode.removeChild(child);
+		}
+		
+		child = next;
+	}
+	
+	mxUtils.write(this.title, title || '');
+};
+
+/**
+ * Function: setScrollable
+ * 
+ * Sets if the window contents should be scrollable.
+ */
+mxWindow.prototype.setScrollable = function(scrollable)
+{
+	// Workaround for hang in Presto 2.5.22 (Opera 10.5)
+	if (navigator.userAgent.indexOf('Presto/2.5') < 0)
+	{
+		if (scrollable)
+		{
+			this.contentWrapper.style.overflow = 'auto';
+		}
+		else
+		{
+			this.contentWrapper.style.overflow = 'hidden';
+		}
+	}
+};
+
+/**
+ * Function: activate
+ * 
+ * Puts the window on top of all other windows.
+ */
+mxWindow.prototype.activate = function()
+{
+	if (mxWindow.activeWindow != this)
+	{
+		var style = mxUtils.getCurrentStyle(this.getElement());
+		var index = (style != null) ? style.zIndex : 3;
+
+		if (mxWindow.activeWindow)
+		{
+			var elt = mxWindow.activeWindow.getElement();
+			
+			if (elt != null && elt.style != null)
+			{
+				elt.style.zIndex = index;
+			}
+		}
+		
+		var previousWindow = mxWindow.activeWindow;
+		this.getElement().style.zIndex = parseInt(index) + 1;
+		mxWindow.activeWindow = this;
+		
+		this.fireEvent(new mxEventObject(mxEvent.ACTIVATE, 'previousWindow', previousWindow));
+	}
+};
+
+/**
+ * Function: getElement
+ * 
+ * Returuns the outermost DOM node that makes up the window.
+ */
+mxWindow.prototype.getElement = function()
+{
+	return this.div;
+};
+
+/**
+ * Function: fit
+ * 
+ * Makes sure the window is inside the client area of the window.
+ */
+mxWindow.prototype.fit = function()
+{
+	mxUtils.fit(this.div);
+};
+
+/**
+ * Function: isResizable
+ * 
+ * Returns true if the window is resizable.
+ */
+mxWindow.prototype.isResizable = function()
+{
+	if (this.resize != null)
+	{
+		return this.resize.style.display != 'none';
+	}
+	
+	return false;
+};
+
+/**
+ * Function: setResizable
+ * 
+ * Sets if the window should be resizable.
+ */
+mxWindow.prototype.setResizable = function(resizable)
+{
+	if (resizable)
+	{
+		if (this.resize == null)
+		{
+			this.resize = document.createElement('img');
+			this.resize.style.position = 'absolute';
+			this.resize.style.bottom = '2px';
+			this.resize.style.right = '2px';
+
+			this.resize.setAttribute('src', mxClient.imageBasePath + '/resize.gif');
+			this.resize.style.cursor = 'nw-resize';
+			
+			var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+			var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+			var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+
+			mxEvent.addListener(this.resize, md, mxUtils.bind(this, function(evt)
+			{
+				this.activate();
+				var startX = mxEvent.getClientX(evt);
+				var startY = mxEvent.getClientY(evt);
+				var width = this.div.offsetWidth;
+				var height = this.div.offsetHeight;
+
+				// Adds a temporary pair of listeners to intercept
+				// the gesture event in the document
+				var dragHandler = mxUtils.bind(this, function(evt)
+				{
+					var dx = mxEvent.getClientX(evt) - startX;
+					var dy = mxEvent.getClientY(evt) - startY;
+
+					this.setSize(width + dx, height + dy);
+	
+					this.fireEvent(new mxEventObject(mxEvent.RESIZE, 'event', evt));
+					mxEvent.consume(evt);
+				});
+				
+				var dropHandler = mxUtils.bind(this, function(evt)
+				{
+					mxEvent.removeListener(document, mm, dragHandler);
+					mxEvent.removeListener(document, mu, dropHandler);
+	
+					this.fireEvent(new mxEventObject(mxEvent.RESIZE_END, 'event', evt));
+					mxEvent.consume(evt);
+				});
+	
+				mxEvent.addListener(document, mm, dragHandler);
+				mxEvent.addListener(document, mu, dropHandler);
+
+				this.fireEvent(new mxEventObject(mxEvent.RESIZE_START, 'event', evt));
+				mxEvent.consume(evt);
+			}));
+
+			this.div.appendChild(this.resize);
+		}
+		else 
+		{
+			this.resize.style.display = 'inline';
+		}
+	}
+	else if (this.resize != null)
+	{
+		this.resize.style.display = 'none';
+	}
+};
+	
+/**
+ * Function: setSize
+ * 
+ * Sets the size of the window.
+ */
+mxWindow.prototype.setSize = function(width, height)
+{
+	width = Math.max(this.minimumSize.width, width);
+	height = Math.max(this.minimumSize.height, height);
+
+	// Workaround for table size problems in FF
+	if (!mxClient.IS_IE)
+	{
+		this.div.style.width =  width + 'px';
+		this.div.style.height = height + 'px';
+	}
+	
+	this.table.style.width =  width + 'px';
+	this.table.style.height = height + 'px';
+
+	if (!mxClient.IS_IE)
+	{
+		this.contentWrapper.style.height =
+			(this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
+	}
+};
+	
+/**
+ * Function: setMinimizable
+ * 
+ * Sets if the window is minimizable.
+ */
+mxWindow.prototype.setMinimizable = function(minimizable)
+{
+	this.minimize.style.display = (minimizable) ? '' : 'none';
+};
+
+/**
+ * Function: getMinimumSize
+ * 
+ * Returns an  that specifies the size for the minimized window.
+ * A width or height of 0 means keep the existing width or height. This
+ * implementation returns the height of the window title and keeps the width.
+ */
+mxWindow.prototype.getMinimumSize = function()
+{
+	return new mxRectangle(0, 0, 0, this.title.offsetHeight);
+};
+
+/**
+ * Function: installMinimizeHandler
+ * 
+ * Installs the event listeners required for minimizing the window.
+ */
+mxWindow.prototype.installMinimizeHandler = function()
+{
+	this.minimize = document.createElement('img');
+	
+	this.minimize.setAttribute('src', this.minimizeImage);
+	this.minimize.setAttribute('align', 'right');
+	this.minimize.setAttribute('title', 'Minimize');
+	this.minimize.style.cursor = 'pointer';
+	this.minimize.style.marginRight = '1px';
+	this.minimize.style.display = 'none';
+	
+	this.title.appendChild(this.minimize);
+	
+	var minimized = false;
+	var maxDisplay = null;
+	var height = null;
+
+	var funct = mxUtils.bind(this, function(evt)
+	{
+		this.activate();
+		
+		if (!minimized)
+		{
+			minimized = true;
+			
+			this.minimize.setAttribute('src', this.normalizeImage);
+			this.minimize.setAttribute('title', 'Normalize');
+			this.contentWrapper.style.display = 'none';
+			maxDisplay = this.maximize.style.display;
+			
+			this.maximize.style.display = 'none';
+			height = this.table.style.height;
+			
+			var minSize = this.getMinimumSize();
+			
+			if (minSize.height > 0)
+			{
+				if (!mxClient.IS_IE)
+				{
+					this.div.style.height = minSize.height + 'px';
+				}
+				
+				this.table.style.height = minSize.height + 'px';
+			}
+			
+			if (minSize.width > 0)
+			{
+				if (!mxClient.IS_IE)
+				{
+					this.div.style.width = minSize.width + 'px';
+				}
+				
+				this.table.style.width = minSize.width + 'px';
+			}
+			
+			if (this.resize != null)
+			{
+				this.resize.style.visibility = 'hidden';
+			}
+			
+			this.fireEvent(new mxEventObject(mxEvent.MINIMIZE, 'event', evt));
+		}
+		else
+		{
+			minimized = false;
+			
+			this.minimize.setAttribute('src', this.minimizeImage);
+			this.minimize.setAttribute('title', 'Minimize');
+			this.contentWrapper.style.display = ''; // default
+			this.maximize.style.display = maxDisplay;
+			
+			if (!mxClient.IS_IE)
+			{
+				this.div.style.height = height;
+			}
+			
+			this.table.style.height = height;
+
+			if (this.resize != null)
+			{
+				this.resize.style.visibility = '';
+			}
+			
+			this.fireEvent(new mxEventObject(mxEvent.NORMALIZE, 'event', evt));
+		}
+		
+		mxEvent.consume(evt);
+	});
+	
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	mxEvent.addListener(this.minimize, md, funct);
+};
+	
+/**
+ * Function: setMaximizable
+ * 
+ * Sets if the window is maximizable.
+ */
+mxWindow.prototype.setMaximizable = function(maximizable)
+{
+	this.maximize.style.display = (maximizable) ? '' : 'none';
+};
+
+/**
+ * Function: installMaximizeHandler
+ * 
+ * Installs the event listeners required for maximizing the window.
+ */
+mxWindow.prototype.installMaximizeHandler = function()
+{
+	this.maximize = document.createElement('img');
+	
+	this.maximize.setAttribute('src', this.maximizeImage);
+	this.maximize.setAttribute('align', 'right');
+	this.maximize.setAttribute('title', 'Maximize');
+	this.maximize.style.cursor = 'default';
+	this.maximize.style.marginLeft = '1px';
+	this.maximize.style.cursor = 'pointer';
+	this.maximize.style.display = 'none';
+	
+	this.title.appendChild(this.maximize);
+	
+	var maximized = false;
+	var x = null;
+	var y = null;
+	var height = null;
+	var width = null;
+
+	var funct = mxUtils.bind(this, function(evt)
+	{
+		this.activate();
+		
+		if (this.maximize.style.display != 'none')
+		{
+			if (!maximized)
+			{
+				maximized = true;
+				
+				this.maximize.setAttribute('src', this.normalizeImage);
+				this.maximize.setAttribute('title', 'Normalize');
+				this.contentWrapper.style.display = '';
+				this.minimize.style.visibility = 'hidden';
+				
+				// Saves window state
+				x = parseInt(this.div.style.left);
+				y = parseInt(this.div.style.top);
+				height = this.table.style.height;
+				width = this.table.style.width;
+
+				this.div.style.left = '0px';
+				this.div.style.top = '0px';
+
+				if (!mxClient.IS_IE)
+				{
+					this.div.style.height = (document.body.clientHeight-2)+'px';
+					this.div.style.width = (document.body.clientWidth-2)+'px';
+				}
+
+				this.table.style.width = (document.body.clientWidth-2)+'px';
+				this.table.style.height = (document.body.clientHeight-2)+'px';
+				
+				if (this.resize != null)
+				{
+					this.resize.style.visibility = 'hidden';
+				}
+
+				if (!mxClient.IS_IE)
+				{
+					var style = mxUtils.getCurrentStyle(this.contentWrapper);
+		
+					if (style.overflow == 'auto' || this.resize != null)
+					{
+						this.contentWrapper.style.height =
+							(this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
+					}
+				}
+
+				this.fireEvent(new mxEventObject(mxEvent.MAXIMIZE, 'event', evt));
+			}
+			else
+			{
+				maximized = false;
+				
+				this.maximize.setAttribute('src', this.maximizeImage);
+				this.maximize.setAttribute('title', 'Maximize');
+				this.contentWrapper.style.display = '';
+				this.minimize.style.visibility = '';
+
+				// Restores window state
+				this.div.style.left = x+'px';
+				this.div.style.top = y+'px';
+				
+				if (!mxClient.IS_IE)
+				{
+					this.div.style.height = height;
+					this.div.style.width = width;
+
+					var style = mxUtils.getCurrentStyle(this.contentWrapper);
+		
+					if (style.overflow == 'auto' || this.resize != null)
+					{
+						this.contentWrapper.style.height =
+							(this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
+					}
+				}
+				
+				this.table.style.height = height;
+				this.table.style.width = width;
+
+				if (this.resize != null)
+				{
+					this.resize.style.visibility = '';
+				}
+				
+				this.fireEvent(new mxEventObject(mxEvent.NORMALIZE, 'event', evt));
+			}
+			
+			mxEvent.consume(evt);
+		}
+	});
+	
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	mxEvent.addListener(this.maximize, md, funct);
+	mxEvent.addListener(this.title, 'dblclick', funct);
+};
+	
+/**
+ * Function: installMoveHandler
+ * 
+ * Installs the event listeners required for moving the window.
+ */
+mxWindow.prototype.installMoveHandler = function()
+{
+	this.title.style.cursor = 'move';
+	
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+	var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+	
+	mxEvent.addListener(this.title, md, mxUtils.bind(this, function(evt)
+	{
+		var startX = mxEvent.getClientX(evt);
+		var startY = mxEvent.getClientY(evt);
+		var x = this.getX();
+		var y = this.getY();
+					
+		// Adds a temporary pair of listeners to intercept
+		// the gesture event in the document
+		var dragHandler = mxUtils.bind(this, function(evt)
+		{
+			var dx = mxEvent.getClientX(evt) - startX;
+			var dy = mxEvent.getClientY(evt) - startY;
+			this.setLocation(x + dx, y + dy);
+			this.fireEvent(new mxEventObject(mxEvent.MOVE, 'event', evt));
+			mxEvent.consume(evt);
+		});
+		
+		var dropHandler = mxUtils.bind(this, function(evt)
+		{
+			mxEvent.removeListener(document, mm, dragHandler);
+			mxEvent.removeListener(document, mu, dropHandler);
+
+			this.fireEvent(new mxEventObject(mxEvent.MOVE_END, 'event', evt));
+			mxEvent.consume(evt);
+		});
+
+		mxEvent.addListener(document, mm, dragHandler);
+		mxEvent.addListener(document, mu, dropHandler);
+		
+		this.fireEvent(new mxEventObject(mxEvent.MOVE_START, 'event', evt));
+		mxEvent.consume(evt);
+	}));
+};
+
+/**
+ * Function: setLocation
+ * 
+ * Sets the upper, left corner of the window.
+ */
+ mxWindow.prototype.setLocation = function(x, y)
+ {
+	this.div.style.left = x + 'px';
+	this.div.style.top = y + 'px';
+ };
+
+/**
+ * Function: getX
+ *
+ * Returns the current position on the x-axis.
+ */
+mxWindow.prototype.getX = function()
+{
+	return parseInt(this.div.style.left);
+};
+
+/**
+ * Function: getY
+ *
+ * Returns the current position on the y-axis.
+ */
+mxWindow.prototype.getY = function()
+{
+	return parseInt(this.div.style.top);
+};
+
+/**
+ * Function: installCloseHandler
+ *
+ * Adds the  as a new image node in  and installs the
+ *  event.
+ */
+mxWindow.prototype.installCloseHandler = function()
+{
+	this.closeImg = document.createElement('img');
+	
+	this.closeImg.setAttribute('src', this.closeImage);
+	this.closeImg.setAttribute('align', 'right');
+	this.closeImg.setAttribute('title', 'Close');
+	this.closeImg.style.marginLeft = '2px';
+	this.closeImg.style.cursor = 'pointer';
+	this.closeImg.style.display = 'none';
+	
+	this.title.insertBefore(this.closeImg, this.title.firstChild);
+
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	mxEvent.addListener(this.closeImg, md, mxUtils.bind(this, function(evt)
+	{
+		this.fireEvent(new mxEventObject(mxEvent.CLOSE, 'event', evt));
+		
+		if (this.destroyOnClose)
+		{
+			this.destroy();
+		}
+		else
+		{
+			this.setVisible(false);
+		}
+		
+		mxEvent.consume(evt);
+	}));
+};
+
+/**
+ * Function: setImage
+ * 
+ * Sets the image associated with the window.
+ * 
+ * Parameters:
+ * 
+ * image - URL of the image to be used.
+ */
+mxWindow.prototype.setImage = function(image)
+{
+	this.image = document.createElement('img');
+	this.image.setAttribute('src', image);
+	this.image.setAttribute('align', 'left');
+	this.image.style.marginRight = '4px';
+	this.image.style.marginLeft = '0px';
+	this.image.style.marginTop = '-2px';
+	
+	this.title.insertBefore(this.image, this.title.firstChild);
+};
+
+/**
+ * Function: setClosable
+ * 
+ * Sets the image associated with the window.
+ * 
+ * Parameters:
+ * 
+ * closable - Boolean specifying if the window should be closable.
+ */
+mxWindow.prototype.setClosable = function(closable)
+{
+	this.closeImg.style.display = (closable) ? '' : 'none';
+};
+
+/**
+ * Function: isVisible
+ * 
+ * Returns true if the window is visible.
+ */
+mxWindow.prototype.isVisible = function()
+{
+	if (this.div != null)
+	{
+		return this.div.style.visibility != 'hidden';
+	}
+	
+	return false;
+};
+
+/**
+ * Function: setVisible
+ *
+ * Shows or hides the window depending on the given flag.
+ * 
+ * Parameters:
+ * 
+ * visible - Boolean indicating if the window should be made visible.
+ */
+mxWindow.prototype.setVisible = function(visible)
+{
+	if (this.div != null && this.isVisible() != visible)
+	{
+		if (visible)
+		{
+			this.show();
+		}
+		else
+		{
+			this.hide();
+		}
+	}
+};
+
+/**
+ * Function: show
+ *
+ * Shows the window.
+ */
+mxWindow.prototype.show = function()
+{
+	this.div.style.visibility = '';
+	this.activate();
+	
+	var style = mxUtils.getCurrentStyle(this.contentWrapper);
+	
+	if (!mxClient.IS_IE && (style.overflow == 'auto' || this.resize != null))
+	{
+		this.contentWrapper.style.height =
+			(this.div.offsetHeight - this.title.offsetHeight - 2)+'px';
+	}
+	
+	this.fireEvent(new mxEventObject(mxEvent.SHOW));
+};
+
+/**
+ * Function: hide
+ *
+ * Hides the window.
+ */
+mxWindow.prototype.hide = function()
+{
+	this.div.style.visibility = 'hidden';
+	this.fireEvent(new mxEventObject(mxEvent.HIDE));
+};
+
+/**
+ * Function: destroy
+ *
+ * Destroys the window and removes all associated resources. Fires a
+ *  event prior to destroying the window.
+ */
+mxWindow.prototype.destroy = function()
+{
+	this.fireEvent(new mxEventObject(mxEvent.DESTROY));
+	
+	if (this.div != null)
+	{
+		mxEvent.release(this.div);
+		this.div.parentNode.removeChild(this.div);
+		this.div = null;
+	}
+	
+	this.title = null;
+	this.content = null;
+	this.contentWrapper = null;
+};
+/**
+ * $Id: mxForm.js,v 1.16 2010-10-08 04:21:45 david Exp $
+ * Copyright (c) 2006-2010, Gaudenz Alder, David Benson
+ */
+/**
+ * Class: mxForm
+ * 
+ * A simple class for creating HTML forms.
+ * 
+ * Constructor: mxForm
+ * 
+ * Creates a HTML table using the specified classname.
+ */
+function mxForm(className)
+{
+	this.table = document.createElement('table');
+	this.table.className = className;
+	this.body = document.createElement('tbody');
+	
+	this.table.appendChild(this.body);
+};
+
+/**
+ * Variable: table
+ * 
+ * Holds the DOM node that represents the table.
+ */
+mxForm.prototype.table = null;
+
+/**
+ * Variable: body
+ * 
+ * Holds the DOM node that represents the tbody (table body). New rows
+ * can be added to this object using DOM API.
+ */
+mxForm.prototype.body = false;
+
+/**
+ * Function: getTable
+ * 
+ * Returns the table that contains this form.
+ */
+mxForm.prototype.getTable = function()
+{
+	return this.table;
+};
+
+/**
+ * Function: addButtons
+ * 
+ * Helper method to add an OK and Cancel button using the respective
+ * functions.
+ */
+mxForm.prototype.addButtons = function(okFunct, cancelFunct)
+{
+	var tr = document.createElement('tr');
+	var td = document.createElement('td');
+	tr.appendChild(td);
+	td = document.createElement('td');
+
+	// Adds the ok button
+	var button = document.createElement('button');
+	mxUtils.write(button, mxResources.get('ok') || 'OK');
+	td.appendChild(button);
+
+	mxEvent.addListener(button, 'click', function()
+	{
+		okFunct();
+	});
+	
+	// Adds the cancel button
+	button = document.createElement('button');
+	mxUtils.write(button, mxResources.get('cancel') || 'Cancel');
+	td.appendChild(button);
+	
+	mxEvent.addListener(button, 'click', function()
+	{
+		cancelFunct();
+	});
+	
+	tr.appendChild(td);
+	this.body.appendChild(tr);
+};
+
+/**
+ * Function: addText
+ * 
+ * Adds a textfield for the given name and value and returns the textfield.
+ */
+mxForm.prototype.addText = function(name, value)
+{
+	var input = document.createElement('input');
+	
+	input.setAttribute('type', 'text');
+	input.value = value;
+	
+	return this.addField(name, input);
+};
+
+/**
+ * Function: addCheckbox
+ * 
+ * Adds a checkbox for the given name and value and returns the textfield.
+ */
+mxForm.prototype.addCheckbox = function(name, value)
+{
+	var input = document.createElement('input');
+	
+	input.setAttribute('type', 'checkbox');
+	this.addField(name, input);
+
+	// IE can only change the checked value if the input is inside the DOM
+	if (value)
+	{
+		input.checked = true;
+	}
+
+	return input;
+};
+
+/**
+ * Function: addTextarea
+ * 
+ * Adds a textarea for the given name and value and returns the textarea.
+ */
+mxForm.prototype.addTextarea = function(name, value, rows)
+{
+	var input = document.createElement('textarea');
+	
+	if (mxClient.IS_NS)
+	{
+		rows--;
+	}
+	
+	input.setAttribute('rows', rows || 2);
+	input.value = value;
+	
+	return this.addField(name, input);
+};
+
+/**
+ * Function: addCombo
+ * 
+ * Adds a combo for the given name and returns the combo.
+ */
+mxForm.prototype.addCombo = function(name, isMultiSelect, size)
+{
+	var select = document.createElement('select');
+	
+	if (size != null)
+	{
+		select.setAttribute('size', size);
+	}
+	
+	if (isMultiSelect)
+	{
+		select.setAttribute('multiple', 'true');
+	}
+	
+	return this.addField(name, select);
+};
+
+/**
+ * Function: addOption
+ * 
+ * Adds an option for the given label to the specified combo.
+ */
+mxForm.prototype.addOption = function(combo, label, value, isSelected)
+{
+	var option = document.createElement('option');
+	
+	mxUtils.writeln(option, label);
+	option.setAttribute('value', value);
+	
+	if (isSelected)
+	{
+		option.setAttribute('selected', isSelected);
+	}
+	
+	combo.appendChild(option);
+};
+
+/**
+ * Function: addField
+ * 
+ * Adds a new row with the name and the input field in two columns and
+ * returns the given input.
+ */
+mxForm.prototype.addField = function(name, input)
+{
+	var tr = document.createElement('tr');
+	var td = document.createElement('td');
+	mxUtils.write(td, name);
+	tr.appendChild(td);
+	
+	td = document.createElement('td');
+	td.appendChild(input);
+	tr.appendChild(td);
+	this.body.appendChild(tr);
+	
+	return input;
+};
+/**
+ * $Id: mxImage.js,v 1.7 2010-01-02 09:45:14 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxImage
+ *
+ * Encapsulates the URL, width and height of an image.
+ * 
+ * Constructor: mxImage
+ * 
+ * Constructs a new image.
+ */
+function mxImage(src, width, height)
+{
+	this.src = src;
+	this.width = width;
+	this.height = height;
+};
+
+/**
+ * Variable: src
+ *
+ * String that specifies the URL of the image.
+ */
+mxImage.prototype.src = null;
+
+/**
+ * Variable: width
+ *
+ * Integer that specifies the width of the image.
+ */
+mxImage.prototype.width = null;
+
+/**
+ * Variable: height
+ *
+ * Integer that specifies the height of the image.
+ */
+mxImage.prototype.height = null;
+/**
+ * $Id: mxDivResizer.js,v 1.22 2010-01-02 09:45:14 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxDivResizer
+ * 
+ * Maintains the size of a div element in Internet Explorer. This is a
+ * workaround for the right and bottom style being ignored in IE.
+ * 
+ * If you need a div to cover the scrollwidth and -height of a document,
+ * then you can use this class as follows:
+ * 
+ * (code)
+ * var resizer = new mxDivResizer(background);
+ * resizer.getDocumentHeight = function()
+ * {
+ *   return document.body.scrollHeight;
+ * }
+ * resizer.getDocumentWidth = function()
+ * {
+ *   return document.body.scrollWidth;
+ * }
+ * resizer.resize();
+ * (end)
+ * 
+ * Constructor: mxDivResizer
+ * 
+ * Constructs an object that maintains the size of a div
+ * element when the window is being resized. This is only
+ * required for Internet Explorer as it ignores the respective
+ * stylesheet information for DIV elements.
+ * 
+ * Parameters:
+ * 
+ * div - Reference to the DOM node whose size should be maintained.
+ * container - Optional Container that contains the div. Default is the
+ * window.
+ */
+function mxDivResizer(div, container)
+{
+	if (div.nodeName.toLowerCase() == 'div')
+	{
+		if (container == null)
+		{
+			container = window;
+		}
+
+		this.div = div;
+		var style = mxUtils.getCurrentStyle(div);
+		
+		if (style != null)
+		{
+			this.resizeWidth = style.width == 'auto';
+			this.resizeHeight = style.height == 'auto';
+		}
+		
+		mxEvent.addListener(container, 'resize',
+			mxUtils.bind(this, function(evt)
+			{
+				if (!this.handlingResize)
+				{
+					this.handlingResize = true;
+					this.resize();
+					this.handlingResize = false;
+				}
+			})
+		);
+		
+		this.resize();
+	}
+};
+
+/**
+ * Function: resizeWidth
+ * 
+ * Boolean specifying if the width should be updated.
+ */
+mxDivResizer.prototype.resizeWidth = true;
+
+/**
+ * Function: resizeHeight
+ * 
+ * Boolean specifying if the height should be updated.
+ */
+mxDivResizer.prototype.resizeHeight = true;
+
+/**
+ * Function: handlingResize
+ * 
+ * Boolean specifying if the width should be updated.
+ */
+mxDivResizer.prototype.handlingResize = false;
+
+/**
+ * Function: resize
+ * 
+ * Updates the style of the DIV after the window has been resized.
+ */
+mxDivResizer.prototype.resize = function()
+{
+	var w = this.getDocumentWidth();
+	var h = this.getDocumentHeight();
+
+	var l = parseInt(this.div.style.left);
+	var r = parseInt(this.div.style.right);
+	var t = parseInt(this.div.style.top);
+	var b = parseInt(this.div.style.bottom);
+	
+	if (this.resizeWidth &&
+		!isNaN(l) &&
+		!isNaN(r) &&
+		l >= 0 &&
+		r >= 0 &&
+		w - r - l > 0)
+	{
+		this.div.style.width = (w - r - l)+'px';
+	}
+	
+	if (this.resizeHeight &&
+		!isNaN(t) &&
+		!isNaN(b) &&
+		t >= 0 &&
+		b >= 0 &&
+		h - t - b > 0)
+	{
+		this.div.style.height = (h - t - b)+'px';
+	}
+};
+
+/**
+ * Function: getDocumentWidth
+ * 
+ * Hook for subclassers to return the width of the document (without
+ * scrollbars).
+ */
+mxDivResizer.prototype.getDocumentWidth = function()
+{
+	return document.body.clientWidth;
+};
+
+/**
+ * Function: getDocumentHeight
+ * 
+ * Hook for subclassers to return the height of the document (without
+ * scrollbars).
+ */
+mxDivResizer.prototype.getDocumentHeight = function()
+{
+	return document.body.clientHeight;
+};
+/**
+ * $Id: mxDragSource.js,v 1.11 2012-05-09 12:19:25 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxDragSource
+ * 
+ * Wrapper to create a drag source from a DOM element so that the element can
+ * be dragged over a graph and dropped into the graph as a new cell.
+ * 
+ * TODO: Problem is that in the dropHandler the current preview location is
+ * not available, so the preview and the dropHandler must match.
+ * 
+ * Constructor: mxDragSource
+ * 
+ * Constructs a new drag source for the given element.
+ */
+function mxDragSource(element, dropHandler)
+{
+	this.element = element;
+	this.dropHandler = dropHandler;
+	
+	// Handles a drag gesture on the element
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	mxEvent.addListener(element, md, mxUtils.bind(this, this.mouseDown));
+};
+
+/**
+ * Variable: element
+ *
+ * Reference to the DOM node which was made draggable.
+ */
+mxDragSource.prototype.element = null;
+
+/**
+ * Variable: dropHandler
+ *
+ * Holds the DOM node that is used to represent the drag preview. If this is
+ * null then the source element will be cloned and used for the drag preview.
+ */
+mxDragSource.prototype.dropHandler = null;
+
+/**
+ * Variable: dragOffset
+ *
+ *  that specifies the offset of the . Default is null.
+ */
+mxDragSource.prototype.dragOffset = null;
+
+/**
+ * Variable: dragElement
+ *
+ * Holds the DOM node that is used to represent the drag preview. If this is
+ * null then the source element will be cloned and used for the drag preview.
+ */
+mxDragSource.prototype.dragElement = null;
+
+/**
+ * Variable: previewElement
+ *
+ * Optional  that specifies the unscaled size of the preview.
+ */
+mxDragSource.prototype.previewElement = null;
+
+/**
+ * Variable: enabled
+ *
+ * Specifies if this drag source is enabled. Default is true.
+ */
+mxDragSource.prototype.enabled = true;
+
+/**
+ * Variable: currentGraph
+ *
+ * Reference to the  that is the current drop target.
+ */
+mxDragSource.prototype.currentGraph = null;
+
+/**
+ * Variable: currentDropTarget
+ *
+ * Holds the current drop target under the mouse.
+ */
+mxDragSource.prototype.currentDropTarget = null;
+
+/**
+ * Variable: currentPoint
+ *
+ * Holds the current drop location.
+ */
+mxDragSource.prototype.currentPoint = null;
+
+/**
+ * Variable: currentGuide
+ *
+ * Holds an  for the  if  is not null.
+ */
+mxDragSource.prototype.currentGuide = null;
+
+/**
+ * Variable: currentGuide
+ *
+ * Holds an  for the  if  is not null.
+ */
+mxDragSource.prototype.currentHighlight = null;
+
+/**
+ * Variable: autoscroll
+ *
+ * Specifies if the graph should scroll automatically. Default is true.
+ */
+mxDragSource.prototype.autoscroll = true;
+
+/**
+ * Variable: guidesEnabled
+ *
+ * Specifies if  should be enabled. Default is true.
+ */
+mxDragSource.prototype.guidesEnabled = true;
+
+/**
+ * Variable: gridEnabled
+ *
+ * Specifies if the grid should be allowed. Default is true.
+ */
+mxDragSource.prototype.gridEnabled = true;
+
+/**
+ * Variable: highlightDropTargets
+ *
+ * Specifies if drop targets should be highlighted. Default is true.
+ */
+mxDragSource.prototype.highlightDropTargets = true;
+
+/**
+ * Function: isEnabled
+ * 
+ * Returns .
+ */
+mxDragSource.prototype.isEnabled = function()
+{
+	return this.enabled;
+};
+
+/**
+ * Function: setEnabled
+ * 
+ * Sets .
+ */
+mxDragSource.prototype.setEnabled = function(value)
+{
+	this.enabled = value;
+};
+
+/**
+ * Function: isGuidesEnabled
+ * 
+ * Returns .
+ */
+mxDragSource.prototype.isGuidesEnabled = function()
+{
+	return this.guidesEnabled;
+};
+
+/**
+ * Function: setGuidesEnabled
+ * 
+ * Sets .
+ */
+mxDragSource.prototype.setGuidesEnabled = function(value)
+{
+	this.guidesEnabled = value;
+};
+
+/**
+ * Function: isGridEnabled
+ * 
+ * Returns .
+ */
+mxDragSource.prototype.isGridEnabled = function()
+{
+	return this.gridEnabled;
+};
+
+/**
+ * Function: setGridEnabled
+ * 
+ * Sets .
+ */
+mxDragSource.prototype.setGridEnabled = function(value)
+{
+	this.gridEnabled = value;
+};
+
+/**
+ * Function: getGraphForEvent
+ * 
+ * Returns the graph for the given mouse event. This implementation returns
+ * null.
+ */
+mxDragSource.prototype.getGraphForEvent = function(evt)
+{
+	return null;
+};
+
+/**
+ * Function: getDropTarget
+ * 
+ * Returns the drop target for the given graph and coordinates. This
+ * implementation uses .
+ */
+mxDragSource.prototype.getDropTarget = function(graph, x, y)
+{
+	return graph.getCellAt(x, y);
+};
+
+/**
+ * Function: createDragElement
+ * 
+ * Creates and returns a clone of the  or the 
+ * if the former is not defined.
+ */
+mxDragSource.prototype.createDragElement = function(evt)
+{
+	return this.element.cloneNode(true);
+};
+
+/**
+ * Function: createPreviewElement
+ * 
+ * Creates and returns an element which can be used as a preview in the given
+ * graph.
+ */
+mxDragSource.prototype.createPreviewElement = function(graph)
+{
+	return null;
+};
+
+/**
+ * Function: mouseDown
+ * 
+ * Returns the drop target for the given graph and coordinates. This
+ * implementation uses .
+ */
+mxDragSource.prototype.mouseDown = function(evt)
+{
+	if (this.enabled && !mxEvent.isConsumed(evt))
+	{
+		this.startDrag(evt);
+		
+		var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+		var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+		
+		this.mouseMoveHandler = mxUtils.bind(this, this.mouseMove);
+		mxEvent.addListener(document, mm, this.mouseMoveHandler);
+		this.mouseUpHandler = mxUtils.bind(this, this.mouseUp);
+		mxEvent.addListener(document, mu, this.mouseUpHandler);
+		
+		// Prevents default action (native DnD for images in FF 10)
+		// but does not stop event propagation
+		mxEvent.consume(evt, true, false);
+	}
+};
+
+/**
+ * Function: startDrag
+ * 
+ * Creates the  using .
+ */
+mxDragSource.prototype.startDrag = function(evt)
+{
+	this.dragElement = this.createDragElement(evt);
+	this.dragElement.style.position = 'absolute';
+	this.dragElement.style.zIndex = '3';
+	mxUtils.setOpacity(this.dragElement, 70);
+};
+
+
+/**
+ * Function: stopDrag
+ * 
+ * Removes and destroys the .
+ */
+mxDragSource.prototype.stopDrag = function(evt)
+{
+	if (this.dragElement != null)
+	{
+		if (this.dragElement.parentNode != null)
+		{
+			this.dragElement.parentNode.removeChild(this.dragElement);
+		}
+		
+		this.dragElement = null;
+	}
+};
+
+/**
+ * Function: graphContainsEvent
+ * 
+ * Returns true if the given graph contains the given event.
+ */
+mxDragSource.prototype.graphContainsEvent = function(graph, evt)
+{
+	var x = mxEvent.getClientX(evt);
+	var y = mxEvent.getClientY(evt);
+	var offset = mxUtils.getOffset(graph.container);
+	var origin = mxUtils.getScrollOrigin();
+
+	// Checks if event is inside the bounds of the graph container
+	return x >= offset.x - origin.x && y >= offset.y - origin.y &&
+		x <= offset.x - origin.x + graph.container.offsetWidth &&
+		y <= offset.y - origin.y + graph.container.offsetHeight;
+};
+
+/**
+ * Function: mouseMove
+ * 
+ * Gets the graph for the given event using , updates the
+ * , calling  and  on the new and old graph,
+ * respectively, and invokes  if  is not null.
+ */
+mxDragSource.prototype.mouseMove = function(evt)
+{
+	var graph = this.getGraphForEvent(evt);
+	
+	// Checks if event is inside the bounds of the graph container
+	if (graph != null && !this.graphContainsEvent(graph, evt))
+	{
+		graph = null;
+	}
+
+	if (graph != this.currentGraph)
+	{
+		if (this.currentGraph != null)
+		{
+			this.dragExit(this.currentGraph);
+		}
+		
+		this.currentGraph = graph;
+		
+		if (this.currentGraph != null)
+		{
+			this.dragEnter(this.currentGraph);
+		}
+	}
+	
+	if (this.currentGraph != null)
+	{
+		this.dragOver(this.currentGraph, evt);
+	}
+
+	if (this.dragElement != null && (this.previewElement == null || this.previewElement.style.visibility != 'visible'))
+	{
+		var x = mxEvent.getClientX(evt);
+		var y = mxEvent.getClientY(evt);
+		
+		if (this.dragElement.parentNode == null)
+		{
+			document.body.appendChild(this.dragElement);
+		}
+
+		this.dragElement.style.visibility = 'visible';
+		
+		if (this.dragOffset != null)
+		{
+			x += this.dragOffset.x;
+			y += this.dragOffset.y;
+		}
+		
+		x += document.body.scrollLeft || document.documentElement.scrollLeft;
+		y += document.body.scrollTop || document.documentElement.scrollTop;
+		this.dragElement.style.left = x + 'px';
+		this.dragElement.style.top = y + 'px';
+	}
+	else if (this.dragElement != null)
+	{
+		this.dragElement.style.visibility = 'hidden';
+	}
+	
+	mxEvent.consume(evt);
+};
+
+/**
+ * Function: mouseUp
+ * 
+ * Processes the mouse up event and invokes ,  and 
+ * as required.
+ */
+mxDragSource.prototype.mouseUp = function(evt)
+{
+	if (this.currentGraph != null)
+	{
+		if (this.currentPoint != null && (this.previewElement == null ||
+			this.previewElement.style.visibility != 'hidden'))
+		{
+			var scale = this.currentGraph.view.scale;
+			var tr = this.currentGraph.view.translate;
+			var x = this.currentPoint.x / scale - tr.x;
+			var y = this.currentPoint.y / scale - tr.y;
+			
+			this.drop(this.currentGraph, evt, this.currentDropTarget, x, y);
+		}
+		
+		this.dragExit(this.currentGraph);
+	}
+
+	this.stopDrag(evt);
+	
+	this.currentGraph = null;
+
+	if (this.mouseMoveHandler != null)
+	{
+		var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+		mxEvent.removeListener(document, mm, this.mouseMoveHandler);
+		this.mouseMoveHandler = null;
+	}
+	
+	if (this.mouseUpHandler != null)
+	{
+		var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+		mxEvent.removeListener(document, mu, this.mouseUpHandler);
+		this.mouseUpHandler = null;
+	}
+		
+	mxEvent.consume(evt);
+};
+
+/**
+ * Function: dragEnter
+ * 
+ * Actives the given graph as a drop target.
+ */
+mxDragSource.prototype.dragEnter = function(graph)
+{
+	graph.isMouseDown = true;
+	this.previewElement = this.createPreviewElement(graph);
+	
+	// Guide is only needed if preview element is used
+	if (this.isGuidesEnabled() && this.previewElement != null)
+	{
+		this.currentGuide = new mxGuide(graph, graph.graphHandler.getGuideStates());
+	}
+	
+	if (this.highlightDropTargets)
+	{
+		this.currentHighlight = new mxCellHighlight(graph, mxConstants.DROP_TARGET_COLOR);
+	}
+};
+
+/**
+ * Function: dragExit
+ * 
+ * Deactivates the given graph as a drop target.
+ */
+mxDragSource.prototype.dragExit = function(graph)
+{
+	this.currentDropTarget = null;
+	this.currentPoint = null;
+	graph.isMouseDown = false;
+	
+	if (this.previewElement != null)
+	{
+		if (this.previewElement.parentNode != null)
+		{
+			this.previewElement.parentNode.removeChild(this.previewElement);
+		}
+		
+		this.previewElement = null;
+	}
+	
+	if (this.currentGuide != null)
+	{
+		this.currentGuide.destroy();
+		this.currentGuide = null;
+	}
+	
+	if (this.currentHighlight != null)
+	{
+		this.currentHighlight.destroy();
+		this.currentHighlight = null;
+	}
+};
+
+/**
+ * Function: dragOver
+ * 
+ * Implements autoscroll, updates the , highlights any drop
+ * targets and updates the preview.
+ */
+mxDragSource.prototype.dragOver = function(graph, evt)
+{
+	var offset = mxUtils.getOffset(graph.container);
+	var origin = mxUtils.getScrollOrigin(graph.container);
+	var x = mxEvent.getClientX(evt) - offset.x + origin.x;
+	var y = mxEvent.getClientY(evt) - offset.y + origin.y;
+
+	if (graph.autoScroll && (this.autoscroll == null || this.autoscroll))
+	{
+		graph.scrollPointToVisible(x, y, graph.autoExtend);
+	}
+
+	// Highlights the drop target under the mouse
+	if (this.currentHighlight != null && graph.isDropEnabled())
+	{
+		this.currentDropTarget = this.getDropTarget(graph, x, y);
+		var state = graph.getView().getState(this.currentDropTarget);
+		this.currentHighlight.highlight(state);
+	}
+
+	// Updates the location of the preview
+	if (this.previewElement != null)
+	{
+		if (this.previewElement.parentNode == null)
+		{
+			graph.container.appendChild(this.previewElement);
+			
+			this.previewElement.style.zIndex = '3';
+			this.previewElement.style.position = 'absolute';
+		}
+		
+		var gridEnabled = this.isGridEnabled() && graph.isGridEnabledEvent(evt);
+		var hideGuide = true;
+
+		// Grid and guides
+		if (this.currentGuide != null && this.currentGuide.isEnabledForEvent(evt))
+		{
+			// LATER: HTML preview appears smaller than SVG preview
+			var w = parseInt(this.previewElement.style.width);
+			var h = parseInt(this.previewElement.style.height);
+			var bounds = new mxRectangle(0, 0, w, h);
+			var delta = new mxPoint(x, y);
+			delta = this.currentGuide.move(bounds, delta, gridEnabled);
+			hideGuide = false;
+			x = delta.x;
+			y = delta.y;
+		}
+		else if (gridEnabled)
+		{
+			var scale = graph.view.scale;
+			var tr = graph.view.translate;
+			var off = graph.gridSize / 2;
+			x = (graph.snap(x / scale - tr.x - off) + tr.x) * scale;
+			y = (graph.snap(y / scale - tr.y - off) + tr.y) * scale;
+		}
+		
+		if (this.currentGuide != null && hideGuide)
+		{
+			this.currentGuide.hide();
+		}
+		
+		if (this.previewOffset != null)
+		{
+			x += this.previewOffset.x;
+			y += this.previewOffset.y;
+		}
+
+		this.previewElement.style.left = Math.round(x) + 'px';
+		this.previewElement.style.top = Math.round(y) + 'px';
+		this.previewElement.style.visibility = 'visible';
+	}
+	
+	this.currentPoint = new mxPoint(x, y);
+};
+
+/**
+ * Function: drop
+ * 
+ * Returns the drop target for the given graph and coordinates. This
+ * implementation uses .
+ */
+mxDragSource.prototype.drop = function(graph, evt, dropTarget, x, y)
+{
+	this.dropHandler(graph, evt, dropTarget, x, y);
+	
+	// Had to move this to after the insert because it will
+	// affect the scrollbars of the window in IE to try and
+	// make the complete container visible.
+	// LATER: Should be made optional.
+	graph.container.focus();
+};
+/**
+ * $Id: mxToolbar.js,v 1.35 2012-04-11 07:00:52 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxToolbar
+ * 
+ * Creates a toolbar inside a given DOM node. The toolbar may contain icons,
+ * buttons and combo boxes.
+ * 
+ * Event: mxEvent.SELECT
+ * 
+ * Fires when an item was selected in the toolbar. The function
+ * property contains the function that was selected in .
+ * 
+ * Constructor: mxToolbar
+ * 
+ * Constructs a toolbar in the specified container.
+ *
+ * Parameters:
+ *
+ * container - DOM node that contains the toolbar.
+ */
+function mxToolbar(container)
+{
+	this.container = container;
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxToolbar.prototype = new mxEventSource();
+mxToolbar.prototype.constructor = mxToolbar;
+
+/**
+ * Variable: container
+ * 
+ * Reference to the DOM nodes that contains the toolbar.
+ */
+mxToolbar.prototype.container = null;
+
+/**
+ * Variable: enabled
+ * 
+ * Specifies if events are handled. Default is true.
+ */
+mxToolbar.prototype.enabled = true;
+
+/**
+ * Variable: noReset
+ * 
+ * Specifies if  requires a forced flag of true for resetting
+ * the current mode in the toolbar. Default is false. This is set to true
+ * if the toolbar item is double clicked to avoid a reset after a single
+ * use of the item.
+ */
+mxToolbar.prototype.noReset = false;
+
+/**
+ * Variable: updateDefaultMode
+ * 
+ * Boolean indicating if the default mode should be the last selected
+ * switch mode or the first inserted switch mode. Default is true, that
+ * is the last selected switch mode is the default mode. The default mode
+ * is the mode to be selected after a reset of the toolbar. If this is
+ * false, then the default mode is the first inserted mode item regardless
+ * of what was last selected. Otherwise, the selected item after a reset is
+ * the previously selected item.
+ */
+mxToolbar.prototype.updateDefaultMode = true;
+
+/**
+ * Function: addItem
+ * 
+ * Adds the given function as an image with the specified title and icon
+ * and returns the new image node.
+ * 
+ * Parameters:
+ * 
+ * title - Optional string that is used as the tooltip.
+ * icon - Optional URL of the image to be used. If no URL is given, then a
+ * button is created.
+ * funct - Function to execute on a mouse click.
+ * pressedIcon - Optional URL of the pressed image. Default is a gray
+ * background.
+ * style - Optional style classname. Default is mxToolbarItem.
+ * factoryMethod - Optional factory method for popup menu, eg.
+ * function(menu, evt, cell) { menu.addItem('Hello, World!'); }
+ */
+mxToolbar.prototype.addItem = function(title, icon, funct, pressedIcon, style, factoryMethod)
+{
+	var img = document.createElement((icon != null) ? 'img' : 'button');
+	var initialClassName = style || ((factoryMethod != null) ?
+			'mxToolbarMode' : 'mxToolbarItem');
+	img.className = initialClassName;
+	img.setAttribute('src', icon);
+	
+	if (title != null)
+	{
+		if (icon != null)
+		{
+			img.setAttribute('title', title);
+		}
+		else
+		{
+			mxUtils.write(img, title);
+		}
+	}
+	
+	this.container.appendChild(img);
+
+	// Invokes the function on a click on the toolbar item
+	if (funct != null)
+	{
+		mxEvent.addListener(img, (mxClient.IS_TOUCH) ? 'touchend' : 'click', funct);
+	}
+	
+	var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+	var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+
+	// Highlights the toolbar item with a gray background
+	// while it is being clicked with the mouse
+	mxEvent.addListener(img, md, mxUtils.bind(this, function(evt)
+	{
+		if (pressedIcon != null)
+		{
+			img.setAttribute('src', pressedIcon);
+		}
+		else
+		{
+			img.style.backgroundColor = 'gray';
+		}
+		
+		// Popup Menu
+		if (factoryMethod != null)
+		{
+			if (this.menu == null)
+			{
+				this.menu = new mxPopupMenu();
+				this.menu.init();
+			}
+			
+			var last = this.currentImg;
+			
+			if (this.menu.isMenuShowing())
+			{
+				this.menu.hideMenu();
+			}
+			
+			if (last != img)
+			{
+				// Redirects factory method to local factory method
+				this.currentImg = img;
+				this.menu.factoryMethod = factoryMethod;
+				
+				var point = new mxPoint(
+					img.offsetLeft,
+					img.offsetTop + img.offsetHeight);
+				this.menu.popup(point.x, point.y, null, evt);
+
+				// Sets and overrides to restore classname
+				if (this.menu.isMenuShowing())
+				{
+					img.className = initialClassName + 'Selected';
+					
+					this.menu.hideMenu = function()
+					{
+						mxPopupMenu.prototype.hideMenu.apply(this);
+						img.className = initialClassName;
+						this.currentImg = null;
+					};
+				}
+			}
+		}
+	}));
+
+	var mouseHandler = mxUtils.bind(this, function(evt)
+	{
+		if (pressedIcon != null)
+		{
+			img.setAttribute('src', icon);
+		}
+		else
+		{
+			img.style.backgroundColor = '';
+		}
+	});
+	
+	mxEvent.addListener(img, mu, mouseHandler);
+	mxEvent.addListener(img, 'mouseout', mouseHandler);
+	
+	return img;
+};
+
+/**
+ * Function: addCombo
+ * 
+ * Adds and returns a new SELECT element using the given style. The element
+ * is placed inside a DIV with the mxToolbarComboContainer style classname.
+ * 
+ * Parameters:
+ * 
+ * style - Optional style classname. Default is mxToolbarCombo.
+ */
+mxToolbar.prototype.addCombo = function(style)
+{
+	var div = document.createElement('div');
+	div.style.display = 'inline';
+	div.className = 'mxToolbarComboContainer';
+	
+	var select = document.createElement('select');
+	select.className = style || 'mxToolbarCombo';
+	div.appendChild(select);
+	
+	this.container.appendChild(div);
+	
+	return select;
+};
+
+/**
+ * Function: addCombo
+ * 
+ * Adds and returns a new SELECT element using the given title as the
+ * default element. The selection is reset to this element after each
+ * change.
+ * 
+ * Parameters:
+ * 
+ * title - String that specifies the title of the default element.
+ * style - Optional style classname. Default is mxToolbarCombo.
+ */
+mxToolbar.prototype.addActionCombo = function(title, style)
+{
+	var select = document.createElement('select');
+	select.className = style || 'mxToolbarCombo';
+	
+	this.addOption(select, title, null);
+	
+	mxEvent.addListener(select, 'change', function(evt)
+	{
+		var value = select.options[select.selectedIndex];
+		select.selectedIndex = 0;
+		if (value.funct != null)
+		{
+			value.funct(evt);
+		}
+	});
+	
+	this.container.appendChild(select);
+	
+	return select;
+};
+
+/**
+ * Function: addOption
+ * 
+ * Adds and returns a new OPTION element inside the given SELECT element.
+ * If the given value is a function then it is stored in the option's funct
+ * field.
+ * 
+ * Parameters:
+ * 
+ * combo - SELECT element that will contain the new entry.
+ * title - String that specifies the title of the option.
+ * value - Specifies the value associated with this option.
+ */
+mxToolbar.prototype.addOption = function(combo, title, value)
+{
+	var option = document.createElement('option');
+	mxUtils.writeln(option, title);
+	
+	if (typeof(value) == 'function')
+	{
+		option.funct = value;
+	}
+	else
+	{
+		option.setAttribute('value', value);
+	}
+	
+	combo.appendChild(option);
+	
+	return option;
+};
+
+/**
+ * Function: addSwitchMode
+ * 
+ * Adds a new selectable item to the toolbar. Only one switch mode item may
+ * be selected at a time. The currently selected item is the default item
+ * after a reset of the toolbar.
+ */
+mxToolbar.prototype.addSwitchMode = function(title, icon, funct, pressedIcon, style)
+{
+	var img = document.createElement('img');
+	img.initialClassName = style || 'mxToolbarMode';
+	img.className = img.initialClassName;
+	img.setAttribute('src', icon);
+	img.altIcon = pressedIcon;
+	
+	if (title != null)
+	{
+		img.setAttribute('title', title);
+	}
+	
+	mxEvent.addListener(img, 'click', mxUtils.bind(this, function(evt)
+	{
+		var tmp = this.selectedMode.altIcon;
+		
+		if (tmp != null)
+		{
+			this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
+			this.selectedMode.setAttribute('src', tmp);
+		}
+		else
+		{
+			this.selectedMode.className = this.selectedMode.initialClassName;
+		}
+		
+		if (this.updateDefaultMode)
+		{
+			this.defaultMode = img;
+		}
+		
+		this.selectedMode = img;
+		
+		var tmp = img.altIcon;
+		
+		if (tmp != null)
+		{
+			img.altIcon = img.getAttribute('src');
+			img.setAttribute('src', tmp);
+		}
+		else
+		{
+			img.className = img.initialClassName+'Selected';
+		}
+		
+		this.fireEvent(new mxEventObject(mxEvent.SELECT));
+		funct();
+	}));
+	
+	this.container.appendChild(img);
+	
+	if (this.defaultMode == null)
+	{
+		this.defaultMode = img;
+		this.selectedMode = img;
+		
+		var tmp = img.altIcon;
+		
+		if (tmp != null)
+		{
+			img.altIcon = img.getAttribute('src');
+			img.setAttribute('src', tmp);
+		}
+		else
+		{
+			img.className = img.initialClassName+'Selected';
+		}
+		
+		funct();
+	}
+	
+	return img;
+};
+
+/**
+ * Function: addMode
+ * 
+ * Adds a new item to the toolbar. The selection is typically reset after
+ * the item has been consumed, for example by adding a new vertex to the
+ * graph. The reset is not carried out if the item is double clicked.
+ * 
+ * The function argument uses the following signature: funct(evt, cell) where
+ * evt is the native mouse event and cell is the cell under the mouse.
+ */
+mxToolbar.prototype.addMode = function(title, icon, funct, pressedIcon, style, toggle)
+{
+	toggle = (toggle != null) ? toggle : true;
+	var img = document.createElement((icon != null) ? 'img' : 'button');
+	
+	img.initialClassName = style || 'mxToolbarMode';
+	img.className = img.initialClassName;
+	img.setAttribute('src', icon);
+	img.altIcon = pressedIcon;
+
+	if (title != null)
+	{
+		img.setAttribute('title', title);
+	}
+	
+	if (this.enabled && toggle)
+	{
+		mxEvent.addListener(img, 'click', mxUtils.bind(this, function(evt)
+		{
+			this.selectMode(img, funct);
+			this.noReset = false;
+		}));
+		mxEvent.addListener(img, 'dblclick',
+			mxUtils.bind(this, function(evt)
+			{
+				this.selectMode(img, funct);
+				this.noReset = true;
+			})
+		);
+		
+		if (this.defaultMode == null)
+		{
+			this.defaultMode = img;
+			this.selectedMode = img;
+			
+			var tmp = img.altIcon;
+			
+			if (tmp != null)
+			{
+				img.altIcon = img.getAttribute('src');
+				img.setAttribute('src', tmp);
+			}
+			else
+			{
+				img.className = img.initialClassName+'Selected';
+			}
+		}
+	}
+
+	this.container.appendChild(img);					
+
+	return img;
+};
+
+/**
+ * Function: selectMode
+ * 
+ * Resets the state of the previously selected mode and displays the given
+ * DOM node as selected. This function fires a select event with the given
+ * function as a parameter.
+ */
+mxToolbar.prototype.selectMode = function(domNode, funct)
+{
+	if (this.selectedMode != domNode)
+	{
+		var tmp = this.selectedMode.altIcon;
+		
+		if (tmp != null)
+		{
+			this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
+			this.selectedMode.setAttribute('src', tmp);
+		}
+		else
+		{
+			this.selectedMode.className = this.selectedMode.initialClassName;
+		}
+		
+		this.selectedMode = domNode;
+		var tmp = this.selectedMode.altIcon;
+		
+		if (tmp != null)
+		{
+			this.selectedMode.altIcon = this.selectedMode.getAttribute('src');
+			this.selectedMode.setAttribute('src', tmp);
+		}
+		else
+		{
+			this.selectedMode.className = this.selectedMode.initialClassName+'Selected';
+		}
+		
+		this.fireEvent(new mxEventObject(mxEvent.SELECT, "function", funct));
+	}
+};
+
+/**
+ * Function: resetMode
+ * 
+ * Selects the default mode and resets the state of the previously selected
+ * mode.
+ */
+mxToolbar.prototype.resetMode = function(forced)
+{
+	if ((forced || !this.noReset) &&
+		this.selectedMode != this.defaultMode)
+	{
+		// The last selected switch mode will be activated
+		// so the function was already executed and is
+		// no longer required here
+		this.selectMode(this.defaultMode, null);
+	}
+};
+
+/**
+ * Function: addSeparator
+ * 
+ * Adds the specifies image as a separator.
+ * 
+ * Parameters:
+ * 
+ * icon - URL of the separator icon.
+ */
+mxToolbar.prototype.addSeparator = function(icon)
+{
+	return this.addItem(null, icon, null);
+};
+
+/**
+ * Function: addBreak
+ * 
+ * Adds a break to the container.
+ */
+mxToolbar.prototype.addBreak = function()
+{
+	mxUtils.br(this.container);
+};
+
+/**
+ * Function: addLine
+ * 
+ * Adds a horizontal line to the container.
+ */
+mxToolbar.prototype.addLine = function()
+{
+	var hr = document.createElement('hr');
+	
+	hr.style.marginRight = '6px';
+	hr.setAttribute('size', '1');
+	
+	this.container.appendChild(hr);
+};
+
+/**
+ * Function: destroy
+ * 
+ * Removes the toolbar and all its associated resources.
+ */
+mxToolbar.prototype.destroy = function ()
+{
+	mxEvent.release(this.container);
+	this.container = null;
+	this.defaultMode = null;
+	this.selectedMode = null;
+	
+	if (this.menu != null)
+	{
+		this.menu.destroy();
+	}
+};
+/**
+ * $Id: mxSession.js,v 1.45 2010-09-16 11:11:59 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxSession
+ *
+ * Session for sharing an  with other parties
+ * via a backend that acts as a multicaster for all changes.
+ * 
+ * Diagram Sharing:
+ * 
+ * The diagram sharing is a mechanism where each atomic change of the model is
+ * encoded into XML using  and then transmitted to the server by the
+ *  object. On the server, the XML data is dispatched to each
+ * listener on the same diagram (except the sender), and the XML is decoded
+ * back into atomic changes on the client side, which are then executed on the
+ * model and stored in the command history.
+ * 
+ * The  specifies how these changes are
+ * treated with respect to undo: The default value (true) will undo the last
+ * change regardless of whether it was a remote or a local change. If the
+ * switch is false, then an undo will go back until the last local change,
+ * silently undoing all remote changes up to that point. Note that these
+ * changes will be added as new remote changes to the history of the other
+ * clients.
+ * 
+ * Event: mxEvent.CONNECT
+ *
+ * Fires after the session has been started, that is, after the response to the
+ * initial request was received and the session goes into polling mode. This
+ * event has no properties.
+ *
+ * Event: mxEvent.SUSPEND
+ *
+ * Fires after  was called an the session was not already in suspended
+ * state. This event has no properties.
+ *
+ * Event: mxEvent.RESUME
+ *
+ * Fires after the session was resumed in . This event has no
+ * properties.
+ *
+ * Event: mxEvent.DISCONNECT
+ *
+ * Fires after the session was stopped in . The reason
+ * property contains the optional exception that was passed to the stop method.
+ *
+ * Event: mxEvent.NOTIFY
+ *
+ * Fires after a notification was sent in . The url
+ * property contains the URL and the xml property contains the XML
+ * data of the request.
+ *
+ * Event: mxEvent.GET
+ *
+ * Fires after a response was received in . The url property
+ * contains the URL and the request is the  that
+ * contains the response.
+ *
+ * Event: mxEvent.FIRED
+ * 
+ * Fires after an array of edits has been executed on the model. The
+ * changes property contains the array of changes.
+ * 
+ * Event: mxEvent.RECEIVE
+ *
+ * Fires after an XML node was received in . The node
+ * property contains the node that was received.
+ * 
+ * Constructor: mxSession
+ * 
+ * Constructs a new session using the given  and URLs to
+ * communicate with the backend.
+ * 
+ * Parameters:
+ * 
+ * model -  that contains the data.
+ * urlInit - URL to be used for initializing the session.
+ * urlPoll - URL to be used for polling the backend.
+ * urlNotify - URL to be used for sending changes to the backend.
+ */
+function mxSession(model, urlInit, urlPoll, urlNotify)
+{
+	this.model = model;
+	this.urlInit = urlInit;
+	this.urlPoll = urlPoll;
+	this.urlNotify = urlNotify;
+
+	// Resolves cells by id using the model
+	if (model != null)
+	{
+		this.codec = new mxCodec();
+		
+		this.codec.lookup = function(id)
+		{
+			return model.getCell(id);
+		};
+	}
+	
+	// Adds the listener for notifying the backend of any
+	// changes in the model
+	model.addListener(mxEvent.NOTIFY,
+		mxUtils.bind(this, function(sender, evt)
+		{
+			var edit = evt.getProperty('edit');
+			
+			if (edit != null && this.debug ||
+				(this.connected && !this.suspended))
+			{
+				this.notify(''+this.encodeChanges(edit.changes, edit.undone)+'');
+			}
+		})
+	);
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxSession.prototype = new mxEventSource();
+mxSession.prototype.constructor = mxSession;
+
+/**
+ * Variable: model
+ * 
+ * Reference to the enclosing .
+ */
+mxSession.prototype.model = null;
+
+/**
+ * Variable: urlInit
+ * 
+ * URL to initialize the session.
+ */
+mxSession.prototype.urlInit = null;
+
+/**
+ * Variable: urlPoll
+ * 
+ * URL for polling the backend.
+ */
+mxSession.prototype.urlPoll = null;
+
+/**
+ * Variable: urlNotify
+ * 
+ * URL to send changes to the backend.
+ */
+mxSession.prototype.urlNotify = null;
+
+/**
+ * Variable: codec
+ * 
+ * Reference to the  used to encoding and decoding changes.
+ */
+mxSession.prototype.codec = null;
+
+/**
+ * Variable: linefeed
+ * 
+ * Used for encoding linefeeds. Default is '
'.
+ */
+mxSession.prototype.linefeed = '
';
+
+/**
+ * Variable: escapePostData
+ * 
+ * Specifies if the data in the post request sent in 
+ * should be converted using encodeURIComponent. Default is true.
+ */
+mxSession.prototype.escapePostData = true;
+
+/**
+ * Variable: significantRemoteChanges
+ * 
+ * Whether remote changes should be significant in the
+ * local command history. Default is true.
+ */
+mxSession.prototype.significantRemoteChanges = true;
+
+/**
+ * Variable: sent
+ * 
+ * Total number of sent bytes.
+ */
+mxSession.prototype.sent = 0;
+
+/**
+ * Variable: received
+ * 
+ * Total number of received bytes.
+ */
+mxSession.prototype.received = 0;
+
+/**
+ * Variable: debug
+ * 
+ * Specifies if the session should run in debug mode. In this mode, no
+ * connection is established. The data is written to the console instead.
+ * Default is false.
+ */
+mxSession.prototype.debug = false;
+
+/**
+ * Variable: connected
+ */
+mxSession.prototype.connected = false;
+	
+/**
+ * Variable: send
+ */
+mxSession.prototype.suspended = false;
+	
+/**
+ * Variable: polling
+ */
+mxSession.prototype.polling = false;
+
+/**
+ * Function: start
+ */
+mxSession.prototype.start = function()
+{
+	if (this.debug)
+	{
+		this.connected = true;
+		this.fireEvent(new mxEventObject(mxEvent.CONNECT));
+	}
+	else if (!this.connected)
+	{
+		this.get(this.urlInit, mxUtils.bind(this, function(req)
+		{
+			this.connected = true;
+			this.fireEvent(new mxEventObject(mxEvent.CONNECT));
+			this.poll();
+		}));
+	}
+};
+
+/**
+ * Function: suspend
+ * 
+ * Suspends the polling. Use  to reactive the session. Fires a
+ * suspend event.
+ */
+mxSession.prototype.suspend = function()
+{
+	if (this.connected && !this.suspended)
+	{
+		this.suspended = true;
+		this.fireEvent(new mxEventObject(mxEvent.SUSPEND));
+	}
+};
+	
+/**
+ * Function: resume
+ * 
+ * Resumes the session if it has been suspended. Fires a resume-event
+ * before starting the polling.
+ */
+mxSession.prototype.resume = function(type, attr, value)
+{
+	if (this.connected &&
+		this.suspended)
+	{
+		this.suspended = false;
+		this.fireEvent(new mxEventObject(mxEvent.RESUME));
+		
+		if (!this.polling)
+		{
+			this.poll();
+		}
+	}
+};
+		
+/**
+ * Function: stop
+ * 
+ * Stops the session and fires a disconnect event. The given reason is
+ * passed to the disconnect event listener as the second argument.
+ */
+mxSession.prototype.stop = function(reason)
+{
+	if (this.connected)
+	{
+		this.connected = false;
+	}
+	
+	this.fireEvent(new mxEventObject(mxEvent.DISCONNECT,
+			'reason', reason));
+};
+
+/**
+ * Function: poll
+ * 
+ * Sends an asynchronous GET request to .
+ */
+mxSession.prototype.poll = function()
+{
+	if (this.connected &&
+		!this.suspended &&
+		this.urlPoll != null)
+	{
+		this.polling = true;
+
+		this.get(this.urlPoll, mxUtils.bind(this, function()
+		{
+			this.poll();
+		}));
+	}
+	else
+	{
+		this.polling = false;
+	}
+};
+
+/**
+ * Function: notify
+ * 
+ * Sends out the specified XML to  and fires a  event.
+ */
+mxSession.prototype.notify = function(xml, onLoad, onError)
+{
+	if (xml != null &&
+		xml.length > 0)
+	{
+		if (this.urlNotify != null)
+		{
+			if (this.debug)
+			{
+				mxLog.show();
+				mxLog.debug('mxSession.notify: '+this.urlNotify+' xml='+xml);			
+			}
+			else
+			{
+				xml = ''+xml+'';
+				
+				if (this.escapePostData)
+				{
+					xml = encodeURIComponent(xml);
+				}
+				
+				mxUtils.post(this.urlNotify, 'xml='+xml, onLoad, onError);
+			}
+		}
+		
+		this.sent += xml.length;
+		this.fireEvent(new mxEventObject(mxEvent.NOTIFY,
+				'url', this.urlNotify, 'xml', xml));
+	}
+};
+
+/**
+ * Function: get
+ * 
+ * Sends an asynchronous get request to the given URL, fires a  event
+ * and invokes the given onLoad function when a response is received.
+ */
+mxSession.prototype.get = function(url, onLoad, onError)
+{
+	// Response after browser refresh has no global scope
+	// defined. This response is ignored and the session
+	// stops implicitely.
+	if (typeof(mxUtils) != 'undefined')
+	{
+		var onErrorWrapper = mxUtils.bind(this, function(ex)
+		{
+			if (onError != null)
+			{
+				onError(ex);
+			}
+			else
+			{
+				this.stop(ex);
+			}
+		});
+
+		// Handles a successful response for
+		// the above request.
+		var req = mxUtils.get(url,
+			mxUtils.bind(this, function(req)
+			{
+				if (typeof(mxUtils) != 'undefined')
+				{
+					//try
+					{
+		    			if (req.isReady() &&
+		    				req.getStatus() != 404)
+		    			{
+		    				this.received += req.getText().length;
+							this.fireEvent(new mxEventObject(mxEvent.GET,
+									'url', url, 'request', req));
+
+							if (this.isValidResponse(req))
+							{
+				    			if (req.getText().length > 0)
+				    			{
+									var node = req.getDocumentElement();
+									
+									if (node == null)
+									{
+										onErrorWrapper('Invalid response: '+req.getText());
+									}
+									else
+									{
+										this.receive(node);
+									}
+								}
+				    			
+				    			if (onLoad != null)
+				    			{
+									onLoad(req);
+								}
+							}
+						}
+						else
+						{
+							onErrorWrapper('Response not ready');
+						}
+					}
+					/*catch (ex)
+					{
+						onErrorWrapper(ex);
+						throw ex; // debugging
+					}*/
+				}
+			}),
+			
+			// Handles a transmission error for the
+			// above request
+			function(req)
+			{
+				onErrorWrapper('Transmission error');
+			}
+		);
+	}
+};
+
+/**
+ * Function: isValidResponse
+ * 
+ * Returns true if the response data in the given  is valid.
+ */
+mxSession.prototype.isValidResponse = function(req)
+{
+	// TODO: Find condition to check if response
+	// contains valid XML (not eg. the PHP code).
+	return req.getText().indexOf('= 0 && i < changes.length; i += step)
+	{	
+		// Newlines must be kept, they will be converted
+		// to 
 when the server sends data to the
+		// client
+		var node = this.codec.encode(changes[i]);
+		xml += mxUtils.getXml(node, this.linefeed);
+	}
+	
+	return xml;
+};
+
+/**
+ * Function: receive
+ * 
+ * Processes the given node by applying the changes to the model. If the nodename
+ * is state, then the namespace is used as a prefix for creating Ids in the model,
+ * and the child nodes are visited recursively. If the nodename is delta, then the
+ * changes encoded in the child nodes are applied to the model. Each call to the
+ * receive function fires a  event with the given node as the second argument
+ * after processing. If changes are processed, then the function additionally fires
+ * a  event before the  event.
+ */
+mxSession.prototype.receive = function(node)
+{
+	if (node != null &&
+		node.nodeType == mxConstants.NODETYPE_ELEMENT)
+	{
+		// Uses the namespace in the model
+		var ns = node.getAttribute('namespace');
+		
+		if (ns != null)
+		{
+			this.model.prefix = ns + '-';
+		}
+		
+		var child = node.firstChild;
+		
+		while (child != null)
+		{
+			var name = child.nodeName.toLowerCase();
+			
+			if (name == 'state')
+			{
+				this.processState(child);
+			}
+			else if (name == 'delta')
+			{
+				this.processDelta(child);	
+			}
+			
+			child = child.nextSibling;
+		}
+		
+		// Fires receive event
+		this.fireEvent(new mxEventObject(mxEvent.RECEIVE, 'node', node));
+	}
+};
+
+/**
+ * Function: processState
+ * 
+ * Processes the given state node which contains the current state of the
+ * remote model.
+ */
+mxSession.prototype.processState = function(node)
+{
+	var dec = new mxCodec(node.ownerDocument);
+	dec.decode(node.firstChild, this.model);
+};
+
+/**
+ * Function: processDelta
+ * 
+ * Processes the given delta node which contains a sequence of edits which in
+ * turn map to one transaction on the remote model each.
+ */
+mxSession.prototype.processDelta = function(node)
+{
+	var edit = node.firstChild;
+	
+	while (edit != null)
+	{
+		if (edit.nodeName == 'edit')
+		{
+			this.processEdit(edit);
+		}
+		
+		edit = edit.nextSibling;
+	}
+};
+
+/**
+ * Function: processEdit
+ * 
+ * Processes the given edit by executing its changes and firing the required
+ * events via the model.
+ */
+mxSession.prototype.processEdit = function(node)
+{
+	var changes = this.decodeChanges(node);
+	
+	if (changes.length > 0)
+	{
+		var edit = this.createUndoableEdit(changes);
+		
+		// No notify event here to avoid the edit from being encoded and transmitted
+		// LATER: Remove changes property (deprecated)
+		this.model.fireEvent(new mxEventObject(mxEvent.CHANGE,
+			'edit', edit, 'changes', changes));
+		this.model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
+		this.fireEvent(new mxEventObject(mxEvent.FIRED, 'edit', edit));
+	}
+};
+
+/**
+ * Function: createUndoableEdit
+ * 
+ * Creates a new  that implements the notify function to fire a
+ *  and  event via the model.
+ */
+mxSession.prototype.createUndoableEdit = function(changes)
+{
+	var edit = new mxUndoableEdit(this.model, this.significantRemoteChanges);
+	edit.changes = changes;
+	
+	edit.notify = function()
+	{
+		// LATER: Remove changes property (deprecated)
+		edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
+			'edit', edit, 'changes', edit.changes));
+		edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
+			'edit', edit, 'changes', edit.changes));
+	};
+	
+	return edit;
+};
+
+/**
+ * Function: decodeChanges
+ * 
+ * Decodes and executes the changes represented by the children in the
+ * given node. Returns an array that contains all changes.
+ */
+mxSession.prototype.decodeChanges = function(node)
+{
+	// Updates the document in the existing codec
+	this.codec.document = node.ownerDocument;
+
+	// Parses and executes the changes on the model
+	var changes = [];
+	node = node.firstChild;
+	
+	while (node != null)
+	{
+		if (node.nodeType == mxConstants.NODETYPE_ELEMENT)
+		{
+			var change = null;
+			
+			if (node.nodeName == 'mxRootChange')
+			{
+				// Handles the special case were no ids should be
+				// resolved in the existing model. This change will
+				// replace all registered ids and cells from the
+				// model and insert a new cell hierarchy instead.
+				var tmp = new mxCodec(node.ownerDocument);
+				change = tmp.decode(node);
+			}
+			else
+			{
+				change = this.codec.decode(node);
+			}
+			
+			if (change != null)
+			{
+				change.model = this.model;
+				change.execute();
+				
+				// Workaround for references not being resolved if cells have
+				// been removed from the model prior to being referenced. This
+				// adds removed cells in the codec object lookup table.
+				if (node.nodeName == 'mxChildChange' &&
+					change.parent == null)
+				{
+					this.cellRemoved(change.child);
+				}
+				
+				changes.push(change);
+			}
+		}
+		
+		node = node.nextSibling;
+	}
+	
+	return changes;
+};
+
+/**
+ * Function: cellRemoved
+ * 
+ * Adds removed cells to the codec object lookup for references to the removed
+ * cells after this point in time.
+ */
+mxSession.prototype.cellRemoved = function(cell, codec)
+{
+	this.codec.putObject(cell.getId(), cell);
+	
+	var childCount = this.model.getChildCount(cell);
+	
+	for (var i = 0; i < childCount; i++)
+	{
+		this.cellRemoved(this.model.getChildAt(cell, i));
+	}
+};
+/**
+ * $Id: mxUndoableEdit.js,v 1.14 2010-09-15 16:58:51 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxUndoableEdit
+ * 
+ * Implements a composite undoable edit.
+ * 
+ * Constructor: mxUndoableEdit
+ * 
+ * Constructs a new undoable edit for the given source.
+ */
+function mxUndoableEdit(source, significant)
+{
+	this.source = source;
+	this.changes = [];
+	this.significant = (significant != null) ? significant : true;
+};
+
+/**
+ * Variable: source
+ * 
+ * Specifies the source of the edit.
+ */
+mxUndoableEdit.prototype.source = null;
+
+/**
+ * Variable: changes
+ * 
+ * Array that contains the changes that make up this edit. The changes are
+ * expected to either have an undo and redo function, or an execute
+ * function. Default is an empty array.
+ */
+mxUndoableEdit.prototype.changes = null;
+
+/**
+ * Variable: significant
+ * 
+ * Specifies if the undoable change is significant.
+ * Default is true.
+ */
+mxUndoableEdit.prototype.significant = null;
+
+/**
+ * Variable: undone
+ * 
+ * Specifies if this edit has been undone. Default is false.
+ */
+mxUndoableEdit.prototype.undone = false;
+
+/**
+ * Variable: redone
+ * 
+ * Specifies if this edit has been redone. Default is false.
+ */
+mxUndoableEdit.prototype.redone = false;
+
+/**
+ * Function: isEmpty
+ * 
+ * Returns true if the this edit contains no changes.
+ */
+mxUndoableEdit.prototype.isEmpty = function()
+{
+	return this.changes.length == 0;
+};
+
+/**
+ * Function: isSignificant
+ * 
+ * Returns .
+ */
+mxUndoableEdit.prototype.isSignificant = function()
+{
+	return this.significant;
+};
+
+/**
+ * Function: add
+ * 
+ * Adds the specified change to this edit. The change is an object that is
+ * expected to either have an undo and redo, or an execute function.
+ */
+mxUndoableEdit.prototype.add = function(change)
+{
+	this.changes.push(change);
+};
+
+/**
+ * Function: notify
+ * 
+ * Hook to notify any listeners of the changes after an  or 
+ * has been carried out. This implementation is empty.
+ */
+mxUndoableEdit.prototype.notify = function() { };
+
+/**
+ * Function: die
+ * 
+ * Hook to free resources after the edit has been removed from the command
+ * history. This implementation is empty.
+ */
+mxUndoableEdit.prototype.die = function() { };
+
+/**
+ * Function: undo
+ * 
+ * Undoes all changes in this edit.
+ */
+mxUndoableEdit.prototype.undo = function()
+{
+	if (!this.undone)
+	{
+		var count = this.changes.length;
+		
+		for (var i = count - 1; i >= 0; i--)
+		{
+			var change = this.changes[i];
+			
+			if (change.execute != null)
+			{
+				change.execute();
+			}
+			else if (change.undo != null)
+			{
+				change.undo();
+			}
+		}
+		
+		this.undone = true;
+		this.redone = false;
+	}
+	
+	this.notify();
+};
+
+/**
+ * Function: redo
+ * 
+ * Redoes all changes in this edit.
+ */
+mxUndoableEdit.prototype.redo = function()
+{
+	if (!this.redone)
+	{
+		var count = this.changes.length;
+		
+		for (var i = 0; i < count; i++)
+		{
+			var change = this.changes[i];
+			
+			if (change.execute != null)
+			{
+				change.execute();
+			}
+			else if (change.redo != null)
+			{
+				change.redo();
+			}
+		}
+		
+		this.undone = false;
+		this.redone = true;
+	}
+	
+	this.notify();
+};
+/**
+ * $Id: mxUndoManager.js,v 1.30 2011-10-05 06:39:19 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxUndoManager
+ *
+ * Implements a command history. When changing the graph model, an
+ *  object is created at the start of the transaction (when
+ * model.beginUpdate is called). All atomic changes are then added to this
+ * object until the last model.endUpdate call, at which point the
+ *  is dispatched in an event, and added to the history inside
+ * . This is done by an event listener in
+ * .
+ * 
+ * Each atomic change of the model is represented by an object (eg.
+ * , ,  etc) which contains the
+ * complete undo information. The  also listens to the
+ *  and stores it's changes to the current root as insignificant
+ * undoable changes, so that drilling (step into, step up) is undone.
+ * 
+ * This means when you execute an atomic change on the model, then change the
+ * current root on the view and click undo, the change of the root will be
+ * undone together with the change of the model so that the display represents
+ * the state at which the model was changed. However, these changes are not
+ * transmitted for sharing as they do not represent a state change.
+ *
+ * Example:
+ * 
+ * When adding an undo manager to a graph, make sure to add it
+ * to the model and the view as well to maintain a consistent
+ * display across multiple undo/redo steps.
+ *
+ * (code)
+ * var undoManager = new mxUndoManager();
+ * var listener = function(sender, evt)
+ * {
+ *   undoManager.undoableEditHappened(evt.getProperty('edit'));
+ * };
+ * graph.getModel().addListener(mxEvent.UNDO, listener);
+ * graph.getView().addListener(mxEvent.UNDO, listener);
+ * (end)
+ * 
+ * The code creates a function that informs the undoManager
+ * of an undoable edit and binds it to the undo event of
+ *  and  using
+ * .
+ * 
+ * Event: mxEvent.CLEAR
+ * 
+ * Fires after  was invoked. This event has no properties.
+ * 
+ * Event: mxEvent.UNDO
+ * 
+ * Fires afer a significant edit was undone in . The edit
+ * property contains the  that was undone.
+ * 
+ * Event: mxEvent.REDO
+ * 
+ * Fires afer a significant edit was redone in . The edit
+ * property contains the  that was redone.
+ * 
+ * Event: mxEvent.ADD
+ * 
+ * Fires after an undoable edit was added to the history. The edit
+ * property contains the  that was added.
+ * 
+ * Constructor: mxUndoManager
+ *
+ * Constructs a new undo manager with the given history size. If no history
+ * size is given, then a default size of 100 steps is used.
+ */
+function mxUndoManager(size)
+{
+	this.size = (size != null) ? size : 100;
+	this.clear();
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxUndoManager.prototype = new mxEventSource();
+mxUndoManager.prototype.constructor = mxUndoManager;
+
+/**
+ * Variable: size
+ * 
+ * Maximum command history size. 0 means unlimited history. Default is
+ * 100.
+ */
+mxUndoManager.prototype.size = null;
+
+/**
+ * Variable: history
+ * 
+ * Array that contains the steps of the command history.
+ */
+mxUndoManager.prototype.history = null;
+
+/**
+ * Variable: indexOfNextAdd
+ * 
+ * Index of the element to be added next.
+ */
+mxUndoManager.prototype.indexOfNextAdd = 0;
+
+/**
+ * Function: isEmpty
+ * 
+ * Returns true if the history is empty.
+ */
+mxUndoManager.prototype.isEmpty = function()
+{
+	return this.history.length == 0;
+};
+
+/**
+ * Function: clear
+ * 
+ * Clears the command history.
+ */
+mxUndoManager.prototype.clear = function()
+{
+	this.history = [];
+	this.indexOfNextAdd = 0;
+	this.fireEvent(new mxEventObject(mxEvent.CLEAR));
+};
+
+/**
+ * Function: canUndo
+ * 
+ * Returns true if an undo is possible.
+ */
+mxUndoManager.prototype.canUndo = function()
+{
+	return this.indexOfNextAdd > 0;
+};
+
+/**
+ * Function: undo
+ * 
+ * Undoes the last change.
+ */
+mxUndoManager.prototype.undo = function()
+{
+    while (this.indexOfNextAdd > 0)
+    {
+        var edit = this.history[--this.indexOfNextAdd];
+        edit.undo();
+
+		if (edit.isSignificant())
+        {
+        	this.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
+            break;
+        }
+    }
+};
+
+/**
+ * Function: canRedo
+ * 
+ * Returns true if a redo is possible.
+ */
+mxUndoManager.prototype.canRedo = function()
+{
+	return this.indexOfNextAdd < this.history.length;
+};
+
+/**
+ * Function: redo
+ * 
+ * Redoes the last change.
+ */
+mxUndoManager.prototype.redo = function()
+{
+    var n = this.history.length;
+    
+    while (this.indexOfNextAdd < n)
+    {
+        var edit =  this.history[this.indexOfNextAdd++];
+        edit.redo();
+        
+        if (edit.isSignificant())
+        {
+        	this.fireEvent(new mxEventObject(mxEvent.REDO, 'edit', edit));
+            break;
+        }
+    }
+};
+
+/**
+ * Function: undoableEditHappened
+ * 
+ * Method to be called to add new undoable edits to the .
+ */
+mxUndoManager.prototype.undoableEditHappened = function(undoableEdit)
+{
+	this.trim();
+	
+	if (this.size > 0 &&
+		this.size == this.history.length)
+	{
+		this.history.shift();
+	}
+	
+	this.history.push(undoableEdit);
+	this.indexOfNextAdd = this.history.length;
+	this.fireEvent(new mxEventObject(mxEvent.ADD, 'edit', undoableEdit));
+};
+
+/**
+ * Function: trim
+ * 
+ * Removes all pending steps after  from the history,
+ * invoking die on each edit. This is called from .
+ */
+mxUndoManager.prototype.trim = function()
+{
+	if (this.history.length > this.indexOfNextAdd)
+	{
+		var edits = this.history.splice(this.indexOfNextAdd,
+			this.history.length - this.indexOfNextAdd);
+			
+		for (var i = 0; i < edits.length; i++)
+		{
+			edits[i].die();
+		}
+	}
+};
+/**
+ * $Id: mxUrlConverter.js,v 1.2 2012-05-18 14:27:52 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ *
+ * Class: mxUrlConverter
+ * 
+ * Converts relative to absolute URLs.
+ */
+var mxUrlConverter = function(root)
+{
+	/**
+	 * Variable: enabled
+	 * 
+	 * Specifies if the converter is enabled. Default is true.
+	 */
+	var enabled = true;
+
+	/**
+	 * Variable: baseUrl
+	 * 
+	 * Specifies the base URL to be used as a prefix for relative URLs.
+	 */
+	var baseUrl = null;
+	
+	// Private helper function to update the base URL
+	var updateBaseUrl = function()
+	{
+		baseUrl = document.URL;
+		var tmp = baseUrl.lastIndexOf('/');
+		
+		if (tmp > 0)
+		{
+			baseUrl = baseUrl.substring(0, tmp + 1);
+		}
+	};
+
+	// Returns public interface
+	return {
+
+		/**
+		 * Function: isEnabled
+		 * 
+		 * Returns .
+		 */
+		isEnabled: function()
+		{
+			return enabled;
+		},
+
+		/**
+		 * Function: setEnabled
+		 * 
+		 * Sets .
+		 */
+		setEnabled: function(value)
+		{
+			enabled = value;
+		},
+
+		/**
+		 * Function: getBaseUrl
+		 * 
+		 * Returns .
+		 */
+		getBaseUrl: function()
+		{
+			return baseUrl;
+		},
+
+		/**
+		 * Function: setBaseUrl
+		 * 
+		 * Sets .
+		 */
+		setBaseUrl: function(value)
+		{
+			baseUrl = value;
+		},
+
+		/**
+		 * Function: convert
+		 * 
+		 * Converts the given URL to an absolute URL.
+		 */
+		convert: function(url)
+		{
+			if (enabled && url.indexOf('http://') != 0 && url.indexOf('https://') != 0 && url.indexOf('data:image') != 0)
+			{
+				if (baseUrl == null)
+				{
+					updateBaseUrl();
+				}
+				
+				url = baseUrl + url;
+			}
+			
+			return url;
+		}
+
+	};
+
+};/**
+ * $Id: mxPanningManager.js,v 1.6 2012-06-01 10:30:07 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxPanningManager
+ *
+ * Implements a handler for panning.
+ */
+function mxPanningManager(graph)
+{
+	this.thread = null;
+	this.active = false;
+	this.tdx = 0;
+	this.tdy = 0;
+	this.t0x = 0;
+	this.t0y = 0;
+	this.dx = 0;
+	this.dy = 0;
+	this.scrollbars = false;
+	this.scrollLeft = 0;
+	this.scrollTop = 0;
+	
+	this.mouseListener =
+	{
+	    mouseDown: function(sender, me) { },
+	    mouseMove: function(sender, me) { },
+	    mouseUp: mxUtils.bind(this, function(sender, me)
+	    {
+	    	if (this.active)
+	    	{
+	    		this.stop();
+	    	}
+	    })
+	};
+	
+	graph.addMouseListener(this.mouseListener);
+	
+	var createThread = mxUtils.bind(this, function()
+	{
+    	this.scrollbars = mxUtils.hasScrollbars(graph.container);
+    	this.scrollLeft = graph.container.scrollLeft;
+    	this.scrollTop = graph.container.scrollTop;
+
+    	return window.setInterval(mxUtils.bind(this, function()
+		{
+			this.tdx -= this.dx;
+			this.tdy -= this.dy;
+
+			if (this.scrollbars)
+			{
+				var left = -graph.container.scrollLeft - Math.ceil(this.dx);
+				var top = -graph.container.scrollTop - Math.ceil(this.dy);
+				graph.panGraph(left, top);
+				graph.panDx = this.scrollLeft - graph.container.scrollLeft;
+				graph.panDy = this.scrollTop - graph.container.scrollTop;
+				graph.fireEvent(new mxEventObject(mxEvent.PAN));
+				// TODO: Implement graph.autoExtend
+			}
+			else
+			{
+				graph.panGraph(this.getDx(), this.getDy());
+			}
+		}), this.delay);
+	});
+	
+	this.isActive = function()
+	{
+		return active;
+	};
+	
+	this.getDx = function()
+	{
+		return Math.round(this.tdx);
+	};
+	
+	this.getDy = function()
+	{
+		return Math.round(this.tdy);
+	};
+	
+	this.start = function()
+	{
+		this.t0x = graph.view.translate.x;
+		this.t0y = graph.view.translate.y;
+		this.active = true;
+	};
+	
+	this.panTo = function(x, y, w, h)
+	{
+		if (!this.active)
+		{
+			this.start();
+		}
+		
+    	this.scrollLeft = graph.container.scrollLeft;
+    	this.scrollTop = graph.container.scrollTop;
+		
+		w = (w != null) ? w : 0;
+		h = (h != null) ? h : 0;
+		
+		var c = graph.container;
+		this.dx = x + w - c.scrollLeft - c.clientWidth;
+		
+		if (this.dx < 0 && Math.abs(this.dx) < this.border)
+		{
+			this.dx = this.border + this.dx;
+		}
+		else if (this.handleMouseOut)
+		{
+			this.dx = Math.max(this.dx, 0);
+		}
+		else
+		{
+			this.dx = 0;
+		}
+		
+		if (this.dx == 0)
+		{
+			this.dx = x - c.scrollLeft;
+			
+			if (this.dx > 0 && this.dx < this.border)
+			{
+				this.dx = this.dx - this.border;
+			}
+			else if (this.handleMouseOut)
+			{
+				this.dx = Math.min(0, this.dx);
+			}
+			else
+			{
+				this.dx = 0;
+			}
+		}
+		
+		this.dy = y + h - c.scrollTop - c.clientHeight;
+
+		if (this.dy < 0 && Math.abs(this.dy) < this.border)
+		{
+			this.dy = this.border + this.dy;
+		}
+		else if (this.handleMouseOut)
+		{
+			this.dy = Math.max(this.dy, 0);
+		}
+		else
+		{
+			this.dy = 0;
+		}
+		
+		if (this.dy == 0)
+		{
+			this.dy = y - c.scrollTop;
+			
+			if (this.dy > 0 && this.dy < this.border)
+			{
+				this.dy = this.dy - this.border;
+			}
+			else if (this.handleMouseOut)
+			{
+				this.dy = Math.min(0, this.dy);
+			} 
+			else
+			{
+				this.dy = 0;
+			}
+		}
+		
+		if (this.dx != 0 || this.dy != 0)
+		{
+			this.dx *= this.damper;
+			this.dy *= this.damper;
+			
+			if (this.thread == null)
+			{
+				this.thread = createThread();
+			}
+		}
+		else if (this.thread != null)
+		{
+			window.clearInterval(this.thread);
+			this.thread = null;
+		}
+	};
+	
+	this.stop = function()
+	{
+		if (this.active)
+		{
+			this.active = false;
+		
+			if (this.thread != null)
+	    	{
+				window.clearInterval(this.thread);
+				this.thread = null;
+	    	}
+			
+			this.tdx = 0;
+			this.tdy = 0;
+			
+			if (!this.scrollbars)
+			{
+				var px = graph.panDx;
+				var py = graph.panDy;
+		    	
+		    	if (px != 0 || py != 0)
+		    	{
+		    		graph.panGraph(0, 0);
+			    	graph.view.setTranslate(this.t0x + px / graph.view.scale, this.t0y + py / graph.view.scale);
+		    	}
+			}
+			else
+			{
+				graph.panDx = 0;
+				graph.panDy = 0;
+				graph.fireEvent(new mxEventObject(mxEvent.PAN));
+			}
+		}
+	};
+	
+	this.destroy = function()
+	{
+		graph.removeMouseListener(this.mouseListener);
+	};
+};
+
+/**
+ * Variable: damper
+ * 
+ * Damper value for the panning. Default is 1/6.
+ */
+mxPanningManager.prototype.damper = 1/6;
+
+/**
+ * Variable: delay
+ * 
+ * Delay in milliseconds for the panning. Default is 10.
+ */
+mxPanningManager.prototype.delay = 10;
+
+/**
+ * Variable: handleMouseOut
+ * 
+ * Specifies if mouse events outside of the component should be handled. Default is true. 
+ */
+mxPanningManager.prototype.handleMouseOut = true;
+
+/**
+ * Variable: border
+ * 
+ * Border to handle automatic panning inside the component. Default is 0 (disabled).
+ */
+mxPanningManager.prototype.border = 0;
+/**
+ * $Id: mxPath.js,v 1.21 2012-05-21 18:27:17 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxPath
+ *
+ * An abstraction for creating VML and SVG paths. See  for using this
+ * object inside an  for painting cells.
+ * 
+ * Constructor: mxPath
+ *
+ * Constructs a path for the given format, which is one of svg or vml.
+ * 
+ * Parameters:
+ * 
+ * format - String specifying the . May be one of vml or svg
+ * (default).
+ */
+function mxPath(format)
+{
+	this.format = format;
+	this.path = [];
+	this.translate = new mxPoint(0, 0);
+};
+
+/**
+ * Variable: format
+ *
+ * Defines the format for the output of this path. Possible values are
+ * svg and vml.
+ */
+mxPath.prototype.format = null;
+
+/**
+ * Variable: translate
+ *
+ *  that specifies the translation of the complete path.
+ */
+mxPath.prototype.translate = null;
+
+/**
+ * Variable: scale
+ *
+ * Number that specifies the translation of the path.
+ */
+mxPath.prototype.scale = 1;
+
+/**
+ * Variable: path
+ *
+ * Contains the textual representation of the path as an array.
+ */
+mxPath.prototype.path = null;
+
+/**
+ * Function: isVml
+ *
+ * Returns true if  is vml.
+ */
+mxPath.prototype.isVml = function()
+{
+	return this.format == 'vml';
+};
+
+/**
+ * Function: getPath
+ *
+ * Returns string that represents the path in .
+ */
+mxPath.prototype.getPath = function()
+{
+	return this.path.join('');
+};
+
+/**
+ * Function: setTranslate
+ *
+ * Set the global translation of this path, that is, the origin of the 
+ * coordinate system.
+ * 
+ * Parameters:
+ * 
+ * x - X-coordinate of the new origin.
+ * y - Y-coordinate of the new origin.
+ */
+mxPath.prototype.setTranslate = function(x, y)
+{
+	this.translate = new mxPoint(x, y);
+};
+
+/**
+ * Function: moveTo
+ *
+ * Moves the cursor to (x, y).
+ * 
+ * Parameters:
+ * 
+ * x - X-coordinate of the new cursor location.
+ * y - Y-coordinate of the new cursor location.
+ */
+mxPath.prototype.moveTo = function(x, y)
+{
+	x += this.translate.x;
+	y += this.translate.y;
+	
+	x *= this.scale;
+	y *= this.scale;
+	
+	if (this.isVml())
+	{
+		this.path.push('m ', Math.round(x), ' ', Math.round(y), ' ');
+	}
+	else
+	{
+		this.path.push('M ', x, ' ', y, ' ');
+	}
+};
+	
+/**
+ * Function: lineTo
+ *
+ * Draws a straight line from the current poin to (x, y).
+ * 
+ * Parameters:
+ * 
+ * x - X-coordinate of the endpoint.
+ * y - Y-coordinate of the endpoint.
+ */
+mxPath.prototype.lineTo = function(x, y)
+{
+	x += this.translate.x;
+	y += this.translate.y;
+	
+	x *= this.scale;
+	y *= this.scale;
+	
+	if (this.isVml())
+	{
+		this.path.push('l ', Math.round(x), ' ', Math.round(y), ' ');
+	}
+	else
+	{
+		this.path.push('L ', x, ' ', y, ' ');
+	}
+};
+
+/**
+ * Function: quadTo
+ * 
+ * Draws a quadratic Bézier curve from the current point to (x, y) using
+ * (x1, y1) as the control point.
+ * 
+ * Parameters:
+ * 
+ * x1 - X-coordinate of the control point.
+ * y1 - Y-coordinate of the control point.
+ * x - X-coordinate of the endpoint. 
+ * y - Y-coordinate of the endpoint.
+ */
+mxPath.prototype.quadTo = function(x1, y1, x, y)
+{
+	x1 += this.translate.x;
+	y1 += this.translate.y;
+	
+	x1 *= this.scale;
+	y1 *= this.scale;
+	
+	x += this.translate.x;
+	y += this.translate.y;
+	
+	x *= this.scale;
+	y *= this.scale;
+	
+	if (this.isVml())
+	{
+		this.path.push('c ', Math.round(x1), ' ', Math.round(y1), ' ', Math.round(x), ' ',
+			Math.round(y), ' ', Math.round(x), ' ', Math.round(y), ' ');
+	}
+	else
+	{
+		this.path.push('Q ', x1, ' ', y1, ' ', x, ' ', y, ' ');
+	}
+};
+
+/**
+ * Function: curveTo
+ *
+ * Draws a cubic Bézier curve from the current point to (x, y) using
+ * (x1, y1) as the control point at the beginning of the curve and (x2, y2)
+ * as the control point at the end of the curve.
+ * 
+ * Parameters:
+ * 
+ * x1 - X-coordinate of the first control point.
+ * y1 - Y-coordinate of the first control point.
+ * x2 - X-coordinate of the second control point.
+ * y2 - Y-coordinate of the second control point.
+ * x - X-coordinate of the endpoint. 
+ * y - Y-coordinate of the endpoint.
+ */
+mxPath.prototype.curveTo = function(x1, y1, x2, y2, x, y)
+{
+	x1 += this.translate.x;
+	y1 += this.translate.y;
+	
+	x1 *= this.scale;
+	y1 *= this.scale;
+	
+	x2 += this.translate.x;
+	y2 += this.translate.y;
+	
+	x2 *= this.scale;
+	y2 *= this.scale;
+	
+	x += this.translate.x;
+	y += this.translate.y;
+	
+	x *= this.scale;
+	y *= this.scale;
+	
+	if (this.isVml())
+	{
+		this.path.push('c ', Math.round(x1), ' ', Math.round(y1), ' ', Math.round(x2),
+			' ', Math.round(y2), ' ', Math.round(x), ' ', Math.round(y), ' ');
+	}
+	else
+	{
+		this.path.push('C ', x1, ' ', y1, ' ', x2,
+			' ', y2, ' ', x, ' ', y, ' ');
+	}
+};
+
+/**
+ * Function: addPath
+ *
+ * Adds the given path.
+ */
+mxPath.prototype.addPath = function(path)
+{
+	this.path = this.path.concat(path.path);
+};
+
+/**
+ * Function: write
+ *
+ * Writes directly into the path. This bypasses all conversions.
+ */
+mxPath.prototype.write = function(string)
+{
+	this.path.push(string, ' ');
+};
+
+/**
+ * Function: end
+ *
+ * Ends the path.
+ */
+mxPath.prototype.end = function()
+{
+	if (this.format == 'vml')
+	{
+		this.path.push('e');
+	}
+};
+
+/**
+ * Function: close
+ *
+ * Closes the path.
+ */
+mxPath.prototype.close = function()
+{
+	if (this.format == 'vml')
+	{
+		this.path.push('x e');
+	}
+	else
+	{
+		this.path.push('Z');
+	}
+};
+/**
+ * $Id: mxPopupMenu.js,v 1.37 2012-04-22 10:16:23 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxPopupMenu
+ * 
+ * Event handler that pans and creates popupmenus. To use the left
+ * mousebutton for panning without interfering with cell moving and
+ * resizing, use  and . For grid size
+ * steps while panning, use . This handler is built-into
+ *  and enabled using .
+ * 
+ * Constructor: mxPopupMenu
+ * 
+ * Constructs an event handler that creates a popupmenu. The
+ * event handler is not installed anywhere in this ctor.
+ * 
+ * Event: mxEvent.SHOW
+ *
+ * Fires after the menu has been shown in .
+ */
+function mxPopupMenu(factoryMethod)
+{
+	this.factoryMethod = factoryMethod;
+	
+	if (factoryMethod != null)
+	{
+		this.init();
+	}
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxPopupMenu.prototype = new mxEventSource();
+mxPopupMenu.prototype.constructor = mxPopupMenu;
+
+/**
+ * Variable: submenuImage
+ * 
+ * URL of the image to be used for the submenu icon.
+ */
+mxPopupMenu.prototype.submenuImage = mxClient.imageBasePath + '/submenu.gif';
+
+/**
+ * Variable: zIndex
+ * 
+ * Specifies the zIndex for the popupmenu and its shadow. Default is 1006.
+ */
+mxPopupMenu.prototype.zIndex = 10006;
+
+/**
+ * Variable: factoryMethod
+ * 
+ * Function that is used to create the popup menu. The function takes the
+ * current panning handler, the  under the mouse and the mouse
+ * event that triggered the call as arguments.
+ */
+mxPopupMenu.prototype.factoryMethod = null;
+
+/**
+ * Variable: useLeftButtonForPopup
+ * 
+ * Specifies if popupmenus should be activated by clicking the left mouse
+ * button. Default is false.
+ */
+mxPopupMenu.prototype.useLeftButtonForPopup = false;
+
+/**
+ * Variable: enabled
+ * 
+ * Specifies if events are handled. Default is true.
+ */
+mxPopupMenu.prototype.enabled = true;
+
+/**
+ * Variable: itemCount
+ * 
+ * Contains the number of times  has been called for a new menu.
+ */
+mxPopupMenu.prototype.itemCount = 0;
+
+/**
+ * Variable: autoExpand
+ * 
+ * Specifies if submenus should be expanded on mouseover. Default is false.
+ */
+mxPopupMenu.prototype.autoExpand = false;
+
+/**
+ * Variable: smartSeparators
+ * 
+ * Specifies if separators should only be added if a menu item follows them.
+ * Default is false.
+ */
+mxPopupMenu.prototype.smartSeparators = false;
+
+/**
+ * Variable: labels
+ * 
+ * Specifies if any labels should be visible. Default is true.
+ */
+mxPopupMenu.prototype.labels = true;
+
+/**
+ * Function: init
+ * 
+ * Initializes the shapes required for this vertex handler.
+ */
+mxPopupMenu.prototype.init = function()
+{
+	// Adds the inner table
+	this.table = document.createElement('table');
+	this.table.className = 'mxPopupMenu';
+	
+	this.tbody = document.createElement('tbody');
+	this.table.appendChild(this.tbody);
+
+	// Adds the outer div
+	this.div = document.createElement('div');
+	this.div.className = 'mxPopupMenu';
+	this.div.style.display = 'inline';
+	this.div.style.zIndex = this.zIndex;
+	this.div.appendChild(this.table);
+
+	// Disables the context menu on the outer div
+	mxEvent.disableContextMenu(this.div);
+};
+
+/**
+ * Function: isEnabled
+ * 
+ * Returns true if events are handled. This implementation
+ * returns .
+ */
+mxPopupMenu.prototype.isEnabled = function()
+{
+	return this.enabled;
+};
+	
+/**
+ * Function: setEnabled
+ * 
+ * Enables or disables event handling. This implementation
+ * updates .
+ */
+mxPopupMenu.prototype.setEnabled = function(enabled)
+{
+	this.enabled = enabled;
+};
+
+/**
+ * Function: isPopupTrigger
+ * 
+ * Returns true if the given event is a popupmenu trigger for the optional
+ * given cell.
+ * 
+ * Parameters:
+ * 
+ * me -  that represents the mouse event.
+ */
+mxPopupMenu.prototype.isPopupTrigger = function(me)
+{
+	return me.isPopupTrigger() || (this.useLeftButtonForPopup &&
+		mxEvent.isLeftMouseButton(me.getEvent()));
+};
+
+/**
+ * Function: addItem
+ * 
+ * Adds the given item to the given parent item. If no parent item is specified
+ * then the item is added to the top-level menu. The return value may be used
+ * as the parent argument, ie. as a submenu item. The return value is the table
+ * row that represents the item.
+ * 
+ * Paramters:
+ * 
+ * title - String that represents the title of the menu item.
+ * image - Optional URL for the image icon.
+ * funct - Function associated that takes a mouseup or touchend event.
+ * parent - Optional item returned by .
+ * iconCls - Optional string that represents the CSS class for the image icon.
+ * IconsCls is ignored if image is given.
+ * enabled - Optional boolean indicating if the item is enabled. Default is true.
+ */
+mxPopupMenu.prototype.addItem = function(title, image, funct, parent, iconCls, enabled)
+{
+	parent = parent || this;
+	this.itemCount++;
+	
+	// Smart separators only added if element contains items
+	if (parent.willAddSeparator)
+	{
+		if (parent.containsItems)
+		{
+			this.addSeparator(parent, true);
+		}
+
+		parent.willAddSeparator = false;
+	}
+
+	parent.containsItems = true;
+	var tr = document.createElement('tr');
+	tr.className = 'mxPopupMenuItem';
+	var col1 = document.createElement('td');
+	col1.className = 'mxPopupMenuIcon';
+	
+	// Adds the given image into the first column
+	if (image != null)
+	{
+		var img = document.createElement('img');
+		img.src = image;
+		col1.appendChild(img);
+	}
+	else if (iconCls != null)
+	{
+		var div = document.createElement('div');
+		div.className = iconCls;
+		col1.appendChild(div);
+	}
+	
+	tr.appendChild(col1);
+	
+	if (this.labels)
+	{
+		var col2 = document.createElement('td');
+		col2.className = 'mxPopupMenuItem' +
+			((enabled != null && !enabled) ? ' disabled' : '');
+		mxUtils.write(col2, title);
+		col2.align = 'left';
+		tr.appendChild(col2);
+	
+		var col3 = document.createElement('td');
+		col3.className = 'mxPopupMenuItem' +
+			((enabled != null && !enabled) ? ' disabled' : '');
+		col3.style.paddingRight = '6px';
+		col3.style.textAlign = 'right';
+		
+		tr.appendChild(col3);
+		
+		if (parent.div == null)
+		{
+			this.createSubmenu(parent);
+		}
+	}
+	
+	parent.tbody.appendChild(tr);
+
+	if (enabled == null || enabled)
+	{
+		var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
+		var mm = (mxClient.IS_TOUCH) ? 'touchmove' : 'mousemove';
+		var mu = (mxClient.IS_TOUCH) ? 'touchend' : 'mouseup';
+		
+		// Consumes the event on mouse down
+		mxEvent.addListener(tr, md, mxUtils.bind(this, function(evt)
+		{
+			this.eventReceiver = tr;
+			
+			if (parent.activeRow != tr && parent.activeRow != parent)
+			{
+				if (parent.activeRow != null &&
+					parent.activeRow.div.parentNode != null)
+				{
+					this.hideSubmenu(parent);
+				}
+				
+				if (tr.div != null)
+				{
+					this.showSubmenu(parent, tr);
+					parent.activeRow = tr;
+				}
+			}
+			
+			mxEvent.consume(evt);
+		}));
+		
+		mxEvent.addListener(tr, mm, mxUtils.bind(this, function(evt)
+		{
+			if (parent.activeRow != tr && parent.activeRow != parent)
+			{
+				if (parent.activeRow != null &&
+					parent.activeRow.div.parentNode != null)
+				{
+					this.hideSubmenu(parent);
+				}
+				
+				if (this.autoExpand && tr.div != null)
+				{
+					this.showSubmenu(parent, tr);
+					parent.activeRow = tr;
+				}
+			}
+	
+			// Sets hover style because TR in IE doesn't have hover
+			tr.className = 'mxPopupMenuItemHover';
+		}));
+	
+		mxEvent.addListener(tr, mu, mxUtils.bind(this, function(evt)
+		{
+			// EventReceiver avoids clicks on a submenu item
+			// which has just been shown in the mousedown
+			if (this.eventReceiver == tr)
+			{
+				if (parent.activeRow != tr)
+				{
+					this.hideMenu();
+				}
+				
+				if (funct != null)
+				{
+					funct(evt);
+				}
+			}
+			
+			this.eventReceiver = null;
+			mxEvent.consume(evt);
+		}));
+	
+		// Resets hover style because TR in IE doesn't have hover
+		mxEvent.addListener(tr, 'mouseout',
+			mxUtils.bind(this, function(evt)
+			{
+				tr.className = 'mxPopupMenuItem';
+			})
+		);
+	}
+	
+	return tr;
+};
+
+/**
+ * Function: createSubmenu
+ * 
+ * Creates the nodes required to add submenu items inside the given parent
+ * item. This is called in  if a parent item is used for the first
+ * time. This adds various DOM nodes and a  to the parent.
+ * 
+ * Parameters:
+ * 
+ * parent - An item returned by .
+ */
+mxPopupMenu.prototype.createSubmenu = function(parent)
+{
+	parent.table = document.createElement('table');
+	parent.table.className = 'mxPopupMenu';
+
+	parent.tbody = document.createElement('tbody');
+	parent.table.appendChild(parent.tbody);
+
+	parent.div = document.createElement('div');
+	parent.div.className = 'mxPopupMenu';
+
+	parent.div.style.position = 'absolute';
+	parent.div.style.display = 'inline';
+	parent.div.style.zIndex = this.zIndex;
+	
+	parent.div.appendChild(parent.table);
+	
+	var img = document.createElement('img');
+	img.setAttribute('src', this.submenuImage);
+	
+	// Last column of the submenu item in the parent menu
+	td = parent.firstChild.nextSibling.nextSibling;
+	td.appendChild(img);
+};
+
+/**
+ * Function: showSubmenu
+ * 
+ * Shows the submenu inside the given parent row.
+ */
+mxPopupMenu.prototype.showSubmenu = function(parent, row)
+{
+	if (row.div != null)
+	{
+		row.div.style.left = (parent.div.offsetLeft +
+			row.offsetLeft+row.offsetWidth - 1) + 'px';
+		row.div.style.top = (parent.div.offsetTop+row.offsetTop) + 'px';
+		document.body.appendChild(row.div);
+		
+		// Moves the submenu to the left side if there is no space
+		var left = parseInt(row.div.offsetLeft);
+		var width = parseInt(row.div.offsetWidth);
+		
+		var b = document.body;
+		var d = document.documentElement;
+		
+		var right = (b.scrollLeft || d.scrollLeft) + (b.clientWidth || d.clientWidth);
+		
+		if (left + width > right)
+		{
+			row.div.style.left = (parent.div.offsetLeft - width +
+				((mxClient.IS_IE) ? 6 : -6)) + 'px';
+		}
+		
+		mxUtils.fit(row.div);
+	}
+};
+
+/**
+ * Function: addSeparator
+ * 
+ * Adds a horizontal separator in the given parent item or the top-level menu
+ * if no parent is specified.
+ * 
+ * Parameters:
+ * 
+ * parent - Optional item returned by .
+ * force - Optional boolean to ignore . Default is false.
+ */
+mxPopupMenu.prototype.addSeparator = function(parent, force)
+{
+	parent = parent || this;
+	
+	if (this.smartSeparators && !force)
+	{
+		parent.willAddSeparator = true;
+	}
+	else if (parent.tbody != null)
+	{
+		parent.willAddSeparator = false;
+		var tr = document.createElement('tr');
+		
+		var col1 = document.createElement('td');
+		col1.className = 'mxPopupMenuIcon';
+		col1.style.padding = '0 0 0 0px';
+		
+		tr.appendChild(col1);
+		
+		var col2 = document.createElement('td');
+		col2.style.padding = '0 0 0 0px';
+		col2.setAttribute('colSpan', '2');
+	
+		var hr = document.createElement('hr');
+		hr.setAttribute('size', '1');
+		col2.appendChild(hr);
+		
+		tr.appendChild(col2);
+		
+		parent.tbody.appendChild(tr);
+	}
+};
+
+/**
+ * Function: popup
+ * 
+ * Shows the popup menu for the given event and cell.
+ * 
+ * Example:
+ * 
+ * (code)
+ * graph.panningHandler.popup = function(x, y, cell, evt)
+ * {
+ *   mxUtils.alert('Hello, World!');
+ * }
+ * (end)
+ */
+mxPopupMenu.prototype.popup = function(x, y, cell, evt)
+{
+	if (this.div != null && this.tbody != null && this.factoryMethod != null)
+	{
+		this.div.style.left = x + 'px';
+		this.div.style.top = y + 'px';
+		
+		// Removes all child nodes from the existing menu
+		while (this.tbody.firstChild != null)
+		{
+			mxEvent.release(this.tbody.firstChild);
+			this.tbody.removeChild(this.tbody.firstChild);
+		}
+		
+		this.itemCount = 0;
+		this.factoryMethod(this, cell, evt);
+		
+		if (this.itemCount > 0)
+		{
+			this.showMenu();
+			this.fireEvent(new mxEventObject(mxEvent.SHOW));
+		}
+	}
+};
+
+/**
+ * Function: isMenuShowing
+ * 
+ * Returns true if the menu is showing.
+ */
+mxPopupMenu.prototype.isMenuShowing = function()
+{
+	return this.div != null && this.div.parentNode == document.body;
+};
+
+/**
+ * Function: showMenu
+ * 
+ * Shows the menu.
+ */
+mxPopupMenu.prototype.showMenu = function()
+{
+	// Disables filter-based shadow in IE9 standards mode
+	if (document.documentMode >= 9)
+	{
+		this.div.style.filter = 'none';
+	}
+	
+	// Fits the div inside the viewport
+	document.body.appendChild(this.div);
+	mxUtils.fit(this.div);
+};
+
+/**
+ * Function: hideMenu
+ * 
+ * Removes the menu and all submenus.
+ */
+mxPopupMenu.prototype.hideMenu = function()
+{
+	if (this.div != null)
+	{
+		if (this.div.parentNode != null)
+		{
+			this.div.parentNode.removeChild(this.div);
+		}
+		
+		this.hideSubmenu(this);
+		this.containsItems = false;
+	}
+};
+
+/**
+ * Function: hideSubmenu
+ * 
+ * Removes all submenus inside the given parent.
+ * 
+ * Parameters:
+ * 
+ * parent - An item returned by .
+ */
+mxPopupMenu.prototype.hideSubmenu = function(parent)
+{
+	if (parent.activeRow != null)
+	{
+		this.hideSubmenu(parent.activeRow);
+		
+		if (parent.activeRow.div.parentNode != null)
+		{
+			parent.activeRow.div.parentNode.removeChild(parent.activeRow.div);
+		}
+		
+		parent.activeRow = null;
+	}
+};
+
+/**
+ * Function: destroy
+ * 
+ * Destroys the handler and all its resources and DOM nodes.
+ */
+mxPopupMenu.prototype.destroy = function()
+{
+	if (this.div != null)
+	{
+		mxEvent.release(this.div);
+		
+		if (this.div.parentNode != null)
+		{
+			this.div.parentNode.removeChild(this.div);
+		}
+		
+		this.div = null;
+	}
+};
+/**
+ * $Id: mxAutoSaveManager.js,v 1.9 2010-09-16 09:10:21 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxAutoSaveManager
+ * 
+ * Manager for automatically saving diagrams. The  hook must be
+ * implemented.
+ * 
+ * Example:
+ * 
+ * (code)
+ * var mgr = new mxAutoSaveManager(editor.graph);
+ * mgr.save = function()
+ * {
+ *   mxLog.show();
+ *   mxLog.debug('save');
+ * };
+ * (end)
+ * 
+ * Constructor: mxAutoSaveManager
+ *
+ * Constructs a new automatic layout for the given graph.
+ *
+ * Arguments:
+ * 
+ * graph - Reference to the enclosing graph. 
+ */
+function mxAutoSaveManager(graph)
+{
+	// Notifies the manager of a change
+	this.changeHandler = mxUtils.bind(this, function(sender, evt)
+	{
+		if (this.isEnabled())
+		{
+			this.graphModelChanged(evt.getProperty('edit').changes);
+		}
+	});
+
+	this.setGraph(graph);
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxAutoSaveManager.prototype = new mxEventSource();
+mxAutoSaveManager.prototype.constructor = mxAutoSaveManager;
+
+/**
+ * Variable: graph
+ * 
+ * Reference to the enclosing .
+ */
+mxAutoSaveManager.prototype.graph = null;
+
+/**
+ * Variable: autoSaveDelay
+ * 
+ * Minimum amount of seconds between two consecutive autosaves. Eg. a
+ * value of 1 (s) means the graph is not stored more than once per second.
+ * Default is 10.
+ */
+mxAutoSaveManager.prototype.autoSaveDelay = 10;
+
+/**
+ * Variable: autoSaveThrottle
+ * 
+ * Minimum amount of seconds between two consecutive autosaves triggered by
+ * more than  changes within a timespan of less than
+ *  seconds. Eg. a value of 1 (s) means the graph is not
+ * stored more than once per second even if there are more than
+ *  changes within that timespan. Default is 2.
+ */
+mxAutoSaveManager.prototype.autoSaveThrottle = 2;
+
+/**
+ * Variable: autoSaveThreshold
+ * 
+ * Minimum amount of ignored changes before an autosave. Eg. a value of 2
+ * means after 2 change of the graph model the autosave will trigger if the
+ * condition below is true. Default is 5.
+ */
+mxAutoSaveManager.prototype.autoSaveThreshold = 5;
+
+/**
+ * Variable: ignoredChanges
+ * 
+ * Counter for ignored changes in autosave.
+ */
+mxAutoSaveManager.prototype.ignoredChanges = 0;
+
+/**
+ * Variable: lastSnapshot
+ * 
+ * Used for autosaving. See .
+ */
+mxAutoSaveManager.prototype.lastSnapshot = 0;
+
+/**
+ * Variable: enabled
+ * 
+ * Specifies if event handling is enabled. Default is true.
+ */
+mxAutoSaveManager.prototype.enabled = true;
+
+/**
+ * Variable: changeHandler
+ * 
+ * Holds the function that handles graph model changes.
+ */
+mxAutoSaveManager.prototype.changeHandler = null;
+
+/**
+ * Function: isEnabled
+ * 
+ * Returns true if events are handled. This implementation
+ * returns .
+ */
+mxAutoSaveManager.prototype.isEnabled = function()
+{
+	return this.enabled;
+};
+
+/**
+ * Function: setEnabled
+ * 
+ * Enables or disables event handling. This implementation
+ * updates .
+ * 
+ * Parameters:
+ * 
+ * enabled - Boolean that specifies the new enabled state.
+ */
+mxAutoSaveManager.prototype.setEnabled = function(value)
+{
+	this.enabled = value;
+};
+
+/**
+ * Function: setGraph
+ * 
+ * Sets the graph that the layouts operate on.
+ */
+mxAutoSaveManager.prototype.setGraph = function(graph)
+{
+	if (this.graph != null)
+	{
+		this.graph.getModel().removeListener(this.changeHandler);
+	}
+	
+	this.graph = graph;
+	
+	if (this.graph != null)
+	{
+		this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler);
+	}
+};
+
+/**
+ * Function: save
+ * 
+ * Empty hook that is called if the graph should be saved.
+ */
+mxAutoSaveManager.prototype.save = function()
+{
+	// empty
+};
+
+/**
+ * Function: graphModelChanged
+ * 
+ * Invoked when the graph model has changed.
+ */
+mxAutoSaveManager.prototype.graphModelChanged = function(changes)
+{
+	var now = new Date().getTime();
+	var dt = (now - this.lastSnapshot) / 1000;
+	
+	if (dt > this.autoSaveDelay ||
+		(this.ignoredChanges >= this.autoSaveThreshold &&
+		 dt > this.autoSaveThrottle))
+	{
+		this.save();
+		this.reset();
+	}
+	else
+	{
+		// Increments the number of ignored changes
+		this.ignoredChanges++;
+	}
+};
+
+/**
+ * Function: reset
+ * 
+ * Resets all counters.
+ */
+mxAutoSaveManager.prototype.reset = function()
+{
+	this.lastSnapshot = new Date().getTime();
+	this.ignoredChanges = 0;
+};
+
+/**
+ * Function: destroy
+ * 
+ * Removes all handlers from the  and deletes the reference to it.
+ */
+mxAutoSaveManager.prototype.destroy = function()
+{
+	this.setGraph(null);
+};
+/**
+ * $Id: mxAnimation.js,v 1.2 2010-03-19 12:53:29 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ *
+ * Class: mxAnimation
+ * 
+ * Implements a basic animation in JavaScript.
+ * 
+ * Constructor: mxAnimation
+ * 
+ * Constructs an animation.
+ * 
+ * Parameters:
+ * 
+ * graph - Reference to the enclosing .
+ */
+function mxAnimation(delay)
+{
+	this.delay = (delay != null) ? delay : 20;
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxAnimation.prototype = new mxEventSource();
+mxAnimation.prototype.constructor = mxAnimation;
+
+/**
+ * Variable: delay
+ * 
+ * Specifies the delay between the animation steps. Defaul is 30ms.
+ */
+mxAnimation.prototype.delay = null;
+
+/**
+ * Variable: thread
+ * 
+ * Reference to the thread while the animation is running.
+ */
+mxAnimation.prototype.thread = null;
+
+/**
+ * Function: startAnimation
+ *
+ * Starts the animation by repeatedly invoking updateAnimation.
+ */
+mxAnimation.prototype.startAnimation = function()
+{
+	if (this.thread == null)
+	{
+		this.thread = window.setInterval(mxUtils.bind(this, this.updateAnimation), this.delay);
+	}
+};
+
+/**
+ * Function: updateAnimation
+ *
+ * Hook for subclassers to implement the animation. Invoke stopAnimation
+ * when finished, startAnimation to resume. This is called whenever the
+ * timer fires and fires an mxEvent.EXECUTE event with no properties.
+ */
+mxAnimation.prototype.updateAnimation = function()
+{
+	this.fireEvent(new mxEventObject(mxEvent.EXECUTE));
+};
+
+/**
+ * Function: stopAnimation
+ *
+ * Stops the animation by deleting the timer and fires an .
+ */
+mxAnimation.prototype.stopAnimation = function()
+{
+	if (this.thread != null)
+	{
+		window.clearInterval(this.thread);
+		this.thread = null;
+		this.fireEvent(new mxEventObject(mxEvent.DONE));
+	}
+};
+/**
+ * $Id: mxMorphing.js,v 1.4 2010-06-03 13:37:07 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ *
+ * Class: mxMorphing
+ * 
+ * Implements animation for morphing cells. Here is an example of
+ * using this class for animating the result of a layout algorithm:
+ * 
+ * (code)
+ * graph.getModel().beginUpdate();
+ * try
+ * {
+ *   var circleLayout = new mxCircleLayout(graph);
+ *   circleLayout.execute(graph.getDefaultParent());
+ * }
+ * finally
+ * {
+ *   var morph = new mxMorphing(graph);
+ *   morph.addListener(mxEvent.DONE, function()
+ *   {
+ *     graph.getModel().endUpdate();
+ *   });
+ *   
+ *   morph.startAnimation();
+ * }
+ * (end)
+ * 
+ * Constructor: mxMorphing
+ * 
+ * Constructs an animation.
+ * 
+ * Parameters:
+ * 
+ * graph - Reference to the enclosing .
+ * steps - Optional number of steps in the morphing animation. Default is 6.
+ * ease - Optional easing constant for the animation. Default is 1.5.
+ * delay - Optional delay between the animation steps. Passed to .
+ */
+function mxMorphing(graph, steps, ease, delay)
+{
+	mxAnimation.call(this, delay);
+	this.graph = graph;
+	this.steps = (steps != null) ? steps : 6;
+	this.ease = (ease != null) ? ease : 1.5;
+};
+
+/**
+ * Extends mxEventSource.
+ */
+mxMorphing.prototype = new mxAnimation();
+mxMorphing.prototype.constructor = mxMorphing;
+
+/**
+ * Variable: graph
+ * 
+ * Specifies the delay between the animation steps. Defaul is 30ms.
+ */
+mxMorphing.prototype.graph = null;
+
+/**
+ * Variable: steps
+ * 
+ * Specifies the maximum number of steps for the morphing.
+ */
+mxMorphing.prototype.steps = null;
+
+/**
+ * Variable: step
+ * 
+ * Contains the current step.
+ */
+mxMorphing.prototype.step = 0;
+
+/**
+ * Variable: ease
+ * 
+ * Ease-off for movement towards the given vector. Larger values are
+ * slower and smoother. Default is 4.
+ */
+mxMorphing.prototype.ease = null;
+
+/**
+ * Variable: cells
+ * 
+ * Optional array of cells to be animated. If this is not specified
+ * then all cells are checked and animated if they have been moved
+ * in the current transaction.
+ */
+mxMorphing.prototype.cells = null;
+
+/**
+ * Function: updateAnimation
+ *
+ * Animation step.
+ */
+mxMorphing.prototype.updateAnimation = function()
+{
+	var move = new mxCellStatePreview(this.graph);
+
+	if (this.cells != null)
+	{
+		// Animates the given cells individually without recursion
+		for (var i = 0; i < this.cells.length; i++)
+		{
+			this.animateCell(cells[i], move, false);
+		}
+	}
+	else
+	{
+		// Animates all changed cells by using recursion to find
+		// the changed cells but not for the animation itself
+		this.animateCell(this.graph.getModel().getRoot(), move, true);
+	}
+	
+	this.show(move);
+	
+	if (move.isEmpty() ||
+		this.step++ >= this.steps)
+	{
+		this.stopAnimation();
+	}
+};
+
+/**
+ * Function: show
+ *
+ * Shows the changes in the given .
+ */
+mxMorphing.prototype.show = function(move)
+{
+	move.show();
+};
+
+/**
+ * Function: animateCell
+ *
+ * Animates the given cell state using .
+ */
+mxMorphing.prototype.animateCell = function(cell, move, recurse)
+{
+	var state = this.graph.getView().getState(cell);
+	var delta = null;
+
+	if (state != null)
+	{
+		// Moves the animated state from where it will be after the model
+		// change by subtracting the given delta vector from that location
+		delta = this.getDelta(state);
+
+		if (this.graph.getModel().isVertex(cell) &&
+			(delta.x != 0 || delta.y != 0))
+		{
+			var translate = this.graph.view.getTranslate();
+			var scale = this.graph.view.getScale();
+			
+			delta.x += translate.x * scale;
+			delta.y += translate.y * scale;
+			
+			move.moveState(state, -delta.x / this.ease, -delta.y / this.ease);
+		}
+	}
+	
+	if (recurse && !this.stopRecursion(state, delta))
+	{
+		var childCount = this.graph.getModel().getChildCount(cell);
+
+		for (var i = 0; i < childCount; i++)
+		{
+			this.animateCell(this.graph.getModel().getChildAt(cell, i), move, recurse);
+		}
+	}
+};
+
+/**
+ * Function: stopRecursion
+ *
+ * Returns true if the animation should not recursively find more
+ * deltas for children if the given parent state has been animated.
+ */
+mxMorphing.prototype.stopRecursion = function(state, delta)
+{
+	return delta != null && (delta.x != 0 || delta.y != 0);
+};
+
+/**
+ * Function: getDelta
+ *
+ * Returns the vector between the current rendered state and the future
+ * location of the state after the display will be updated.
+ */
+mxMorphing.prototype.getDelta = function(state)
+{
+	var origin = this.getOriginForCell(state.cell);
+	var translate = this.graph.getView().getTranslate();
+	var scale = this.graph.getView().getScale();
+	var current = new mxPoint(
+		state.x / scale - translate.x,
+		state.y / scale - translate.y);
+
+	return new mxPoint(
+		(origin.x - current.x) * scale,
+		(origin.y - current.y) * scale);
+};
+
+/**
+ * Function: getOriginForCell
+ *
+ * Returns the top, left corner of the given cell. TODO: Improve performance
+ * by using caching inside this method as the result per cell never changes
+ * during the lifecycle of this object.
+ */
+mxMorphing.prototype.getOriginForCell = function(cell)
+{
+	var result = null;
+	
+	if (cell != null)
+	{
+		result = this.getOriginForCell(this.graph.getModel().getParent(cell));
+		var geo = this.graph.getCellGeometry(cell);
+		
+		// TODO: Handle offset, relative geometries etc
+		if (geo != null)
+		{
+			result.x += geo.x;
+			result.y += geo.y;
+		}
+	}
+	
+	if (result == null)
+	{
+		var t = this.graph.view.getTranslate();
+		result = new mxPoint(-t.x, -t.y);
+	}
+	
+	return result;
+};
+/**
+ * $Id: mxImageBundle.js,v 1.3 2011-01-20 19:08:11 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxImageBundle
+ *
+ * Maps from keys to base64 encoded images or file locations. All values must
+ * be URLs or use the format data:image/format followed by a comma and the base64
+ * encoded image data, eg. "data:image/gif,XYZ", where XYZ is the base64 encoded
+ * image data.
+ * 
+ * To add a new image bundle to an existing graph, the following code is used:
+ * 
+ * (code)
+ * var bundle = new mxImageBundle(alt);
+ * bundle.putImage('myImage', 'data:image/gif,R0lGODlhEAAQAMIGAAAAAICAAICAgP' +
+ *   '//AOzp2O3r2////////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgAHACwAAAAA' +
+ *   'EAAQAAADTXi63AowynnAMDfjPUDlnAAJhmeBFxAEloliKltWmiYCQvfVr6lBPB1ggxN1hi' +
+ *   'laSSASFQpIV5HJBDyHpqK2ejVRm2AAgZCdmCGO9CIBADs=', fallback);
+ * graph.addImageBundle(bundle);
+ * (end);
+ * 
+ * Alt is an optional boolean (default is false) that specifies if the value
+ * or the fallback should be returned in .
+ * 
+ * The image can then be referenced in any cell style using image=myImage.
+ * If you are using mxOutline, you should use the same image bundles in the
+ * graph that renders the outline.
+ * 
+ * The keys for images are resolved in  and
+ * turned into a data URI if the returned value has a short data URI format
+ * as specified above.
+ * 
+ * A typical value for the fallback is a MTHML link as defined in RFC 2557.
+ * Note that this format requires a file to be dynamically created on the
+ * server-side, or the page that contains the graph to be modified to contain
+ * the resources, this can be done by adding a comment that contains the
+ * resource in the HEAD section of the page after the title tag.
+ * 
+ * This type of fallback mechanism should be used in IE6 and IE7. IE8 does
+ * support data URIs, but the maximum size is limited to 32 KB, which means
+ * all data URIs should be limited to 32 KB.
+ */
+function mxImageBundle(alt)
+{
+	this.images = [];
+	this.alt = (alt != null) ? alt : false;
+};
+
+/**
+ * Variable: images
+ * 
+ * Maps from keys to images.
+ */
+mxImageBundle.prototype.images = null;
+
+/**
+ * Variable: alt
+ * 
+ * Specifies if the fallback representation should be returned.
+ */
+mxImageBundle.prototype.images = null;
+
+/**
+ * Function: putImage
+ * 
+ * Adds the specified entry to the map. The entry is an object with a value and
+ * fallback property as specified in the arguments.
+ */
+mxImageBundle.prototype.putImage = function(key, value, fallback)
+{
+	this.images[key] = {value: value, fallback: fallback};
+};
+
+/**
+ * Function: getImage
+ * 
+ * Returns the value for the given key. This returns the value
+ * or fallback, depending on . The fallback is returned if
+ *  is true, the value is returned otherwise.
+ */
+mxImageBundle.prototype.getImage = function(key)
+{
+	var result = null;
+	
+	if (key != null)
+	{
+		var img = this.images[key];
+		
+		if (img != null)
+		{
+			result = (this.alt) ? img.fallback : img.value;
+		}
+	}
+	
+	return result;
+};
+/**
+ * $Id: mxImageExport.js,v 1.44 2012-05-21 10:17:17 gaudenz Exp $
+ * Copyright (c) 2006-2010, JGraph Ltd
+ */
+/**
+ * Class: mxImageExport
+ * 
+ * Creates a new image export instance to be used with an export canvas. Here
+ * is an example that uses this class to create an image via a backend using
+ * .
+ * 
+ * (code)
+ * var xmlDoc = mxUtils.createXmlDocument();
+ * var root = xmlDoc.createElement('output');
+ * xmlDoc.appendChild(root);
+ * 
+ * var xmlCanvas = new mxXmlCanvas2D(root);
+ * var imgExport = new mxImageExport();
+ * imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
+ * 
+ * var bounds = graph.getGraphBounds();
+ * var w = Math.ceil(bounds.x + bounds.width);
+ * var h = Math.ceil(bounds.y + bounds.height);
+ * 
+ * var xml = mxUtils.getXml(root);
+ * new mxXmlRequest('export', 'format=png&w=' + w +
+ * 		'&h=' + h + '&bg=#F9F7ED&xml=' + encodeURIComponent(xml))
+ * 		.simulate(document, '_blank');
+ * (end)
+ * 
+ * In order to export images for a graph whose container is not visible or not
+ * part of the DOM, the following workaround can be used to compute the size of
+ * the labels.
+ * 
+ * (code)
+ * mxText.prototype.getTableSize = function(table)
+ * {
+ *   var oldParent = table.parentNode;
+ *   
+ *   document.body.appendChild(table);
+ *   var size = new mxRectangle(0, 0, table.offsetWidth, table.offsetHeight);
+ *   oldParent.appendChild(table);
+ *   
+ *   return size;
+ * };
+ * (end) 
+ * 
+ * Constructor: mxImageExport
+ * 
+ * Constructs a new image export.
+ */
+function mxImageExport()
+{
+	this.initShapes();
+	this.initMarkers();
+};
+
+/**
+ * Variable: includeOverlays
+ * 
+ * Specifies if overlays should be included in the export. Default is false.
+ */
+mxImageExport.prototype.includeOverlays = false;
+
+/**
+ * Variable: glassSize
+ * 
+ * Reference to the thread while the animation is running.
+ */
+mxImageExport.prototype.glassSize = 0.4;
+
+/**
+ * Variable: shapes
+ * 
+ * Holds implementations for the built-in shapes.
+ */
+mxImageExport.prototype.shapes = null;
+
+/**
+ * Variable: markers
+ * 
+ * Holds implementations for the built-in markers.
+ */
+mxImageExport.prototype.markers = null;
+
+/**
+ * Function: drawState
+ * 
+ * Draws the given state and all its descendants to the given canvas.
+ */
+mxImageExport.prototype.drawState = function(state, canvas)
+{
+	if (state != null)
+	{
+		if (state.shape != null)
+		{
+			var shape = (state.shape.stencil != null) ?
+				state.shape.stencil :
+				this.shapes[state.style[mxConstants.STYLE_SHAPE]];
+
+			if (shape == null)
+			{
+				// Checks if there is a custom shape
+				if (typeof(state.shape.redrawPath) == 'function')
+				{
+					shape = this.createShape(state, canvas);
+				}
+				// Uses a rectangle for all vertices where no shape can be found
+				else if (state.view.graph.getModel().isVertex(state.cell))
+				{
+					shape = this.shapes['rectangle'];
+				}
+			}
+			
+			if (shape != null)
+			{
+				this.drawShape(state, canvas, shape);
+
+				if (this.includeOverlays)
+				{
+					this.drawOverlays(state, canvas);
+				}
+			}
+		}
+		
+		var graph = state.view.graph;
+		var childCount = graph.model.getChildCount(state.cell);
+		
+		for (var i = 0; i < childCount; i++)
+		{
+			var childState = graph.view.getState(graph.model.getChildAt(state.cell, i));
+			this.drawState(childState, canvas);
+		}
+	}
+};
+
+/**
+ * Function: createShape
+ * 
+ * Creates a shape wrapper for the custom shape in the given cell state and
+ * links its output to the given canvas.
+ */
+mxImageExport.prototype.createShape = function(state, canvas)
+{
+	return {
+		drawShape: function(canvas, state, bounds, background)
+		{
+			var path =
+			{
+				translate: new mxPoint(bounds.x, bounds.y),
+				moveTo: function(x, y)
+				{
+					canvas.moveTo(this.translate.x + x, this.translate.y + y);
+				},
+				lineTo: function(x, y)
+				{
+					canvas.lineTo(this.translate.x + x, this.translate.y + y);
+				},
+				quadTo: function(x1, y1, x, y)
+				{
+					canvas.quadTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x, this.translate.y + y);
+				},
+				curveTo: function(x1, y1, x2, y2, x, y)
+				{
+					canvas.curveTo(this.translate.x + x1, this.translate.y + y1, this.translate.x + x2, this.translate.y + y2, this.translate.x + x, this.translate.y + y);
+				},
+				end: function()
+				{
+					// do nothing
+				},
+				close: function()
+				{
+					canvas.close();
+				}
+			};
+			
+			if (!background)
+			{
+				canvas.fillAndStroke();
+			}
+			
+			// LATER: Remove empty path if shape does not implement foreground, add shadow/clipping
+			canvas.begin();
+			state.shape.redrawPath.call(state.shape, path, bounds.x, bounds.y, bounds.width, bounds.height, !background);
+			
+			if (!background)
+			{
+				canvas.fillAndStroke();
+			}
+			
+			return true;
+		}
+	};
+};
+
+/**
+ * Function: drawOverlays
+ * 
+ * Draws the overlays for the given state.
+ */
+mxImageExport.prototype.drawOverlays = function(state, canvas)
+{
+	if (state.overlays != null)
+	{
+		for (var i = 0; i < state.overlays.length; i++)
+		{
+			if (state.overlays[i].bounds != null)
+			{
+				var bounds = state.overlays[i].bounds;
+				canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, state.overlays[i].image);
+			}
+		}
+	}
+};
+
+/**
+ * Function: drawShape
+ * 
+ * Draws the given state to the given canvas.
+ */
+mxImageExport.prototype.drawShape = function(state, canvas, shape)
+{
+	var rotation = mxUtils.getNumber(state.style, mxConstants.STYLE_ROTATION, 0);
+	var direction = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION, null);
+
+	// Default direction is east (ignored if rotation exists)
+	if (direction != null)
+	{
+		if (direction == 'north')
+		{
+			rotation += 270;
+		}
+		else if (direction == 'west')
+		{
+			rotation += 180;
+		}
+		else if (direction == 'south')
+		{
+			rotation += 90;
+		}
+	}
+
+	// New styles for shape flipping the stencil
+	var flipH = state.style[mxConstants.STYLE_STENCIL_FLIPH];
+	var flipV = state.style[mxConstants.STYLE_STENCIL_FLIPV];
+	
+	if (flipH && flipV)
+	{
+		rotation += 180;
+		flipH = false;
+		flipV = false;
+	}
+
+	// Saves the global state for each cell
+	canvas.save();
+
+	// Adds rotation and horizontal/vertical flipping
+	// FIXME: Rotation and stencil flip only supported for stencil shapes
+	rotation = rotation % 360;
+
+	if (rotation != 0 || flipH || flipV)
+	{
+		canvas.rotate(rotation, flipH, flipV, state.getCenterX(), state.getCenterY());
+	}
+
+	// Note: Overwritten in mxStencil.paintShape (can depend on aspect)
+	var scale = state.view.scale;
+	var sw = mxUtils.getNumber(state.style, mxConstants.STYLE_STROKEWIDTH, 1) * scale;
+	canvas.setStrokeWidth(sw);
+
+	var sw2 = sw / 2;
+	var bg = this.getBackgroundBounds(state);
+	
+	// Stencils will rotate the bounds as required
+	if (state.shape.stencil == null && (direction == 'south' || direction == 'north'))
+	{
+		var dx = (bg.width - bg.height) / 2;
+		bg.x += dx;
+		bg.y += -dx;
+		var tmp = bg.width;
+		bg.width = bg.height;
+		bg.height = tmp;
+	}
+	
+	var bb = new mxRectangle(bg.x - sw2, bg.y - sw2, bg.width + sw, bg.height + sw);
+	var alpha = mxUtils.getValue(state.style, mxConstants.STYLE_OPACITY, 100) / 100;
+
+	var shp = state.style[mxConstants.STYLE_SHAPE];
+	var imageShape = shp == mxConstants.SHAPE_IMAGE;
+	var gradientColor = (imageShape) ? null : mxUtils.getValue(state.style, mxConstants.STYLE_GRADIENTCOLOR);
+	
+	// Converts colors with special keyword none to null
+	if (gradientColor == mxConstants.NONE)
+	{
+		gradientColor = null;
+	}
+
+	var fcKey = (imageShape) ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR; 
+	var fillColor = mxUtils.getValue(state.style, fcKey, null);
+	
+	if (fillColor == mxConstants.NONE)
+	{
+		fillColor = null;
+	}
+
+	var scKey = (imageShape) ? mxConstants.STYLE_IMAGE_BORDER : mxConstants.STYLE_STROKECOLOR; 
+	var strokeColor = mxUtils.getValue(state.style, scKey, null);
+	
+	if (strokeColor == mxConstants.NONE)
+	{
+		strokeColor = null;
+	}
+
+	var glass = (fillColor != null && (shp == mxConstants.SHAPE_LABEL || shp == mxConstants.SHAPE_RECTANGLE));
+	
+	// Draws the shadow if the fillColor is not transparent
+	if (mxUtils.getValue(state.style, mxConstants.STYLE_SHADOW, false))
+	{
+		this.drawShadow(canvas, state, shape, rotation, flipH, flipV, bg, alpha, fillColor != null);
+	}
+	
+	canvas.setAlpha(alpha);
+	
+	// Sets the dashed state
+	if (mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1')
+	{
+		canvas.setDashed(true);
+		
+		// Supports custom dash patterns
+		var dash = state.style['dashPattern'];
+		
+		if (dash != null)
+		{
+			canvas.setDashPattern(dash);
+		}
+	}
+
+	// Draws background and foreground
+	if (strokeColor != null || fillColor != null)
+	{
+		if (strokeColor != null)
+		{
+			canvas.setStrokeColor(strokeColor);
+		}
+		
+		if (fillColor != null)
+		{
+			if (gradientColor != null && gradientColor != 'transparent')
+			{
+				canvas.setGradient(fillColor, gradientColor, bg.x, bg.y, bg.width, bg.height, direction);
+			}
+			else 
+			{
+				canvas.setFillColor(fillColor);
+			}
+		}
+		
+		// Draws background and foreground of shape
+		glass = shape.drawShape(canvas, state, bg, true, false) && glass;
+		shape.drawShape(canvas, state, bg, false, false);
+	}
+
+	// Draws the glass effect
+	// Requires background in generic shape for clipping
+	if (glass && mxUtils.getValue(state.style, mxConstants.STYLE_GLASS, 0) == 1)
+	{
+		this.drawGlass(state, canvas, bb, shape, this.glassSize);
+	}
+	
+	// Draws the image (currently disabled for everything but image and label shapes)
+	if (imageShape || shp == mxConstants.SHAPE_LABEL)
+	{
+		var src = state.view.graph.getImage(state);
+		
+		if (src != null)
+		{
+			var imgBounds = this.getImageBounds(state);
+			
+			if (imgBounds != null)
+			{
+				this.drawImage(state, canvas, imgBounds, src);
+			}
+		}
+	}
+
+	// Restores canvas state
+	canvas.restore();
+
+	// Draws the label (label has separate rotation)
+	var txt = state.text;
+	
+	// Does not use mxCellRenderer.getLabelValue to avoid conversion of HTML entities for VML
+	var label = state.view.graph.getLabel(state.cell);
+	
+	if (txt != null && label != null && label.length > 0)
+	{
+		canvas.save();
+		canvas.setAlpha(mxUtils.getValue(state.style, mxConstants.STYLE_TEXT_OPACITY, 100) / 100);
+		var bounds = new mxRectangle(txt.boundingBox.x, txt.boundingBox.y, txt.boundingBox.width, txt.boundingBox.height);
+		var vert = mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0;
+		
+		// Vertical error offset
+		bounds.y += 2;
+
+		if (vert)
+		{
+			if (txt.dialect != mxConstants.DIALECT_SVG)
+			{
+				var cx = bounds.x + bounds.width / 2;
+				var cy = bounds.y + bounds.height / 2;
+				var tmp = bounds.width;
+				bounds.width = bounds.height;
+				bounds.height = tmp;
+				bounds.x = cx - bounds.width / 2;
+				bounds.y = cy - bounds.height / 2;
+			}
+			else if (txt.dialect == mxConstants.DIALECT_SVG)
+			{
+				// Workarounds for different label bounding boxes (mostly ignoring rotation).
+				// LATER: Fix in mxText so that the bounding box is consistent and rotated.
+				// TODO: Check non-center/middle-aligned vertical labels in VML for IE8.
+				var b = state.y + state.height;
+				var cx = bounds.getCenterX() - state.x;
+				var cy = bounds.getCenterY() - state.y;
+				
+				var y = b - cx - bounds.height / 2;
+				bounds.x = state.x + cy - bounds.width / 2;
+				bounds.y = y;
+				//bounds.x -= state.height / 2 - state.width / 2;
+				//bounds.y -= state.width / 2 - state.height / 2;
+			}
+		}
+		
+		this.drawLabelBackground(state, canvas, bounds, vert);
+		this.drawLabel(state, canvas, bounds, vert, label);
+		canvas.restore();
+	}
+};
+
+/**
+ * Function: drawGlass
+ * 
+ * Draws the given state to the given canvas.
+ */
+mxImageExport.prototype.drawShadow = function(canvas, state, shape, rotation, flipH, flipV, bounds, alpha, filled)
+{
+	// Requires background in generic shape for shadow, looks like only one
+	// fillAndStroke is allowed per current path, try working around that
+	// Computes rotated shadow offset
+	var rad = rotation * Math.PI / 180;
+	var cos = Math.cos(-rad);
+	var sin = Math.sin(-rad);
+	var offset = mxUtils.getRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSET_X, mxConstants.SHADOW_OFFSET_Y), cos, sin);
+	
+	if (flipH)
+	{
+		offset.x *= -1;
+	}
+	
+	if (flipV)
+	{
+		offset.y *= -1;
+	}
+	
+	// TODO: Use save/restore instead of negative offset to restore (requires fix for HTML canvas)
+	canvas.translate(offset.x, offset.y);
+	
+	// Returns true if a shadow has been painted (path has been created)
+	if (shape.drawShape(canvas, state, bounds, true, true))
+	{
+		canvas.setAlpha(mxConstants.SHADOW_OPACITY * alpha);
+		canvas.shadow(mxConstants.SHADOWCOLOR, filled);
+	}
+
+	canvas.translate(-offset.x, -offset.y);
+};
+
+/**
+ * Function: drawGlass
+ * 
+ * Draws the given state to the given canvas.
+ */
+mxImageExport.prototype.drawGlass = function(state, canvas, bounds, shape, size)
+{
+	// LATER: Clipping region should include stroke
+	if (shape.drawShape(canvas, state, bounds, true, false))
+	{
+		canvas.save();
+		canvas.clip();
+		canvas.setGlassGradient(bounds.x, bounds.y, bounds.width, bounds.height);
+	
+		canvas.begin();
+		canvas.moveTo(bounds.x, bounds.y);
+		canvas.lineTo(bounds.x, (bounds.y + bounds.height * size));
+		canvas.quadTo((bounds.x + bounds.width * 0.5),
+				(bounds.y + bounds.height * 0.7), bounds.x + bounds.width,
+				(bounds.y + bounds.height * size));
+		canvas.lineTo(bounds.x + bounds.width, bounds.y);
+		canvas.close();
+
+		canvas.fill();
+		canvas.restore();
+	}
+};
+
+/**
+ * Function: drawImage
+ * 
+ * Draws the given state to the given canvas.
+ */
+mxImageExport.prototype.drawImage = function(state, canvas, bounds, image)
+{
+	var aspect = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_ASPECT, 1) == 1;
+	var flipH = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPH, 0) == 1;
+	var flipV = mxUtils.getValue(state.style, mxConstants.STYLE_IMAGE_FLIPV, 0) == 1;
+	
+	canvas.image(bounds.x, bounds.y, bounds.width, bounds.height, image, aspect, flipH, flipV);
+};
+
+/**
+ * Function: drawLabelBackground
+ * 
+ * Draws background for the label of the given state to the given canvas.
+ */
+mxImageExport.prototype.drawLabelBackground = function(state, canvas, bounds, vert)
+{
+	var stroke = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BORDERCOLOR);
+	var fill = mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_BACKGROUNDCOLOR);
+	
+	if (stroke == mxConstants.NONE)
+	{
+		stroke = null;
+	}
+	
+	if (fill == mxConstants.NONE)
+	{
+		fill = null;
+	}
+	
+	if (stroke != null || fill != null)
+	{
+		var x = bounds.x;
+		var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0);
+		var w = bounds.width;
+		var h = bounds.height;
+		
+		if (vert)
+		{
+			x += (w - h) / 2;
+			y += (h - w) / 2;
+			var tmp = w;
+			w = h;
+			h = tmp;
+		}
+		
+		if (fill != null)
+		{
+			canvas.setFillColor(fill);
+		}
+		
+		if (stroke != null)
+		{
+			canvas.setStrokeColor(stroke);
+			canvas.setStrokeWidth(1);
+			canvas.setDashed(false);
+		}
+		
+		canvas.rect(x, y, w, h);
+
+		if (fill != null && stroke != null)
+		{
+			canvas.fillAndStroke();
+		}
+		else if (fill != null)
+		{
+			canvas.fill();
+		}
+		else if (stroke != null)
+		{
+			canvas.stroke();
+		}
+	}
+};
+
+/**
+ * Function: drawLabel
+ * 
+ * Draws the given state to the given canvas.
+ */
+mxImageExport.prototype.drawLabel = function(state, canvas, bounds, vert, str)
+{
+	var scale = state.view.scale;
+	
+	// Applies color
+	canvas.setFontColor(mxUtils.getValue(state.style, mxConstants.STYLE_FONTCOLOR, '#000000'));
+	
+	// Applies font settings
+	canvas.setFontFamily(mxUtils.getValue(state.style, mxConstants.STYLE_FONTFAMILY,
+			mxConstants.DEFAULT_FONTFAMILY));
+	canvas.setFontStyle(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSTYLE, 0));
+	canvas.setFontSize(mxUtils.getValue(state.style, mxConstants.STYLE_FONTSIZE,
+			mxConstants.DEFAULT_FONTSIZE) * scale);
+	
+	var align = mxUtils.getValue(state.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_LEFT);
+	
+	// Uses null alignment for default values (valign default is 'top' which is fine)
+	if (align == 'left')
+	{
+		align = null;
+	}
+		
+	var y = bounds.y - mxUtils.getValue(state.style, mxConstants.STYLE_LABEL_PADDING, 0);
+	var wrap = state.view.graph.isWrapping(state.cell);
+	var html = state.view.graph.isHtmlLabel(state.cell);
+	
+	// Replaces linefeeds in HTML markup to match the display output
+	if (html && mxText.prototype.replaceLinefeeds)
+	{
+		str = str.replace(/\n/g, '
'); + } + + canvas.text(bounds.x, y, bounds.width, bounds.height, str, align, null, vert, wrap, (html) ? 'html' : ''); +}; + +/** + * Function: getBackgroundBounds + * + * Draws the given state to the given canvas. + */ +mxImageExport.prototype.getBackgroundBounds = function(state) +{ + if (state.style[mxConstants.STYLE_SHAPE] == mxConstants.SHAPE_SWIMLANE) + { + var scale = state.view.scale; + var start = mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE) * scale; + var w = state.width; + var h = state.height; + + if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, true)) + { + h = start; + } + else + { + w = start; + } + + return new mxRectangle(state.x, state.y, Math.min(state.width, w), Math.min(state.height, h)); + } + else + { + return new mxRectangle(state.x, state.y, state.width, state.height); + } +}; + +/** + * Function: getImageBounds + * + * Draws the given state to the given canvas. + */ +mxImageExport.prototype.getImageBounds = function(state) +{ + var bounds = new mxRectangle(state.x, state.y, state.width, state.height); + var style = state.style; + + if (mxUtils.getValue(style, mxConstants.STYLE_SHAPE) != mxConstants.SHAPE_IMAGE) + { + var imgAlign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_ALIGN, mxConstants.ALIGN_LEFT); + var imgValign = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE); + var imgWidth = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_WIDTH, mxConstants.DEFAULT_IMAGESIZE); + var imgHeight = mxUtils.getValue(style, mxConstants.STYLE_IMAGE_HEIGHT, mxConstants.DEFAULT_IMAGESIZE); + var spacing = mxUtils.getValue(style, mxConstants.STYLE_SPACING, 2); + + if (imgAlign == mxConstants.ALIGN_CENTER) + { + bounds.x += (bounds.width - imgWidth) / 2; + } + else if (imgAlign == mxConstants.ALIGN_RIGHT) + { + bounds.x += bounds.width - imgWidth - spacing - 2; + } + else + // LEFT + { + bounds.x += spacing + 4; + } + + if (imgValign == mxConstants.ALIGN_TOP) + { + bounds.y += spacing; + } + else if (imgValign == mxConstants.ALIGN_BOTTOM) + { + bounds.y += bounds.height - imgHeight - spacing; + } + else + // MIDDLE + { + bounds.y += (bounds.height - imgHeight) / 2; + } + + bounds.width = imgWidth; + bounds.height = imgHeight; + } + + return bounds; +}; + +/** + * Function: drawMarker + * + * Initializes the built-in shapes. + */ +mxImageExport.prototype.drawMarker = function(canvas, state, source) +{ + var offset = null; + + // Computes the norm and the inverse norm + var pts = state.absolutePoints; + var n = pts.length; + + var p0 = (source) ? pts[1] : pts[n - 2]; + var pe = (source) ? pts[0] : pts[n - 1]; + + var dx = pe.x - p0.x; + var dy = pe.y - p0.y; + + var dist = Math.max(1, Math.sqrt(dx * dx + dy * dy)); + + var unitX = dx / dist; + var unitY = dy / dist; + + var size = mxUtils.getValue(state.style, (source) ? + mxConstants.STYLE_STARTSIZE : + mxConstants.STYLE_ENDSIZE, + mxConstants.DEFAULT_MARKERSIZE); + + // Allow for stroke width in the end point used and the + // orthogonal vectors describing the direction of the marker + // TODO: Should get strokewidth from canvas (same for strokecolor) + var sw = mxUtils.getValue(state.style, mxConstants.STYLE_STROKEWIDTH, 1); + + pe = pe.clone(); + + var type = mxUtils.getValue(state.style, (source) ? + mxConstants.STYLE_STARTARROW : + mxConstants.STYLE_ENDARROW); + var f = this.markers[type]; + + if (f != null) + { + offset = f(canvas, state, type, pe, unitX, unitY, size, source, sw); + } + + return offset; +}; + +/** + * Function: initShapes + * + * Initializes the built-in shapes. + */ +mxImageExport.prototype.initShapes = function() +{ + this.shapes = []; + + // Implements the rectangle and rounded rectangle shape + this.shapes['rectangle'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + // Paints the shape + if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) + { + var f = mxUtils.getValue(state.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100; + var r = Math.min(bounds.width * f, bounds.height * f); + canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r); + } + else + { + canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height); + } + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + // Implements the swimlane shape + this.shapes['swimlane'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) + { + var r = Math.min(bounds.width * mxConstants.RECTANGLE_ROUNDING_FACTOR, + bounds.height * mxConstants.RECTANGLE_ROUNDING_FACTOR); + canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, r, r); + } + else + { + canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height); + } + + return true; + } + else + { + canvas.fillAndStroke(); + var x = state.x; + var y = state.y; + var w = state.width; + var h = state.height; + + if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 0) + { + x += bounds.width; + w -= bounds.width; + } + else + { + y += bounds.height; + h -= bounds.height; + } + + canvas.begin(); + canvas.moveTo(x, y); + canvas.lineTo(x, y + h); + canvas.lineTo(x + w, y + h); + canvas.lineTo(x + w, y); + canvas.stroke(); + } + } + }; + + this.shapes['image'] = this.shapes['rectangle']; + this.shapes['label'] = this.shapes['rectangle']; + + var imageExport = this; + + this.shapes['connector'] = + { + translatePoint: function(points, index, offset) + { + if (offset != null) + { + var pt = points[index].clone(); + pt.x += offset.x; + pt.y += offset.y; + points[index] = pt; + } + }, + + drawShape: function(canvas, state, bounds, background, shadow) + { + if (background) + { + var rounded = mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false); + var arcSize = mxConstants.LINE_ARCSIZE / 2; + + // Does not draw the markers in the shadow to match the display + canvas.setFillColor((shadow) ? mxConstants.NONE : mxUtils.getValue(state.style, mxConstants.STYLE_STROKECOLOR, "#000000")); + canvas.setDashed(false); + var pts = state.absolutePoints.slice(); + this.translatePoint(pts, 0, imageExport.drawMarker(canvas, state, true)); + this.translatePoint(pts, pts.length - 1, imageExport.drawMarker(canvas, state, false)); + canvas.setDashed(mxUtils.getValue(state.style, mxConstants.STYLE_DASHED, '0') == '1'); + + var pt = pts[0]; + var pe = pts[pts.length - 1]; + canvas.begin(); + canvas.moveTo(pt.x, pt.y); + + // Draws the line segments + for (var i = 1; i < pts.length - 1; i++) + { + var tmp = pts[i]; + var dx = pt.x - tmp.x; + var dy = pt.y - tmp.y; + + if ((rounded && i < pts.length - 1) && (dx != 0 || dy != 0)) + { + // Draws a line from the last point to the current + // point with a spacing of size off the current point + // into direction of the last point + var dist = Math.sqrt(dx * dx + dy * dy); + var nx1 = dx * Math.min(arcSize, dist / 2) / dist; + var ny1 = dy * Math.min(arcSize, dist / 2) / dist; + + var x1 = tmp.x + nx1; + var y1 = tmp.y + ny1; + canvas.lineTo(x1, y1); + + // Draws a curve from the last point to the current + // point with a spacing of size off the current point + // into direction of the next point + var next = pts[i + 1]; + dx = next.x - tmp.x; + dy = next.y - tmp.y; + + dist = Math.max(1, Math.sqrt(dx * dx + dy * dy)); + var nx2 = dx * Math.min(arcSize, dist / 2) / dist; + var ny2 = dy * Math.min(arcSize, dist / 2) / dist; + + var x2 = tmp.x + nx2; + var y2 = tmp.y + ny2; + + canvas.curveTo(tmp.x, tmp.y, tmp.x, tmp.y, x2, y2); + tmp = new mxPoint(x2, y2); + } + else + { + canvas.lineTo(tmp.x, tmp.y); + } + + pt = tmp; + } + + canvas.lineTo(pe.x, pe.y); + canvas.stroke(); + + return true; + } + else + { + // no foreground + } + } + }; + + this.shapes['arrow'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + // Geometry of arrow + var spacing = mxConstants.ARROW_SPACING; + var width = mxConstants.ARROW_WIDTH; + var arrow = mxConstants.ARROW_SIZE; + + // Base vector (between end points) + var pts = state.absolutePoints; + var p0 = pts[0]; + var pe = pts[pts.length - 1]; + var dx = pe.x - p0.x; + var dy = pe.y - p0.y; + var dist = Math.sqrt(dx * dx + dy * dy); + var length = dist - 2 * spacing - arrow; + + // Computes the norm and the inverse norm + var nx = dx / dist; + var ny = dy / dist; + var basex = length * nx; + var basey = length * ny; + var floorx = width * ny/3; + var floory = -width * nx/3; + + // Computes points + var p0x = p0.x - floorx / 2 + spacing * nx; + var p0y = p0.y - floory / 2 + spacing * ny; + var p1x = p0x + floorx; + var p1y = p0y + floory; + var p2x = p1x + basex; + var p2y = p1y + basey; + var p3x = p2x + floorx; + var p3y = p2y + floory; + // p4 not necessary + var p5x = p3x - 3 * floorx; + var p5y = p3y - 3 * floory; + + canvas.begin(); + canvas.moveTo(p0x, p0y); + canvas.lineTo(p1x, p1y); + canvas.lineTo(p2x, p2y); + canvas.lineTo(p3x, p3y); + canvas.lineTo(pe.x - spacing * nx, pe.y - spacing * ny); + canvas.lineTo(p5x, p5y); + canvas.lineTo(p5x + floorx, p5y + floory); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + this.shapes['cylinder'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + return false; + } + else + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + var dy = Math.min(mxCylinder.prototype.maxHeight, Math.floor(h / 5)); + + canvas.begin(); + canvas.moveTo(x, y + dy); + canvas.curveTo(x, y - dy / 3, x + w, y - dy / 3, x + w, y + dy); + canvas.lineTo(x + w, y + h - dy); + canvas.curveTo(x + w, y + h + dy / 3, x, y + h + dy / 3, x, y + h - dy); + canvas.close(); + canvas.fillAndStroke(); + + canvas.begin(); + canvas.moveTo(x, y + dy); + canvas.curveTo(x, y + 2 * dy, x + w, y + 2 * dy, x + w, y + dy); + canvas.stroke(); + } + } + }; + + this.shapes['line'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + return false; + } + else + { + canvas.begin(); + + var mid = state.getCenterY(); + canvas.moveTo(bounds.x, mid); + canvas.lineTo(bounds.x + bounds.width, mid); + + canvas.stroke(); + } + } + }; + + this.shapes['ellipse'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + canvas.ellipse(bounds.x, bounds.y, bounds.width, bounds.height); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + this.shapes['doubleEllipse'] = + { + drawShape: function(canvas, state, bounds, background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + + if (background) + { + canvas.ellipse(x, y, w, h); + + return true; + } + else + { + canvas.fillAndStroke(); + + var inset = Math.min(4, Math.min(w / 5, h / 5)); + x += inset; + y += inset; + w -= 2 * inset; + h -= 2 * inset; + + if (w > 0 && h > 0) + { + canvas.ellipse(x, y, w, h); + } + + canvas.stroke(); + } + } + }; + + this.shapes['triangle'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + canvas.begin(); + canvas.moveTo(x, y); + canvas.lineTo(x + w, y + h / 2); + canvas.lineTo(x, y + h); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + this.shapes['rhombus'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + var hw = w / 2; + var hh = h / 2; + + canvas.begin(); + canvas.moveTo(x + hw, y); + canvas.lineTo(x + w, y + hh); + canvas.lineTo(x + hw, y + h); + canvas.lineTo(x, y + hh); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + + }; + + this.shapes['hexagon'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + + canvas.begin(); + canvas.moveTo(x + 0.25 * w, y); + canvas.lineTo(x + 0.75 * w, y); + canvas.lineTo(x + w, y + 0.5 * h); + canvas.lineTo(x + 0.75 * w, y + h); + canvas.lineTo(x + 0.25 * w, y + h); + canvas.lineTo(x, y + 0.5 * h); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + this.shapes['actor'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + var width = w * 2 / 6; + + canvas.begin(); + canvas.moveTo(x, y + h); + canvas.curveTo(x, y + 3 * h / 5, x, y + 2 * h / 5, x + w / 2, y + 2 * h + / 5); + canvas.curveTo(x + w / 2 - width, y + 2 * h / 5, x + w / 2 - width, y, x + + w / 2, y); + canvas.curveTo(x + w / 2 + width, y, x + w / 2 + width, y + 2 * h / 5, x + + w / 2, y + 2 * h / 5); + canvas.curveTo(x + w, y + 2 * h / 5, x + w, y + 3 * h / 5, x + w, y + h); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + + this.shapes['cloud'] = + { + drawShape: function(canvas, state, bounds, background) + { + if (background) + { + var x = bounds.x; + var y = bounds.y; + var w = bounds.width; + var h = bounds.height; + + canvas.begin(); + canvas.moveTo(x + 0.25 * w, y + 0.25 * h); + canvas.curveTo(x + 0.05 * w, y + 0.25 * h, x, + y + 0.5 * h, x + 0.16 * w, y + 0.55 * h); + canvas.curveTo(x, y + 0.66 * h, x + 0.18 * w, + y + 0.9 * h, x + 0.31 * w, y + 0.8 * h); + canvas.curveTo(x + 0.4 * w, y + h, x + 0.7 * w, + y + h, x + 0.8 * w, y + 0.8 * h); + canvas.curveTo(x + w, y + 0.8 * h, x + w, + y + 0.6 * h, x + 0.875 * w, y + 0.5 * h); + canvas.curveTo(x + w, y + 0.3 * h, x + 0.8 * w, + y + 0.1 * h, x + 0.625 * w, y + 0.2 * h); + canvas.curveTo(x + 0.5 * w, y + 0.05 * h, + x + 0.3 * w, y + 0.05 * h, + x + 0.25 * w, y + 0.25 * h); + canvas.close(); + + return true; + } + else + { + canvas.fillAndStroke(); + } + } + }; + +}; + +/** + * Function: initMarkers + * + * Initializes the built-in markers. + */ +mxImageExport.prototype.initMarkers = function() +{ + this.markers = []; + + var tmp = function(canvas, state, type, pe, unitX, unitY, size, source, sw) + { + // The angle of the forward facing arrow sides against the x axis is + // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for + // only half the strokewidth is processed ). + var endOffsetX = unitX * sw * 1.118; + var endOffsetY = unitY * sw * 1.118; + + pe.x -= endOffsetX; + pe.y -= endOffsetY; + + unitX = unitX * (size + sw); + unitY = unitY * (size + sw); + + canvas.begin(); + canvas.moveTo(pe.x, pe.y); + canvas.lineTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2); + + if (type == mxConstants.ARROW_CLASSIC) + { + canvas.lineTo(pe.x - unitX * 3 / 4, pe.y - unitY * 3 / 4); + } + + canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2); + canvas.close(); + + var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; + + if (state.style[key] == 0) + { + canvas.stroke(); + } + else + { + canvas.fillAndStroke(); + } + + var f = (type != mxConstants.ARROW_CLASSIC) ? 1 : 3 / 4; + return new mxPoint(-unitX * f - endOffsetX, -unitY * f - endOffsetY); + }; + + this.markers['classic'] = tmp; + this.markers['block'] = tmp; + + this.markers['open'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw) + { + // The angle of the forward facing arrow sides against the x axis is + // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for + // only half the strokewidth is processed ). + var endOffsetX = unitX * sw * 1.118; + var endOffsetY = unitY * sw * 1.118; + + pe.x -= endOffsetX; + pe.y -= endOffsetY; + + unitX = unitX * (size + sw); + unitY = unitY * (size + sw); + + canvas.begin(); + canvas.moveTo(pe.x - unitX - unitY / 2, pe.y - unitY + unitX / 2); + canvas.lineTo(pe.x, pe.y); + canvas.lineTo(pe.x + unitY / 2 - unitX, pe.y - unitY - unitX / 2); + canvas.stroke(); + + return new mxPoint(-endOffsetX * 2, -endOffsetY * 2); + }; + + this.markers['oval'] = function(canvas, state, type, pe, unitX, unitY, size, source, sw) + { + var a = size / 2; + + canvas.ellipse(pe.x - a, pe.y - a, size, size); + + var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; + + if (state.style[key] == 0) + { + canvas.stroke(); + } + else + { + canvas.fillAndStroke(); + } + + return new mxPoint(-unitX / 2, -unitY / 2); + }; + + var tmp_diamond = function(canvas, state, type, pe, unitX, unitY, size, source, sw) + { + // The angle of the forward facing arrow sides against the x axis is + // 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for + // only half the strokewidth is processed ). Or 0.9862 for thin diamond. + // Note these values and the tk variable below are dependent, update + // both together (saves trig hard coding it). + var swFactor = (type == mxConstants.ARROW_DIAMOND) ? 0.7071 : 0.9862; + var endOffsetX = unitX * sw * swFactor; + var endOffsetY = unitY * sw * swFactor; + + unitX = unitX * (size + sw); + unitY = unitY * (size + sw); + + pe.x -= endOffsetX; + pe.y -= endOffsetY; + + // thickness factor for diamond + var tk = ((type == mxConstants.ARROW_DIAMOND) ? 2 : 3.4); + + canvas.begin(); + canvas.moveTo(pe.x, pe.y); + canvas.lineTo(pe.x - unitX / 2 - unitY / tk, pe.y + unitX / tk - unitY / 2); + canvas.lineTo(pe.x - unitX, pe.y - unitY); + canvas.lineTo(pe.x - unitX / 2 + unitY / tk, pe.y - unitY / 2 - unitX / tk); + canvas.close(); + + var key = (source) ? mxConstants.STYLE_STARTFILL : mxConstants.STYLE_ENDFILL; + + if (state.style[key] == 0) + { + canvas.stroke(); + } + else + { + canvas.fillAndStroke(); + } + + return new mxPoint(-endOffsetX - unitX, -endOffsetY - unitY); + }; + + this.markers['diamond'] = tmp_diamond; + this.markers['diamondThin'] = tmp_diamond; +}; +/** + * $Id: mxXmlCanvas2D.js,v 1.9 2012-04-24 13:56:56 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * + * Class: mxXmlCanvas2D + * + * Implements a canvas to be used with . This canvas writes all + * calls as child nodes to the given root XML node. + * + * (code) + * var xmlDoc = mxUtils.createXmlDocument(); + * var root = xmlDoc.createElement('output'); + * xmlDoc.appendChild(root); + * var xmlCanvas = new mxXmlCanvas2D(root); + * (end) + * + * Constructor: mxXmlCanvas2D + * + * Constructs a XML canvas. + * + * Parameters: + * + * root - XML node for adding child nodes. + */ +var mxXmlCanvas2D = function(root) +{ + /** + * Variable: converter + * + * Holds the to convert image URLs. + */ + var converter = new mxUrlConverter(); + + /** + * Variable: compressed + * + * Specifies if the output should be compressed by removing redundant calls. + * Default is true. + */ + var compressed = true; + + /** + * Variable: textEnabled + * + * Specifies if text output should be enabled. Default is true. + */ + var textEnabled = true; + + // Private reference to the owner document + var doc = root.ownerDocument; + + // Implements stack for save/restore + var stack = []; + + // Implements state for redundancy checks + var state = + { + alpha: 1, + dashed: false, + strokewidth: 1, + fontsize: mxConstants.DEFAULT_FONTSIZE, + fontfamily: mxConstants.DEFAULT_FONTFAMILY, + fontcolor: '#000000' + }; + + // Private helper function set set precision to 2 + var f2 = function(x) + { + return Math.round(parseFloat(x) * 100) / 100; + }; + + // Returns public interface + return { + + /** + * Function: getConverter + * + * Returns . + */ + getConverter: function() + { + return converter; + }, + + /** + * Function: isCompressed + * + * Returns . + */ + isCompressed: function() + { + return compressed; + }, + + /** + * Function: setCompressed + * + * Sets . + */ + setCompressed: function(value) + { + compressed = value; + }, + + /** + * Function: isTextEnabled + * + * Returns . + */ + isTextEnabled: function() + { + return textEnabled; + }, + + /** + * Function: setTextEnabled + * + * Sets . + */ + setTextEnabled: function(value) + { + textEnabled = value; + }, + + /** + * Function: getDocument + * + * Returns the owner document of the root element. + */ + getDocument: function() + { + return doc; + }, + + /** + * Function: save + * + * Saves the state of the graphics object. + */ + save: function() + { + if (compressed) + { + stack.push(state); + state = mxUtils.clone(state); + } + + root.appendChild(doc.createElement('save')); + }, + + /** + * Function: restore + * + * Restores the state of the graphics object. + */ + restore: function() + { + if (compressed) + { + state = stack.pop(); + } + + root.appendChild(doc.createElement('restore')); + }, + + /** + * Function: scale + * + * Scales the current graphics object. + */ + scale: function(value) + { + var elem = doc.createElement('scale'); + elem.setAttribute('scale', value); + root.appendChild(elem); + }, + + /** + * Function: translate + * + * Translates the current graphics object. + */ + translate: function(dx, dy) + { + var elem = doc.createElement('translate'); + elem.setAttribute('dx', f2(dx)); + elem.setAttribute('dy', f2(dy)); + root.appendChild(elem); + }, + + /** + * Function: rotate + * + * Rotates and/or flips the current graphics object. + */ + rotate: function(theta, flipH, flipV, cx, cy) + { + var elem = doc.createElement('rotate'); + elem.setAttribute('theta', f2(theta)); + elem.setAttribute('flipH', (flipH) ? '1' : '0'); + elem.setAttribute('flipV', (flipV) ? '1' : '0'); + elem.setAttribute('cx', f2(cx)); + elem.setAttribute('cy', f2(cy)); + root.appendChild(elem); + }, + + /** + * Function: setStrokeWidth + * + * Sets the stroke width. + */ + setStrokeWidth: function(value) + { + if (compressed) + { + if (state.strokewidth == value) + { + return; + } + + state.strokewidth = value; + } + + var elem = doc.createElement('strokewidth'); + elem.setAttribute('width', f2(value)); + root.appendChild(elem); + }, + + /** + * Function: setStrokeColor + * + * Sets the stroke color. + */ + setStrokeColor: function(value) + { + var elem = doc.createElement('strokecolor'); + elem.setAttribute('color', value); + root.appendChild(elem); + }, + + /** + * Function: setDashed + * + * Sets the dashed state to true or false. + */ + setDashed: function(value) + { + if (compressed) + { + if (state.dashed == value) + { + return; + } + + state.dashed = value; + } + + var elem = doc.createElement('dashed'); + elem.setAttribute('dashed', (value) ? '1' : '0'); + root.appendChild(elem); + }, + + /** + * Function: setDashPattern + * + * Sets the dashed pattern to the given space separated list of numbers. + */ + setDashPattern: function(value) + { + var elem = doc.createElement('dashpattern'); + elem.setAttribute('pattern', value); + root.appendChild(elem); + }, + + /** + * Function: setLineCap + * + * Sets the linecap. + */ + setLineCap: function(value) + { + var elem = doc.createElement('linecap'); + elem.setAttribute('cap', value); + root.appendChild(elem); + }, + + /** + * Function: setLineJoin + * + * Sets the linejoin. + */ + setLineJoin: function(value) + { + var elem = doc.createElement('linejoin'); + elem.setAttribute('join', value); + root.appendChild(elem); + }, + + /** + * Function: setMiterLimit + * + * Sets the miterlimit. + */ + setMiterLimit: function(value) + { + var elem = doc.createElement('miterlimit'); + elem.setAttribute('limit', value); + root.appendChild(elem); + }, + + /** + * Function: setFontSize + * + * Sets the fontsize. + */ + setFontSize: function(value) + { + if (textEnabled) + { + if (compressed) + { + if (state.fontsize == value) + { + return; + } + + state.fontsize = value; + } + + var elem = doc.createElement('fontsize'); + elem.setAttribute('size', value); + root.appendChild(elem); + } + }, + + /** + * Function: setFontColor + * + * Sets the fontcolor. + */ + setFontColor: function(value) + { + if (textEnabled) + { + if (compressed) + { + if (state.fontcolor == value) + { + return; + } + + state.fontcolor = value; + } + + var elem = doc.createElement('fontcolor'); + elem.setAttribute('color', value); + root.appendChild(elem); + } + }, + + /** + * Function: setFontFamily + * + * Sets the fontfamily. + */ + setFontFamily: function(value) + { + if (textEnabled) + { + if (compressed) + { + if (state.fontfamily == value) + { + return; + } + + state.fontfamily = value; + } + + var elem = doc.createElement('fontfamily'); + elem.setAttribute('family', value); + root.appendChild(elem); + } + }, + + /** + * Function: setFontStyle + * + * Sets the fontstyle. + */ + setFontStyle: function(value) + { + if (textEnabled) + { + var elem = doc.createElement('fontstyle'); + elem.setAttribute('style', value); + root.appendChild(elem); + } + }, + + /** + * Function: setAlpha + * + * Sets the current alpha. + */ + setAlpha: function(alpha) + { + if (compressed) + { + if (state.alpha == alpha) + { + return; + } + + state.alpha = alpha; + } + + var elem = doc.createElement('alpha'); + elem.setAttribute('alpha', f2(alpha)); + root.appendChild(elem); + }, + + /** + * Function: setFillColor + * + * Sets the fillcolor. + */ + setFillColor: function(value) + { + var elem = doc.createElement('fillcolor'); + elem.setAttribute('color', value); + root.appendChild(elem); + }, + + /** + * Function: setGradient + * + * Sets the gradient color. + */ + setGradient: function(color1, color2, x, y, w, h, direction) + { + var elem = doc.createElement('gradient'); + elem.setAttribute('c1', color1); + elem.setAttribute('c2', color2); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + + // Default direction is south + if (direction != null) + { + elem.setAttribute('direction', direction); + } + + root.appendChild(elem); + }, + + /** + * Function: setGlassGradient + * + * Sets the glass gradient. + */ + setGlassGradient: function(x, y, w, h) + { + var elem = doc.createElement('glass'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + root.appendChild(elem); + }, + + /** + * Function: rect + * + * Sets the current path to a rectangle. + */ + rect: function(x, y, w, h) + { + var elem = doc.createElement('rect'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + root.appendChild(elem); + }, + + /** + * Function: roundrect + * + * Sets the current path to a rounded rectangle. + */ + roundrect: function(x, y, w, h, dx, dy) + { + var elem = doc.createElement('roundrect'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + elem.setAttribute('dx', f2(dx)); + elem.setAttribute('dy', f2(dy)); + root.appendChild(elem); + }, + + /** + * Function: ellipse + * + * Sets the current path to an ellipse. + */ + ellipse: function(x, y, w, h) + { + var elem = doc.createElement('ellipse'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + root.appendChild(elem); + }, + + /** + * Function: image + * + * Paints an image. + */ + image: function(x, y, w, h, src, aspect, flipH, flipV) + { + src = converter.convert(src); + + // TODO: Add option for embedding images as base64 + var elem = doc.createElement('image'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + elem.setAttribute('src', src); + elem.setAttribute('aspect', (aspect) ? '1' : '0'); + elem.setAttribute('flipH', (flipH) ? '1' : '0'); + elem.setAttribute('flipV', (flipV) ? '1' : '0'); + root.appendChild(elem); + }, + + /** + * Function: text + * + * Paints the given text. + */ + text: function(x, y, w, h, str, align, valign, vertical, wrap, format) + { + if (textEnabled) + { + var elem = doc.createElement('text'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + elem.setAttribute('w', f2(w)); + elem.setAttribute('h', f2(h)); + elem.setAttribute('str', str); + + if (align != null) + { + elem.setAttribute('align', align); + } + + if (valign != null) + { + elem.setAttribute('valign', valign); + } + + elem.setAttribute('vertical', (vertical) ? '1' : '0'); + elem.setAttribute('wrap', (wrap) ? '1' : '0'); + elem.setAttribute('format', format); + root.appendChild(elem); + } + }, + + /** + * Function: begin + * + * Starts a new path. + */ + begin: function() + { + root.appendChild(doc.createElement('begin')); + }, + + /** + * Function: moveTo + * + * Moves the current path the given coordinates. + */ + moveTo: function(x, y) + { + var elem = doc.createElement('move'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + root.appendChild(elem); + }, + + /** + * Function: lineTo + * + * Adds a line to the current path. + */ + lineTo: function(x, y) + { + var elem = doc.createElement('line'); + elem.setAttribute('x', f2(x)); + elem.setAttribute('y', f2(y)); + root.appendChild(elem); + }, + + /** + * Function: quadTo + * + * Adds a quadratic curve to the current path. + */ + quadTo: function(x1, y1, x2, y2) + { + var elem = doc.createElement('quad'); + elem.setAttribute('x1', f2(x1)); + elem.setAttribute('y1', f2(y1)); + elem.setAttribute('x2', f2(x2)); + elem.setAttribute('y2', f2(y2)); + root.appendChild(elem); + }, + + /** + * Function: curveTo + * + * Adds a bezier curve to the current path. + */ + curveTo: function(x1, y1, x2, y2, x3, y3) + { + var elem = doc.createElement('curve'); + elem.setAttribute('x1', f2(x1)); + elem.setAttribute('y1', f2(y1)); + elem.setAttribute('x2', f2(x2)); + elem.setAttribute('y2', f2(y2)); + elem.setAttribute('x3', f2(x3)); + elem.setAttribute('y3', f2(y3)); + root.appendChild(elem); + }, + + /** + * Function: close + * + * Closes the current path. + */ + close: function() + { + root.appendChild(doc.createElement('close')); + }, + + /** + * Function: stroke + * + * Paints the outline of the current path. + */ + stroke: function() + { + root.appendChild(doc.createElement('stroke')); + }, + + /** + * Function: fill + * + * Fills the current path. + */ + fill: function() + { + root.appendChild(doc.createElement('fill')); + }, + + /** + * Function: fillstroke + * + * Fills and paints the outline of the current path. + */ + fillAndStroke: function() + { + root.appendChild(doc.createElement('fillstroke')); + }, + + /** + * Function: shadow + * + * Paints the current path as a shadow of the given color. + */ + shadow: function(value, filled) + { + var elem = doc.createElement('shadow'); + elem.setAttribute('value', value); + + if (filled != null) + { + elem.setAttribute('filled', (filled) ? '1' : '0'); + } + + root.appendChild(elem); + }, + + /** + * Function: clip + * + * Uses the current path for clipping. + */ + clip: function() + { + root.appendChild(doc.createElement('clip')); + } + }; + +};/** + * $Id: mxSvgCanvas2D.js,v 1.14 2012-04-24 13:56:56 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * + * Class: mxSvgCanvas2D + * + * Implements a canvas to be used with . This canvas writes all + * calls as SVG output to the given SVG root node. + * + * (code) + * var svgDoc = mxUtils.createXmlDocument(); + * var root = (svgDoc.createElementNS != null) ? + * svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg'); + * + * if (svgDoc.createElementNS == null) + * { + * root.setAttribute('xmlns', mxConstants.NS_SVG); + * } + * + * var bounds = graph.getGraphBounds(); + * root.setAttribute('width', (bounds.x + bounds.width + 4) + 'px'); + * root.setAttribute('height', (bounds.y + bounds.height + 4) + 'px'); + * root.setAttribute('version', '1.1'); + * + * svgDoc.appendChild(root); + * + * var svgCanvas = new mxSvgCanvas2D(root); + * (end) + * + * Constructor: mxSvgCanvas2D + * + * Constructs an SVG canvas. + * + * Parameters: + * + * root - SVG container for the output. + * styleEnabled - Optional boolean that specifies if a style section should be + * added. The style section sets the default font-size, font-family and + * stroke-miterlimit globally. Default is false. + */ +var mxSvgCanvas2D = function(root, styleEnabled) +{ + styleEnabled = (styleEnabled != null) ? styleEnabled : false; + + /** + * Variable: converter + * + * Holds the to convert image URLs. + */ + var converter = new mxUrlConverter(); + + /** + * Variable: autoAntiAlias + * + * Specifies if anti aliasing should be disabled for rectangles + * and orthogonal paths. Default is true. + */ + var autoAntiAlias = true; + + /** + * Variable: textEnabled + * + * Specifies if text output should be enabled. Default is true. + */ + var textEnabled = true; + + /** + * Variable: foEnabled + * + * Specifies if use of foreignObject for HTML markup is allowed. Default is true. + */ + var foEnabled = true; + + // Private helper function to create SVG elements + var create = function(tagName, namespace) + { + if (root.ownerDocument.createElementNS != null) + { + return root.ownerDocument.createElementNS(namespace || mxConstants.NS_SVG, tagName); + } + else + { + var elt = root.ownerDocument.createElement(tagName); + + if (namespace != null) + { + elt.setAttribute('xmlns', namespace); + } + + return elt; + } + }; + + // Defs section contains optional style and gradients + var defs = create('defs'); + + // Creates defs section with optional global style + if (styleEnabled) + { + var style = create('style'); + style.setAttribute('type', 'text/css'); + mxUtils.write(style, 'svg{font-family:' + mxConstants.DEFAULT_FONTFAMILY + + ';font-size:' + mxConstants.DEFAULT_FONTSIZE + + ';fill:none;stroke-miterlimit:10}'); + + if (autoAntiAlias) + { + mxUtils.write(style, 'rect{shape-rendering:crispEdges}'); + } + + // Appends style to defs and defs to SVG container + defs.appendChild(style); + } + + root.appendChild(defs); + + // Defines the current state + var currentState = + { + dx: 0, + dy: 0, + scale: 1, + transform: '', + fill: null, + gradient: null, + stroke: null, + strokeWidth: 1, + dashed: false, + dashpattern: '3 3', + alpha: 1, + linecap: 'flat', + linejoin: 'miter', + miterlimit: 10, + fontColor: '#000000', + fontSize: mxConstants.DEFAULT_FONTSIZE, + fontFamily: mxConstants.DEFAULT_FONTFAMILY, + fontStyle: 0 + }; + + // Local variables + var currentPathIsOrthogonal = true; + var glassGradient = null; + var currentNode = null; + var currentPath = null; + var lastPoint = null; + var gradients = []; + var refCount = 0; + var stack = []; + + // Other private helper methods + var createGradientId = function(start, end, direction) + { + // Removes illegal characters from gradient ID + if (start.charAt(0) == '#') + { + start = start.substring(1); + } + + if (end.charAt(0) == '#') + { + end = end.substring(1); + } + + // Workaround for gradient IDs not working in Safari 5 / Chrome 6 + // if they contain uppercase characters + start = start.toLowerCase(); + end = end.toLowerCase(); + + // Wrong gradient directions possible? + var dir = null; + + if (direction == null || direction == mxConstants.DIRECTION_SOUTH) + { + dir = 's'; + } + else if (direction == mxConstants.DIRECTION_EAST) + { + dir = 'e'; + } + else + { + var tmp = start; + start = end; + end = tmp; + + if (direction == mxConstants.DIRECTION_NORTH) + { + dir = 's'; + } + else if (direction == mxConstants.DIRECTION_WEST) + { + dir = 'e'; + } + } + + return start+'-'+end+'-'+dir; + }; + + var createHtmlBody = function(str, align, valign) + { + var style = 'margin:0px;font-size:' + Math.floor(currentState.fontSize) + 'px;' + + 'font-family:' + currentState.fontFamily + ';color:' + currentState.fontColor+ ';'; + + if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD) + { + style += 'font-weight:bold;'; + } + + if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC) + { + style += 'font-style:italic;'; + } + + if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) + { + style += 'font-decoration:underline;'; + } + + if (align == mxConstants.ALIGN_CENTER) + { + style += 'text-align:center;'; + } + else if (align == mxConstants.ALIGN_RIGHT) + { + style += 'text-align:right;'; + } + + // LATER: Add vertical align support via table + var body = create('body', 'http://www.w3.org/1999/xhtml'); + body.setAttribute('style', style); + + // Adds surrounding DIV to guarantee one root element, adds xmlns to workaround empty NS in IE9 standards + var node = mxUtils.parseXml('
' + str + '
').documentElement; + + if (body.ownerDocument.importNode != null) + { + node = body.ownerDocument.importNode(node, true); + } + + body.appendChild(node); + + return body; + }; + + var getSvgGradient = function(start, end, direction) + { + var id = createGradientId(start, end, direction); + var gradient = gradients[id]; + + if (gradient == null) + { + gradient = create('linearGradient'); + gradient.setAttribute('id', ++refCount); + gradient.setAttribute('x1', '0%'); + gradient.setAttribute('y1', '0%'); + gradient.setAttribute('x2', '0%'); + gradient.setAttribute('y2', '0%'); + + if (direction == null || direction == mxConstants.DIRECTION_SOUTH) + { + gradient.setAttribute('y2', '100%'); + } + else if (direction == mxConstants.DIRECTION_EAST) + { + gradient.setAttribute('x2', '100%'); + } + else if (direction == mxConstants.DIRECTION_NORTH) + { + gradient.setAttribute('y1', '100%'); + } + else if (direction == mxConstants.DIRECTION_WEST) + { + gradient.setAttribute('x1', '100%'); + } + + var stop = create('stop'); + stop.setAttribute('offset', '0%'); + stop.setAttribute('style', 'stop-color:'+start); + gradient.appendChild(stop); + + stop = create('stop'); + stop.setAttribute('offset', '100%'); + stop.setAttribute('style', 'stop-color:'+end); + gradient.appendChild(stop); + + defs.appendChild(gradient); + gradients[id] = gradient; + } + + return gradient.getAttribute('id'); + }; + + var appendNode = function(node, state, filled, stroked) + { + if (node != null) + { + if (state.clip != null) + { + node.setAttribute('clip-path', 'url(#' + state.clip + ')'); + state.clip = null; + } + + if (currentPath != null) + { + node.setAttribute('d', currentPath.join(' ')); + currentPath = null; + + if (autoAntiAlias && currentPathIsOrthogonal) + { + node.setAttribute('shape-rendering', 'crispEdges'); + state.strokeWidth = Math.max(1, state.strokeWidth); + } + } + + if (state.alpha < 1) + { + // LATER: Check if using fill/stroke-opacity here is faster + node.setAttribute('opacity', state.alpha); + //node.setAttribute('fill-opacity', state.alpha); + //node.setAttribute('stroke-opacity', state.alpha); + } + + if (filled && (state.fill != null || state.gradient != null)) + { + if (state.gradient != null) + { + node.setAttribute('fill', 'url(#' + state.gradient + ')'); + } + else + { + node.setAttribute('fill', state.fill.toLowerCase()); + } + } + else if (!styleEnabled) + { + node.setAttribute('fill', 'none'); + } + + if (stroked && state.stroke != null) + { + node.setAttribute('stroke', state.stroke.toLowerCase()); + + // Sets the stroke properties (1 is default is SVG) + if (state.strokeWidth != 1) + { + if (node.nodeName == 'rect' && autoAntiAlias) + { + state.strokeWidth = Math.max(1, state.strokeWidth); + } + + node.setAttribute('stroke-width', state.strokeWidth); + } + + if (node.nodeName == 'path') + { + // Linejoin miter is default in SVG + if (state.linejoin != null && state.linejoin != 'miter') + { + node.setAttribute('stroke-linejoin', state.linejoin); + } + + if (state.linecap != null) + { + // flat is called butt in SVG + var value = state.linecap; + + if (value == 'flat') + { + value = 'butt'; + } + + // Linecap butt is default in SVG + if (value != 'butt') + { + node.setAttribute('stroke-linecap', value); + } + } + + // Miterlimit 10 is default in our document + if (state.miterlimit != null && (!styleEnabled || state.miterlimit != 10)) + { + node.setAttribute('stroke-miterlimit', state.miterlimit); + } + } + + if (state.dashed) + { + var dash = state.dashpattern.split(' '); + + if (dash.length > 0) + { + var pat = []; + + for (var i = 0; i < dash.length; i++) + { + pat[i] = Number(dash[i]) * currentState.strokeWidth; + } + + + node.setAttribute('stroke-dasharray', pat.join(' ')); + } + } + } + + if (state.transform.length > 0) + { + node.setAttribute('transform', state.transform); + } + + root.appendChild(node); + } + }; + + // Private helper function to format a number + var f2 = function(x) + { + return Math.round(parseFloat(x) * 100) / 100; + }; + + // Returns public interface + return { + + /** + * Function: getConverter + * + * Returns . + */ + getConverter: function() + { + return converter; + }, + + /** + * Function: isAutoAntiAlias + * + * Returns . + */ + isAutoAntiAlias: function() + { + return autoAntiAlias; + }, + + /** + * Function: setAutoAntiAlias + * + * Sets . + */ + setAutoAntiAlias: function(value) + { + autoAntiAlias = value; + }, + + /** + * Function: isTextEnabled + * + * Returns . + */ + isTextEnabled: function() + { + return textEnabled; + }, + + /** + * Function: setTextEnabled + * + * Sets . + */ + setTextEnabled: function(value) + { + textEnabled = value; + }, + + /** + * Function: isFoEnabled + * + * Returns . + */ + isFoEnabled: function() + { + return foEnabled; + }, + + /** + * Function: setFoEnabled + * + * Sets . + */ + setFoEnabled: function(value) + { + foEnabled = value; + }, + + /** + * Function: save + * + * Saves the state of the graphics object. + */ + save: function() + { + stack.push(currentState); + currentState = mxUtils.clone(currentState); + }, + + /** + * Function: restore + * + * Restores the state of the graphics object. + */ + restore: function() + { + currentState = stack.pop(); + }, + + /** + * Function: scale + * + * Scales the current graphics object. + */ + scale: function(value) + { + currentState.scale *= value; + currentState.strokeWidth *= value; + }, + + /** + * Function: translate + * + * Translates the current graphics object. + */ + translate: function(dx, dy) + { + currentState.dx += dx; + currentState.dy += dy; + }, + + /** + * Function: rotate + * + * Rotates and/or flips the current graphics object. + */ + rotate: function(theta, flipH, flipV, cx, cy) + { + cx += currentState.dx; + cy += currentState.dy; + + cx *= currentState.scale; + cy *= currentState.scale; + + // This implementation uses custom scale/translate and built-in rotation + // Rotation state is part of the AffineTransform in state.transform + if (flipH ^ flipV) + { + var tx = (flipH) ? cx : 0; + var sx = (flipH) ? -1 : 1; + + var ty = (flipV) ? cy : 0; + var sy = (flipV) ? -1 : 1; + + currentState.transform += 'translate(' + f2(tx) + ',' + f2(ty) + ')'; + currentState.transform += 'scale(' + f2(sx) + ',' + f2(sy) + ')'; + currentState.transform += 'translate(' + f2(-tx) + ' ' + f2(-ty) + ')'; + } + + currentState.transform += 'rotate(' + f2(theta) + ',' + f2(cx) + ',' + f2(cy) + ')'; + }, + + /** + * Function: setStrokeWidth + * + * Sets the stroke width. + */ + setStrokeWidth: function(value) + { + currentState.strokeWidth = value * currentState.scale; + }, + + /** + * Function: setStrokeColor + * + * Sets the stroke color. + */ + setStrokeColor: function(value) + { + currentState.stroke = value; + }, + + /** + * Function: setDashed + * + * Sets the dashed state to true or false. + */ + setDashed: function(value) + { + currentState.dashed = value; + }, + + /** + * Function: setDashPattern + * + * Sets the dashed pattern to the given space separated list of numbers. + */ + setDashPattern: function(value) + { + currentState.dashpattern = value; + }, + + /** + * Function: setLineCap + * + * Sets the linecap. + */ + setLineCap: function(value) + { + currentState.linecap = value; + }, + + /** + * Function: setLineJoin + * + * Sets the linejoin. + */ + setLineJoin: function(value) + { + currentState.linejoin = value; + }, + + /** + * Function: setMiterLimit + * + * Sets the miterlimit. + */ + setMiterLimit: function(value) + { + currentState.miterlimit = value; + }, + + /** + * Function: setFontSize + * + * Sets the fontsize. + */ + setFontSize: function(value) + { + currentState.fontSize = value; + }, + + /** + * Function: setFontColor + * + * Sets the fontcolor. + */ + setFontColor: function(value) + { + currentState.fontColor = value; + }, + + /** + * Function: setFontFamily + * + * Sets the fontfamily. + */ + setFontFamily: function(value) + { + currentState.fontFamily = value; + }, + + /** + * Function: setFontStyle + * + * Sets the fontstyle. + */ + setFontStyle: function(value) + { + currentState.fontStyle = value; + }, + + /** + * Function: setAlpha + * + * Sets the current alpha. + */ + setAlpha: function(alpha) + { + currentState.alpha = alpha; + }, + + /** + * Function: setFillColor + * + * Sets the fillcolor. + */ + setFillColor: function(value) + { + currentState.fill = value; + currentState.gradient = null; + }, + + /** + * Function: setGradient + * + * Sets the gradient color. + */ + setGradient: function(color1, color2, x, y, w, h, direction) + { + if (color1 != null && color2 != null) + { + currentState.gradient = getSvgGradient(color1, color2, direction); + currentState.fill = color1; + } + }, + + /** + * Function: setGlassGradient + * + * Sets the glass gradient. + */ + setGlassGradient: function(x, y, w, h) + { + // Creates glass overlay gradient + if (glassGradient == null) + { + glassGradient = create('linearGradient'); + glassGradient.setAttribute('id', '0'); + glassGradient.setAttribute('x1', '0%'); + glassGradient.setAttribute('y1', '0%'); + glassGradient.setAttribute('x2', '0%'); + glassGradient.setAttribute('y2', '100%'); + + var stop1 = create('stop'); + stop1.setAttribute('offset', '0%'); + stop1.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.9'); + glassGradient.appendChild(stop1); + + var stop2 = create('stop'); + stop2.setAttribute('offset', '100%'); + stop2.setAttribute('style', 'stop-color:#ffffff;stop-opacity:0.1'); + glassGradient.appendChild(stop2); + + // Makes it the first entry of all gradients in defs + if (defs.firstChild.nextSibling != null) + { + defs.insertBefore(glassGradient, defs.firstChild.nextSibling); + } + else + { + defs.appendChild(glassGradient); + } + } + + // Glass gradient has hardcoded ID (see above) + currentState.gradient = '0'; + }, + + /** + * Function: rect + * + * Sets the current path to a rectangle. + */ + rect: function(x, y, w, h) + { + x += currentState.dx; + y += currentState.dy; + + currentNode = create('rect'); + currentNode.setAttribute('x', f2(x * currentState.scale)); + currentNode.setAttribute('y', f2(y * currentState.scale)); + currentNode.setAttribute('width', f2(w * currentState.scale)); + currentNode.setAttribute('height', f2(h * currentState.scale)); + + if (!styleEnabled && autoAntiAlias) + { + currentNode.setAttribute('shape-rendering', 'crispEdges'); + } + }, + + /** + * Function: roundrect + * + * Sets the current path to a rounded rectangle. + */ + roundrect: function(x, y, w, h, dx, dy) + { + x += currentState.dx; + y += currentState.dy; + + currentNode = create('rect'); + currentNode.setAttribute('x', f2(x * currentState.scale)); + currentNode.setAttribute('y', f2(y * currentState.scale)); + currentNode.setAttribute('width', f2(w * currentState.scale)); + currentNode.setAttribute('height', f2(h * currentState.scale)); + + if (dx > 0) + { + currentNode.setAttribute('rx', f2(dx * currentState.scale)); + } + + if (dy > 0) + { + currentNode.setAttribute('ry', f2(dy * currentState.scale)); + } + + if (!styleEnabled && autoAntiAlias) + { + currentNode.setAttribute('shape-rendering', 'crispEdges'); + } + }, + + /** + * Function: ellipse + * + * Sets the current path to an ellipse. + */ + ellipse: function(x, y, w, h) + { + x += currentState.dx; + y += currentState.dy; + + currentNode = create('ellipse'); + currentNode.setAttribute('cx', f2((x + w / 2) * currentState.scale)); + currentNode.setAttribute('cy', f2((y + h / 2) * currentState.scale)); + currentNode.setAttribute('rx', f2(w / 2 * currentState.scale)); + currentNode.setAttribute('ry', f2(h / 2 * currentState.scale)); + }, + + /** + * Function: image + * + * Paints an image. + */ + image: function(x, y, w, h, src, aspect, flipH, flipV) + { + src = converter.convert(src); + + // TODO: Add option for embedded images as base64. Current + // known issues are binary loading of cross-domain images. + aspect = (aspect != null) ? aspect : true; + flipH = (flipH != null) ? flipH : false; + flipV = (flipV != null) ? flipV : false; + x += currentState.dx; + y += currentState.dy; + + var node = create('image'); + node.setAttribute('x', f2(x * currentState.scale)); + node.setAttribute('y', f2(y * currentState.scale)); + node.setAttribute('width', f2(w * currentState.scale)); + node.setAttribute('height', f2(h * currentState.scale)); + + if (mxClient.IS_VML) + { + node.setAttribute('xlink:href', src); + } + else + { + node.setAttributeNS(mxConstants.NS_XLINK, 'xlink:href', src); + } + + if (!aspect) + { + node.setAttribute('preserveAspectRatio', 'none'); + } + + if (currentState.alpha < 1) + { + node.setAttribute('opacity', currentState.alpha); + } + + + var tr = currentState.transform; + + if (flipH || flipV) + { + var sx = 1; + var sy = 1; + var dx = 0; + var dy = 0; + + if (flipH) + { + sx = -1; + dx = -w - 2 * x; + } + + if (flipV) + { + sy = -1; + dy = -h - 2 * y; + } + + // Adds image tansformation to existing transforms + tr += 'scale(' + sx + ',' + sy + ')translate(' + dx + ',' + dy + ')'; + } + + if (tr.length > 0) + { + node.setAttribute('transform', tr); + } + + root.appendChild(node); + }, + + /** + * Function: text + * + * Paints the given text. Possible values for format are empty string for + * plain text and html for HTML markup. + */ + text: function(x, y, w, h, str, align, valign, vertical, wrap, format) + { + if (textEnabled) + { + x += currentState.dx; + y += currentState.dy; + + if (foEnabled && format == 'html') + { + var node = create('g'); + node.setAttribute('transform', currentState.transform + 'scale(' + currentState.scale + ',' + currentState.scale + ')'); + + if (currentState.alpha < 1) + { + node.setAttribute('opacity', currentState.alpha); + } + + var fo = create('foreignObject'); + fo.setAttribute('x', Math.round(x)); + fo.setAttribute('y', Math.round(y)); + fo.setAttribute('width', Math.round(w)); + fo.setAttribute('height', Math.round(h)); + fo.appendChild(createHtmlBody(str, align, valign)); + node.appendChild(fo); + root.appendChild(node); + } + else + { + var size = Math.floor(currentState.fontSize); + var node = create('g'); + var tr = currentState.transform; + + if (vertical) + { + var cx = x + w / 2; + var cy = y + h / 2; + tr += 'rotate(-90,' + f2(cx * currentState.scale) + ',' + f2(cy * currentState.scale) + ')'; + } + + if (tr.length > 0) + { + node.setAttribute('transform', tr); + } + + if (currentState.alpha < 1) + { + node.setAttribute('opacity', currentState.alpha); + } + + // Default is left + var anchor = (align == mxConstants.ALIGN_RIGHT) ? 'end' : + (align == mxConstants.ALIGN_CENTER) ? 'middle' : + 'start'; + + if (anchor == 'end') + { + x += Math.max(0, w - 2); + } + else if (anchor == 'middle') + { + x += w / 2; + } + else + { + x += (w > 0) ? 2 : 0; + } + + if ((currentState.fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD) + { + node.setAttribute('font-weight', 'bold'); + } + + if ((currentState.fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC) + { + node.setAttribute('font-style', 'italic'); + } + + if ((currentState.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) + { + node.setAttribute('text-decoration', 'underline'); + } + + // Text-anchor start is default in SVG + if (anchor != 'start') + { + node.setAttribute('text-anchor', anchor); + } + + if (!styleEnabled || size != mxConstants.DEFAULT_FONTSIZE) + { + node.setAttribute('font-size', Math.floor(size * currentState.scale) + 'px'); + } + + if (!styleEnabled || currentState.fontFamily != mxConstants.DEFAULT_FONTFAMILY) + { + node.setAttribute('font-family', currentState.fontFamily); + } + + node.setAttribute('fill', currentState.fontColor); + + var lines = str.split('\n'); + + var lineHeight = size * 1.25; + var textHeight = (h > 0) ? size + (lines.length - 1) * lineHeight : lines.length * lineHeight - 1; + var dy = h - textHeight; + + // Top is default + if (valign == null || valign == mxConstants.ALIGN_TOP) + { + y = Math.max(y - 3 * currentState.scale, y + dy / 2 + ((h > 0) ? lineHeight / 2 - 8 : 0)); + } + else if (valign == mxConstants.ALIGN_MIDDLE) + { + y = y + dy / 2; + } + else if (valign == mxConstants.ALIGN_BOTTOM) + { + y = Math.min(y, y + dy + 2 * currentState.scale); + } + + y += size; + + for (var i = 0; i < lines.length; i++) + { + var text = create('text'); + text.setAttribute('x', f2(x * currentState.scale)); + text.setAttribute('y', f2(y * currentState.scale)); + + mxUtils.write(text, lines[i]); + node.appendChild(text); + y += size * 1.3; + } + + root.appendChild(node); + } + } + }, + + /** + * Function: begin + * + * Starts a new path. + */ + begin: function() + { + currentNode = create('path'); + currentPath = []; + lastPoint = null; + currentPathIsOrthogonal = true; + }, + + /** + * Function: moveTo + * + * Moves the current path the given coordinates. + */ + moveTo: function(x, y) + { + if (currentPath != null) + { + x += currentState.dx; + y += currentState.dy; + currentPath.push('M ' + f2(x * currentState.scale) + ' ' + f2(y * currentState.scale)); + + if (autoAntiAlias) + { + lastPoint = new mxPoint(x, y); + } + } + }, + + /** + * Function: lineTo + * + * Adds a line to the current path. + */ + lineTo: function(x, y) + { + if (currentPath != null) + { + x += currentState.dx; + y += currentState.dy; + currentPath.push('L ' + f2(x * currentState.scale) + ' ' + f2(y * currentState.scale)); + + if (autoAntiAlias) + { + if (lastPoint != null && currentPathIsOrthogonal && x != lastPoint.x && y != lastPoint.y) + { + currentPathIsOrthogonal = false; + } + + lastPoint = new mxPoint(x, y); + } + } + }, + + /** + * Function: quadTo + * + * Adds a quadratic curve to the current path. + */ + quadTo: function(x1, y1, x2, y2) + { + if (currentPath != null) + { + x1 += currentState.dx; + y1 += currentState.dy; + x2 += currentState.dx; + y2 += currentState.dy; + currentPath.push('Q ' + f2(x1 * currentState.scale) + ' ' + f2(y1 * currentState.scale) + + ' ' + f2(x2 * currentState.scale) + ' ' + f2(y2 * currentState.scale)); + currentPathIsOrthogonal = false; + } + }, + + /** + * Function: curveTo + * + * Adds a bezier curve to the current path. + */ + curveTo: function(x1, y1, x2, y2, x3, y3) + { + if (currentPath != null) + { + x1 += currentState.dx; + y1 += currentState.dy; + x2 += currentState.dx; + y2 += currentState.dy; + x3 += currentState.dx; + y3 += currentState.dy; + currentPath.push('C ' + f2(x1 * currentState.scale) + ' ' + f2(y1 * currentState.scale) + + ' ' + f2(x2 * currentState.scale) + ' ' + f2(y2 * currentState.scale) +' ' + + f2(x3 * currentState.scale) + ' ' + f2(y3 * currentState.scale)); + currentPathIsOrthogonal = false; + } + }, + + /** + * Function: close + * + * Closes the current path. + */ + close: function() + { + if (currentPath != null) + { + currentPath.push('Z'); + } + }, + + /** + * Function: stroke + * + * Paints the outline of the current path. + */ + stroke: function() + { + appendNode(currentNode, currentState, false, true); + }, + + /** + * Function: fill + * + * Fills the current path. + */ + fill: function() + { + appendNode(currentNode, currentState, true, false); + }, + + /** + * Function: fillstroke + * + * Fills and paints the outline of the current path. + */ + fillAndStroke: function() + { + appendNode(currentNode, currentState, true, true); + }, + + /** + * Function: shadow + * + * Paints the current path as a shadow of the given color. + */ + shadow: function(value, filled) + { + this.save(); + this.setStrokeColor(value); + + if (filled) + { + this.setFillColor(value); + this.fillAndStroke(); + } + else + { + this.stroke(); + } + + this.restore(); + }, + + /** + * Function: clip + * + * Uses the current path for clipping. + */ + clip: function() + { + if (currentNode != null) + { + if (currentPath != null) + { + currentNode.setAttribute('d', currentPath.join(' ')); + currentPath = null; + } + + var id = ++refCount; + var clip = create('clipPath'); + clip.setAttribute('id', id); + clip.appendChild(currentNode); + defs.appendChild(clip); + currentState.clip = id; + } + } + }; + +};/** + * $Id: mxGuide.js,v 1.7 2012-04-13 12:53:30 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxGuide + * + * Implements the alignment of selection cells to other cells in the graph. + * + * Constructor: mxGuide + * + * Constructs a new guide object. + */ +function mxGuide(graph, states) +{ + this.graph = graph; + this.setStates(states); +}; + +/** + * Variable: graph + * + * Reference to the enclosing instance. + */ +mxGuide.prototype.graph = null; + +/** + * Variable: states + * + * Contains the that are used for alignment. + */ +mxGuide.prototype.states = null; + +/** + * Variable: horizontal + * + * Specifies if horizontal guides are enabled. Default is true. + */ +mxGuide.prototype.horizontal = true; + +/** + * Variable: vertical + * + * Specifies if vertical guides are enabled. Default is true. + */ +mxGuide.prototype.vertical = true; + +/** + * Variable: vertical + * + * Holds the for the horizontal guide. + */ +mxGuide.prototype.guideX = null; + +/** + * Variable: vertical + * + * Holds the for the vertical guide. + */ +mxGuide.prototype.guideY = null; + +/** + * Variable: crisp + * + * Specifies if theguide should be rendered in crisp mode if applicable. + * Default is true. + */ +mxGuide.prototype.crisp = true; + +/** + * Function: setStates + * + * Sets the that should be used for alignment. + */ +mxGuide.prototype.setStates = function(states) +{ + this.states = states; +}; + +/** + * Function: isEnabledForEvent + * + * Returns true if the guide should be enabled for the given native event. This + * implementation always returns true. + */ +mxGuide.prototype.isEnabledForEvent = function(evt) +{ + return true; +}; + +/** + * Function: getGuideTolerance + * + * Returns the tolerance for the guides. Default value is + * gridSize * scale / 2. + */ +mxGuide.prototype.getGuideTolerance = function() +{ + return this.graph.gridSize * this.graph.view.scale / 2; +}; + +/** + * Function: createGuideShape + * + * Returns the mxShape to be used for painting the respective guide. This + * implementation returns a new, dashed and crisp using + * and as the format. + * + * Parameters: + * + * horizontal - Boolean that specifies which guide should be created. + */ +mxGuide.prototype.createGuideShape = function(horizontal) +{ + var guide = new mxPolyline([], mxConstants.GUIDE_COLOR, mxConstants.GUIDE_STROKEWIDTH); + guide.crisp = this.crisp; + guide.isDashed = true; + + return guide; +}; + +/** + * Function: move + * + * Moves the by the given and returnt the snapped point. + */ +mxGuide.prototype.move = function(bounds, delta, gridEnabled) +{ + if (this.states != null && (this.horizontal || this.vertical) && bounds != null && delta != null) + { + var trx = this.graph.getView().translate; + var scale = this.graph.getView().scale; + var dx = delta.x; + var dy = delta.y; + + var overrideX = false; + var overrideY = false; + + var tt = this.getGuideTolerance(); + var ttX = tt; + var ttY = tt; + + var b = bounds.clone(); + b.x += delta.x; + b.y += delta.y; + + var left = b.x; + var right = b.x + b.width; + var center = b.getCenterX(); + var top = b.y; + var bottom = b.y + b.height; + var middle = b.getCenterY(); + + // Snaps the left, center and right to the given x-coordinate + function snapX(x) + { + x += this.graph.panDx; + var override = false; + + if (Math.abs(x - center) < ttX) + { + dx = x - bounds.getCenterX(); + ttX = Math.abs(x - center); + override = true; + } + else if (Math.abs(x - left) < ttX) + { + dx = x - bounds.x; + ttX = Math.abs(x - left); + override = true; + } + else if (Math.abs(x - right) < ttX) + { + dx = x - bounds.x - bounds.width; + ttX = Math.abs(x - right); + override = true; + } + + if (override) + { + if (this.guideX == null) + { + this.guideX = this.createGuideShape(true); + + // Makes sure to use either VML or SVG shapes in order to implement + // event-transparency on the background area of the rectangle since + // HTML shapes do not let mouseevents through even when transparent + this.guideX.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? + mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; + this.guideX.init(this.graph.getView().getOverlayPane()); + + if (this.graph.dialect == mxConstants.DIALECT_SVG) + { + this.guideX.node.setAttribute('pointer-events', 'none'); + this.guideX.pipe.setAttribute('pointer-events', 'none'); + } + } + + var c = this.graph.container; + x -= this.graph.panDx; + this.guideX.points = [new mxPoint(x, -this.graph.panDy), new mxPoint(x, c.scrollHeight - 3 - this.graph.panDy)]; + } + + overrideX = overrideX || override; + }; + + // Snaps the top, middle or bottom to the given y-coordinate + function snapY(y) + { + y += this.graph.panDy; + var override = false; + + if (Math.abs(y - middle) < ttY) + { + dy = y - bounds.getCenterY(); + ttY = Math.abs(y - middle); + override = true; + } + else if (Math.abs(y - top) < ttY) + { + dy = y - bounds.y; + ttY = Math.abs(y - top); + override = true; + } + else if (Math.abs(y - bottom) < ttY) + { + dy = y - bounds.y - bounds.height; + ttY = Math.abs(y - bottom); + override = true; + } + + if (override) + { + if (this.guideY == null) + { + this.guideY = this.createGuideShape(false); + + // Makes sure to use either VML or SVG shapes in order to implement + // event-transparency on the background area of the rectangle since + // HTML shapes do not let mouseevents through even when transparent + this.guideY.dialect = (this.graph.dialect != mxConstants.DIALECT_SVG) ? + mxConstants.DIALECT_VML : mxConstants.DIALECT_SVG; + this.guideY.init(this.graph.getView().getOverlayPane()); + + if (this.graph.dialect == mxConstants.DIALECT_SVG) + { + this.guideY.node.setAttribute('pointer-events', 'none'); + this.guideY.pipe.setAttribute('pointer-events', 'none'); + } + } + + var c = this.graph.container; + y -= this.graph.panDy; + this.guideY.points = [new mxPoint(-this.graph.panDx, y), new mxPoint(c.scrollWidth - 3 - this.graph.panDx, y)]; + } + + overrideY = overrideY || override; + }; + + for (var i = 0; i < this.states.length; i++) + { + var state = this.states[i]; + + if (state != null) + { + // Align x + if (this.horizontal) + { + snapX.call(this, state.getCenterX()); + snapX.call(this, state.x); + snapX.call(this, state.x + state.width); + } + + // Align y + if (this.vertical) + { + snapY.call(this, state.getCenterY()); + snapY.call(this, state.y); + snapY.call(this, state.y + state.height); + } + } + } + + if (!overrideX && this.guideX != null) + { + this.guideX.node.style.visibility = 'hidden'; + } + else if (this.guideX != null) + { + this.guideX.node.style.visibility = 'visible'; + this.guideX.redraw(); + } + + if (!overrideY && this.guideY != null) + { + this.guideY.node.style.visibility = 'hidden'; + } + else if (this.guideY != null) + { + this.guideY.node.style.visibility = 'visible'; + this.guideY.redraw(); + } + + // Moves cells that are off-grid back to the grid on move + if (gridEnabled) + { + if (!overrideX) + { + var tx = bounds.x - (this.graph.snap(bounds.x / + scale - trx.x) + trx.x) * scale; + dx = this.graph.snap(dx / scale) * scale - tx; + } + + if (!overrideY) + { + var ty = bounds.y - (this.graph.snap(bounds.y / + scale - trx.y) + trx.y) * scale; + dy = this.graph.snap(dy / scale) * scale - ty; + } + } + + delta = new mxPoint(dx, dy); + } + + return delta; +}; + +/** + * Function: hide + * + * Hides all current guides. + */ +mxGuide.prototype.hide = function() +{ + if (this.guideX != null) + { + this.guideX.node.style.visibility = 'hidden'; + } + + if (this.guideY != null) + { + this.guideY.node.style.visibility = 'hidden'; + } +}; + +/** + * Function: destroy + * + * Destroys all resources that this object uses. + */ +mxGuide.prototype.destroy = function() +{ + if (this.guideX != null) + { + this.guideX.destroy(); + this.guideX = null; + } + + if (this.guideY != null) + { + this.guideY.destroy(); + this.guideY = null; + } +}; +/** + * $Id: mxShape.js,v 1.171 2012-05-23 08:22:29 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxShape + * + * Base class for all shapes. A shape in mxGraph is a + * separate implementation for SVG, VML and HTML. Which + * implementation to use is controlled by the + * property which is assigned from within the + * when the shape is created. The dialect must be assigned + * for a shape, and it does normally depend on the browser and + * the confiuration of the graph (see rendering hint). + * + * For each supported shape in SVG and VML, a corresponding + * shape exists in mxGraph, namely for text, image, rectangle, + * rhombus, ellipse and polyline. The other shapes are a + * combination of these shapes (eg. label and swimlane) + * or they consist of one or more (filled) path objects + * (eg. actor and cylinder). The HTML implementation is + * optional but may be required for a HTML-only view of + * the graph. + * + * Custom Shapes: + * + * To extend from this class, the basic code looks as follows. + * In the special case where the custom shape consists only of + * one filled region or one filled region and an additional stroke + * the and should be subclassed, + * respectively. These implement in order to create + * the path expression for VML and SVG via a unified API (see + * ). has an additional boolean + * argument to draw the foreground and background separately. + * + * (code) + * function CustomShape() { } + * + * CustomShape.prototype = new mxShape(); + * CustomShape.prototype.constructor = CustomShape; + * (end) + * + * To register a custom shape in an existing graph instance, + * one must register the shape under a new name in the graph's + * cell renderer as follows: + * + * (code) + * graph.cellRenderer.registerShape('customShape', CustomShape); + * (end) + * + * The second argument is the name of the constructor. + * + * In order to use the shape you can refer to the given name above + * in a stylesheet. For example, to change the shape for the default + * vertex style, the following code is used: + * + * (code) + * var style = graph.getStylesheet().getDefaultVertexStyle(); + * style[mxConstants.STYLE_SHAPE] = 'customShape'; + * (end) + * + * Constructor: mxShape + * + * Constructs a new shape. + */ +function mxShape() { }; + +/** + * Variable: SVG_STROKE_TOLERANCE + * + * Event-tolerance for SVG strokes (in px). Default is 8. + */ +mxShape.prototype.SVG_STROKE_TOLERANCE = 8; + +/** + * Variable: scale + * + * Holds the scale in which the shape is being painted. + */ +mxShape.prototype.scale = 1; + +/** + * Variable: dialect + * + * Holds the dialect in which the shape is to be painted. + * This can be one of the DIALECT constants in . + */ +mxShape.prototype.dialect = null; + +/** + * Variable: crisp + * + * Special attribute for SVG rendering to set the shape-rendering attribute to + * crispEdges in the output. This is ignored in IE. Default is false. To + * disable antialias in IE, the explorer.css file can be changed as follows: + * + * [code] + * v\:* { + * behavior: url(#default#VML); + * antialias: false; + * } + * [/code] + */ +mxShape.prototype.crisp = false; + +/** + * Variable: roundedCrispSvg + * + * Specifies if crisp rendering should be enabled for rounded shapes. + * Default is true. + */ +mxShape.prototype.roundedCrispSvg = true; + +/** + * Variable: mixedModeHtml + * + * Specifies if should be used in mixed Html mode. + * Default is true. + */ +mxShape.prototype.mixedModeHtml = true; + +/** + * Variable: preferModeHtml + * + * Specifies if should be used in prefer Html mode. + * Default is true. + */ +mxShape.prototype.preferModeHtml = true; + +/** + * Variable: bounds + * + * Holds the that specifies the bounds of this shape. + */ +mxShape.prototype.bounds = null; + +/** + * Variable: points + * + * Holds the array of that specify the points of this shape. + */ +mxShape.prototype.points = null; + +/** + * Variable: node + * + * Holds the outermost DOM node that represents this shape. + */ +mxShape.prototype.node = null; + +/** + * Variable: label + * + * Reference to the DOM node that should contain the label. This is null + * if the label should be placed inside or . + */ +mxShape.prototype.label = null; + +/** + * Variable: innerNode + * + * Holds the DOM node that graphically represents this shape. This may be + * null if the outermost DOM represents this shape. + */ +mxShape.prototype.innerNode = null; + +/** + * Variable: style + * + * Holds the style of the cell state that corresponds to this shape. This may + * be null if the shape is used directly, without a cell state. + */ +mxShape.prototype.style = null; + +/** + * Variable: startOffset + * + * Specifies the offset in pixels from the first point in and + * the actual start of the shape. + */ +mxShape.prototype.startOffset = null; + +/** + * Variable: endOffset + * + * Specifies the offset in pixels from the last point in and + * the actual start of the shape. + */ +mxShape.prototype.endOffset = null; + +/** + * Variable: boundingBox + * + * Contains the bounding box of the shape, that is, the smallest rectangle + * that includes all pixels of the shape. + */ +mxShape.prototype.boundingBox = null; + +/** + * Variable: vmlNodes + * + * Array if VML node names to fix in IE8 standards mode. + */ +mxShape.prototype.vmlNodes = ['node', 'strokeNode', 'fillNode', 'shadowNode']; + +/** + * Variable: vmlScale + * + * Internal scaling for VML using coordsize for better precision. + */ +mxShape.prototype.vmlScale = 1; + +/** + * Function: setCursor + * + * Sets the cursor on the given shape. + * + * Parameters: + * + * cursor - The cursor to be used. + */ +mxShape.prototype.setCursor = function(cursor) +{ + if (cursor == null) + { + cursor = ''; + } + + this.cursor = cursor; + + if (this.innerNode != null) + { + this.innerNode.style.cursor = cursor; + } + + if (this.node != null) + { + this.node.style.cursor = cursor; + } + + if (this.pipe != null) + { + this.pipe.style.cursor = cursor; + } +}; + +/** + * Function: getCursor + * + * Returns the current cursor. + */ +mxShape.prototype.getCursor = function() +{ + return this.cursor; +}; + +/** + * Function: init + * + * Initializes the shape by creaing the DOM node using + * and adding it into the given container. + * + * Parameters: + * + * container - DOM node that will contain the shape. + */ +mxShape.prototype.init = function(container) +{ + if (this.node == null) + { + this.node = this.create(container); + + if (container != null) + { + // Workaround for broken VML in IE8 standards mode. This gives an ID to + // each element that is referenced from this instance. After adding the + // DOM to the document, the outerHTML is overwritten to fix the VML + // rendering and the references are restored. + var vmlFix = document.documentMode == 8 && mxUtils.isVml(this.node); + + if (vmlFix) + { + // Assigns temporary IDs to VML nodes so that references can be restored when + // inserted into the DOM as a string + for (var i = 0; i < this.vmlNodes.length; i++) + { + if (this[this.vmlNodes[i]] != null) + { + this[this.vmlNodes[i]].setAttribute('id', 'mxTemporaryReference-' + this.vmlNodes[i]); + } + } + + // Inserts the node as a string + container.insertAdjacentHTML('beforeEnd', this.node.outerHTML); + + // Restores references to the actual DOM nodes + for (var i = 0; i < this.vmlNodes.length; i++) + { + if (this[this.vmlNodes[i]] != null) + { + this[this.vmlNodes[i]] = container.ownerDocument.getElementById('mxTemporaryReference-' + this.vmlNodes[i]); + this[this.vmlNodes[i]].removeAttribute('id'); + } + } + } + else + { + container.appendChild(this.node); + } + } + } + + // Gradients are inserted late when the owner SVG element is known + if (this.insertGradientNode != null) + { + this.insertGradient(this.insertGradientNode); + this.insertGradientNode = null; + } +}; + +/** + * Function: insertGradient + * + * Inserts the given gradient node. + */ +mxShape.prototype.insertGradient = function(node) +{ + // Gradients are inserted late when the owner SVG element is known + if (node != null) + { + // Checks if the given gradient already exists inside the SVG element + // that also contains the node that represents this shape. If the gradient + // with the same ID exists in another SVG element, then this will add + // a copy of the gradient with a different ID to the SVG element and update + // the reference accordingly. This is required in Firefox because if the + // referenced fill element is removed from the DOM the shape appears black. + var count = 0; + var id = node.getAttribute('id'); + var gradient = document.getElementById(id); + + while (gradient != null && gradient.ownerSVGElement != this.node.ownerSVGElement) + { + count++; + id = node.getAttribute('id') + '-' + count; + gradient = document.getElementById(id); + } + + // According to specification, gradients should be put in a defs + // section in the first child of the owner SVG element. However, + // it turns out that gradients only work when added as follows. + if (gradient == null) + { + node.setAttribute('id', id); + this.node.ownerSVGElement.appendChild(node); + gradient = node; + } + + if (gradient != null) + { + var ref = 'url(#' + id + ')'; + var tmp = (this.innerNode != null) ? this.innerNode : this.node; + + if (tmp != null && tmp.getAttribute('fill') != ref) + { + tmp.setAttribute('fill', ref); + } + } + } +}; + +/** + * Function: isMixedModeHtml + * + * Used to determine if a shape can be rendered using in mixed + * mode Html without compromising the display accuracy. The default + * implementation will check if the shape is not rounded and has no + * gradient, and will use a DIV if that is the case. It will also check if + * is true, which is the default settings. + * Subclassers can either override or this function if the + * result depends on dynamic values. The graph's dialect is available via + * . + */ +mxShape.prototype.isMixedModeHtml = function() +{ + return this.mixedModeHtml && !this.isRounded && !this.isShadow && this.gradient == null && + mxUtils.getValue(this.style, mxConstants.STYLE_GLASS, 0) == 0; +}; + +/** + * Function: create + * + * Creates and returns the DOM node(s) for the shape in + * the given container. This implementation invokes + * , or depending + * on the and style settings. + * + * Parameters: + * + * container - DOM node that will contain the shape. + */ +mxShape.prototype.create = function(container) +{ + var node = null; + + if (this.dialect == mxConstants.DIALECT_SVG) + { + node = this.createSvg(); + } + else if (this.dialect == mxConstants.DIALECT_STRICTHTML || + (this.preferModeHtml && this.dialect == mxConstants.DIALECT_PREFERHTML) || + (this.isMixedModeHtml() && this.dialect == mxConstants.DIALECT_MIXEDHTML)) + { + node = this.createHtml(); + } + else + { + node = this.createVml(); + } + + return node; +}; + +/** + * Function: createHtml + * + * Creates and returns the HTML DOM node(s) to represent + * this shape. This implementation falls back to + * so that the HTML creation is optional. + */ +mxShape.prototype.createHtml = function() +{ + var node = document.createElement('DIV'); + this.configureHtmlShape(node); + + return node; +}; + +/** + * Function: destroy + * + * Destroys the shape by removing it from the DOM and releasing the DOM + * node associated with the shape using . + */ +mxShape.prototype.destroy = function() +{ + if (this.node != null) + { + mxEvent.release(this.node); + + if (this.node.parentNode != null) + { + this.node.parentNode.removeChild(this.node); + } + + if (this.node.glassOverlay) + { + this.node.glassOverlay.parentNode.removeChild(this.node.glassOverlay); + this.node.glassOverlay = null; + } + + this.node = null; + } +}; + +/** + * Function: apply + * + * Applies the style of the given to the shape. This + * implementation assigns the following styles to local fields: + * + * - => fill + * - => gradient + * - => gradientDirection + * - => opacity + * - => stroke + * - => strokewidth + * - => isShadow + * - => isDashed + * - => spacing + * - => startSize + * - => endSize + * - => isRounded + * - => startArrow + * - => endArrow + * - => rotation + * - => direction + * + * This keeps a reference to the '); +}; + +/** + * Function: createPageSelector + * + * Creates the page selector table. + */ +mxPrintPreview.prototype.createPageSelector = function(vpages, hpages) +{ + var doc = this.wnd.document; + var table = doc.createElement('table'); + table.className = 'mxPageSelector'; + table.setAttribute('border', '0'); + + var tbody = doc.createElement('tbody'); + + for (var i = 0; i < vpages; i++) + { + var row = doc.createElement('tr'); + + for (var j = 0; j < hpages; j++) + { + var pageNum = i * hpages + j + 1; + var cell = doc.createElement('td'); + + // Needs anchor for all browers to work without JavaScript + // LATER: Does not work in Firefox because the generated document + // has the URL of the opening document, the anchor is appended + // to that URL and the full URL is loaded on click. + if (!mxClient.IS_NS || mxClient.IS_SF || mxClient.IS_GC) + { + var a = doc.createElement('a'); + a.setAttribute('href', '#mxPage-' + pageNum); + mxUtils.write(a, pageNum, doc); + cell.appendChild(a); + } + else + { + mxUtils.write(cell, pageNum, doc); + } + + row.appendChild(cell); + } + + tbody.appendChild(row); + } + + table.appendChild(tbody); + + return table; +}; + +/** + * Function: renderPage + * + * Creates a DIV that prints a single page of the given + * graph using the given scale and returns the DIV that + * represents the page. + * + * Parameters: + * + * w - Width of the page in pixels. + * h - Height of the page in pixels. + * dx - Horizontal translation for the diagram. + * dy - Vertical translation for the diagram. + * scale - Scale for the diagram. + * pageNumber - Number of the page to be rendered. + */ +mxPrintPreview.prototype.renderPage = function(w, h, dx, dy, scale, pageNumber) +{ + var div = document.createElement('div'); + + try + { + div.style.width = w + 'px'; + div.style.height = h + 'px'; + div.style.overflow = 'hidden'; + div.style.pageBreakInside = 'avoid'; + + var innerDiv = document.createElement('div'); + innerDiv.style.top = this.border + 'px'; + innerDiv.style.left = this.border + 'px'; + innerDiv.style.width = (w - 2 * this.border) + 'px'; + innerDiv.style.height = (h - 2 * this.border) + 'px'; + innerDiv.style.overflow = 'hidden'; + + if (this.graph.dialect == mxConstants.DIALECT_VML) + { + innerDiv.style.position = 'absolute'; + } + + div.appendChild(innerDiv); + document.body.appendChild(div); + var view = this.graph.getView(); + + var previousContainer = this.graph.container; + this.graph.container = innerDiv; + + var canvas = view.getCanvas(); + var backgroundPane = view.getBackgroundPane(); + var drawPane = view.getDrawPane(); + var overlayPane = view.getOverlayPane(); + + if (this.graph.dialect == mxConstants.DIALECT_SVG) + { + view.createSvg(); + } + else if (this.graph.dialect == mxConstants.DIALECT_VML) + { + view.createVml(); + } + else + { + view.createHtml(); + } + + // Disables events on the view + var eventsEnabled = view.isEventsEnabled(); + view.setEventsEnabled(false); + + // Disables the graph to avoid cursors + var graphEnabled = this.graph.isEnabled(); + this.graph.setEnabled(false); + + // Resets the translation + var translate = view.getTranslate(); + view.translate = new mxPoint(dx, dy); + + var temp = null; + + try + { + // Creates the temporary cell states in the view and + // draws them onto the temporary DOM nodes in the view + var model = this.graph.getModel(); + var cells = [model.getRoot()]; + temp = new mxTemporaryCellStates(view, scale, cells); + } + finally + { + // Removes overlay pane with selection handles + // controls and icons from the print output + if (mxClient.IS_IE) + { + view.overlayPane.innerHTML = ''; + } + else + { + // Removes everything but the SVG node + var tmp = innerDiv.firstChild; + + while (tmp != null) + { + var next = tmp.nextSibling; + var name = tmp.nodeName.toLowerCase(); + + // Note: Width and heigh are required in FF 11 + if (name == 'svg') + { + tmp.setAttribute('width', parseInt(innerDiv.style.width)); + tmp.setAttribute('height', parseInt(innerDiv.style.height)); + } + // Tries to fetch all text labels and only text labels + else if (tmp.style.cursor != 'default' && name != 'table') + { + tmp.parentNode.removeChild(tmp); + } + + tmp = next; + } + } + + // Completely removes the overlay pane to remove more handles + view.overlayPane.parentNode.removeChild(view.overlayPane); + + // Restores the state of the view + this.graph.setEnabled(graphEnabled); + this.graph.container = previousContainer; + view.canvas = canvas; + view.backgroundPane = backgroundPane; + view.drawPane = drawPane; + view.overlayPane = overlayPane; + view.translate = translate; + temp.destroy(); + view.setEventsEnabled(eventsEnabled); + } + } + catch (e) + { + div.parentNode.removeChild(div); + div = null; + + throw e; + } + + return div; +}; + +/** + * Function: print + * + * Opens the print preview and shows the print dialog. + */ +mxPrintPreview.prototype.print = function() +{ + var wnd = this.open(); + + if (wnd != null) + { + wnd.print(); + } +}; + +/** + * Function: close + * + * Closes the print preview window. + */ +mxPrintPreview.prototype.close = function() +{ + if (this.wnd != null) + { + this.wnd.close(); + this.wnd = null; + } +}; +/** + * $Id: mxStylesheet.js,v 1.35 2010-03-26 10:24:58 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxStylesheet + * + * Defines the appearance of the cells in a graph. See for an + * example of creating a new cell style. It is recommended to use objects, not + * arrays for holding cell styles. Existing styles can be cloned using + * and turned into a string for debugging using + * . + * + * Default Styles: + * + * The stylesheet contains two built-in styles, which are used if no style is + * defined for a cell: + * + * defaultVertex - Default style for vertices + * defaultEdge - Default style for edges + * + * Example: + * + * (code) + * var vertexStyle = stylesheet.getDefaultVertexStyle(); + * vertexStyle[mxConstants.ROUNDED] = true; + * var edgeStyle = stylesheet.getDefaultEdgeStyle(); + * edgeStyle[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation; + * (end) + * + * Modifies the built-in default styles. + * + * To avoid the default style for a cell, add a leading semicolon + * to the style definition, eg. + * + * (code) + * ;shadow=1 + * (end) + * + * Removing keys: + * + * For removing a key in a cell style of the form [stylename;|key=value;] the + * special value none can be used, eg. highlight;fillColor=none + * + * See also the helper methods in mxUtils to modify strings of this format, + * namely , , + * , , + * and . + * + * Constructor: mxStylesheet + * + * Constructs a new stylesheet and assigns default styles. + */ +function mxStylesheet() +{ + this.styles = new Object(); + + this.putDefaultVertexStyle(this.createDefaultVertexStyle()); + this.putDefaultEdgeStyle(this.createDefaultEdgeStyle()); +}; + +/** + * Function: styles + * + * Maps from names to cell styles. Each cell style is a map of key, + * value pairs. + */ +mxStylesheet.prototype.styles; + +/** + * Function: createDefaultVertexStyle + * + * Creates and returns the default vertex style. + */ +mxStylesheet.prototype.createDefaultVertexStyle = function() +{ + var style = new Object(); + + style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE; + style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter; + style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE; + style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER; + style[mxConstants.STYLE_FILLCOLOR] = '#C3D9FF'; + style[mxConstants.STYLE_STROKECOLOR] = '#6482B9'; + style[mxConstants.STYLE_FONTCOLOR] = '#774400'; + + return style; +}; + +/** + * Function: createDefaultEdgeStyle + * + * Creates and returns the default edge style. + */ +mxStylesheet.prototype.createDefaultEdgeStyle = function() +{ + var style = new Object(); + + style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_CONNECTOR; + style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC; + style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE; + style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER; + style[mxConstants.STYLE_STROKECOLOR] = '#6482B9'; + style[mxConstants.STYLE_FONTCOLOR] = '#446299'; + + return style; +}; + +/** + * Function: putDefaultVertexStyle + * + * Sets the default style for vertices using defaultVertex as the + * stylename. + * + * Parameters: + * style - Key, value pairs that define the style. + */ +mxStylesheet.prototype.putDefaultVertexStyle = function(style) +{ + this.putCellStyle('defaultVertex', style); +}; + +/** + * Function: putDefaultEdgeStyle + * + * Sets the default style for edges using defaultEdge as the stylename. + */ +mxStylesheet.prototype.putDefaultEdgeStyle = function(style) +{ + this.putCellStyle('defaultEdge', style); +}; + +/** + * Function: getDefaultVertexStyle + * + * Returns the default style for vertices. + */ +mxStylesheet.prototype.getDefaultVertexStyle = function() +{ + return this.styles['defaultVertex']; +}; + +/** + * Function: getDefaultEdgeStyle + * + * Sets the default style for edges. + */ +mxStylesheet.prototype.getDefaultEdgeStyle = function() +{ + return this.styles['defaultEdge']; +}; + +/** + * Function: putCellStyle + * + * Stores the given map of key, value pairs under the given name in + * . + * + * Example: + * + * The following example adds a new style called 'rounded' into an + * existing stylesheet: + * + * (code) + * var style = new Object(); + * style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE; + * style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter; + * style[mxConstants.STYLE_ROUNDED] = true; + * graph.getStylesheet().putCellStyle('rounded', style); + * (end) + * + * In the above example, the new style is an object. The possible keys of + * the object are all the constants in that start with STYLE + * and the values are either JavaScript objects, such as + * (which is in fact a function) + * or expressions, such as true. Note that not all keys will be + * interpreted by all shapes (eg. the line shape ignores the fill color). + * The final call to this method associates the style with a name in the + * stylesheet. The style is used in a cell with the following code: + * + * (code) + * model.setStyle(cell, 'rounded'); + * (end) + * + * Parameters: + * + * name - Name for the style to be stored. + * style - Key, value pairs that define the style. + */ +mxStylesheet.prototype.putCellStyle = function(name, style) +{ + this.styles[name] = style; +}; + +/** + * Function: getCellStyle + * + * Returns the cell style for the specified stylename or the given + * defaultStyle if no style can be found for the given stylename. + * + * Parameters: + * + * name - String of the form [(stylename|key=value);] that represents the + * style. + * defaultStyle - Default style to be returned if no style can be found. + */ +mxStylesheet.prototype.getCellStyle = function(name, defaultStyle) +{ + var style = defaultStyle; + + if (name != null && name.length > 0) + { + var pairs = name.split(';'); + + if (style != null && + name.charAt(0) != ';') + { + style = mxUtils.clone(style); + } + else + { + style = new Object(); + } + + // Parses each key, value pair into the existing style + for (var i = 0; i < pairs.length; i++) + { + var tmp = pairs[i]; + var pos = tmp.indexOf('='); + + if (pos >= 0) + { + var key = tmp.substring(0, pos); + var value = tmp.substring(pos + 1); + + if (value == mxConstants.NONE) + { + delete style[key]; + } + else if (mxUtils.isNumeric(value)) + { + style[key] = parseFloat(value); + } + else + { + style[key] = value; + } + } + else + { + // Merges the entries from a named style + var tmpStyle = this.styles[tmp]; + + if (tmpStyle != null) + { + for (var key in tmpStyle) + { + style[key] = tmpStyle[key]; + } + } + } + } + } + + return style; +}; +/** + * $Id: mxCellState.js,v 1.42 2012-03-19 10:47:08 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxCellState + * + * Represents the current state of a cell in a given . + * + * For edges, the edge label position is stored in . + * + * The size for oversize labels can be retrieved using the boundingBox property + * of the field as shown below. + * + * (code) + * var bbox = (state.text != null) ? state.text.boundingBox : null; + * (end) + * + * Constructor: mxCellState + * + * Constructs a new object that represents the current state of the given + * cell in the specified view. + * + * Parameters: + * + * view - that contains the state. + * cell - that this state represents. + * style - Array of key, value pairs that constitute the style. + */ +function mxCellState(view, cell, style) +{ + this.view = view; + this.cell = cell; + this.style = style; + + this.origin = new mxPoint(); + this.absoluteOffset = new mxPoint(); +}; + +/** + * Extends mxRectangle. + */ +mxCellState.prototype = new mxRectangle(); +mxCellState.prototype.constructor = mxCellState; + +/** + * Variable: view + * + * Reference to the enclosing . + */ +mxCellState.prototype.view = null; + +/** + * Variable: cell + * + * Reference to the that is represented by this state. + */ +mxCellState.prototype.cell = null; + +/** + * Variable: style + * + * Contains an array of key, value pairs that represent the style of the + * cell. + */ +mxCellState.prototype.style = null; + +/** + * Variable: invalid + * + * Specifies if the state is invalid. Default is true. + */ +mxCellState.prototype.invalid = true; + +/** + * Variable: invalidOrder + * + * Specifies if the cell has an invalid order. For internal use. Default is + * false. + */ +mxCellState.prototype.invalidOrder = false; + +/** + * Variable: orderChanged + * + * Specifies if the cell has changed order and the display needs to be + * updated. + */ +mxCellState.prototype.orderChanged = false; + +/** + * Variable: origin + * + * that holds the origin for all child cells. Default is a new + * empty . + */ +mxCellState.prototype.origin = null; + +/** + * Variable: absolutePoints + * + * Holds an array of that represent the absolute points of an + * edge. + */ +mxCellState.prototype.absolutePoints = null; + +/** + * Variable: absoluteOffset + * + * that holds the absolute offset. For edges, this is the + * absolute coordinates of the label position. For vertices, this is the + * offset of the label relative to the top, left corner of the vertex. + */ +mxCellState.prototype.absoluteOffset = null; + +/** + * Variable: visibleSourceState + * + * Caches the visible source terminal state. + */ +mxCellState.prototype.visibleSourceState = null; + +/** + * Variable: visibleTargetState + * + * Caches the visible target terminal state. + */ +mxCellState.prototype.visibleTargetState = null; + +/** + * Variable: terminalDistance + * + * Caches the distance between the end points for an edge. + */ +mxCellState.prototype.terminalDistance = 0; + +/** + * Variable: length + * + * Caches the length of an edge. + */ +mxCellState.prototype.length = 0; + +/** + * Variable: segments + * + * Array of numbers that represent the cached length of each segment of the + * edge. + */ +mxCellState.prototype.segments = null; + +/** + * Variable: shape + * + * Holds the that represents the cell graphically. + */ +mxCellState.prototype.shape = null; + +/** + * Variable: text + * + * Holds the that represents the label of the cell. Thi smay be + * null if the cell has no label. + */ +mxCellState.prototype.text = null; + +/** + * Function: getPerimeterBounds + * + * Returns the that should be used as the perimeter of the + * cell. + * + * Parameters: + * + * border - Optional border to be added around the perimeter bounds. + * bounds - Optional to be used as the initial bounds. + */ +mxCellState.prototype.getPerimeterBounds = function (border, bounds) +{ + border = border || 0; + bounds = (bounds != null) ? bounds : new mxRectangle(this.x, this.y, this.width, this.height); + + if (this.shape != null && this.shape.stencil != null) + { + var aspect = this.shape.stencil.computeAspect(this, bounds, null); + + bounds.x = aspect.x; + bounds.y = aspect.y; + bounds.width = this.shape.stencil.w0 * aspect.width; + bounds.height = this.shape.stencil.h0 * aspect.height; + } + + if (border != 0) + { + bounds.grow(border); + } + + return bounds; +}; + +/** + * Function: setAbsoluteTerminalPoint + * + * Sets the first or last point in depending on isSource. + * + * Parameters: + * + * point - that represents the terminal point. + * isSource - Boolean that specifies if the first or last point should + * be assigned. + */ +mxCellState.prototype.setAbsoluteTerminalPoint = function (point, isSource) +{ + if (isSource) + { + if (this.absolutePoints == null) + { + this.absolutePoints = []; + } + + if (this.absolutePoints.length == 0) + { + this.absolutePoints.push(point); + } + else + { + this.absolutePoints[0] = point; + } + } + else + { + if (this.absolutePoints == null) + { + this.absolutePoints = []; + this.absolutePoints.push(null); + this.absolutePoints.push(point); + } + else if (this.absolutePoints.length == 1) + { + this.absolutePoints.push(point); + } + else + { + this.absolutePoints[this.absolutePoints.length - 1] = point; + } + } +}; + +/** + * Function: setCursor + * + * Sets the given cursor on the shape and text shape. + */ +mxCellState.prototype.setCursor = function (cursor) +{ + if (this.shape != null) + { + this.shape.setCursor(cursor); + } + + if (this.text != null) + { + this.text.setCursor(cursor); + } +}; + +/** + * Function: getVisibleTerminal + * + * Returns the visible source or target terminal cell. + * + * Parameters: + * + * source - Boolean that specifies if the source or target cell should be + * returned. + */ +mxCellState.prototype.getVisibleTerminal = function (source) +{ + var tmp = this.getVisibleTerminalState(source); + + return (tmp != null) ? tmp.cell : null; +}; + +/** + * Function: getVisibleTerminalState + * + * Returns the visible source or target terminal state. + * + * Parameters: + * + * source - Boolean that specifies if the source or target state should be + * returned. + */ +mxCellState.prototype.getVisibleTerminalState = function (source) +{ + return (source) ? this.visibleSourceState : this.visibleTargetState; +}; + +/** + * Function: setVisibleTerminalState + * + * Sets the visible source or target terminal state. + * + * Parameters: + * + * terminalState - that represents the terminal. + * source - Boolean that specifies if the source or target state should be set. + */ +mxCellState.prototype.setVisibleTerminalState = function (terminalState, source) +{ + if (source) + { + this.visibleSourceState = terminalState; + } + else + { + this.visibleTargetState = terminalState; + } +}; + +/** + * Destructor: destroy + * + * Destroys the state and all associated resources. + */ +mxCellState.prototype.destroy = function () +{ + this.view.graph.cellRenderer.destroy(this); +}; + +/** + * Function: clone + * + * Returns a clone of this . + */ +mxCellState.prototype.clone = function() +{ + var clone = new mxCellState(this.view, this.cell, this.style); + + // Clones the absolute points + if (this.absolutePoints != null) + { + clone.absolutePoints = []; + + for (var i = 0; i < this.absolutePoints.length; i++) + { + clone.absolutePoints[i] = this.absolutePoints[i].clone(); + } + } + + if (this.origin != null) + { + clone.origin = this.origin.clone(); + } + + if (this.absoluteOffset != null) + { + clone.absoluteOffset = this.absoluteOffset.clone(); + } + + if (this.boundingBox != null) + { + clone.boundingBox = this.boundingBox.clone(); + } + + clone.terminalDistance = this.terminalDistance; + clone.segments = this.segments; + clone.length = this.length; + clone.x = this.x; + clone.y = this.y; + clone.width = this.width; + clone.height = this.height; + + return clone; +}; +/** + * $Id: mxGraphSelectionModel.js,v 1.14 2011-11-25 10:16:08 gaudenz Exp $ + * Copyright (c) 2006-2010, JGraph Ltd + */ +/** + * Class: mxGraphSelectionModel + * + * Implements the selection model for a graph. Here is a listener that handles + * all removed selection cells. + * + * (code) + * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt) + * { + * var cells = evt.getProperty('added'); + * + * for (var i = 0; i < cells.length; i++) + * { + * // Handle cells[i]... + * } + * }); + * (end) + * + * Event: mxEvent.UNDO + * + * Fires after the selection was changed in . The + * edit property contains the which contains the + * . + * + * Event: mxEvent.CHANGE + * + * Fires after the selection changes by executing an . The + * added and removed properties contain arrays of + * cells that have been added to or removed from the selection, respectively. + * + * Constructor: mxGraphSelectionModel + * + * Constructs a new graph selection model for the given . + * + * Parameters: + * + * graph - Reference to the enclosing . + */ +function mxGraphSelectionModel(graph) +{ + this.graph = graph; + this.cells = []; +}; + +/** + * Extends mxEventSource. + */ +mxGraphSelectionModel.prototype = new mxEventSource(); +mxGraphSelectionModel.prototype.constructor = mxGraphSelectionModel; + +/** + * Variable: doneResource + * + * Specifies the resource key for the status message after a long operation. + * If the resource for this key does not exist then the value is used as + * the status message. Default is 'done'. + */ +mxGraphSelectionModel.prototype.doneResource = (mxClient.language != 'none') ? 'done' : ''; + +/** + * Variable: updatingSelectionResource + * + * Specifies the resource key for the status message while the selection is + * being updated. If the resource for this key does not exist then the + * value is used as the status message. Default is 'updatingSelection'. + */ +mxGraphSelectionModel.prototype.updatingSelectionResource = (mxClient.language != 'none') ? 'updatingSelection' : ''; + +/** + * Variable: graph + * + * Reference to the enclosing . + */ +mxGraphSelectionModel.prototype.graph = null; + +/** + * Variable: singleSelection + * + * Specifies if only one selected item at a time is allowed. + * Default is false. + */ +mxGraphSelectionModel.prototype.singleSelection = false; + +/** + * Function: isSingleSelection + * + * Returns as a boolean. + */ +mxGraphSelectionModel.prototype.isSingleSelection = function() +{ + return this.singleSelection; +}; + +/** + * Function: setSingleSelection + * + * Sets the flag. + * + * Parameters: + * + * singleSelection - Boolean that specifies the new value for + * . + */ +mxGraphSelectionModel.prototype.setSingleSelection = function(singleSelection) +{ + this.singleSelection = singleSelection; +}; + +/** + * Function: isSelected + * + * Returns true if the given is selected. + */ +mxGraphSelectionModel.prototype.isSelected = function(cell) +{ + if (cell != null) + { + return mxUtils.indexOf(this.cells, cell) >= 0; + } + + return false; +}; + +/** + * Function: isEmpty + * + * Returns true if no cells are currently selected. + */ +mxGraphSelectionModel.prototype.isEmpty = function() +{ + return this.cells.length == 0; +}; + +/** + * Function: clear + * + * Clears the selection and fires a event if the selection was not + * empty. + */ +mxGraphSelectionModel.prototype.clear = function() +{ + this.changeSelection(null, this.cells); +}; + +/** + * Function: setCell + * + * Selects the specified using . + * + * Parameters: + * + * cell - to be selected. + */ +mxGraphSelectionModel.prototype.setCell = function(cell) +{ + if (cell != null) + { + this.setCells([cell]); + } +}; + +/** + * Function: setCells + * + * Selects the given array of and fires a event. + * + * Parameters: + * + * cells - Array of to be selected. + */ +mxGraphSelectionModel.prototype.setCells = function(cells) +{ + if (cells != null) + { + if (this.singleSelection) + { + cells = [this.getFirstSelectableCell(cells)]; + } + + var tmp = []; + + for (var i = 0; i < cells.length; i++) + { + if (this.graph.isCellSelectable(cells[i])) + { + tmp.push(cells[i]); + } + } + + this.changeSelection(tmp, this.cells); + } +}; + +/** + * Function: getFirstSelectableCell + * + * Returns the first selectable cell in the given array of cells. + */ +mxGraphSelectionModel.prototype.getFirstSelectableCell = function(cells) +{ + if (cells != null) + { + for (var i = 0; i < cells.length; i++) + { + if (this.graph.isCellSelectable(cells[i])) + { + return cells[i]; + } + } + } + + return null; +}; + +/** + * Function: addCell + * + * Adds the given to the selection and fires a + * event. + * + * Parameters: + * + * cells - Array of to add to the selection. + */ +mxGraphSelectionModel.prototype.addCells = function(cells) +{ + if (cells != null) + { + var remove = null; + + if (this.singleSelection) + { + remove = this.cells; + cells = [this.getFirstSelectableCell(cells)]; + } + + var tmp = []; + + for (var i = 0; i < cells.length; i++) + { + if (!this.isSelected(cells[i]) && + this.graph.isCellSelectable(cells[i])) + { + tmp.push(cells[i]); + } + } + + this.changeSelection(tmp, remove); + } +}; + +/** + * Function: removeCell + * + * Removes the specified from the selection and fires a