瀏覽代碼

7.1.1 release

Gaudenz Alder 8 年之前
父節點
當前提交
38ab575c2b

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+16-AUG-2017: 7.1.1
+
+- Disables drafts in Confluence Cloud add-on
+- Uses mxGraph 3.7.5 beta 9
+- Fixes label positions, adds callout shape in general sidebar
+
 14-AUG-2017: 7.1.0
 
 - Improves Lucidchart import

+ 1 - 1
VERSION

@@ -1 +1 @@
-7.1.0
+7.1.1

+ 4 - 0
etc/electron/README

@@ -0,0 +1,4 @@
+1. Go to this directory
+2. Run "npm install" once
+3. Execute "export NODE_ENV=development" for dev mode
+4. Run "npm start" to start the client

文件差異過大導致無法顯示
+ 1000 - 0
etc/electron/yarn.lock


文件差異過大導致無法顯示
+ 54 - 51
etc/mxgraph/mxClient.js


+ 405 - 1
war/cache.manifest

@@ -1,5 +1,409 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 08/14/2017 10:34 PM
+# 08/16/2017 08:32 AM
 
+app.html
+index.html?offline=1
+index.html?offline=1&https=0
+offline.html
+open.html
+js/app.min.js
+js/shapes.min.js
+styles/grapheditor.css
+styles/atlas.css
+stencils.xml
+search.xml
+favicon.ico
+mxgraph/css/common.css
+js/jscolor/jscolor.js
+mxgraph/images/maximize.gif
+mxgraph/images/minimize.gif
+mxgraph/images/close.gif
+mxgraph/images/resize.gif
+mxgraph/images/separator.gif
+mxgraph/images/window.gif
+mxgraph/images/window-title.gif
+mxgraph/images/button.gif
+mxgraph/images/point.gif
+mxgraph/images/transparent.gif
+resources/dia.txt
+styles/default.xml
+styles/default-old.xml
+img/clipart/Gear_128x128.png
+images/delete.png
+images/droptarget.png
+images/edit.gif
+images/help.png
+images/download.png
+images/logo-flat.png
+images/osa_drive-harddisk.png
+images/osa_database.png
+images/glyphicons_star.png
+images/logo-confluence.png
+images/logo-jira.png
+images/clear.gif
+images/spin.gif
+images/checkmark.gif
+images/favicon-16x16.png
+images/favicon-32x32.png
+images/android-chrome-192x192.png
+images/android-chrome-512x512.png
+images/glyphicons_google.png
+images/glyphicons_facebook.png
+images/glyphicons_twitter.png
+images/glyphicons_github.png
+js/jscolor/arrow.gif
+js/jscolor/hs.png
+js/jscolor/cross.gif
+img/clipart/Battery_0_128x128.png
+img/clipart/Battery_100_128x128.png
+img/clipart/Battery_50_128x128.png
+img/clipart/Battery_75_128x128.png
+img/clipart/Battery_allstates_128x128.png
+img/clipart/Bluetooth_128x128.png
+img/clipart/Earth_globe_128x128.png
+img/clipart/Empty_Folder_128x128.png
+img/clipart/Full_Folder_128x128.png
+img/clipart/Gear_128x128.png
+img/clipart/Keys_128x128.png
+img/clipart/Lock_128x128.png
+img/clipart/Mouse_Pointer_128x128.png
+img/clipart/Plug_128x128.png
+img/clipart/Ships_Wheel_128x128.png
+img/clipart/Star_128x128.png
+img/clipart/Tire_128x128.png
+img/computers/Antivirus_128x128.png
+img/computers/Data_Filtering_128x128.png
+img/computers/Database_128x128.png
+img/computers/Database_Add_128x128.png
+img/computers/Database_Minus_128x128.png
+img/computers/Database_Move_Stack_128x128.png
+img/computers/Database_Remove_128x128.png
+img/computers/Fujitsu_Tablet_128x128.png
+img/computers/Harddrive_128x128.png
+img/computers/IBM_Tablet_128x128.png
+img/computers/iMac_128x128.png
+img/computers/iPad_128x128.png
+img/computers/Laptop_128x128.png
+img/computers/MacBook_128x128.png
+img/computers/Mainframe_128x128.png
+img/computers/Monitor_128x128.png
+img/computers/Monitor_Tower_128x128.png
+img/computers/Monitor_Tower_Behind_128x128.png
+img/computers/Netbook_128x128.png
+img/computers/Network_128x128.png
+img/computers/Network_2_128x128.png
+img/computers/Printer_128x128.png
+img/computers/Printer_Commercial_128x128.png
+img/computers/Secure_System_128x128.png
+img/computers/Server_128x128.png
+img/computers/Server_Rack_128x128.png
+img/computers/Server_Rack_Empty_128x128.png
+img/computers/Server_Rack_Partial_128x128.png
+img/computers/Server_Tower_128x128.png
+img/computers/Software_128x128.png
+img/computers/Stylus_128x128.png
+img/computers/Touch_128x128.png
+img/computers/USB_Hub_128x128.png
+img/computers/Virtual_Application_128x128.png
+img/computers/Virtual_Machine_128x128.png
+img/computers/Virus_128x128.png
+img/computers/Workstation_128x128.png
+img/finance/Arrow_Down_128x128.png
+img/finance/Arrow_Up_128x128.png
+img/finance/Coins_128x128.png
+img/finance/Credit_Card_128x128.png
+img/finance/Dollar_128x128.png
+img/finance/Graph_128x128.png
+img/finance/Pie_Chart_128x128.png
+img/finance/Piggy_Bank_128x128.png
+img/finance/Safe_128x128.png
+img/finance/Shopping_Cart_128x128.png
+img/finance/Stock_Down_128x128.png
+img/finance/Stock_Up_128x128.png
+img/lib/clip_art/computers/Antivirus_128x128.png
+img/lib/clip_art/computers/Data_Filtering_128x128.png
+img/lib/clip_art/computers/Database_128x128.png
+img/lib/clip_art/computers/Database_Add_128x128.png
+img/lib/clip_art/computers/Database_Minus_128x128.png
+img/lib/clip_art/computers/Database_Move_Stack_128x128.png
+img/lib/clip_art/computers/Database_Remove_128x128.png
+img/lib/clip_art/computers/Fujitsu_Tablet_128x128.png
+img/lib/clip_art/computers/Harddrive_128x128.png
+img/lib/clip_art/computers/IBM_Tablet_128x128.png
+img/lib/clip_art/computers/iMac_128x128.png
+img/lib/clip_art/computers/iPad_128x128.png
+img/lib/clip_art/computers/Laptop_128x128.png
+img/lib/clip_art/computers/MacBook_128x128.png
+img/lib/clip_art/computers/Mainframe_128x128.png
+img/lib/clip_art/computers/Monitor_128x128.png
+img/lib/clip_art/computers/Monitor_Tower_128x128.png
+img/lib/clip_art/computers/Monitor_Tower_Behind_128x128.png
+img/lib/clip_art/computers/Netbook_128x128.png
+img/lib/clip_art/computers/Network_128x128.png
+img/lib/clip_art/computers/Network_2_128x128.png
+img/lib/clip_art/computers/Printer_128x128.png
+img/lib/clip_art/computers/Printer_Commercial_128x128.png
+img/lib/clip_art/computers/Secure_System_128x128.png
+img/lib/clip_art/computers/Server_128x128.png
+img/lib/clip_art/computers/Server_Rack_128x128.png
+img/lib/clip_art/computers/Server_Rack_Empty_128x128.png
+img/lib/clip_art/computers/Server_Rack_Partial_128x128.png
+img/lib/clip_art/computers/Server_Tower_128x128.png
+img/lib/clip_art/computers/Software_128x128.png
+img/lib/clip_art/computers/Stylus_128x128.png
+img/lib/clip_art/computers/Touch_128x128.png
+img/lib/clip_art/computers/USB_Hub_128x128.png
+img/lib/clip_art/computers/Virtual_Application_128x128.png
+img/lib/clip_art/computers/Virtual_Machine_128x128.png
+img/lib/clip_art/computers/Virus_128x128.png
+img/lib/clip_art/computers/Workstation_128x128.png
+img/lib/clip_art/finance/Arrow_Down_128x128.png
+img/lib/clip_art/finance/Arrow_Up_128x128.png
+img/lib/clip_art/finance/Coins_128x128.png
+img/lib/clip_art/finance/Credit_Card_128x128.png
+img/lib/clip_art/finance/Dollar_128x128.png
+img/lib/clip_art/finance/Graph_128x128.png
+img/lib/clip_art/finance/Pie_Chart_128x128.png
+img/lib/clip_art/finance/Piggy_Bank_128x128.png
+img/lib/clip_art/finance/Safe_128x128.png
+img/lib/clip_art/finance/Shopping_Cart_128x128.png
+img/lib/clip_art/finance/Stock_Down_128x128.png
+img/lib/clip_art/finance/Stock_Up_128x128.png
+img/lib/clip_art/general/Battery_0_128x128.png
+img/lib/clip_art/general/Battery_100_128x128.png
+img/lib/clip_art/general/Battery_50_128x128.png
+img/lib/clip_art/general/Battery_75_128x128.png
+img/lib/clip_art/general/Battery_allstates_128x128.png
+img/lib/clip_art/general/Bluetooth_128x128.png
+img/lib/clip_art/general/Earth_globe_128x128.png
+img/lib/clip_art/general/Empty_Folder_128x128.png
+img/lib/clip_art/general/Full_Folder_128x128.png
+img/lib/clip_art/general/Gear_128x128.png
+img/lib/clip_art/general/Keys_128x128.png
+img/lib/clip_art/general/Lock_128x128.png
+img/lib/clip_art/general/Mouse_Pointer_128x128.png
+img/lib/clip_art/general/Plug_128x128.png
+img/lib/clip_art/general/Ships_Wheel_128x128.png
+img/lib/clip_art/general/Star_128x128.png
+img/lib/clip_art/general/Tire_128x128.png
+img/lib/clip_art/networking/Bridge_128x128.png
+img/lib/clip_art/networking/Certificate_128x128.png
+img/lib/clip_art/networking/Certificate_Off_128x128.png
+img/lib/clip_art/networking/Cloud_128x128.png
+img/lib/clip_art/networking/Cloud_Computer_128x128.png
+img/lib/clip_art/networking/Cloud_Computer_Private_128x128.png
+img/lib/clip_art/networking/Cloud_Rack_128x128.png
+img/lib/clip_art/networking/Cloud_Rack_Private_128x128.png
+img/lib/clip_art/networking/Cloud_Server_128x128.png
+img/lib/clip_art/networking/Cloud_Server_Private_128x128.png
+img/lib/clip_art/networking/Cloud_Storage_128x128.png
+img/lib/clip_art/networking/Concentrator_128x128.png
+img/lib/clip_art/networking/Email_128x128.png
+img/lib/clip_art/networking/Firewall-page1_128x128.png
+img/lib/clip_art/networking/Firewall_02_128x128.png
+img/lib/clip_art/networking/Firewall_128x128.png
+img/lib/clip_art/networking/Ip_Camera_128x128.png
+img/lib/clip_art/networking/Modem_128x128.png
+img/lib/clip_art/networking/power_distribution_unit_128x128.png
+img/lib/clip_art/networking/Print_Server_128x128.png
+img/lib/clip_art/networking/Print_Server_Wireless_128x128.png
+img/lib/clip_art/networking/Repeater_128x128.png
+img/lib/clip_art/networking/Router_128x128.png
+img/lib/clip_art/networking/Router_Icon_128x128.png
+img/lib/clip_art/networking/Switch_128x128.png
+img/lib/clip_art/networking/UPS_128x128.png
+img/lib/clip_art/networking/Wireless_Router_128x128.png
+img/lib/clip_art/networking/Wireless_Router_N_128x128.png
+img/lib/clip_art/people/Construction_Worker_Man_128x128.png
+img/lib/clip_art/people/Construction_Worker_Man_Black_128x128.png
+img/lib/clip_art/people/Construction_Worker_Woman_128x128.png
+img/lib/clip_art/people/Construction_Worker_Woman_Black_128x128.png
+img/lib/clip_art/people/Doctor_Man_128x128.png
+img/lib/clip_art/people/Doctor_Man_Black_128x128.png
+img/lib/clip_art/people/Doctor_Woman_128x128.png
+img/lib/clip_art/people/Doctor_Woman_Black_128x128.png
+img/lib/clip_art/people/Farmer_Man_128x128.png
+img/lib/clip_art/people/Farmer_Man_Black_128x128.png
+img/lib/clip_art/people/Farmer_Woman_128x128.png
+img/lib/clip_art/people/Farmer_Woman_Black_128x128.png
+img/lib/clip_art/people/Military_Officer_128x128.png
+img/lib/clip_art/people/Military_Officer_Black_128x128.png
+img/lib/clip_art/people/Military_Officer_Woman_128x128.png
+img/lib/clip_art/people/Military_Officer_Woman_Black_128x128.png
+img/lib/clip_art/people/Nurse_Man_128x128.png
+img/lib/clip_art/people/Nurse_Man_Black_128x128.png
+img/lib/clip_art/people/Nurse_Man_Green_128x128.png
+img/lib/clip_art/people/Nurse_Man_Red_128x128.png
+img/lib/clip_art/people/Nurse_Woman_128x128.png
+img/lib/clip_art/people/Nurse_Woman_Black_128x128.png
+img/lib/clip_art/people/Nurse_Woman_Green_128x128.png
+img/lib/clip_art/people/Nurse_Woman_Red_128x128.png
+img/lib/clip_art/people/Pilot_Man_128x128.png
+img/lib/clip_art/people/Pilot_Man_Black_128x128.png
+img/lib/clip_art/people/Pilot_Woman_128x128.png
+img/lib/clip_art/people/Pilot_Woman_Black_128x128.png
+img/lib/clip_art/people/Scientist_Man_128x128.png
+img/lib/clip_art/people/Scientist_Man_Black_128x128.png
+img/lib/clip_art/people/Scientist_Woman_128x128.png
+img/lib/clip_art/people/Scientist_Woman_Black_128x128.png
+img/lib/clip_art/people/Security_Man_128x128.png
+img/lib/clip_art/people/Security_Man_Black_128x128.png
+img/lib/clip_art/people/Security_Woman_128x128.png
+img/lib/clip_art/people/Security_Woman_Black_128x128.png
+img/lib/clip_art/people/Soldier_128x128.png
+img/lib/clip_art/people/Soldier_Black_128x128.png
+img/lib/clip_art/people/Suit_Man_128x128.png
+img/lib/clip_art/people/Suit_Man_Black_128x128.png
+img/lib/clip_art/people/Suit_Man_Blue_128x128.png
+img/lib/clip_art/people/Suit_Man_Green_128x128.png
+img/lib/clip_art/people/Suit_Man_Green_Black_128x128.png
+img/lib/clip_art/people/Suit_Woman_128x128.png
+img/lib/clip_art/people/Suit_Woman_Black_128x128.png
+img/lib/clip_art/people/Suit_Woman_Blue_128x128.png
+img/lib/clip_art/people/Suit_Woman_Green_128x128.png
+img/lib/clip_art/people/Suit_Woman_Green_Black_128x128.png
+img/lib/clip_art/people/Tech_Man_128x128.png
+img/lib/clip_art/people/Tech_Man_Black_128x128.png
+img/lib/clip_art/people/Telesales_Man_128x128.png
+img/lib/clip_art/people/Telesales_Man_Black_128x128.png
+img/lib/clip_art/people/Telesales_Woman_128x128.png
+img/lib/clip_art/people/Telesales_Woman_Black_128x128.png
+img/lib/clip_art/people/Waiter_128x128.png
+img/lib/clip_art/people/Waiter_Black_128x128.png
+img/lib/clip_art/people/Waiter_Woman_128x128.png
+img/lib/clip_art/people/Waiter_Woman_Black_128x128.png
+img/lib/clip_art/people/Worker_Black_128x128.png
+img/lib/clip_art/people/Worker_Man_128x128.png
+img/lib/clip_art/people/Worker_Woman_128x128.png
+img/lib/clip_art/people/Worker_Woman_Black_128x128.png
+img/lib/clip_art/telecommunication/BlackBerry_128x128.png
+img/lib/clip_art/telecommunication/Cellphone_128x128.png
+img/lib/clip_art/telecommunication/HTC_smartphone_128x128.png
+img/lib/clip_art/telecommunication/iPhone_128x128.png
+img/lib/clip_art/telecommunication/Palm_Treo_128x128.png
+img/lib/clip_art/telecommunication/Signal_tower_off_128x128.png
+img/lib/clip_art/telecommunication/Signal_tower_on_128x128.png
+img/lib/clip_art/telecommunication/Telephone_128x128.png
+img/networking/Bridge_128x128.png
+img/networking/Certificate_128x128.png
+img/networking/Certificate_Off_128x128.png
+img/networking/Cloud_128x128.png
+img/networking/Cloud_Computer_128x128.png
+img/networking/Cloud_Computer_Private_128x128.png
+img/networking/Cloud_Rack_128x128.png
+img/networking/Cloud_Rack_Private_128x128.png
+img/networking/Cloud_Server_128x128.png
+img/networking/Cloud_Server_Private_128x128.png
+img/networking/Cloud_Storage_128x128.png
+img/networking/Concentrator_128x128.png
+img/networking/Data_Filtering_128x128.png
+img/networking/Database_128x128.png
+img/networking/Database_Add_128x128.png
+img/networking/Database_Minus_128x128.png
+img/networking/Database_Move_Stack_128x128.png
+img/networking/Database_Remove_128x128.png
+img/networking/Email_128x128.png
+img/networking/Firewall-page1_128x128.png
+img/networking/Firewall_02_128x128.png
+img/networking/Firewall_128x128.png
+img/networking/Ip_Camera_128x128.png
+img/networking/Mainframe_128x128.png
+img/networking/Modem_128x128.png
+img/networking/power_distribution_unit_128x128.png
+img/networking/Print_Server_128x128.png
+img/networking/Print_Server_Wireless_128x128.png
+img/networking/Repeater_128x128.png
+img/networking/Router_128x128.png
+img/networking/Router_Icon_128x128.png
+img/networking/Server_128x128.png
+img/networking/Server_Rack_128x128.png
+img/networking/Server_Rack_Empty_128x128.png
+img/networking/Server_Rack_Partial_128x128.png
+img/networking/Switch_128x128.png
+img/networking/UPS_128x128.png
+img/networking/Wireless_Router_128x128.png
+img/networking/Wireless_Router_N_128x128.png
+img/people/Construction_Worker_Man_128x128.png
+img/people/Construction_Worker_Man_Black_128x128.png
+img/people/Construction_Worker_Woman_128x128.png
+img/people/Construction_Worker_Woman_Black_128x128.png
+img/people/Doctor_Man_128x128.png
+img/people/Doctor_Man_Black_128x128.png
+img/people/Doctor_Woman_128x128.png
+img/people/Doctor_Woman_Black_128x128.png
+img/people/Farmer_Man_128x128.png
+img/people/Farmer_Man_Black_128x128.png
+img/people/Farmer_Woman_128x128.png
+img/people/Farmer_Woman_Black_128x128.png
+img/people/Military_Officer_128x128.png
+img/people/Military_Officer_Black_128x128.png
+img/people/Military_Officer_Woman_128x128.png
+img/people/Military_Officer_Woman_Black_128x128.png
+img/people/Nurse_Man_128x128.png
+img/people/Nurse_Man_Black_128x128.png
+img/people/Nurse_Man_Green_128x128.png
+img/people/Nurse_Man_Red_128x128.png
+img/people/Nurse_Woman_128x128.png
+img/people/Nurse_Woman_Black_128x128.png
+img/people/Nurse_Woman_Green_128x128.png
+img/people/Nurse_Woman_Red_128x128.png
+img/people/Pilot_Man_128x128.png
+img/people/Pilot_Man_Black_128x128.png
+img/people/Pilot_Woman_128x128.png
+img/people/Pilot_Woman_Black_128x128.png
+img/people/Scientist_Man_128x128.png
+img/people/Scientist_Man_Black_128x128.png
+img/people/Scientist_Woman_128x128.png
+img/people/Scientist_Woman_Black_128x128.png
+img/people/Security_Man_128x128.png
+img/people/Security_Man_Black_128x128.png
+img/people/Security_Woman_128x128.png
+img/people/Security_Woman_Black_128x128.png
+img/people/Soldier_128x128.png
+img/people/Soldier_Black_128x128.png
+img/people/Suit_Man_128x128.png
+img/people/Suit_Man_Black_128x128.png
+img/people/Suit_Man_Blue_128x128.png
+img/people/Suit_Man_Green_128x128.png
+img/people/Suit_Man_Green_Black_128x128.png
+img/people/Suit_Woman_128x128.png
+img/people/Suit_Woman_Black_128x128.png
+img/people/Suit_Woman_Blue_128x128.png
+img/people/Suit_Woman_Green_128x128.png
+img/people/Suit_Woman_Green_Black_128x128.png
+img/people/Tech_Man_128x128.png
+img/people/Tech_Man_Black_128x128.png
+img/people/Telesales_Man_128x128.png
+img/people/Telesales_Man_Black_128x128.png
+img/people/Telesales_Woman_128x128.png
+img/people/Telesales_Woman_Black_128x128.png
+img/people/Waiter_128x128.png
+img/people/Waiter_Black_128x128.png
+img/people/Waiter_Woman_128x128.png
+img/people/Waiter_Woman_Black_128x128.png
+img/people/Worker_Black_128x128.png
+img/people/Worker_Man_128x128.png
+img/people/Worker_Woman_128x128.png
+img/people/Worker_Woman_Black_128x128.png
+img/telecommunication/Battery_0_128x128.png
+img/telecommunication/Battery_100_128x128.png
+img/telecommunication/Battery_50_128x128.png
+img/telecommunication/Battery_75_128x128.png
+img/telecommunication/Battery_allstates_128x128.png
+img/telecommunication/BlackBerry_128x128.png
+img/telecommunication/Cellphone_128x128.png
+img/telecommunication/HTC_smartphone_128x128.png
+img/telecommunication/iPhone_128x128.png
+img/telecommunication/Palm_Treo_128x128.png
+img/telecommunication/Signal_tower_off_128x128.png
+img/telecommunication/Signal_tower_on_128x128.png
+
+# Redirect app to app.html which redirects to index.html?offline=1
+# this is required to get the URL parameters into the index page.
+FALLBACK:
+app app.html
+
+NETWORK:
+*

+ 21 - 46
war/electron.js

@@ -104,64 +104,47 @@ function createWindow (opt = {}) {
 // This method will be called when Electron has finished
 // initialization and is ready to create browser windows.
 // Some APIs can only be used after this event occurs.
-app.on('ready', e =>
-{
+app.on('ready', e => {
 	//asynchronous
-	ipcMain.on('asynchronous-message', (event, arg) =>
-	{
-		//console.log(arg)  // prints "ping"
+	ipcMain.on('asynchronous-message', (event, arg) => {
+		console.log(arg)  // prints "ping"
 		event.sender.send('asynchronous-reply', 'pong')
 	})
 	//synchronous
-	ipcMain.on('winman', (event, arg) =>
-	{
-		//console.log('ipcMain.on winman', arg)
-		
-		if (arg.action === 'newfile')
-		{
+	ipcMain.on('winman', (event, arg) => {
+		console.log('ipcMain.on winman', arg)
+		if (arg.action === 'newfile') {
 			event.returnValue = createWindow(arg.opt)
 			return
 		}
 		event.returnValue = 'pong'
 	})
-
 	createWindow()
-	
-	if (process.platform !== 'linux')
-	{
-		checkUpdate()
-	}
+	checkUpdate()
 })
 
 // Quit when all windows are closed.
-app.on('window-all-closed', function ()
-{
-	// console.log('window-all-closed', windowsRegistry.length)
+app.on('window-all-closed', function () {
+	console.log('window-all-closed', windowsRegistry.length)
 	// On OS X it is common for applications and their menu bar
 	// to stay active until the user quits explicitly with Cmd + Q
-	if (process.platform !== 'darwin')
-	{
+	if (process.platform !== 'darwin') {
 		app.quit()
 	}
 })
 
-app.on('activate', function ()
-{
-	// console.log('app on activate', windowsRegistry.length)
+app.on('activate', function () {
+	console.log('app on activate', windowsRegistry.length)
 	// On OS X it's common to re-create a window in the app when the
 	// dock icon is clicked and there are no other windows open.
-	if (windowsRegistry.length === 0)
-	{
+	if (windowsRegistry.length === 0) {
 		createWindow()
 	}
 })
 
-function checkUpdate ()
-{
-	autoUpdater.checkForUpdates().then(UpdateCheckResult =>
-	{
-		if (UpdateCheckResult)
-		{
+function checkUpdate () {
+	autoUpdater.checkForUpdates().then(UpdateCheckResult => {
+		if (UpdateCheckResult) {
 			let idx = dialog.showMessageBox({
 				type: 'question',
 				buttons: ['Ok', 'Cancel'],
@@ -169,11 +152,7 @@ function checkUpdate ()
 				message: 'Update available.\n\nWould you like to download and install new version?',
 				detail: 'Application will automatically restart to apply update after download',
 			})
-			
-			if (idx === 0)
-			{
-				return autoUpdater.downloadUpdate()
-			}
+			if (idx === 0) return autoUpdater.downloadUpdate()
 		}
 	}).then((a, b) => {
 		log.info('@cfu update-downloaded@\n', a, b)
@@ -188,21 +167,17 @@ autoUpdater.on('update-available',
 	(a, b) => log.info('@update-available@\n', a, b))
 
 /**/
-autoUpdater.on('update-downloaded', (event, info) =>
-{
+autoUpdater.on('update-downloaded', (event, info) => {
 	log.info('@update-downloaded@\n', info, event)
 	// Ask user to update the app
-	dialog.showMessageBox(
-	{
+	dialog.showMessageBox({
 		type: 'question',
 		buttons: ['Install and Relaunch', 'Later'],
 		defaultId: 0,
 		message: 'A new version of ' + app.getName() + ' has been downloaded',
 		detail: 'It will be installed the next time you restart the application',
-	}, response =>
-	{
-		if (response === 0)
-		{
+	}, response => {
+		if (response === 0) {
 			setTimeout(() => autoUpdater.quitAndInstall(), 1)
 		}
 	})

文件差異過大導致無法顯示
+ 366 - 358
war/js/app.min.js


文件差異過大導致無法顯示
+ 291 - 283
war/js/atlas-viewer.min.js


文件差異過大導致無法顯示
+ 427 - 418
war/js/atlas.min.js


+ 5 - 5
war/js/diagramly/EditorUi.js

@@ -2835,7 +2835,7 @@
 	 */
 	EditorUi.prototype.saveRequest = function(filename, format, fn, data, base64Encoded, mimeType)
 	{
-		var allowTab = !mxClient.IS_IOS || !navigator.standalone;
+		var allowTab = (!mxClient.IS_IOS || !navigator.standalone) && !EditorUi.isElectronApp;
 		
 		var dlg = new CreateDialog(this, filename, mxUtils.bind(this, function(newTitle, mode)
 		{
@@ -2848,7 +2848,7 @@
 				{
 					if (mode == App.MODE_DEVICE || mode == '_blank')
 					{
-						xhr.simulate(document, '_blank');
+						xhr.simulate(document, (!EditorUi.isElectronApp) ? '_blank' : null);
 					}
 					else
 					{
@@ -5000,7 +5000,7 @@
 				{
 					this.handleError(e);
 				}
-				finally
+				finally 
 				{
 				    	if (done != null)
 				    	{
@@ -5016,11 +5016,11 @@
 			
 			if (urlParams['dev'] == '1')
 			{
-				mxscript('/js/diagramly/Extensions.js', delayed);
+				mxscript('js/diagramly/Extensions.js', delayed);
 			}
 			else
 			{
-				mxscript('/js/extensions.min.js', delayed);
+				mxscript('js/extensions.min.js', delayed);
 			}
 		}
 		else

+ 0 - 3
war/js/diagramly/ElectronApp.js

@@ -74,9 +74,6 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 	
 	PrintDialog.previewEnabled = false;
 	
-	// Enables PDF export via print
-	EditorUi.prototype.printPdfExport = true;
-	
 	var menusInit = Menus.prototype.init;
 	Menus.prototype.init = function()
 	{

+ 82 - 7
war/js/diagramly/Extensions.js

@@ -2050,8 +2050,28 @@
 			((props.Value != null) ? props.Value :
 			props.Lane_0);
 		
+		
+		var text2 = null;
+		
+		if (text == null && props.State != null)
+		{
+			if (props.State.t != null)
+			{
+				text2 = props.State.t;
+			}
+		}
+
 		// TODO: Convert text object to HTML
-		return (text != null && text.t != null) ? text.t : '';
+		if (text != null)
+		{
+			if (text.t != null)
+			{
+				return text.t;
+				other = false;
+			}
+		}
+		
+		return (text2 != null) ? text2 : ''; 
 	};
 		
 	function getAction(obj)
@@ -2725,6 +2745,31 @@
 		}
 	};
 
+	var hideObj = function(key, groups, hidden)
+	{
+		if (!hidden.includes(key))
+		{
+			hidden.push(key);
+		}
+
+		if (key in groups)
+		{
+			var obj = groups[key];
+			obj.id = key;
+			
+			if (obj.Members != null)
+			{
+				for (var key2 in obj.Members)
+				{
+					hidden = hideObj(key2, groups, hidden);
+				}
+			}
+		
+		}
+		
+		return hidden;
+	};
+	
 	EditorUi.prototype.pasteLucidChart = function(g, dx, dy, crop)
 	{
 		// Creates a new graph, inserts cells and returns XML for insert
@@ -2737,6 +2782,32 @@
 			var lookup = {};
 			var queue = [];
 
+			//collect IDs that are part of groups and hidden
+			var hidden = [];
+			var i = 0;
+			
+			if (g.Groups != null)
+			{
+				for (var key in g.Groups)
+				{
+					var obj = g.Groups[key];
+					obj.id = key;
+					
+					if (obj.Hidden == true && obj.Members != null)
+					{
+						if (!hidden.includes(key))
+						{
+							hidden.push(key);
+						}
+
+						for (var key2 in obj.Members)
+						{
+							hidden = hideObj(key2, g.Groups, hidden);
+						}
+					}
+				}
+			}
+			
 			// Vertices first (populates lookup table for connecting edges)
 			if (g.Blocks != null)
 			{
@@ -2744,8 +2815,12 @@
 				{
 					var obj = g.Blocks[key];
 					obj.id = key;
-				    lookup[obj.id] = createVertex(obj);
-					queue.push(obj);
+					
+					if (!hidden.includes(key))
+					{
+					    lookup[obj.id] = createVertex(obj);
+						queue.push(obj);
+					}
 				}
 			}
 			else
@@ -2788,14 +2863,14 @@
 				
 				if (src == null && p.Endpoint1 != null)
 				{
-					e.geometry.setTerminalPoint(new mxPoint(Math.round(p.Endpoint1.x * scale + dx),
-						Math.round(p.Endpoint1.y * scale + dy)), true);
+					e.geometry.setTerminalPoint(new mxPoint(Math.round(p.Endpoint1.x * scale),
+						Math.round(p.Endpoint1.y * scale)), true);
 				}
 				
 				if (trg == null && p.Endpoint2 != null)
 				{
-					e.geometry.setTerminalPoint(new mxPoint(Math.round(p.Endpoint2.x * scale + dx),
-						Math.round(p.Endpoint2.y * scale + dy)), false);
+					e.geometry.setTerminalPoint(new mxPoint(Math.round(p.Endpoint2.x * scale),
+						Math.round(p.Endpoint2.y * scale)), false);
 				}
 				
 				select.push(graph.addCell(e, null, null, src, trg));

+ 1 - 1
war/js/diagramly/Init.js

@@ -18,7 +18,7 @@ window.SHAPES_PATH = window.SHAPES_PATH || 'shapes';
 // Path for images inside the diagram
 window.GRAPH_IMAGE_PATH = window.GRAPH_IMAGE_PATH || 'img';
 window.ICONSEARCH_PATH = window.ICONSEARCH_PATH || (navigator.userAgent.indexOf('MSIE') >= 0 ||
-	urlParams['dev']) && window.location.protocol != 'file:' ? 'iconSearch' : 'https://www.draw.io/iconSearch';
+		urlParams['dev']) && window.location.protocol != 'file:' ? 'iconSearch' : 'https://www.draw.io/iconSearch';
 window.TEMPLATE_PATH = window.TEMPLATE_PATH || '/templates';
 
 // Directory for i18 files and basename for main i18n file

+ 1 - 3
war/js/diagramly/Menus.js

@@ -508,12 +508,10 @@
 			if (typeof(VsdxExport) === 'undefined' && !this.loadingVsdx && !editorUi.isOffline())
 			{
 				this.loadingVsdx = true;
-				// Dependencies included in Devel.js
-				mxscript('/js/vsdx.min.js', delayed);
+				mxscript('js/vsdx.min.js', delayed);
 			}
 			else
 			{
-				// Must be async for cell selection
 				window.setTimeout(delayed, 0);
 			}
 		}));

+ 2 - 2
war/js/diagramly/sidebar/Sidebar-Basic.js

@@ -39,8 +39,8 @@
 			this.createVertexTemplateEntry(s + 'oval_callout', w, h * 0.6, '', 'Oval Callout', null, null, this.getTagsForStencil(gn, 'oval_callout', dt).join(' ')),
 			this.createVertexTemplateEntry(s3 + 'parallelogram;whiteSpace=wrap;align=center;size=0.24;', w, h * 0.6, '', 'Parallelepiped', null, null, this.getTagsForStencil(gn, 'parallelepiped', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'pentagon', w, h * 0.9, '', 'Pentagon', null, null, this.getTagsForStencil(gn, 'pentagon', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'rectCallout;dx=30;dy=15;', w, h * 0.6, '', 'Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'roundRectCallout;dx=30;dy=15;size=5;', w, h * 0.6, '', 'Rounded Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
+			this.createVertexTemplateEntry(s + 'rectCallout;dx=30;dy=15;boundedLbl=1;', w, h * 0.6, '', 'Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
+			this.createVertexTemplateEntry(s + 'roundRectCallout;dx=30;dy=15;size=5;boundedLbl=1;', w, h * 0.6, '', 'Rounded Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'smiley', w, h, '', 'Smiley', null, null, this.getTagsForStencil(gn, 'smiley', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'star', w, h * 0.95, '', 'Star', null, null, this.getTagsForStencil(gn, 'star', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'sun', w, h, '', 'Sun', null, null, this.getTagsForStencil(gn, 'sun', dt).join(' ')),

文件差異過大導致無法顯示
+ 307 - 299
war/js/embed-static.min.js


文件差異過大導致無法顯示
+ 60 - 59
war/js/extensions.min.js


+ 1 - 1
war/js/mxgraph/Format.js

@@ -235,7 +235,7 @@ Format.prototype.isRoundedState = function(state)
 			shape == 'parallelogram' || shape == 'swimlane' || shape == 'triangle' || shape == 'trapezoid' ||
 			shape == 'ext' || shape == 'step' || shape == 'tee' || shape == 'process' || shape == 'link' ||
 			shape == 'rhombus' || shape == 'offPageConnector' || shape == 'loopLimit' || shape == 'hexagon' ||
-			shape == 'manualInput' || shape == 'curlyBracket' || shape == 'singleArrow' || 
+			shape == 'manualInput' || shape == 'curlyBracket' || shape == 'singleArrow' || shape == 'callout' ||
 			shape == 'doubleArrow' || shape == 'flexArrow' || shape == 'card' || shape == 'umlLifeline');
 };
 

+ 26 - 3
war/js/mxgraph/Graph.js

@@ -2319,7 +2319,8 @@ Graph.prototype.getTooltipForCell = function(cell)
 		{
 			var ignored = ['label', 'tooltip', 'placeholders', 'placeholder'];
 			var attrs = cell.value.attributes;
-			
+			var temp = [];
+
 			// Hides links in edit mode
 			if (this.isEnabled())
 			{
@@ -2330,9 +2331,31 @@ Graph.prototype.getTooltipForCell = function(cell)
 			{
 				if (mxUtils.indexOf(ignored, attrs[i].nodeName) < 0 && attrs[i].nodeValue.length > 0)
 				{
-					tip += ((attrs[i].nodeName != 'link') ? attrs[i].nodeName + ':' : '') +
-						mxUtils.htmlEntities(attrs[i].nodeValue) + '\n';
+					temp.push({name: attrs[i].nodeName, value: attrs[i].nodeValue});
+				}
+			}
+			
+			// Sorts by name
+			temp.sort(function(a, b)
+			{
+				if (a.name < b.name)
+				{
+					return -1;
 				}
+				else if (a.name > b.name)
+				{
+					return 1;
+				}
+				else
+				{
+					return 0;
+				}
+			});
+
+			for (var i = 0; i < temp.length; i++)
+			{
+				tip += ((temp[i].name != 'link') ? temp[i].name + ':' : '') +
+					mxUtils.htmlEntities(temp[i].value) + '\n';
 			}
 			
 			if (tip.length > 0)

+ 171 - 123
war/js/mxgraph/Shapes.js

@@ -40,7 +40,18 @@
 			path.end();
 		}
 	};
-
+	CubeShape.prototype.getLabelMargins = function(rect)
+	{
+		if (mxUtils.getValue(this.style, 'boundedLbl', false))
+		{
+			var s = parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * this.scale;
+			
+			return new mxRectangle(s, s, 0, 0);
+		}
+		
+		return null;
+	};
+	
 	mxCellRenderer.prototype.defaultShapes['cube'] = CubeShape;
 	
 	var tan30 = Math.tan(mxUtils.toRadians(30));
@@ -162,35 +173,11 @@
 			c.close();
 		}
 	};
-	DataStoreShape.prototype.getLabelBounds = function(rect)
+	DataStoreShape.prototype.getLabelMargins = function(rect)
 	{
-		var dy = 2.5 * Math.min(rect.height / 2, Math.round(rect.height / 8) + this.strokewidth - 1);
-
-		if ((!this.flipV && (this.direction == null || this.direction == mxConstants.DIRECTION_EAST) ||
-			(this.flipV && this.direction == mxConstants.DIRECTION_WEST)))
-		{
-			rect.y += dy;
-			rect.height -= dy;
-		}
-		else if ((!this.flipV && this.direction == mxConstants.DIRECTION_SOUTH) ||
-				((this.flipV && this.direction == mxConstants.DIRECTION_NORTH)))
-		{
-			rect.width -= dy;
-		}
-		else if ((!this.flipV && this.direction == mxConstants.DIRECTION_WEST) ||
-				(this.flipV && (this.direction == null || this.direction == mxConstants.DIRECTION_EAST)))
-		{
-			rect.height -= dy;
-		}
-		else if ((!this.flipV && this.direction == mxConstants.DIRECTION_NORTH) ||
-				(this.flipV && this.direction == mxConstants.DIRECTION_SOUTH))
-		{
-			rect.x += dy;
-			rect.width -= dy;
-		}
-		
-		return rect;
-	};
+		return new mxRectangle(0, 2.5 * Math.min(rect.height / 2, Math.round(rect.height / 8) +
+			this.strokewidth - 1) * this.scale, 0, 0);
+	}
 
 	mxCellRenderer.prototype.defaultShapes['datastore'] = DataStoreShape;
 
@@ -359,11 +346,13 @@
 					this.direction == mxConstants.DIRECTION_WEST)
 			{
 				var dy = h * size;
+				
 				return new mxRectangle(rect.x, rect.y + dy, w, h - 2 * dy);
 			}
 			else
 			{
 				var dx = w * size;
+				
 				return new mxRectangle(rect.x + dx, rect.y, w - 2 * dx, h);
 			}
 		}
@@ -380,6 +369,15 @@
 	};
 	mxUtils.extend(DocumentShape, mxActor);
 	DocumentShape.prototype.size = 0.3;
+	DocumentShape.prototype.getLabelMargins = function(rect)
+	{
+		if (mxUtils.getValue(this.style, 'boundedLbl', false))
+		{
+			return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * rect.height);
+		}
+		
+		return null;
+	};
 	DocumentShape.prototype.redrawPath = function(c, x, y, w, h)
 	{
 		var dy = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
@@ -396,6 +394,16 @@
 	};
 
 	mxCellRenderer.prototype.defaultShapes['document'] = DocumentShape;
+	
+	mxCylinder.prototype.getLabelMargins = function(rect)
+	{
+		if (mxUtils.getValue(this.style, 'boundedLbl', false))
+		{
+			return new mxRectangle(0, Math.min(this.maxHeight * this.scale, rect.height * 0.3), 0, 0);
+		}
+		
+		return null;
+	};
 
 	// Parallelogram shape
 	function ParallelogramShape()
@@ -784,6 +792,37 @@
 
 	mxCellRenderer.prototype.defaultShapes['process'] = ProcessShape;
 
+	// Callout shape
+	function CalloutShape()
+	{
+		mxActor.call(this);
+	};
+	mxUtils.extend(CalloutShape, mxHexagon);
+	CalloutShape.prototype.size = 30;
+	CalloutShape.prototype.position = 0.5;
+	CalloutShape.prototype.position2 = 0.5;
+	CalloutShape.prototype.base = 20;
+	CalloutShape.prototype.getLabelMargins = function()
+	{
+		return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(
+			this.style, 'size', this.size)) * this.scale);
+	};
+	CalloutShape.prototype.redrawPath = function(c, x, y, w, h)
+	{
+		var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
+		var s = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
+		var dx = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position', this.position))));
+		var dx2 = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position2', this.position2))));
+		var base = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'base', this.base))));
+		
+		this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, h - s),
+			new mxPoint(Math.min(w, dx + base), h - s), new mxPoint(dx2, h),
+			new mxPoint(Math.max(0, dx), h - s), new mxPoint(0, h - s)],
+			this.isRounded, arcSize, true, [4]);
+	};
+
+	mxCellRenderer.prototype.defaultShapes['callout'] = CalloutShape;
+
 	// Step shape
 	function StepShape()
 	{
@@ -851,9 +890,11 @@
 	{
 		if (this.style['double'] == 1)
 		{
-			var margin = (Math.max(2, this.strokewidth + 1) * 2 + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;
+			var margin = (Math.max(2, this.strokewidth + 1) * 2 + parseFloat(
+				this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;
 		
-			return new mxRectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin);
+			return new mxRectangle(rect.x + margin, rect.y + margin,
+				rect.width - 2 * margin, rect.height - 2 * margin);
 		}
 		
 		return rect;
@@ -864,7 +905,8 @@
 
 		if (!this.outline && this.style['double'] == 1)
 		{
-			var margin = Math.max(2, this.strokewidth + 1) * 2 + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0);
+			var margin = Math.max(2, this.strokewidth + 1) * 2 +
+				parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0);
 			x += margin;
 			y += margin;
 			w -= 2 * margin;
@@ -895,9 +937,11 @@
 	{
 		if (this.style['double'] == 1)
 		{
-			var margin = (Math.max(2, this.strokewidth + 1) + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;
+			var margin = (Math.max(2, this.strokewidth + 1) + parseFloat(
+				this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;
 		
-			return new mxRectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin);
+			return new mxRectangle(rect.x + margin, rect.y + margin,
+				rect.width - 2 * margin, rect.height - 2 * margin);
 		}
 		
 		return rect;
@@ -1070,9 +1114,9 @@
 		mxShape.call(this);
 	};
 	mxUtils.extend(UmlBoundaryShape, mxShape);
-	UmlBoundaryShape.prototype.getLabelBounds = function(rect)
+	UmlBoundaryShape.prototype.getLabelMargins = function(rect)
 	{
-		return new mxRectangle(rect.x + rect.width / 6, rect.y, rect.width * 5 / 6, rect.height);
+		return new mxRectangle(rect.width / 6, 0, 0, 0);
 	};
 	UmlBoundaryShape.prototype.paintBackground = function(c, x, y, w, h)
 	{
@@ -1191,7 +1235,8 @@
 	};
 	UmlLifeline.prototype.getLabelBounds = function(rect)
 	{
-		var size = Math.max(0, Math.min(rect.height, parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * this.scale));
+		var size = Math.max(0, Math.min(rect.height, parseFloat(
+			mxUtils.getValue(this.style, 'size', this.size)) * this.scale));
 		
 		return new mxRectangle(rect.x, rect.y, rect.width, size);
 	};
@@ -1245,12 +1290,11 @@
 	UmlFrame.prototype.width = 60;
 	UmlFrame.prototype.height = 30;
 	UmlFrame.prototype.corner = 10;
-	UmlFrame.prototype.getLabelBounds = function(rect)
+	UmlFrame.prototype.getLabelMargins = function(rect)
 	{
-		var w = Math.max(0, Math.min(rect.width, parseFloat(mxUtils.getValue(this.style, 'width', this.width)) * this.scale));
-		var h = Math.max(0, Math.min(rect.height, parseFloat(mxUtils.getValue(this.style, 'height', this.height)) * this.scale));
-		
-		return new mxRectangle(rect.x, rect.y, w, h);
+		return new mxRectangle(0, 0,
+			rect.width - (parseFloat(mxUtils.getValue(this.style, 'width', this.width) * this.scale)),
+			rect.height - (parseFloat(mxUtils.getValue(this.style, 'height', this.height) * this.scale)));
 	};
 	UmlFrame.prototype.paintBackground = function(c, x, y, w, h)
 	{
@@ -1345,64 +1389,18 @@
 	};
 	
 	mxStyleRegistry.putValue('backbonePerimeter', mxPerimeter.BackbonePerimeter);
-	
-	mxPerimeter.lineIntersection = function (line1Start, line1End, line2Start, line2End)
-	{
-	  // if the lines intersect, the result contains the the
-	  // intersection point if both line segment 1 and line segment 2 contain the point
-	  // null otherwise
-	  var denominator = ((line2End.y - line2Start.y) * (line1End.x - line1Start.x)) 
-	  						- ((line2End.x - line2Start.x) * (line1End.y - line1Start.y));
-	  
-	  if (denominator == 0) //parallel?
-	  {
-	    return null;
-	  }
-	  else
-	  {
-	    var a = line1Start.y - line2Start.y;
-	    var b = line1Start.x - line2Start.x;
-	    var numerator1 = ((line2End.x - line2Start.x) * a) - ((line2End.y - line2Start.y) * b);
-	    var numerator2 = ((line1End.x - line1Start.x) * a) - ((line1End.y - line1Start.y) * b);
-	    a = numerator1 / denominator;
-	    b = numerator2 / denominator;
-
-	    // if we cast these lines infinitely in both directions, they intersect here:
-	    var x = line1Start.x + (a * (line1End.x - line1Start.x));
-	    var y = line1Start.y + (a * (line1End.y - line1Start.y));
-
-	    if (a >= 0 && a <= 1)// on line1?
-	    	{
-		  	  var dx = line2End.x - x;
-			  var dy = line2End.y - y;
-			  var d = Math.sqrt(dy * dy + dx * dx); //distance from end of line 2 (next) to intersection point
-		      return {dist: d, p: new mxPoint(x, y)};
-	    	}
-	    else
-	    {
-	      return null;
-	    }
-	  }
-	};
-
-	mxPerimeter.getPerimeterPoint = function (points, center, point)
-	{
-		var min = false;
-		
-		for (var i = 0; i < points.length - 1; i++)
-		{
-			var ip = mxPerimeter.lineIntersection(points[i], points[i + 1], center, point);
-			
-			if (ip != null && (!min || min.dist > ip.dist))
-			{
-				min = ip;
-			}
-		}
-		
-		return min.p;
-	};
 
-	//Parallelogram Perimeter
+	// Callout Perimeter
+	mxPerimeter.CalloutPerimeter = function (bounds, vertex, next, orthogonal)
+	{
+		return mxPerimeter.RectanglePerimeter(mxUtils.getDirectedBounds(bounds, new mxRectangle(0, 0, 0,
+			Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(vertex.style, 'size',
+			CalloutShape.prototype.size))))), vertex.style), vertex, next, orthogonal);
+	};
+	
+	mxStyleRegistry.putValue('calloutPerimeter', mxPerimeter.CalloutPerimeter);
+	
+	// Parallelogram Perimeter
 	mxPerimeter.ParallelogramPerimeter = function (bounds, vertex, next, orthogonal)
 	{
 		var size = ParallelogramShape.prototype.size;
@@ -1418,11 +1416,10 @@
 		var h = bounds.height;
 
 		var direction = (vertex != null) ? mxUtils.getValue(
-				vertex.style, mxConstants.STYLE_DIRECTION,
-				mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
-		var vertical = direction == mxConstants.DIRECTION_NORTH
-				|| direction == mxConstants.DIRECTION_SOUTH;
-				
+			vertex.style, mxConstants.STYLE_DIRECTION,
+			mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
+		var vertical = direction == mxConstants.DIRECTION_NORTH ||
+			direction == mxConstants.DIRECTION_SOUTH;
 		var points;
 		
 		if (vertical)
@@ -1446,17 +1443,21 @@
 		if (orthogonal)
 		{
 			if (next.x < x || next.x > x + w)
+			{
 				p1.y = next.y;
+			}
 			else
+			{
 				p1.x = next.x;
+			}
 		}
 		
-		return mxPerimeter.getPerimeterPoint(points, p1, next);
+		return mxUtils.getPerimeterPoint(points, p1, next);
 	};
 	
 	mxStyleRegistry.putValue('parallelogramPerimeter', mxPerimeter.ParallelogramPerimeter);
 	
-	//Trapezoid Perimeter
+	// Trapezoid Perimeter
 	mxPerimeter.TrapezoidPerimeter = function (bounds, vertex, next, orthogonal)
 	{
 		var size = TrapezoidShape.prototype.size;
@@ -1474,7 +1475,6 @@
 		var direction = (vertex != null) ? mxUtils.getValue(
 				vertex.style, mxConstants.STYLE_DIRECTION,
 				mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
-		
 		var points;
 		
 		if (direction == mxConstants.DIRECTION_EAST)
@@ -1510,17 +1510,21 @@
 		if (orthogonal)
 		{
 			if (next.x < x || next.x > x + w)
+			{
 				p1.y = next.y;
+			}
 			else
+			{
 				p1.x = next.x;
+			}
 		}
 
-		return mxPerimeter.getPerimeterPoint(points, p1, next);
+		return mxUtils.getPerimeterPoint(points, p1, next);
 	};
 	
 	mxStyleRegistry.putValue('trapezoidPerimeter', mxPerimeter.TrapezoidPerimeter);
 	
-	//Step Perimeter
+	// Step Perimeter
 	mxPerimeter.StepPerimeter = function (bounds, vertex, next, orthogonal)
 	{
 		var size = StepShape.prototype.size;
@@ -1541,7 +1545,6 @@
 		var direction = (vertex != null) ? mxUtils.getValue(
 				vertex.style, mxConstants.STYLE_DIRECTION,
 				mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
-		
 		var points;
 		
 		if (direction == mxConstants.DIRECTION_EAST)
@@ -1578,17 +1581,21 @@
 		if (orthogonal)
 		{
 			if (next.x < x || next.x > x + w)
+			{
 				p1.y = next.y;
+			}
 			else
+			{
 				p1.x = next.x;
+			}
 		}
 		
-		return mxPerimeter.getPerimeterPoint(points, p1, next);
+		return mxUtils.getPerimeterPoint(points, p1, next);
 	};
 	
 	mxStyleRegistry.putValue('stepPerimeter', mxPerimeter.StepPerimeter);
 	
-	//Hexagon Perimeter (keep existing one)
+	// Hexagon Perimeter 2 (keep existing one)
 	mxPerimeter.HexagonPerimeter2 = function (bounds, vertex, next, orthogonal)
 	{
 		var size = HexagonShape.prototype.size;
@@ -1607,11 +1614,10 @@
 		var cy = bounds.getCenterY();
 		
 		var direction = (vertex != null) ? mxUtils.getValue(
-				vertex.style, mxConstants.STYLE_DIRECTION,
-				mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
-		var vertical = direction == mxConstants.DIRECTION_NORTH
-				|| direction == mxConstants.DIRECTION_SOUTH;
-		
+			vertex.style, mxConstants.STYLE_DIRECTION,
+			mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
+		var vertical = direction == mxConstants.DIRECTION_NORTH ||
+			direction == mxConstants.DIRECTION_SOUTH;
 		var points;
 		
 		if (vertical)
@@ -1634,12 +1640,16 @@
 		if (orthogonal)
 		{
 			if (next.x < x || next.x > x + w)
+			{
 				p1.y = next.y;
+			}
 			else
+			{
 				p1.x = next.x;
+			}
 		}
 		
-		return mxPerimeter.getPerimeterPoint(points, p1, next);
+		return mxUtils.getPerimeterPoint(points, p1, next);
 	};
 	
 	mxStyleRegistry.putValue('hexagonPerimeter2', mxPerimeter.HexagonPerimeter2);
@@ -3101,11 +3111,6 @@
 					this.state.style['height'] = Math.round(Math.max(UmlFrame.prototype.corner * 1.5, Math.min(bounds.height, pt.y - bounds.y)));
 				}, false)];
 				
-				if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false))
-				{
-					handles.push(createArcHandle(state));
-				}
-				
 				return handles;
 			},
 			'process': function(state)
@@ -3187,6 +3192,49 @@
 					this.state.style['size'] = Math.max(0, Math.min(1, (bounds.x + bounds.width - pt.x) / bounds.width));
 				})];
 			},
+			'callout': function(state)
+			{
+				var handles = [createHandle(state, ['size', 'position'], function(bounds)
+				{
+					var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', CalloutShape.prototype.size)));
+					var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));
+					var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));
+					
+					return new mxPoint(bounds.x + position * bounds.width, bounds.y + bounds.height - size);
+				}, function(bounds, pt)
+				{
+					var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));
+					this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y)));
+					this.state.style['position'] = Math.round(Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width)) * 100) / 100;
+				}), createHandle(state, ['position2'], function(bounds)
+				{
+					var position2 = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position2', CalloutShape.prototype.position2)));
+
+					return new mxPoint(bounds.x + position2 * bounds.width, bounds.y + bounds.height);
+				}, function(bounds, pt)
+				{
+					this.state.style['position2'] = Math.round(Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width)) * 100) / 100;
+				}), createHandle(state, ['base'], function(bounds)
+				{
+					var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', CalloutShape.prototype.size)));
+					var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));
+					var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));
+					
+					return new mxPoint(bounds.x + Math.min(bounds.width, position * bounds.width + base), bounds.y + bounds.height - size);
+				}, function(bounds, pt)
+				{
+					var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));
+
+					this.state.style['base'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x - position * bounds.width)));
+				})];
+				
+				if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false))
+				{
+					handles.push(createArcHandle(state));
+				}
+				
+				return handles;
+			},
 			'internalStorage': function(state)
 			{
 				var handles = [createHandle(state, ['dx', 'dy'], function(bounds)

+ 7 - 9
war/js/mxgraph/Sidebar.js

@@ -937,22 +937,22 @@ Sidebar.prototype.addGeneralPalette = function(expand)
 	 	this.createVertexTemplateEntry('shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;', 120, 60, '', 'Parallelogram'),
 	 	this.createVertexTemplateEntry('shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;', 120, 80, '', 'Hexagon', null, null, 'hexagon preparation'),
 	 	this.createVertexTemplateEntry('triangle;whiteSpace=wrap;html=1;', 60, 80, '', 'Triangle', null, null, 'triangle logic inverter buffer'),
-	 	this.createVertexTemplateEntry('shape=cylinder;whiteSpace=wrap;html=1;', 60, 80, '', 'Cylinder', null, null, 'cylinder data database'),
+	 	this.createVertexTemplateEntry('shape=cylinder;whiteSpace=wrap;html=1;boundedLbl=1;', 60, 80, '', 'Cylinder', null, null, 'cylinder data database'),
 	 	this.createVertexTemplateEntry('ellipse;shape=cloud;whiteSpace=wrap;html=1;', 120, 80, '', 'Cloud', null, null, 'cloud network'),
-	 	this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;', 120, 80, '', 'Document'),
+	 	this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;', 120, 80, '', 'Document'),
 	 	this.createVertexTemplateEntry('shape=internalStorage;whiteSpace=wrap;html=1;', 80, 80, '', 'Internal Storage'),
-	 	this.createVertexTemplateEntry('shape=cube;whiteSpace=wrap;html=1;', 120, 80, '', 'Cube'),
+	 	this.createVertexTemplateEntry('shape=cube;whiteSpace=wrap;html=1;boundedLbl=1;', 120, 80, '', 'Cube'),
 	 	this.createVertexTemplateEntry('shape=step;perimeter=stepPerimeter;whiteSpace=wrap;html=1;', 120, 80, '', 'Step'),
 	 	this.createVertexTemplateEntry('shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;', 120, 60, '', 'Trapezoid'),
 	 	this.createVertexTemplateEntry('shape=tape;whiteSpace=wrap;html=1;', 120, 100, '', 'Tape'),
 	 	this.createVertexTemplateEntry('shape=note;whiteSpace=wrap;html=1;', 80, 100, '', 'Note'),
 	    this.createVertexTemplateEntry('shape=card;whiteSpace=wrap;html=1;', 80, 100, '', 'Card'),
-	 	this.createEdgeTemplateEntry('endArrow=classic;html=1;', 50, 50, '', 'Directional Connector', null, lineTags + 'directional directed'),
-	    this.createEdgeTemplateEntry('endArrow=none;html=1;dashed=1;dashPattern=1 4;', 50, 50, '', 'Dotted Line', null, lineTags + 'dotted undirected no'),
+	    this.createVertexTemplateEntry('shape=callout;whiteSpace=wrap;html=1;perimeter=calloutPerimeter;', 120, 80, '', 'Callout'),
 	 	this.createEdgeTemplateEntry('endArrow=none;dashed=1;html=1;', 50, 50, '', 'Dashed Line', null, lineTags + 'dashed undirected no'),
 	 	this.createEdgeTemplateEntry('endArrow=none;html=1;', 50, 50, '', 'Line', null, lineTags + 'simple undirected plain blank no'),
-	 	this.createEdgeTemplateEntry('endArrow=classic;startArrow=classic;html=1;', 50, 50, '', 'Bidirectional Connector', null, lineTags + 'bidirectional')
-	 ];
+	 	this.createEdgeTemplateEntry('endArrow=classic;startArrow=classic;html=1;', 50, 50, '', 'Bidirectional Connector', null, lineTags + 'bidirectional'),
+	 	this.createEdgeTemplateEntry('endArrow=classic;html=1;', 50, 50, '', 'Directional Connector', null, lineTags + 'directional directed')
+	];
 	
 	this.addPaletteFunctions('general', mxResources.get('general'), (expand != null) ? expand : true, fns);
 };
@@ -962,8 +962,6 @@ Sidebar.prototype.addGeneralPalette = function(expand)
  */
 Sidebar.prototype.addBasicPalette = function(dir)
 {
-	console.log('here');
-	
 	this.addStencilPalette('basic', mxResources.get('basic'), dir + '/basic.xml',
 		';whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#000000;strokeWidth=2',
 		null, null, null, null, [

文件差異過大導致無法顯示
+ 307 - 299
war/js/reader.min.js


文件差異過大導致無法顯示
+ 6 - 6
war/js/shapes.min.js


文件差異過大導致無法顯示
+ 290 - 282
war/js/viewer.min.js


+ 72 - 79
war/shapes/mxBasic.js

@@ -2,9 +2,8 @@
  * $Id: mxBasic.js,v 1.5 2016/04/1 12:32:06 mate Exp $
  * Copyright (c) 2006-2016, JGraph Ltd
  */
-
 //**********************************************************************************************************************************************************
-//Cross
+// Cross
 //**********************************************************************************************************************************************************
 /**
 * Extends mxShape.
@@ -24,9 +23,7 @@ function mxShapeBasicCross(bounds, fill, stroke, strokewidth)
 */
 mxUtils.extend(mxShapeBasicCross, mxActor);
 
-mxShapeBasicCross.prototype.cst = {
-		CROSS : 'mxgraph.basic.cross2'
-};
+mxShapeBasicCross.prototype.cst = {CROSS : 'mxgraph.basic.cross2'};
 
 /**
 * Function: paintVertexShape
@@ -63,21 +60,20 @@ mxShapeBasicCross.prototype.constraints = null;
 Graph.handleFactory[mxShapeBasicCross.prototype.cst.CROSS] = function(state)
 {
 	var handles = [Graph.createHandle(state, ['dx'], function(bounds)
-			{
-				var dx = Math.max(0, Math.min(bounds.width / 2, bounds.width / 2, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
-
-				return new mxPoint(bounds.x + bounds.width / 2 + dx, bounds.y + bounds.height / 2 - dx);
-			}, function(bounds, pt)
-			{
-				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2, bounds.width / 2, pt.x - bounds.x - bounds.width / 2))) / 100;
-			})];
+	{
+		var dx = Math.max(0, Math.min(bounds.width / 2, bounds.width / 2, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
+
+		return new mxPoint(bounds.x + bounds.width / 2 + dx, bounds.y + bounds.height / 2 - dx);
+	}, function(bounds, pt)
+	{
+		this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2, bounds.width / 2, pt.x - bounds.x - bounds.width / 2))) / 100;
+	})];
 			
 	return handles;
-
-}
+};
 
 //**********************************************************************************************************************************************************
-//Rectangular Callout
+// Rectangular Callout
 //**********************************************************************************************************************************************************
 /**
 * Extends mxShape.
@@ -98,9 +94,7 @@ function mxShapeBasicRectCallout(bounds, fill, stroke, strokewidth)
 */
 mxUtils.extend(mxShapeBasicRectCallout, mxActor);
 
-mxShapeBasicRectCallout.prototype.cst = {
-		RECT_CALLOUT : 'mxgraph.basic.rectCallout'
-};
+mxShapeBasicRectCallout.prototype.cst = {RECT_CALLOUT : 'mxgraph.basic.rectCallout'};
 
 /**
 * Function: paintVertexShape
@@ -113,7 +107,6 @@ mxShapeBasicRectCallout.prototype.paintVertexShape = function(c, x, y, w, h)
 
 	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
 	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
-	var dh = 20;
 
 	c.begin();
 	c.moveTo(dx - dy * 0.5, h - dy);
@@ -127,6 +120,16 @@ mxShapeBasicRectCallout.prototype.paintVertexShape = function(c, x, y, w, h)
 	c.fillAndStroke();
 };
 
+mxShapeBasicRectCallout.prototype.getLabelMargins = function()
+{
+	if (mxUtils.getValue(this.style, 'boundedLbl', false))
+	{
+		return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy)) * this.scale);
+	}
+	
+	return new mxRectangle(rect.x, rect.y, rect.width, rect.height);
+};
+
 mxCellRenderer.registerShape(mxShapeBasicRectCallout.prototype.cst.RECT_CALLOUT, mxShapeBasicRectCallout);
 
 mxShapeBasicRectCallout.prototype.constraints = null;
@@ -134,24 +137,23 @@ mxShapeBasicRectCallout.prototype.constraints = null;
 Graph.handleFactory[mxShapeBasicRectCallout.prototype.cst.RECT_CALLOUT] = function(state)
 {
 	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
-			{
-				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
-				var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
-
-				return new mxPoint(bounds.x + dx, bounds.y + bounds.height - dy);
-			}, function(bounds, pt)
-			{
-				var y = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 0.6;
-				this.state.style['dx'] = Math.round(100 * Math.max(y, Math.min(bounds.width - y, pt.x - bounds.x))) / 100;
-				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y))) / 100;
-			})];
+	{
+		var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
+		var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
+
+		return new mxPoint(bounds.x + dx, bounds.y + bounds.height - dy);
+	}, function(bounds, pt)
+	{
+		var y = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 0.6;
+		this.state.style['dx'] = Math.round(100 * Math.max(y, Math.min(bounds.width - y, pt.x - bounds.x))) / 100;
+		this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y)));
+	})];
 			
 	return handles;
-
-}
+};
 
 //**********************************************************************************************************************************************************
-//Rounded Rectangular Callout
+// Rounded Rectangular Callout
 //**********************************************************************************************************************************************************
 /**
 * Extends mxShape.
@@ -173,9 +175,9 @@ function mxShapeBasicRoundRectCallout(bounds, fill, stroke, strokewidth)
 */
 mxUtils.extend(mxShapeBasicRoundRectCallout, mxActor);
 
-mxShapeBasicRoundRectCallout.prototype.cst = {
-		ROUND_RECT_CALLOUT : 'mxgraph.basic.roundRectCallout'
-};
+mxShapeBasicRoundRectCallout.prototype.cst = {ROUND_RECT_CALLOUT : 'mxgraph.basic.roundRectCallout'};
+
+mxShapeBasicRoundRectCallout.prototype.getLabelMargins = mxShapeBasicRectCallout.prototype.getLabelMargins;
 
 /**
 * Function: paintVertexShape
@@ -217,38 +219,33 @@ mxShapeBasicRoundRectCallout.prototype.constraints = null;
 
 Graph.handleFactory[mxShapeBasicRoundRectCallout.prototype.cst.ROUND_RECT_CALLOUT] = function(state)
 {
-	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
-			{
-				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
-				var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
-
-				return new mxPoint(bounds.x + dx, bounds.y + bounds.height - dy);
-			}, function(bounds, pt)
-			{
-				var y = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 0.6;
-				this.state.style['dx'] = Math.round(100 * Math.max(y, Math.min(bounds.width - y, pt.x - bounds.x))) / 100;
-				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y))) / 100;
-			})];
-
-	var handle2 = Graph.createHandle(state, ['size'], function(bounds)
-			{
-				var size = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'size', this.size))));
-
-				return new mxPoint(bounds.x + bounds.width - size, bounds.y + 10);
-			}, function(bounds, pt)
-			{
-				var dy = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy));
-				this.state.style['size'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2, (bounds.height - dy) / 2, bounds.x + bounds.width - pt.x))) / 100;
-			});
-	
-	handles.push(handle2);
-
-	return handles;
+	return [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
+	{
+		var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
+		var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
+
+		return new mxPoint(bounds.x + dx, bounds.y + bounds.height - dy);
+	}, function(bounds, pt)
+	{
+		var y = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 0.6;
+		this.state.style['dx'] = Math.round(100 * Math.max(y, Math.min(bounds.width - y, pt.x - bounds.x))) / 100;
+		this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y)));
+	}), Graph.createHandle(state, ['size'], function(bounds)
+	{
+		var size = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'size', this.size))));
+
+		return new mxPoint(bounds.x + bounds.width - size, bounds.y + 10);
+	}, function(bounds, pt)
+	{
+		var dy = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy));
+		this.state.style['size'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2, (bounds.height - dy) / 2, bounds.x + bounds.width - pt.x))) / 100;
+	})];
+};
 
-}
+mxShapeBasicRoundRectCallout.prototype.getLabelBounds = mxShapeBasicRectCallout.prototype.getLabelBounds;
 
 //**********************************************************************************************************************************************************
-//Wave
+// Wave
 //**********************************************************************************************************************************************************
 /**
 * Extends mxShape.
@@ -268,9 +265,7 @@ function mxShapeBasicWave(bounds, fill, stroke, strokewidth)
 */
 mxUtils.extend(mxShapeBasicWave, mxActor);
 
-mxShapeBasicWave.prototype.cst = {
-		WAVE : 'mxgraph.basic.wave2'
-};
+mxShapeBasicWave.prototype.cst = {WAVE : 'mxgraph.basic.wave2'};
 
 /**
 * Function: paintVertexShape
@@ -304,16 +299,14 @@ mxShapeBasicWave.prototype.constraints = null;
 Graph.handleFactory[mxShapeBasicWave.prototype.cst.WAVE] = function(state)
 {
 	var handles = [Graph.createHandle(state, ['dy'], function(bounds)
-			{
-				var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
+	{
+		var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
 
-				return new mxPoint(bounds.x + bounds.width / 2, bounds.y + dy * bounds.height);
-			}, function(bounds, pt)
-			{
-				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height))) / 100;
-			})];
+		return new mxPoint(bounds.x + bounds.width / 2, bounds.y + dy * bounds.height);
+	}, function(bounds, pt)
+	{
+		this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height))) / 100;
+	})];
 
 	return handles;
-
-}
-
+};