1 /* 2 * HomePane.js 3 * 4 * Sweet Home 3D, Copyright (c) 2024 Space Mushrooms <[email protected]> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 // Requires toolkit.js 22 23 /** 24 * Creates home view associated with its controller. 25 * @param {Home} home 26 * @param {UserPreferences} preferences 27 * @param {HomeController} controller 28 * @constructor 29 * @author Emmanuel Puybaret 30 * @author Renaud Pawlak 31 * @author Louis Grignon 32 */ 33 function HomePane(containerId, home, preferences, controller) { 34 if (containerId != null) { 35 this.container = document.getElementById(containerId); 36 } 37 if (!this.container) { 38 this.container = document.body; 39 } 40 this.home = home; 41 this.preferences = preferences; 42 this.controller = controller; 43 this.clipboardEmpty = true; 44 this.actionMap = {}; 45 this.inputMap = {}; 46 this.transferHandlerEnabled = false; 47 48 this.createActions(home, preferences, controller); 49 this.initActions(preferences); 50 this.addHomeListener(home); 51 this.addLevelVisibilityListener(home); 52 this.addUserPreferencesListener(preferences); 53 this.addPlanControllerListener(controller.getPlanController()); 54 this.addFocusListener(); 55 this.createToolBar(home, preferences, controller); 56 this.createPopupMenus(home, preferences); 57 this.initSplitters(); 58 this.addOrientationChangeListener(); 59 60 // Additional implementation for Sweet Home 3D JS 61 62 // Keyboard accelerators management 63 var homePane = this; 64 this.keydownListener = function(ev) { 65 if (JSDialog.getTopMostDialog() !== null) { 66 // ignore keystrokes when dialog is displayed 67 return; 68 } 69 70 var keyStroke = KeyStroke.getKeyStrokeForEvent(ev); 71 if (keyStroke !== undefined) { 72 // Search action matching shortcut and call its actionPerformed method 73 for (var actionType in homePane.actionMap) { 74 var action = homePane.actionMap [actionType]; 75 if (action instanceof AbstractAction 76 && action.isEnabled() 77 && action.getValue(AbstractAction.ACCELERATOR_KEY) == keyStroke) { 78 action.actionPerformed(); 79 ev.stopPropagation(); 80 return; 81 } 82 } 83 // Search other actions in input map 84 var actionKey = homePane.inputMap [keyStroke]; 85 if (actionKey !== undefined) { 86 var action = homePane.actionMap [actionKey]; 87 if (action !== undefined) { 88 action.actionPerformed(ev); 89 } 90 ev.stopPropagation(); 91 } 92 } 93 }; 94 document.addEventListener("keydown", this.keydownListener, false); 95 96 var planComponent = controller.getPlanController().getView(); 97 if (planComponent != null) { 98 // Restore viewport position if it exists 99 var viewportX = home.getNumericProperty(HomePane.PLAN_VIEWPORT_X_VISUAL_PROPERTY); 100 var viewportY = home.getNumericProperty(HomePane.PLAN_VIEWPORT_Y_VISUAL_PROPERTY); 101 if (viewportX != null && viewportY != null) { 102 planComponent.scrollPane.scrollLeft = viewportX | 0; 103 planComponent.scrollPane.scrollTop = viewportY | 0; 104 } 105 106 planComponent.scrollPane.addEventListener("scroll", function(ev) { 107 controller.setHomeProperty(HomePane.PLAN_VIEWPORT_X_VISUAL_PROPERTY, planComponent.scrollPane.scrollLeft.toString()); 108 controller.setHomeProperty(HomePane.PLAN_VIEWPORT_Y_VISUAL_PROPERTY, planComponent.scrollPane.scrollTop.toString()); 109 }); 110 } 111 112 // Create level selector 113 this.levelSelector = document.getElementById("level-selector"); 114 var levelsChangeListener = function() { 115 if (homePane.levelSelector) { 116 homePane.levelSelector.innerHTML = ""; 117 if (home.getLevels().length < 2) { 118 homePane.levelSelector.style.display = "none"; 119 } else { 120 for (var i = 0; i < home.getLevels().length; i++) { 121 var option = document.createElement("option"); 122 option.value = i; 123 option.innerHTML = home.getLevels()[i].getName(); 124 if (home.getLevels()[i] === home.getSelectedLevel()) { 125 option.selected = "selected"; 126 } 127 homePane.levelSelector.appendChild(option); 128 } 129 homePane.levelSelector.style.display = "inline"; 130 } 131 } 132 }; 133 levelsChangeListener(); 134 if (this.levelSelector) { 135 this.levelSelectorChangeListener = function(ev) { 136 controller.getPlanController().setSelectedLevel(home.getLevels()[parseInt(ev.target.value)]); 137 levelsChangeListener(); 138 }; 139 this.levelSelector.addEventListener("change", this.levelSelectorChangeListener); 140 } 141 home.addPropertyChangeListener("SELECTED_LEVEL", levelsChangeListener); 142 var levelChangeListener = function(ev) { 143 if ("NAME" == ev.getPropertyName() 144 || "ELEVATION" == ev.getPropertyName() 145 || "ELEVATION_INDEX" == ev.getPropertyName()) { 146 levelsChangeListener(); 147 } 148 }; 149 var levels = home.getLevels(); 150 for (var i = 0; i < levels.length; i++) { 151 levels[i].addPropertyChangeListener(levelChangeListener); 152 } 153 home.addLevelsListener(function(ev) { 154 if (ev.getType() === CollectionEvent.Type.ADD) { 155 ev.getItem().addPropertyChangeListener(levelChangeListener); 156 } else if (ev.getType() === CollectionEvent.Type.DELETE) { 157 ev.getItem().removePropertyChangeListener(levelChangeListener); 158 } 159 levelsChangeListener(); 160 }); 161 162 setTimeout(function() { 163 // Give default focus to the plan or the 3D view 164 if (planComponent != null) { 165 planComponent.getHTMLElement().focus(); 166 } else if (controller.getHomeController3D().getView() != null) { 167 controller.getHomeController3D().getView().getHTMLElement().focus(); 168 } 169 }); 170 } 171 HomePane["__class"] = "HomePane"; 172 HomePane["__interfaces"] = ["com.eteks.sweethome3d.viewcontroller.HomeView", "com.eteks.sweethome3d.viewcontroller.View"]; 173 174 HomePane.MAIN_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.MainPaneDividerLocation"; 175 HomePane.CATALOG_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.CatalogPaneDividerLocation"; 176 HomePane.PLAN_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.PlanPaneDividerLocation"; 177 HomePane.PLAN_VIEWPORT_X_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.PlanViewportX"; 178 HomePane.PLAN_VIEWPORT_Y_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.PlanViewportY"; 179 HomePane.FURNITURE_VIEWPORT_Y_VISUAL_PROPERTY = "com.eteks.sweethome3d.SweetHome3D.FurnitureViewportY"; 180 HomePane.DETACHED_VIEW_VISUAL_PROPERTY = ".detachedView"; 181 HomePane.DETACHED_VIEW_DIVIDER_LOCATION_VISUAL_PROPERTY = ".detachedViewDividerLocation"; 182 HomePane.DETACHED_VIEW_X_VISUAL_PROPERTY = ".detachedViewX"; 183 HomePane.DETACHED_VIEW_Y_VISUAL_PROPERTY = ".detachedViewY"; 184 HomePane.DETACHED_VIEW_WIDTH_VISUAL_PROPERTY = ".detachedViewWidth"; 185 HomePane.DETACHED_VIEW_HEIGHT_VISUAL_PROPERTY = ".detachedViewHeight"; 186 187 /** 188 * @private 189 */ 190 HomePane.MenuActionType = {}; 191 HomePane.MenuActionType[HomePane.MenuActionType["FILE_MENU"] = 0] = "FILE_MENU"; 192 HomePane.MenuActionType[HomePane.MenuActionType["EDIT_MENU"] = 1] = "EDIT_MENU"; 193 HomePane.MenuActionType[HomePane.MenuActionType["FURNITURE_MENU"] = 2] = "FURNITURE_MENU"; 194 HomePane.MenuActionType[HomePane.MenuActionType["PLAN_MENU"] = 3] = "PLAN_MENU"; 195 HomePane.MenuActionType[HomePane.MenuActionType["VIEW_3D_MENU"] = 4] = "VIEW_3D_MENU"; 196 HomePane.MenuActionType[HomePane.MenuActionType["HELP_MENU"] = 5] = "HELP_MENU"; 197 HomePane.MenuActionType[HomePane.MenuActionType["OPEN_RECENT_HOME_MENU"] = 6] = "OPEN_RECENT_HOME_MENU"; 198 HomePane.MenuActionType[HomePane.MenuActionType["ALIGN_OR_DISTRIBUTE_MENU"] = 7] = "ALIGN_OR_DISTRIBUTE_MENU"; 199 HomePane.MenuActionType[HomePane.MenuActionType["SORT_HOME_FURNITURE_MENU"] = 8] = "SORT_HOME_FURNITURE_MENU"; 200 HomePane.MenuActionType[HomePane.MenuActionType["DISPLAY_HOME_FURNITURE_PROPERTY_MENU"] = 9] = "DISPLAY_HOME_FURNITURE_PROPERTY_MENU"; 201 HomePane.MenuActionType[HomePane.MenuActionType["MODIFY_TEXT_STYLE"] = 10] = "MODIFY_TEXT_STYLE"; 202 HomePane.MenuActionType[HomePane.MenuActionType["GO_TO_POINT_OF_VIEW"] = 11] = "GO_TO_POINT_OF_VIEW"; 203 HomePane.MenuActionType[HomePane.MenuActionType["SELECT_OBJECT_MENU"] = 12] = "SELECT_OBJECT_MENU"; 204 HomePane.MenuActionType[HomePane.MenuActionType["TOGGLE_SELECTION_MENU"] = 13] = "TOGGLE_SELECTION_MENU"; 205 206 207 /** 208 * Returns the HTML element used to view this component at screen. 209 */ 210 HomePane.prototype.getHTMLElement = function() { 211 return this.container; 212 } 213 214 /** 215 * Returns the actions map registered with this component. 216 */ 217 HomePane.prototype.getActionMap = function() { 218 return this.actionMap; 219 } 220 221 /** 222 * Convenient shortcut method to access an action. 223 * @param {string|HomeView.ActionType} actionType 224 * @private 225 */ 226 HomePane.prototype.getAction = function(actionType) { 227 if (typeof actionType === "string") { 228 return this.actionMap[actionType]; 229 } else { 230 return this.actionMap[HomeView.ActionType[actionType]]; 231 } 232 } 233 234 /** 235 * Create the actions map of this component. 236 * @param {Home} home 237 * @param {UserPreferences} preferences 238 * @param {HomeController} controller 239 * @private 240 */ 241 HomePane.prototype.createActions = function(home, preferences, controller) { 242 var ActionType = HomeView.ActionType; 243 this.createAction(ActionType.NEW_HOME, preferences, controller, "newHome"); 244 this.createAction(ActionType.NEW_HOME_FROM_EXAMPLE, preferences, controller, "newHomeFromExample"); 245 this.createAction(ActionType.OPEN, preferences, controller, "open"); 246 this.createAction(ActionType.DELETE_RECENT_HOMES, preferences, controller, "deleteRecentHomes"); 247 this.createAction(ActionType.CLOSE, preferences, controller, "close"); 248 this.createAction(ActionType.SAVE, preferences, controller, "save"); 249 this.createAction(ActionType.SAVE_AS, preferences, controller, "saveAs"); 250 this.createAction(ActionType.SAVE_AND_COMPRESS, preferences, controller, "saveAndCompress"); 251 this.createAction(ActionType.PAGE_SETUP, preferences, controller, "setupPage"); 252 this.createAction(ActionType.PRINT_PREVIEW, preferences, controller, "previewPrint"); 253 this.createAction(ActionType.PRINT, preferences, controller, "print"); 254 this.createAction(ActionType.PRINT_TO_PDF, preferences, controller, "printToPDF"); 255 this.createAction(ActionType.PREFERENCES, preferences, controller, "editPreferences"); 256 this.createAction(ActionType.EXIT, preferences, controller, "exit"); 257 258 this.createAction(ActionType.UNDO, preferences, controller, "undo"); 259 this.createAction(ActionType.REDO, preferences, controller, "redo"); 260 this.createClipboardAction(ActionType.CUT, preferences, null, true); 261 this.createClipboardAction(ActionType.COPY, preferences, null, true); 262 this.createClipboardAction(ActionType.PASTE, preferences, null, false); 263 this.createAction(ActionType.PASTE_TO_GROUP, preferences, controller, "pasteToGroup"); 264 this.createAction(ActionType.PASTE_STYLE, preferences, controller, "pasteStyle"); 265 this.createAction(ActionType.DELETE, preferences, controller, "delete"); 266 this.createAction(ActionType.SELECT_ALL, preferences, controller, "selectAll"); 267 268 this.createAction(ActionType.ADD_HOME_FURNITURE, preferences, controller, "addHomeFurniture"); 269 this.createAction(ActionType.ADD_FURNITURE_TO_GROUP, preferences, controller, "addFurnitureToGroup"); 270 var furnitureController = controller.getFurnitureController(); 271 this.createAction(ActionType.DELETE_HOME_FURNITURE, preferences, furnitureController, "deleteSelection"); 272 this.createAction(ActionType.MODIFY_FURNITURE, preferences, controller, "modifySelectedFurniture"); 273 this.createAction(ActionType.GROUP_FURNITURE, preferences, furnitureController, "groupSelectedFurniture"); 274 this.createAction(ActionType.UNGROUP_FURNITURE, preferences, furnitureController, "ungroupSelectedFurniture"); 275 this.createAction(ActionType.ALIGN_FURNITURE_ON_TOP, preferences, furnitureController, "alignSelectedFurnitureOnTop"); 276 this.createAction(ActionType.ALIGN_FURNITURE_ON_BOTTOM, preferences, furnitureController, "alignSelectedFurnitureOnBottom"); 277 this.createAction(ActionType.ALIGN_FURNITURE_ON_LEFT, preferences, furnitureController, "alignSelectedFurnitureOnLeft"); 278 this.createAction(ActionType.ALIGN_FURNITURE_ON_RIGHT, preferences, furnitureController, "alignSelectedFurnitureOnRight"); 279 this.createAction(ActionType.ALIGN_FURNITURE_ON_FRONT_SIDE, preferences, furnitureController, "alignSelectedFurnitureOnFrontSide"); 280 this.createAction(ActionType.ALIGN_FURNITURE_ON_BACK_SIDE, preferences, furnitureController, "alignSelectedFurnitureOnBackSide"); 281 this.createAction(ActionType.ALIGN_FURNITURE_ON_LEFT_SIDE, preferences, furnitureController, "alignSelectedFurnitureOnLeftSide"); 282 this.createAction(ActionType.ALIGN_FURNITURE_ON_RIGHT_SIDE, preferences, furnitureController, "alignSelectedFurnitureOnRightSide"); 283 this.createAction(ActionType.ALIGN_FURNITURE_SIDE_BY_SIDE, preferences, furnitureController, "alignSelectedFurnitureSideBySide"); 284 this.createAction(ActionType.DISTRIBUTE_FURNITURE_HORIZONTALLY, preferences, furnitureController, "distributeSelectedFurnitureHorizontally"); 285 this.createAction(ActionType.DISTRIBUTE_FURNITURE_VERTICALLY, preferences, furnitureController, "distributeSelectedFurnitureVertically"); 286 this.createAction(ActionType.RESET_FURNITURE_ELEVATION, preferences, furnitureController, "resetFurnitureElevation"); 287 var homeController3D = controller.getHomeController3D(); 288 if (homeController3D.getView() != null) { 289 this.createAction(ActionType.IMPORT_FURNITURE, preferences, controller, "importFurniture"); 290 } 291 this.createAction(ActionType.IMPORT_FURNITURE_LIBRARY, preferences, controller, "importFurnitureLibrary"); 292 this.createAction(ActionType.IMPORT_TEXTURE, preferences, controller, "importTexture"); 293 this.createAction(ActionType.IMPORT_TEXTURES_LIBRARY, preferences, controller, "importTexturesLibrary"); 294 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_CATALOG_ID, preferences, 295 furnitureController, "toggleFurnitureSort", "CATALOG_ID"); 296 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_NAME, preferences, 297 furnitureController, "toggleFurnitureSort", "NAME"); 298 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_DESCRIPTION, preferences, 299 furnitureController, "toggleFurnitureSort", "DESCRIPTION"); 300 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_CREATOR, preferences, 301 furnitureController, "toggleFurnitureSort", "CREATOR"); 302 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_LICENSE, preferences, 303 furnitureController, "toggleFurnitureSort", "LICENSE"); 304 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_WIDTH, preferences, 305 furnitureController, "toggleFurnitureSort", "WIDTH"); 306 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_DEPTH, preferences, 307 furnitureController, "toggleFurnitureSort", "DEPTH"); 308 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_HEIGHT, preferences, 309 furnitureController, "toggleFurnitureSort", "HEIGHT"); 310 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_X, preferences, 311 furnitureController, "toggleFurnitureSort", "X"); 312 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_Y, preferences, 313 furnitureController, "toggleFurnitureSort", "Y"); 314 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_ELEVATION, preferences, 315 furnitureController, "toggleFurnitureSort", "ELEVATION"); 316 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_ANGLE, preferences, 317 furnitureController, "toggleFurnitureSort", "ANGLE"); 318 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_LEVEL, preferences, 319 furnitureController, "toggleFurnitureSort", "LEVEL"); 320 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_MODEL_SIZE, preferences, 321 furnitureController, "toggleFurnitureSort", "MODEL_SIZE"); 322 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_COLOR, preferences, 323 furnitureController, "toggleFurnitureSort", "COLOR"); 324 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_TEXTURE, preferences, 325 furnitureController, "toggleFurnitureSort", "TEXTURE"); 326 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_MOVABILITY, preferences, 327 furnitureController, "toggleFurnitureSort", "MOVABLE"); 328 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_TYPE, preferences, 329 furnitureController, "toggleFurnitureSort", "DOOR_OR_WINDOW"); 330 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_VISIBILITY, preferences, 331 furnitureController, "toggleFurnitureSort", "VISIBLE"); 332 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_PRICE, preferences, 333 furnitureController, "toggleFurnitureSort", "PRICE"); 334 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX_PERCENTAGE, preferences, 335 furnitureController, "toggleFurnitureSort", "VALUE_ADDED_TAX_PERCENTAGE"); 336 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX, preferences, 337 furnitureController, "toggleFurnitureSort", "VALUE_ADDED_TAX"); 338 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_PRICE_VALUE_ADDED_TAX_INCLUDED, preferences, 339 furnitureController, "toggleFurnitureSort", "PRICE_VALUE_ADDED_TAX_INCLUDED"); 340 this.createAction(ActionType.SORT_HOME_FURNITURE_BY_DESCENDING_ORDER, preferences, 341 furnitureController, "toggleFurnitureSortOrder"); 342 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_CATALOG_ID, preferences, 343 furnitureController, "toggleFurnitureVisibleProperty", "CATALOG_ID"); 344 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_NAME, preferences, 345 furnitureController, "toggleFurnitureVisibleProperty", "NAME"); 346 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_DESCRIPTION, preferences, 347 furnitureController, "toggleFurnitureVisibleProperty", "DESCRIPTION"); 348 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_CREATOR, preferences, 349 furnitureController, "toggleFurnitureVisibleProperty", "CREATOR"); 350 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_LICENSE, preferences, 351 furnitureController, "toggleFurnitureVisibleProperty", "LICENSE"); 352 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_WIDTH, preferences, 353 furnitureController, "toggleFurnitureVisibleProperty", "WIDTH"); 354 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_DEPTH, preferences, 355 furnitureController, "toggleFurnitureVisibleProperty", "DEPTH"); 356 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_HEIGHT, preferences, 357 furnitureController, "toggleFurnitureVisibleProperty", "HEIGHT"); 358 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_X, preferences, 359 furnitureController, "toggleFurnitureVisibleProperty", "X"); 360 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_Y, preferences, 361 furnitureController, "toggleFurnitureVisibleProperty", "Y"); 362 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_ELEVATION, preferences, 363 furnitureController, "toggleFurnitureVisibleProperty", "ELEVATION"); 364 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_ANGLE, preferences, 365 furnitureController, "toggleFurnitureVisibleProperty", "ANGLE"); 366 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_LEVEL, preferences, 367 furnitureController, "toggleFurnitureVisibleProperty", "LEVEL"); 368 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_MODEL_SIZE, preferences, 369 furnitureController, "toggleFurnitureVisibleProperty", "MODEL_SIZE"); 370 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_COLOR, preferences, 371 furnitureController, "toggleFurnitureVisibleProperty", "COLOR"); 372 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_TEXTURE, preferences, 373 furnitureController, "toggleFurnitureVisibleProperty", "TEXTURE"); 374 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_MOVABLE, preferences, 375 furnitureController, "toggleFurnitureVisibleProperty", "MOVABLE"); 376 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_DOOR_OR_WINDOW, preferences, 377 furnitureController, "toggleFurnitureVisibleProperty", "DOOR_OR_WINDOW"); 378 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_VISIBLE, preferences, 379 furnitureController, "toggleFurnitureVisibleProperty", "VISIBLE"); 380 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_PRICE, preferences, 381 furnitureController, "toggleFurnitureVisibleProperty", "PRICE"); 382 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX_PERCENTAGE, preferences, 383 furnitureController, "toggleFurnitureVisibleProperty", "VALUE_ADDED_TAX_PERCENTAGE"); 384 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX, preferences, 385 furnitureController, "toggleFurnitureVisibleProperty", "VALUE_ADDED_TAX"); 386 this.createAction(ActionType.DISPLAY_HOME_FURNITURE_PRICE_VALUE_ADDED_TAX_INCLUDED, preferences, 387 furnitureController, "toggleFurnitureVisibleProperty", "PRICE_VALUE_ADDED_TAX_INCLUDED"); 388 this.createAction(ActionType.EXPORT_TO_CSV, preferences, controller, "exportToCSV"); 389 390 var planController = controller.getPlanController(); 391 if (planController.getView() != null) { 392 this.createAction(ActionType.SELECT_ALL_AT_ALL_LEVELS, preferences, planController, "selectAllAtAllLevels"); 393 var modeGroup = []; 394 this.createToggleAction(ActionType.SELECT, planController.getMode() == PlanController.Mode.SELECTION, modeGroup, 395 preferences, controller, "setMode", PlanController.Mode.SELECTION); 396 this.createToggleAction(ActionType.PAN, planController.getMode() == PlanController.Mode.PANNING, modeGroup, 397 preferences, controller, "setMode", PlanController.Mode.PANNING); 398 this.createToggleAction(ActionType.CREATE_WALLS, planController.getMode() == PlanController.Mode.WALL_CREATION, modeGroup, 399 preferences, controller, "setMode", PlanController.Mode.WALL_CREATION); 400 this.createToggleAction(ActionType.CREATE_ROOMS, planController.getMode() == PlanController.Mode.ROOM_CREATION, modeGroup, 401 preferences, controller, "setMode", PlanController.Mode.ROOM_CREATION); 402 this.createToggleAction(ActionType.CREATE_POLYLINES, planController.getMode() == PlanController.Mode.POLYLINE_CREATION, modeGroup, 403 preferences, controller, "setMode", PlanController.Mode.POLYLINE_CREATION); 404 this.createToggleAction(ActionType.CREATE_DIMENSION_LINES, planController.getMode() == PlanController.Mode.DIMENSION_LINE_CREATION, modeGroup, 405 preferences, controller, "setMode", PlanController.Mode.DIMENSION_LINE_CREATION); 406 this.createToggleAction(ActionType.CREATE_LABELS, planController.getMode() == PlanController.Mode.LABEL_CREATION, modeGroup, 407 preferences, controller, "setMode", PlanController.Mode.LABEL_CREATION); 408 this.createAction(ActionType.DELETE_SELECTION, preferences, planController, "deleteSelection"); 409 this.createAction(ActionType.LOCK_BASE_PLAN, preferences, planController, "lockBasePlan"); 410 this.createAction(ActionType.UNLOCK_BASE_PLAN, preferences, planController, "unlockBasePlan"); 411 this.createAction(ActionType.ENABLE_MAGNETISM, preferences, controller, "enableMagnetism"); 412 this.createAction(ActionType.DISABLE_MAGNETISM, preferences, controller, "disableMagnetism"); 413 this.createAction(ActionType.FLIP_HORIZONTALLY, preferences, planController, "flipHorizontally"); 414 this.createAction(ActionType.FLIP_VERTICALLY, preferences, planController, "flipVertically"); 415 this.createAction(ActionType.MODIFY_COMPASS, preferences, planController, "modifyCompass"); 416 this.createAction(ActionType.MODIFY_WALL, preferences, planController, "modifySelectedWalls"); 417 this.createAction(ActionType.MODIFY_ROOM, preferences, planController, "modifySelectedRooms"); 418 this.createAction(ActionType.JOIN_WALLS, preferences, planController, "joinSelectedWalls"); 419 this.createAction(ActionType.REVERSE_WALL_DIRECTION, preferences, planController, "reverseSelectedWallsDirection"); 420 this.createAction(ActionType.SPLIT_WALL, preferences, planController, "splitSelectedWall"); 421 // ADD_ROOM_POINT and DELETE_ROOM_POINT actions are actually defined later in updateRoomActions 422 this.createAction(ActionType.ADD_ROOM_POINT, preferences); 423 this.createAction(ActionType.DELETE_ROOM_POINT, preferences); 424 this.createAction(ActionType.MODIFY_POLYLINE, preferences, planController, "modifySelectedPolylines"); 425 this.createAction(ActionType.MODIFY_DIMENSION_LINE, preferences, planController, "modifySelectedDimensionLines"); 426 this.createAction(ActionType.MODIFY_LABEL, preferences, planController, "modifySelectedLabels"); 427 this.createAction(ActionType.INCREASE_TEXT_SIZE, preferences, planController, "increaseTextSize"); 428 this.createAction(ActionType.DECREASE_TEXT_SIZE, preferences, planController, "decreaseTextSize"); 429 // Use special toggle models for bold and italic check box menu items and tool bar buttons 430 // that are selected texts in home selected items are all bold or italic 431 var toggleBoldAction = this.createBoldStyleAction(ActionType.TOGGLE_BOLD_STYLE, home, preferences, planController, "toggleBoldStyle"); 432 var toggleItalicAction = this.createItalicStyleToggleModel(ActionType.TOGGLE_ITALIC_STYLE, home, preferences, planController, "toggleItalicStyle"); 433 this.createAction(ActionType.IMPORT_BACKGROUND_IMAGE, preferences, controller, "importBackgroundImage"); 434 this.createAction(ActionType.MODIFY_BACKGROUND_IMAGE, preferences, controller, "modifyBackgroundImage"); 435 this.createAction(ActionType.HIDE_BACKGROUND_IMAGE, preferences, controller, "hideBackgroundImage"); 436 this.createAction(ActionType.SHOW_BACKGROUND_IMAGE, preferences, controller, "showBackgroundImage"); 437 this.createAction(ActionType.DELETE_BACKGROUND_IMAGE, preferences, controller, "deleteBackgroundImage"); 438 this.createAction(ActionType.ADD_LEVEL, preferences, planController, "addLevel"); 439 this.createAction(ActionType.ADD_LEVEL_AT_SAME_ELEVATION, preferences, planController, "addLevelAtSameElevation"); 440 this.createAction(ActionType.MAKE_LEVEL_VIEWABLE, preferences, planController, "toggleSelectedLevelViewability"); 441 this.createAction(ActionType.MAKE_LEVEL_UNVIEWABLE, preferences, planController, "toggleSelectedLevelViewability"); 442 this.createAction(ActionType.MAKE_LEVEL_ONLY_VIEWABLE_ONE, preferences, planController, "setSelectedLevelOnlyViewable"); 443 this.createAction(ActionType.MAKE_ALL_LEVELS_VIEWABLE, preferences, planController, "setAllLevelsViewable"); 444 this.createAction(ActionType.MODIFY_LEVEL, preferences, planController, "modifySelectedLevel"); 445 this.createAction(ActionType.DELETE_LEVEL, preferences, planController, "deleteSelectedLevel"); 446 this.createAction(ActionType.ZOOM_IN, preferences, controller, "zoomIn"); 447 this.createAction(ActionType.ZOOM_OUT, preferences, controller, "zoomOut"); 448 this.createAction(ActionType.EXPORT_TO_SVG, preferences, controller, "exportToSVG"); 449 } 450 451 if (homeController3D.getView() != null) { 452 // SELECT_OBJECT and TOGGLE_SELECTION actions are actually defined later in updatePickingActions 453 this.createAction(ActionType.SELECT_OBJECT, preferences); 454 this.createAction(ActionType.TOGGLE_SELECTION, preferences); 455 var viewGroup = []; 456 this.createToggleAction(ActionType.VIEW_FROM_TOP, home.getCamera() == home.getTopCamera(), viewGroup, 457 preferences, homeController3D, "viewFromTop"); 458 this.createToggleAction(ActionType.VIEW_FROM_OBSERVER, home.getCamera() == home.getObserverCamera(), viewGroup, 459 preferences, homeController3D, "viewFromObserver"); 460 this.createAction(ActionType.MODIFY_OBSERVER, preferences, planController, "modifyObserverCamera"); 461 this.createAction(ActionType.STORE_POINT_OF_VIEW, preferences, controller, "storeCamera"); 462 this.createAction(ActionType.DELETE_POINTS_OF_VIEW, preferences, controller, "deleteCameras"); 463 this.createAction(ActionType.DETACH_3D_VIEW, preferences, controller, "detachView", controller.getHomeController3D().getView()); 464 this.createAction(ActionType.ATTACH_3D_VIEW, preferences, controller, "attachView", controller.getHomeController3D().getView()); 465 466 var allLevelsVisible = home.getEnvironment().isAllLevelsVisible(); 467 var displayLevelGroup = []; 468 this.createToggleAction(ActionType.DISPLAY_ALL_LEVELS, allLevelsVisible, displayLevelGroup, preferences, 469 homeController3D, "displayAllLevels"); 470 this.createToggleAction(ActionType.DISPLAY_SELECTED_LEVEL, !allLevelsVisible, displayLevelGroup, preferences, 471 homeController3D, "displaySelectedLevel"); 472 this.createAction(ActionType.MODIFY_3D_ATTRIBUTES, preferences, homeController3D, "modifyAttributes"); 473 this.createAction(ActionType.CREATE_PHOTO, preferences, controller, "createPhoto"); 474 this.createAction(ActionType.CREATE_PHOTOS_AT_POINTS_OF_VIEW, preferences, controller, "createPhotos"); 475 this.createAction(ActionType.CREATE_VIDEO, preferences, controller, "createVideo"); 476 this.createAction(ActionType.EXPORT_TO_OBJ, preferences, controller, "exportToOBJ"); 477 } 478 479 this.createAction(ActionType.HELP, preferences, controller, "help"); 480 this.createAction(ActionType.ABOUT, preferences, controller, "about"); 481 482 // Additional action for application popup menu 483 var showApplicationMenuAction = new ResourceAction(preferences, "HomePane", "SHOW_APPLICATION_MENU", true); 484 if (showApplicationMenuAction.getValue(AbstractAction.SMALL_ICON) == null) { 485 showApplicationMenuAction.putValue(AbstractAction.NAME, "SHOW_APPLICATION_MENU"); 486 showApplicationMenuAction.putValue(AbstractAction.SMALL_ICON, "menu.png"); 487 } 488 var homePane = this; 489 showApplicationMenuAction.actionPerformed = function(ev) { 490 ev.stopPropagation(); 491 ev.preventDefault(); 492 var planElement = controller.getPlanController().getView().getHTMLElement(); 493 var contextMenuEvent = document.createEvent("Event"); 494 contextMenuEvent.initEvent("contextmenu", true, true); 495 contextMenuEvent.clientX = homePane.showApplicationMenuButton.clientX + homePane.showApplicationMenuButton.clientWidth / 2; 496 contextMenuEvent.clientY = homePane.showApplicationMenuButton.clientY + homePane.showApplicationMenuButton.clientHeight / 2; 497 homePane.showApplicationMenuButton.dispatchEvent(contextMenuEvent); 498 }; 499 this.getActionMap()["SHOW_APPLICATION_MENU"] = showApplicationMenuAction; 500 } 501 502 /** 503 * Returns a new <code>ControllerAction</code> object that calls on <code>controller</code> a given 504 * <code>method</code> with its <code>parameters</code>. This action is added to the action map of this component. 505 * @param {HomeView.ActionType} actionType 506 * @param {UserPreferences} preferences 507 * @param {Object} controller 508 * @param {string} method 509 * @param {...Object} parameters 510 * @return {Object} 511 * @private 512 */ 513 HomePane.prototype.createAction = function(actionType, preferences, controller, method) { 514 var parameters = []; 515 for (var i = 4; i < arguments.length; i++) { 516 parameters[i - 4] = arguments[i]; 517 } 518 try { 519 var action = new ResourceAction(preferences, HomePane, HomeView.ActionType[actionType], false, controller, method, parameters); 520 this.getActionMap()[HomeView.ActionType[actionType]] = action; 521 return action; 522 } catch (ex) { 523 console.log(ex); 524 } 525 } 526 527 /** 528 * Returns a new <code>ControllerAction</code> object associated with other actions if the same <code>group</code>. 529 * @param {HomeView.ActionType} actionType 530 * @param {boolean} selected 531 * @param {string} group 532 * @param {UserPreferences} preferences 533 * @param {Object} controller 534 * @param {string} method 535 * @param {...Object} parameters 536 * @return {Object} 537 * @private 538 */ 539 HomePane.prototype.createToggleAction = function(actionType, selected, group, preferences, controller, method) { 540 var parameters = []; 541 for (var i = 6; i < arguments.length; i++) { 542 parameters[i - 6] = arguments[i]; 543 } 544 var action = this.createAction.apply(this, [actionType, preferences, controller, method].concat(parameters)); 545 if (group != null) { 546 group.push(action); 547 action.putValue(ResourceAction.TOGGLE_BUTTON_GROUP, group); 548 action.putValue(AbstractAction.SELECTED_KEY, selected); 549 action.addPropertyChangeListener(function(ev) { 550 if (ev.getPropertyName() == AbstractAction.SELECTED_KEY) { 551 if (ev.getNewValue()) { 552 var group = ev.getSource().getValue(ResourceAction.TOGGLE_BUTTON_GROUP); 553 for (var i = 0; i < group.length; i++) { 554 if (action !== group [i] 555 && group [i].getValue(AbstractAction.SELECTED_KEY)) { 556 group [i].putValue(AbstractAction.SELECTED_KEY, false); 557 } 558 } 559 } else { 560 ev.getSource().putValue(AbstractAction.SELECTED_KEY, false); 561 } 562 } 563 }) 564 } 565 return action; 566 } 567 568 /** 569 * Creates a <code>ReourceAction</code> object that calls 570 * <code>actionPerfomed</code> method on a given 571 * existing <code>clipboardAction</code> with a source equal to focused component. 572 * @param {HomeView.ActionType} actionType 573 * @param {UserPreferences} preferences 574 * @param {Object} clipboardAction 575 * @param {boolean} copyAction 576 * @private 577 */ 578 HomePane.prototype.createClipboardAction = function(actionType, preferences, clipboardAction, copyAction) { 579 var action = this.createAction(actionType, preferences); 580 var homePane = this; 581 action.actionPerformed = function(ev) { 582 if (copyAction) { 583 homePane.clipboard = Home.duplicate(homePane.home.getSelectedItems()); 584 homePane.clipboardEmpty = false; 585 homePane.controller.enablePasteAction(); 586 } 587 switch (actionType) { 588 case HomeView.ActionType.CUT: 589 homePane.controller.cut(homePane.home.getSelectedItems()); 590 break; 591 case HomeView.ActionType.COPY: 592 break; 593 case HomeView.ActionType.PASTE: 594 homePane.controller.paste(Home.duplicate(homePane.clipboard)); 595 break; 596 } 597 return action; 598 } 599 } 600 601 /** 602 * Creates a <code>ResourceAction</code> for the given menu action type. 603 * @private 604 */ 605 HomePane.prototype.getMenuAction = function(actionType) { 606 return new ResourceAction(this.preferences, HomePane, HomePane.MenuActionType[actionType], true); 607 } 608 609 /** 610 * Adds a property change listener to <code>home</code> to update 611 * View from top and View from observer toggle models according to used camera. 612 * @param {Home} home 613 * @private 614 */ 615 HomePane.prototype.addHomeListener = function(home) { 616 var homePane = this; 617 home.addPropertyChangeListener("CAMERA", function(ev) { 618 homePane.setToggleButtonModelSelected(HomeView.ActionType.VIEW_FROM_TOP, home.getCamera() == home.getTopCamera()); 619 homePane.setToggleButtonModelSelected(HomeView.ActionType.VIEW_FROM_OBSERVER, home.getCamera() == home.getObserverCamera()); 620 }); 621 } 622 623 /** 624 * Changes the selection of the toggle model matching the given action. 625 * @param {HomeView.ActionType} actionType 626 * @param {boolean} selected 627 * @private 628 */ 629 HomePane.prototype.setToggleButtonModelSelected = function(actionType, selected) { 630 this.getAction(actionType).putValue(AbstractAction.SELECTED_KEY, selected); 631 } 632 633 /** 634 * Adds listener to <code>home</code> to update 635 * Display all levels and Display selected level toggle models 636 * according their visibility. 637 * @param {Home} home 638 * @private 639 */ 640 HomePane.prototype.addLevelVisibilityListener = function(home) { 641 var homePane = this; 642 home.getEnvironment().addPropertyChangeListener("ALL_LEVELS_VISIBLE", function(ev) { 643 var allLevelsVisible = home.getEnvironment().isAllLevelsVisible(); 644 homePane.setToggleButtonModelSelected(HomeView.ActionType.DISPLAY_ALL_LEVELS, allLevelsVisible); 645 homePane.setToggleButtonModelSelected(HomeView.ActionType.DISPLAY_SELECTED_LEVEL, !allLevelsVisible); 646 }); 647 } 648 649 /** 650 * Adds a property change listener to <code>preferences</code> to update 651 * actions when some preferences change. 652 * @param {UserPreferences} preferences 653 * @private 654 */ 655 HomePane.prototype.addUserPreferencesListener = function(preferences) { 656 this.preferencesChangeListener = new HomePane.UserPreferencesChangeListener(this); 657 preferences.addPropertyChangeListener("CURRENCY", this.preferencesChangeListener); 658 preferences.addPropertyChangeListener("VALUE_ADDED_TAX_ENABLED", this.preferencesChangeListener); 659 } 660 661 /** 662 * Preferences property listener bound to this component with a weak reference to avoid 663 * strong link between preferences and this component. 664 * @param {HomePane} homePane 665 * @constructor 666 * @ignore 667 */ 668 HomePane.UserPreferencesChangeListener = function(homePane) { 669 // TODO Manage weak reference ? 670 this.homePane = homePane; 671 } 672 673 HomePane.UserPreferencesChangeListener.prototype.propertyChange = function(ev) { 674 var ActionType = HomeView.ActionType; 675 var homePane = this.homePane; 676 var preferences = ev.getSource(); 677 var property = ev.getPropertyName(); 678 if (homePane == null) { 679 preferences.removePropertyChangeListener(property, this); 680 } else { 681 switch (property) { 682 case "CURRENCY": 683 homePane.getAction(ActionType.DISPLAY_HOME_FURNITURE_PRICE).putValue(ResourceAction.VISIBLE, ev.getNewValue() != null); 684 homePane.getAction(ActionType.SORT_HOME_FURNITURE_BY_PRICE).putValue(ResourceAction.VISIBLE, ev.getNewValue() != null); 685 break; 686 case "VALUE_ADDED_TAX_ENABLED": 687 homePane.getAction(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX_PERCENTAGE).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 688 homePane.getAction(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 689 homePane.getAction(ActionType.DISPLAY_HOME_FURNITURE_PRICE_VALUE_ADDED_TAX_INCLUDED).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 690 homePane.getAction(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX_PERCENTAGE).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 691 homePane.getAction(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 692 homePane.getAction(ActionType.SORT_HOME_FURNITURE_BY_PRICE_VALUE_ADDED_TAX_INCLUDED).putValue(ResourceAction.VISIBLE, ev.getNewValue() == true); 693 break; 694 } 695 } 696 } 697 698 /** 699 * Sets whether some actions should be visible or not. 700 * @param {UserPreferences} preferences 701 * @private 702 */ 703 HomePane.prototype.initActions = function(preferences) { 704 this.getAction(HomeView.ActionType.DISPLAY_HOME_FURNITURE_CATALOG_ID).putValue(ResourceAction.VISIBLE, false); 705 this.getAction(HomeView.ActionType.SORT_HOME_FURNITURE_BY_CATALOG_ID).putValue(ResourceAction.VISIBLE, false); 706 this.getAction(HomeView.ActionType.DISPLAY_HOME_FURNITURE_PRICE).putValue(ResourceAction.VISIBLE, preferences.getCurrency() != null); 707 this.getAction(HomeView.ActionType.SORT_HOME_FURNITURE_BY_PRICE).putValue(ResourceAction.VISIBLE, preferences.getCurrency() != null); 708 this.getAction(HomeView.ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX_PERCENTAGE).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 709 this.getAction(HomeView.ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 710 this.getAction(HomeView.ActionType.DISPLAY_HOME_FURNITURE_PRICE_VALUE_ADDED_TAX_INCLUDED).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 711 this.getAction(HomeView.ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX_PERCENTAGE).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 712 this.getAction(HomeView.ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 713 this.getAction(HomeView.ActionType.SORT_HOME_FURNITURE_BY_PRICE_VALUE_ADDED_TAX_INCLUDED).putValue(ResourceAction.VISIBLE, preferences.isValueAddedTaxEnabled()); 714 } 715 716 /** 717 * Adds a property change listener to <code>planController</code> to update 718 * Select and Create walls toggle models according to current mode. 719 * @param {PlanController} planController 720 * @private 721 */ 722 HomePane.prototype.addPlanControllerListener = function(planController) { 723 var homePane = this; 724 planController.addPropertyChangeListener("MODE", function(ev) { 725 var mode = planController.getMode(); 726 homePane.setToggleButtonModelSelected(HomeView.ActionType.SELECT, mode == PlanController.Mode.SELECTION); 727 homePane.setToggleButtonModelSelected(HomeView.ActionType.PAN, mode == PlanController.Mode.PANNING); 728 homePane.setToggleButtonModelSelected(HomeView.ActionType.CREATE_WALLS, mode == PlanController.Mode.WALL_CREATION); 729 homePane.setToggleButtonModelSelected(HomeView.ActionType.CREATE_ROOMS, mode == PlanController.Mode.ROOM_CREATION); 730 homePane.setToggleButtonModelSelected(HomeView.ActionType.CREATE_POLYLINES, mode == PlanController.Mode.POLYLINE_CREATION); 731 homePane.setToggleButtonModelSelected(HomeView.ActionType.CREATE_DIMENSION_LINES, mode == PlanController.Mode.DIMENSION_LINE_CREATION); 732 homePane.setToggleButtonModelSelected(HomeView.ActionType.CREATE_LABELS, mode == PlanController.Mode.LABEL_CREATION); 733 }); 734 } 735 736 /** 737 * Adds a focus change listener to report to controller focus changes. 738 * @private 739 */ 740 HomePane.prototype.addFocusListener = function() { 741 var homePane = this; 742 this.focusListener = function(ev) { 743 // Manage focus only for plan and component 3D to simplify actions choice proposed to the user 744 var focusableViews = [// homePane.controller.getFurnitureCatalogController().getView(), 745 // homePane.controller.getFurnitureController().getView(), 746 homePane.controller.getPlanController().getView(), 747 homePane.controller.getHomeController3D().getView()]; 748 for (var i = 0; i < focusableViews.length; i++) { 749 for (var element = ev.target; element !== null; element = element.parentElement) { 750 if (element === focusableViews [i].getHTMLElement()) { 751 homePane.controller.focusedViewChanged(focusableViews [i]); 752 return; 753 } 754 } 755 } 756 }; 757 this.getHTMLElement().addEventListener("focusin", this.focusListener); 758 } 759 760 /** 761 * Adds the given action to <code>menu</code>. 762 * @param {string|HomeView.ActionType} actionType 763 * @param {Object} menuBuilder 764 * @private 765 */ 766 HomePane.prototype.addActionToMenu = function(actionType, menuBuilder) { 767 var action = this.getAction(actionType); 768 if (action != null && action.getValue(AbstractAction.NAME) != null) { 769 menuBuilder.addMenuItem(action); 770 } 771 } 772 773 /** 774 * Builds align or distribute menu. 775 */ 776 HomePane.prototype.createAlignOrDistributeMenu = function(builder) { 777 var ActionType = HomeView.ActionType; 778 var homePane = this; 779 builder.addSubMenu(homePane.getMenuAction(HomePane.MenuActionType.ALIGN_OR_DISTRIBUTE_MENU), 780 function(builder) { 781 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_TOP, builder); 782 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_BOTTOM, builder); 783 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_LEFT, builder); 784 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_RIGHT, builder); 785 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_FRONT_SIDE, builder); 786 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_BACK_SIDE, builder); 787 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_LEFT_SIDE, builder); 788 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_ON_RIGHT_SIDE, builder); 789 homePane.addActionToMenu(ActionType.ALIGN_FURNITURE_SIDE_BY_SIDE, builder); 790 homePane.addActionToMenu(ActionType.DISTRIBUTE_FURNITURE_HORIZONTALLY, builder); 791 homePane.addActionToMenu(ActionType.DISTRIBUTE_FURNITURE_VERTICALLY, builder); 792 }); 793 } 794 795 /** 796 * Builds furniture sort menu. 797 */ 798 HomePane.prototype.createFurnitureSortMenu = function(home, builder) { 799 var ActionType = HomeView.ActionType; 800 var homePane = this; 801 builder.addSubMenu(homePane.getMenuAction(HomePane.MenuActionType.SORT_HOME_FURNITURE_MENU), 802 function(builder) { 803 /** 804 * @param {HomeView.ActionType} type 805 * @param {string} sortableProperty 806 */ 807 var addItem = function(type, sortableProperty) { 808 var action = homePane.getAction(type); 809 if (action && action.getValue(AbstractAction.NAME) && action.getValue(ResourceAction.VISIBLE)) { 810 builder.addRadioButtonItem(action.getValue(AbstractAction.NAME), function () { 811 action.actionPerformed(); 812 }, sortableProperty == home.getFurnitureSortedProperty()); 813 } 814 }; 815 816 addItem(ActionType.SORT_HOME_FURNITURE_BY_CATALOG_ID, "CATALOG_ID"); 817 addItem(ActionType.SORT_HOME_FURNITURE_BY_NAME, "NAME"); 818 addItem(ActionType.SORT_HOME_FURNITURE_BY_DESCRIPTION, "DESCRIPTION"); 819 addItem(ActionType.SORT_HOME_FURNITURE_BY_CREATOR, "CREATOR"); 820 addItem(ActionType.SORT_HOME_FURNITURE_BY_LICENSE, "LICENSE"); 821 addItem(ActionType.SORT_HOME_FURNITURE_BY_WIDTH, "WIDTH"); 822 addItem(ActionType.SORT_HOME_FURNITURE_BY_DEPTH, "DEPTH"); 823 addItem(ActionType.SORT_HOME_FURNITURE_BY_HEIGHT, "HEIGHT"); 824 addItem(ActionType.SORT_HOME_FURNITURE_BY_X, "X"); 825 addItem(ActionType.SORT_HOME_FURNITURE_BY_Y, "Y"); 826 addItem(ActionType.SORT_HOME_FURNITURE_BY_ELEVATION, "ELEVATION"); 827 addItem(ActionType.SORT_HOME_FURNITURE_BY_ANGLE, "ANGLE"); 828 addItem(ActionType.SORT_HOME_FURNITURE_BY_LEVEL, "LEVEL"); 829 addItem(ActionType.SORT_HOME_FURNITURE_BY_MODEL_SIZE, "MODEL_SIZE"); 830 addItem(ActionType.SORT_HOME_FURNITURE_BY_COLOR, "COLOR"); 831 addItem(ActionType.SORT_HOME_FURNITURE_BY_TEXTURE, "TEXTURE"); 832 addItem(ActionType.SORT_HOME_FURNITURE_BY_MOVABILITY, "MOVABLE"); 833 addItem(ActionType.SORT_HOME_FURNITURE_BY_TYPE, "DOOR_OR_WINDOW"); 834 addItem(ActionType.SORT_HOME_FURNITURE_BY_VISIBILITY, "VISIBLE"); 835 addItem(ActionType.SORT_HOME_FURNITURE_BY_PRICE, "PRICE"); 836 addItem(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX_PERCENTAGE, "VALUE_ADDED_TAX_PERCENTAGE"); 837 addItem(ActionType.SORT_HOME_FURNITURE_BY_VALUE_ADDED_TAX, "VALUE_ADDED_TAX"); 838 addItem(ActionType.SORT_HOME_FURNITURE_BY_PRICE_VALUE_ADDED_TAX_INCLUDED, "PRICE_VALUE_ADDED_TAX_INCLUDED"); 839 builder.addSeparator(); 840 var descSortAction = homePane.getAction(ActionType.SORT_HOME_FURNITURE_BY_DESCENDING_ORDER); 841 if (descSortAction && descSortAction.getValue(AbstractAction.NAME) && descSortAction.getValue(ResourceAction.VISIBLE)) { 842 builder.addCheckBoxItem(descSortAction.getValue(AbstractAction.NAME), function () { 843 descSortAction.actionPerformed(); 844 }, 845 home.isFurnitureDescendingSorted()); 846 } 847 }); 848 } 849 850 /** 851 * Builds furniture display property menu. 852 */ 853 HomePane.prototype.createFurnitureDisplayPropertyMenu = function(home, builder) { 854 var ActionType = HomeView.ActionType; 855 var homePane = this; 856 builder.addSubMenu(homePane.getMenuAction(HomePane.MenuActionType.DISPLAY_HOME_FURNITURE_PROPERTY_MENU), 857 function(builder) { 858 /** 859 * @param {HomeView.ActionType} type 860 * @param {string} sortableProperty 861 */ 862 var addItem = function(type, sortableProperty) { 863 var action = homePane.getAction(type); 864 if (action && action.getValue(AbstractAction.NAME) && action.getValue(ResourceAction.VISIBLE)) { 865 builder.addCheckBoxItem(action.getValue(AbstractAction.NAME), function(){ 866 action.actionPerformed(); 867 }, home.getFurnitureVisibleProperties().indexOf(sortableProperty) > -1); 868 } 869 }; 870 871 addItem(ActionType.DISPLAY_HOME_FURNITURE_CATALOG_ID, "CATALOG_ID"); 872 addItem(ActionType.DISPLAY_HOME_FURNITURE_NAME, "NAME"); 873 addItem(ActionType.DISPLAY_HOME_FURNITURE_DESCRIPTION, "DESCRIPTION"); 874 addItem(ActionType.DISPLAY_HOME_FURNITURE_CREATOR, "CREATOR"); 875 addItem(ActionType.DISPLAY_HOME_FURNITURE_LICENSE, "LICENSE"); 876 addItem(ActionType.DISPLAY_HOME_FURNITURE_WIDTH, "WIDTH"); 877 addItem(ActionType.DISPLAY_HOME_FURNITURE_DEPTH, "DEPTH"); 878 addItem(ActionType.DISPLAY_HOME_FURNITURE_HEIGHT, "HEIGHT"); 879 addItem(ActionType.DISPLAY_HOME_FURNITURE_X, "X"); 880 addItem(ActionType.DISPLAY_HOME_FURNITURE_Y, "Y"); 881 addItem(ActionType.DISPLAY_HOME_FURNITURE_ELEVATION, "ELEVATION"); 882 addItem(ActionType.DISPLAY_HOME_FURNITURE_ANGLE, "ANGLE"); 883 addItem(ActionType.DISPLAY_HOME_FURNITURE_LEVEL, "LEVEL"); 884 addItem(ActionType.DISPLAY_HOME_FURNITURE_MODEL_SIZE, "MODEL_SIZE"); 885 addItem(ActionType.DISPLAY_HOME_FURNITURE_COLOR, "COLOR"); 886 addItem(ActionType.DISPLAY_HOME_FURNITURE_TEXTURE, "TEXTURE"); 887 addItem(ActionType.DISPLAY_HOME_FURNITURE_MOVABLE, "MOVABLE"); 888 addItem(ActionType.DISPLAY_HOME_FURNITURE_DOOR_OR_WINDOW, "DOOR_OR_WINDOW"); 889 addItem(ActionType.DISPLAY_HOME_FURNITURE_VISIBLE, "VISIBLE"); 890 addItem(ActionType.DISPLAY_HOME_FURNITURE_PRICE, "PRICE"); 891 addItem(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX_PERCENTAGE, "VALUE_ADDED_TAX_PERCENTAGE"); 892 addItem(ActionType.DISPLAY_HOME_FURNITURE_VALUE_ADDED_TAX, "VALUE_ADDED_TAX"); 893 addItem(ActionType.DISPLAY_HOME_FURNITURE_PRICE_VALUE_ADDED_TAX_INCLUDED, "PRICE_VALUE_ADDED_TAX_INCLUDED"); 894 }); 895 } 896 897 /** 898 * Returns Lock / Unlock base plan button. 899 * @param {Home} home 900 * @param {string} additionalClass additional CSS class 901 * @return {HTMLButton} 902 * @private 903 */ 904 HomePane.prototype.createLockUnlockBasePlanButton = function(home, additionalClass) { 905 var unlockBasePlanAction = this.getAction(HomeView.ActionType.UNLOCK_BASE_PLAN); 906 var lockBasePlanAction = this.getAction(HomeView.ActionType.LOCK_BASE_PLAN); 907 if (unlockBasePlanAction != null 908 && unlockBasePlanAction.getValue(AbstractAction.NAME) != null 909 && lockBasePlanAction.getValue(AbstractAction.NAME) != null) { 910 var lockUnlockBasePlanButton = this.createToolBarButton( 911 home.isBasePlanLocked() ? unlockBasePlanAction : lockBasePlanAction, additionalClass); 912 home.addPropertyChangeListener("BASE_PLAN_LOCKED", function() { 913 lockUnlockBasePlanButton.setAction(home.isBasePlanLocked() 914 ? unlockBasePlanAction 915 : lockBasePlanAction); 916 }); 917 return lockUnlockBasePlanButton; 918 } 919 else { 920 return null; 921 } 922 } 923 924 /** 925 * Returns Enable / Disable magnetism button. 926 * @param {UserPreferences} preferences 927 * @param {string} additionalClass additional CSS class 928 * @return {HTMLButton} 929 * @private 930 */ 931 HomePane.prototype.createEnableDisableMagnetismButton = function(preferences, additionalClass) { 932 var disableMagnetismAction = this.getAction(HomeView.ActionType.DISABLE_MAGNETISM); 933 var enableMagnetismAction = this.getAction(HomeView.ActionType.ENABLE_MAGNETISM); 934 if (disableMagnetismAction !== null 935 && disableMagnetismAction.getValue(AbstractAction.NAME) !== null 936 && enableMagnetismAction.getValue(AbstractAction.NAME) !== null) { 937 var enableDisableMagnetismButton = this.createToolBarButton( 938 preferences.isMagnetismEnabled() ? disableMagnetismAction : enableMagnetismAction, additionalClass); 939 preferences.addPropertyChangeListener("MAGNETISM_ENABLED", 940 new HomePane.MagnetismChangeListener(this, enableDisableMagnetismButton)); 941 return enableDisableMagnetismButton; 942 } else { 943 return null; 944 } 945 } 946 947 /** 948 * Preferences property listener bound to this component with a weak reference to avoid 949 * strong link between preferences and this component. 950 * @constructor 951 * @private 952 */ 953 HomePane.MagnetismChangeListener = function MagnetismChangeListener(homePane, enableDisableMagnetismButton) { 954 this.enableDisableMagnetismButton = enableDisableMagnetismButton; 955 this.homePane = homePane; 956 } 957 958 /** 959 * @ignore 960 */ 961 HomePane.MagnetismChangeListener.prototype.propertyChange = function(ev) { 962 var homePane = this.homePane; 963 var preferences = ev.getSource(); 964 var property = ev.getPropertyName(); 965 if (homePane == null) { 966 preferences.removePropertyChangeListener(property, this); 967 } else { 968 this.enableDisableMagnetismButton.setAction( 969 preferences.isMagnetismEnabled() 970 ? homePane.getAction(HomeView.ActionType.DISABLE_MAGNETISM) 971 : homePane.getAction(HomeView.ActionType.ENABLE_MAGNETISM)); 972 } 973 } 974 975 /** 976 * Creates an action that is selected when all the text of the 977 * selected items in <code>home</code> use bold style. 978 * @param {HomeView.ActionType} actionType 979 * @param {Home} home 980 * @param {UserPreferences} preferences 981 * @param {Object} controller 982 * @param {string} method 983 * @return {ResourceAction} 984 * @private 985 */ 986 HomePane.prototype.createBoldStyleAction = function(actionType, home, preferences, controller, method) { 987 var action = this.createAction(actionType, preferences, controller, method); 988 home.addSelectionListener({ 989 selectionChanged: function(ev) { 990 // Find if selected items are all bold or not 991 var selectionBoldStyle = null; 992 var selectedItems = home.getSelectedItems(); 993 for (var i = 0; i < selectedItems.length; i++) { 994 item = selectedItems [i]; 995 var bold; 996 if (item instanceof Label) { 997 bold = this.isItemTextBold("Label", item.getStyle()); 998 } else if (item instanceof HomePieceOfFurniture 999 && item.isVisible()) { 1000 bold = this.isItemTextBold("HomePieceOfFurniture", item.getNameStyle()); 1001 } else if (item instanceof Room) { 1002 bold = this.isItemTextBold("Room", item.getNameStyle()); 1003 if (bold != this.isItemTextBold("Room", item.getAreaStyle())) { 1004 bold = null; 1005 } 1006 } else if (item instanceof DimensionLine) { 1007 bold = this.isItemTextBold("DimensionLine", item.getLengthStyle()); 1008 } else { 1009 continue; 1010 } 1011 if (selectionBoldStyle == null) { 1012 selectionBoldStyle = bold; 1013 } else if (bold == null || selectionBoldStyle != bold) { 1014 selectionBoldStyle = null; 1015 break; 1016 } 1017 } 1018 action.putValue(AbstractAction.SELECTED_KEY, selectionBoldStyle != null && selectionBoldStyle); 1019 }, 1020 isItemTextBold: function(itemClass, textStyle) { 1021 if (textStyle == null) { 1022 textStyle = preferences.getDefaultTextStyle(itemClass); 1023 } 1024 return textStyle.isBold(); 1025 } 1026 }); 1027 return action; 1028 } 1029 1030 /** 1031 * Creates an action which is selected when all the text of the 1032 * selected items in <code>home</code> use italic style. 1033 * @param {HomeView.ActionType} actionType 1034 * @param {Home} home 1035 * @param {UserPreferences} preferences 1036 * @param {Object} controller 1037 * @param {string} method 1038 * @return {ResourceAction} 1039 * @private 1040 */ 1041 HomePane.prototype.createItalicStyleToggleModel = function(actionType, home, preferences, controller, method) { 1042 var action = this.createAction(actionType, preferences, controller, method); 1043 home.addSelectionListener({ 1044 selectionChanged: function(ev) { 1045 // Find if selected items are all italic or not 1046 var selectionItalicStyle = null; 1047 var selectedItems = home.getSelectedItems(); 1048 for (var i = 0; i < selectedItems.length; i++) { 1049 item = selectedItems [i]; 1050 var italic; 1051 if (item instanceof Label) { 1052 italic = this.isItemTextItalic("Label", item.getStyle()); 1053 } else if (item instanceof HomePieceOfFurniture 1054 && item.isVisible()) { 1055 italic = this.isItemTextItalic("HomePieceOfFurniture", item.getNameStyle()); 1056 } else if (item instanceof Room) { 1057 italic = this.isItemTextItalic("Room", item.getNameStyle()); 1058 if (italic != this.isItemTextItalic("Room", item.getAreaStyle())) { 1059 italic = null; 1060 } 1061 } else if (item instanceof DimensionLine) { 1062 italic = this.isItemTextItalic("DimensionLine", item.getLengthStyle()); 1063 } else { 1064 continue; 1065 } 1066 if (selectionItalicStyle == null) { 1067 selectionItalicStyle = italic; 1068 } else if (italic == null || selectionItalicStyle != italic) { 1069 selectionItalicStyle = null; 1070 break; 1071 } 1072 } 1073 action.putValue(AbstractAction.SELECTED_KEY, selectionItalicStyle != null && selectionItalicStyle); 1074 }, 1075 isItemTextItalic: function(itemClass, textStyle) { 1076 if (textStyle == null) { 1077 textStyle = preferences.getDefaultTextStyle(itemClass); 1078 } 1079 return textStyle.isItalic(); 1080 } 1081 }); 1082 return action; 1083 } 1084 1085 /** 1086 * Returns the tool bar displayed in this pane. 1087 * @param {Home} home 1088 * @param {UserPreferences} preferences 1089 * @param {HomeController} controller 1090 * @return {Object} 1091 * @private 1092 */ 1093 HomePane.prototype.createToolBar = function(home, preferences, controller) { 1094 var applicationMenuToolBar = document.getElementById("application-menu-toolbar"); 1095 1096 if (applicationMenuToolBar != null) { 1097 this.startToolBarButtonGroup(applicationMenuToolBar); 1098 this.addActionToToolBar("SHOW_APPLICATION_MENU", applicationMenuToolBar); 1099 this.showApplicationMenuButton = applicationMenuToolBar.children[applicationMenuToolBar.children.length - 1].lastChild; 1100 } 1101 1102 var toolBar = document.getElementById("home-pane-toolbar"); 1103 this.toolBarDefaultChildren = Array.prototype.slice.call(toolBar.children); 1104 this.startToolBarButtonGroup(toolBar); 1105 var fileButton = false; 1106 if (toolBar.classList.contains("new-home")) { 1107 this.addActionToToolBar(HomeView.ActionType.NEW_HOME, toolBar); 1108 fileButton = true; 1109 } 1110 if (toolBar.classList.contains("open")) { 1111 this.addActionToToolBar(HomeView.ActionType.OPEN, toolBar); 1112 fileButton = true; 1113 } 1114 if (toolBar.classList.contains("save")) { 1115 this.addActionToToolBar(HomeView.ActionType.SAVE, toolBar); 1116 fileButton = true; 1117 } 1118 if (toolBar.classList.contains("save-as")) { 1119 this.addActionToToolBar(HomeView.ActionType.SAVE_AS, toolBar); 1120 fileButton = true; 1121 } 1122 if (fileButton) { 1123 this.addSeparator(toolBar); 1124 } 1125 1126 this.addToggleActionToToolBar(HomeView.ActionType.VIEW_FROM_TOP, toolBar); 1127 this.addToggleActionToToolBar(HomeView.ActionType.VIEW_FROM_OBSERVER, toolBar); 1128 this.addSeparator(toolBar); 1129 1130 this.addActionToToolBar(HomeView.ActionType.UNDO, toolBar); 1131 this.addActionToToolBar(HomeView.ActionType.REDO, toolBar); 1132 this.addSeparator(toolBar); 1133 1134 this.addActionToToolBar(HomeView.ActionType.DELETE_SELECTION, toolBar); 1135 this.addActionToToolBar(HomeView.ActionType.CUT, toolBar, "toolbar-optional"); 1136 this.addActionToToolBar(HomeView.ActionType.COPY, toolBar); 1137 this.addActionToToolBar(HomeView.ActionType.PASTE, toolBar); 1138 this.addSeparator(toolBar); 1139 1140 this.addActionToToolBar(HomeView.ActionType.ADD_HOME_FURNITURE, toolBar, "toolbar-optional"); 1141 this.addSeparator(toolBar); 1142 1143 this.addToggleActionToToolBar(HomeView.ActionType.SELECT, toolBar); 1144 this.addToggleActionToToolBar(HomeView.ActionType.PAN, toolBar, "toolbar-optional"); 1145 this.addToggleActionToToolBar(HomeView.ActionType.CREATE_WALLS, toolBar); 1146 this.addToggleActionToToolBar(HomeView.ActionType.CREATE_ROOMS, toolBar); 1147 this.addToggleActionToToolBar(HomeView.ActionType.CREATE_POLYLINES, toolBar); 1148 this.addToggleActionToToolBar(HomeView.ActionType.CREATE_DIMENSION_LINES, toolBar); 1149 this.addToggleActionToToolBar(HomeView.ActionType.CREATE_LABELS, toolBar); 1150 this.addSeparator(toolBar); 1151 1152 var enableDisableMagnetismButton = this.createEnableDisableMagnetismButton(preferences); 1153 if (enableDisableMagnetismButton !== null) { 1154 this.addButtonToToolBar(toolBar, enableDisableMagnetismButton); 1155 } 1156 var lockUnlockBasePlanButton = this.createLockUnlockBasePlanButton(home) 1157 if (lockUnlockBasePlanButton !== null) { 1158 this.addButtonToToolBar(toolBar, lockUnlockBasePlanButton); 1159 } 1160 this.addActionToToolBar(HomeView.ActionType.FLIP_HORIZONTALLY, toolBar); 1161 this.addActionToToolBar(HomeView.ActionType.FLIP_VERTICALLY, toolBar); 1162 this.addSeparator(toolBar); 1163 1164 this.addActionToToolBar(HomeView.ActionType.INCREASE_TEXT_SIZE, toolBar); 1165 this.addActionToToolBar(HomeView.ActionType.DECREASE_TEXT_SIZE, toolBar); 1166 this.addToggleActionToToolBar(HomeView.ActionType.TOGGLE_BOLD_STYLE, toolBar); 1167 this.addToggleActionToToolBar(HomeView.ActionType.TOGGLE_ITALIC_STYLE, toolBar); 1168 this.addSeparator(toolBar); 1169 1170 this.addActionToToolBar(HomeView.ActionType.ZOOM_IN, toolBar, "toolbar-optional"); 1171 this.addActionToToolBar(HomeView.ActionType.ZOOM_OUT, toolBar, "toolbar-optional"); 1172 this.addSeparator(toolBar); 1173 if (this.showApplicationMenuButton == null 1174 || !window.matchMedia("(hover: none), (pointer: coarse)").matches) { 1175 this.addActionToToolBar(HomeView.ActionType.ABOUT, toolBar); 1176 this.addSeparator(toolBar); 1177 } 1178 1179 this.addActionToToolBar(HomeView.ActionType.PREFERENCES, toolBar); 1180 1181 return toolBar; 1182 } 1183 1184 /** 1185 * Creates contextual menus for components within this home pane. 1186 * @param {Home} home 1187 * @param {UserPreferences} preferences 1188 * @private 1189 */ 1190 HomePane.prototype.createPopupMenus = function(home, preferences) { 1191 var ActionType = HomeView.ActionType; 1192 var homePane = this; 1193 var controller = this.controller; 1194 1195 if (this.showApplicationMenuButton == null 1196 || !window.matchMedia("(hover: none), (pointer: coarse)").matches) { 1197 // Catalog view popup menu 1198 var furnitureCatalogView = this.controller.getFurnitureCatalogController().getView(); 1199 if (furnitureCatalogView != null) { 1200 this.furnitureCatalogPopupMenu = new JSPopupMenu(preferences, furnitureCatalogView.getHTMLElement(), 1201 function(builder) { 1202 homePane.addActionToMenu(ActionType.ADD_HOME_FURNITURE, builder); 1203 homePane.addActionToMenu(ActionType.ADD_FURNITURE_TO_GROUP, builder); 1204 }); 1205 } 1206 1207 var furnitureView = this.controller.getFurnitureController().getView(); 1208 // Furniture view popup menu 1209 if (furnitureView != null) { 1210 this.furniturePopupMenu = new JSPopupMenu(preferences, furnitureView.getHTMLElement(), 1211 function(builder) { 1212 homePane.addActionToMenu(ActionType.CUT, builder); 1213 homePane.addActionToMenu(ActionType.COPY, builder); 1214 homePane.addActionToMenu(ActionType.PASTE, builder); 1215 homePane.addActionToMenu(ActionType.PASTE_TO_GROUP, builder); 1216 homePane.addActionToMenu(ActionType.PASTE_STYLE, builder); 1217 builder.addSeparator(); 1218 homePane.addActionToMenu(ActionType.MODIFY_FURNITURE, builder); 1219 homePane.addActionToMenu(ActionType.GROUP_FURNITURE, builder); 1220 homePane.addActionToMenu(ActionType.UNGROUP_FURNITURE, builder); 1221 homePane.createAlignOrDistributeMenu(builder); 1222 homePane.addActionToMenu(ActionType.RESET_FURNITURE_ELEVATION, builder); 1223 builder.addSeparator(); 1224 homePane.createFurnitureSortMenu(home, builder); 1225 homePane.createFurnitureDisplayPropertyMenu(home, builder); 1226 }); 1227 } 1228 1229 // Plan view popup menu 1230 var planView = this.controller.getPlanController().getView(); 1231 if (planView != null) { 1232 this.planPopupMenu = new JSPopupMenu(preferences, planView.getHTMLElement(), 1233 function(builder) { 1234 homePane.addActionToMenu(ActionType.UNDO, builder); 1235 homePane.addActionToMenu(ActionType.REDO, builder); 1236 builder.addSeparator(); 1237 homePane.addActionToMenu(ActionType.DELETE_SELECTION, builder); 1238 homePane.addActionToMenu(ActionType.CUT, builder); 1239 homePane.addActionToMenu(ActionType.COPY, builder); 1240 homePane.addActionToMenu(ActionType.PASTE, builder); 1241 homePane.addActionToMenu(ActionType.PASTE_STYLE, builder); 1242 builder.addSeparator(); 1243 homePane.addActionToMenu(ActionType.SELECT_ALL, builder); 1244 homePane.addActionToMenu(ActionType.SELECT_ALL_AT_ALL_LEVELS, builder); 1245 builder.addSeparator(); 1246 homePane.addActionToMenu(ActionType.MODIFY_FURNITURE, builder); 1247 homePane.addActionToMenu(ActionType.GROUP_FURNITURE, builder); 1248 homePane.addActionToMenu(ActionType.UNGROUP_FURNITURE, builder); 1249 homePane.addActionToMenu(ActionType.RESET_FURNITURE_ELEVATION, builder); 1250 builder.addSeparator(); 1251 homePane.addActionToMenu(ActionType.MODIFY_COMPASS, builder); 1252 homePane.addActionToMenu(ActionType.MODIFY_WALL, builder); 1253 homePane.addActionToMenu(ActionType.JOIN_WALLS, builder); 1254 homePane.addActionToMenu(ActionType.REVERSE_WALL_DIRECTION, builder); 1255 homePane.addActionToMenu(ActionType.SPLIT_WALL, builder); 1256 homePane.addActionToMenu(ActionType.MODIFY_ROOM, builder); 1257 homePane.addActionToMenu(ActionType.MODIFY_POLYLINE, builder); 1258 homePane.addActionToMenu(ActionType.MODIFY_DIMENSION_LINE, builder); 1259 homePane.addActionToMenu(ActionType.MODIFY_LABEL, builder); 1260 builder.addSeparator(); 1261 builder.addSubMenu(homePane.getMenuAction(HomePane.MenuActionType.MODIFY_TEXT_STYLE), function(builder) { 1262 homePane.addActionToMenu(ActionType.INCREASE_TEXT_SIZE, builder); 1263 homePane.addActionToMenu(ActionType.DECREASE_TEXT_SIZE, builder); 1264 homePane.addActionToMenu(ActionType.TOGGLE_BOLD_STYLE, builder); 1265 homePane.addActionToMenu(ActionType.TOGGLE_ITALIC_STYLE, builder); 1266 }); 1267 builder.addSeparator(); 1268 homePane.addActionToMenu(ActionType.IMPORT_BACKGROUND_IMAGE, builder); 1269 homePane.addActionToMenu(ActionType.MODIFY_BACKGROUND_IMAGE, builder); 1270 homePane.addActionToMenu(ActionType.HIDE_BACKGROUND_IMAGE, builder); 1271 homePane.addActionToMenu(ActionType.SHOW_BACKGROUND_IMAGE, builder); 1272 homePane.addActionToMenu(ActionType.DELETE_BACKGROUND_IMAGE, builder); 1273 builder.addSeparator(); 1274 homePane.addActionToMenu(ActionType.ADD_LEVEL, builder); 1275 homePane.addActionToMenu(ActionType.ADD_LEVEL_AT_SAME_ELEVATION, builder); 1276 homePane.addActionToMenu(ActionType.MODIFY_LEVEL, builder); 1277 homePane.addActionToMenu(ActionType.DELETE_LEVEL, builder); 1278 }); 1279 } 1280 1281 // 3D view popup menu 1282 var view3D = this.controller.getHomeController3D().getView(); 1283 if (view3D != null) { 1284 this.view3DPopupMenu = new JSPopupMenu(preferences, view3D.getHTMLElement(), 1285 function(builder) { 1286 homePane.addActionToMenu(ActionType.VIEW_FROM_TOP, builder); 1287 homePane.addActionToMenu(ActionType.VIEW_FROM_OBSERVER, builder); 1288 homePane.addActionToMenu(ActionType.MODIFY_OBSERVER, builder); 1289 homePane.addActionToMenu(ActionType.STORE_POINT_OF_VIEW, builder); 1290 var storedCameras = home.getStoredCameras(); 1291 if (storedCameras.length > 0) { 1292 var goToPointOfViewAction = homePane.getMenuAction(HomePane.MenuActionType.GO_TO_POINT_OF_VIEW); 1293 if (goToPointOfViewAction.getValue(AbstractAction.NAME) != null) { 1294 builder.addSubMenu(goToPointOfViewAction, function(builder) { 1295 var cameraMenuItemBuilder = function(camera) { 1296 builder.addMenuItem(camera.getName(), 1297 function() { 1298 controller.getHomeController3D().goToCamera(camera); 1299 }); 1300 }; 1301 var storedCameras = home.getStoredCameras(); 1302 for (var i = 0; i < storedCameras.length; i++) { 1303 cameraMenuItemBuilder(storedCameras[i]); 1304 } 1305 }); 1306 } 1307 homePane.addActionToMenu(ActionType.DELETE_POINTS_OF_VIEW, builder); 1308 } 1309 1310 builder.addSeparator(); 1311 homePane.addActionToMenu(ActionType.DISPLAY_ALL_LEVELS, builder); 1312 homePane.addActionToMenu(ActionType.DISPLAY_SELECTED_LEVEL, builder); 1313 homePane.addActionToMenu(ActionType.MODIFY_3D_ATTRIBUTES, builder); 1314 }); 1315 } 1316 } else { 1317 // Menu button popup menu 1318 new JSPopupMenu(preferences, this.showApplicationMenuButton, 1319 function(builder) { 1320 var toolBar = document.getElementById("home-pane-toolbar"); 1321 this.toolBarDefaultChildren = Array.prototype.slice.call(toolBar.children); 1322 var fileButton = false; 1323 if (toolBar.classList.contains("new-home")) { 1324 homePane.addActionToMenu(HomeView.ActionType.NEW_HOME, builder); 1325 fileButton = true; 1326 } 1327 if (toolBar.classList.contains("open")) { 1328 homePane.addActionToMenu(HomeView.ActionType.OPEN, builder); 1329 fileButton = true; 1330 } 1331 if (toolBar.classList.contains("save")) { 1332 homePane.addActionToMenu(HomeView.ActionType.SAVE, builder); 1333 fileButton = true; 1334 } 1335 if (toolBar.classList.contains("save-as")) { 1336 homePane.addActionToMenu(HomeView.ActionType.SAVE_AS, builder); 1337 fileButton = true; 1338 } 1339 if (fileButton) { 1340 builder.addSeparator(); 1341 } 1342 homePane.addActionToMenu(ActionType.DELETE_SELECTION, builder); 1343 homePane.addActionToMenu(ActionType.CUT, builder); 1344 homePane.addActionToMenu(ActionType.COPY, builder); 1345 homePane.addActionToMenu(ActionType.PASTE, builder); 1346 homePane.addActionToMenu(ActionType.PASTE_TO_GROUP, builder); 1347 homePane.addActionToMenu(ActionType.PASTE_STYLE, builder); 1348 builder.addSeparator(); 1349 homePane.addActionToMenu(ActionType.SELECT_ALL, builder); 1350 homePane.addActionToMenu(ActionType.SELECT_ALL_AT_ALL_LEVELS, builder); 1351 builder.addSeparator(); 1352 homePane.addActionToMenu(ActionType.ADD_HOME_FURNITURE, builder); 1353 homePane.addActionToMenu(ActionType.ADD_FURNITURE_TO_GROUP, builder); 1354 builder.addSeparator(); 1355 homePane.addActionToMenu(ActionType.MODIFY_FURNITURE, builder); 1356 homePane.addActionToMenu(ActionType.GROUP_FURNITURE, builder); 1357 homePane.addActionToMenu(ActionType.UNGROUP_FURNITURE, builder); 1358 homePane.createAlignOrDistributeMenu(builder); 1359 homePane.addActionToMenu(ActionType.RESET_FURNITURE_ELEVATION, builder); 1360 var furnitureView = controller.getFurnitureController().getView(); 1361 if (furnitureView != null 1362 && window.getComputedStyle(furnitureView.getHTMLElement())["display"] != "none") { 1363 homePane.createFurnitureSortMenu(home, builder); 1364 homePane.createFurnitureDisplayPropertyMenu(home, builder); 1365 } 1366 builder.addSeparator(); 1367 homePane.addActionToMenu(ActionType.SELECT, builder); 1368 homePane.addActionToMenu(ActionType.CREATE_WALLS, builder); 1369 homePane.addActionToMenu(ActionType.CREATE_ROOMS, builder); 1370 homePane.addActionToMenu(ActionType.CREATE_POLYLINES, builder); 1371 homePane.addActionToMenu(ActionType.CREATE_DIMENSION_LINES, builder); 1372 homePane.addActionToMenu(ActionType.CREATE_LABELS, builder); 1373 builder.addSeparator(); 1374 homePane.addActionToMenu(ActionType.MODIFY_COMPASS, builder); 1375 homePane.addActionToMenu(ActionType.MODIFY_WALL, builder); 1376 homePane.addActionToMenu(ActionType.JOIN_WALLS, builder); 1377 homePane.addActionToMenu(ActionType.REVERSE_WALL_DIRECTION, builder); 1378 homePane.addActionToMenu(ActionType.SPLIT_WALL, builder); 1379 homePane.addActionToMenu(ActionType.MODIFY_ROOM, builder); 1380 homePane.addActionToMenu(ActionType.MODIFY_POLYLINE, builder); 1381 homePane.addActionToMenu(ActionType.MODIFY_DIMENSION_LINE, builder); 1382 homePane.addActionToMenu(ActionType.MODIFY_LABEL, builder); 1383 builder.addSeparator(); 1384 homePane.addActionToMenu(ActionType.IMPORT_BACKGROUND_IMAGE, builder); 1385 homePane.addActionToMenu(ActionType.MODIFY_BACKGROUND_IMAGE, builder); 1386 homePane.addActionToMenu(ActionType.HIDE_BACKGROUND_IMAGE, builder); 1387 homePane.addActionToMenu(ActionType.SHOW_BACKGROUND_IMAGE, builder); 1388 homePane.addActionToMenu(ActionType.DELETE_BACKGROUND_IMAGE, builder); 1389 builder.addSeparator(); 1390 homePane.addActionToMenu(ActionType.ADD_LEVEL, builder); 1391 homePane.addActionToMenu(ActionType.ADD_LEVEL_AT_SAME_ELEVATION, builder); 1392 homePane.addActionToMenu(ActionType.MODIFY_LEVEL, builder); 1393 homePane.addActionToMenu(ActionType.DELETE_LEVEL, builder); 1394 builder.addSeparator(); 1395 homePane.addActionToMenu(ActionType.MODIFY_OBSERVER, builder); 1396 homePane.addActionToMenu(ActionType.STORE_POINT_OF_VIEW, builder); 1397 var storedCameras = home.getStoredCameras(); 1398 if (storedCameras.length > 0) { 1399 var goToPointOfViewAction = homePane.getMenuAction(HomePane.MenuActionType.GO_TO_POINT_OF_VIEW); 1400 if (goToPointOfViewAction.getValue(AbstractAction.NAME) != null) { 1401 builder.addSubMenu(goToPointOfViewAction, 1402 function(builder) { 1403 var cameraMenuItemBuilder = function(camera) { 1404 builder.addMenuItem(camera.getName(), 1405 function() { 1406 controller.getHomeController3D().goToCamera(camera); 1407 }); 1408 }; 1409 var storedCameras = home.getStoredCameras(); 1410 for (var i = 0; i < storedCameras.length; i++) { 1411 cameraMenuItemBuilder(storedCameras[i]); 1412 } 1413 }); 1414 } 1415 homePane.addActionToMenu(ActionType.DELETE_POINTS_OF_VIEW, builder); 1416 } 1417 1418 builder.addSeparator(); 1419 homePane.addActionToMenu(ActionType.DISPLAY_ALL_LEVELS, builder); 1420 homePane.addActionToMenu(ActionType.DISPLAY_SELECTED_LEVEL, builder); 1421 homePane.addActionToMenu(ActionType.MODIFY_3D_ATTRIBUTES, builder); 1422 builder.addSeparator(); 1423 homePane.addActionToMenu(ActionType.ABOUT, builder); 1424 }); 1425 } 1426 } 1427 1428 /** 1429 * Initializes pane splitters. 1430 * @private 1431 */ 1432 HomePane.prototype.initSplitters = function() { 1433 var controller = this.controller; 1434 1435 var furnitureCatalogView = controller.getFurnitureCatalogController().getView(); 1436 var furnitureView = controller.getFurnitureController().getView(); 1437 var planView = controller.getPlanController().getView(); 1438 var view3D = controller.getHomeController3D().getView(); 1439 1440 var furniturePlanSplitterElement = document.getElementById("furniture-plan-splitter"); 1441 var plan3DViewSplitterElement = document.getElementById("plan-3D-view-splitter"); 1442 var catalogFurnitureSplitterElement = document.getElementById("catalog-furniture-splitter"); 1443 1444 this.furniturePlanSplitter = { 1445 element: furniturePlanSplitterElement, 1446 homePropertyName: HomePane.MAIN_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY, 1447 firstGroupElement: document.getElementById("catalog-furniture-pane"), 1448 secondGroupElement: document.getElementById("plan-3D-view-pane"), 1449 isDisplayed: function() { 1450 return furniturePlanSplitterElement && furniturePlanSplitterElement.clientWidth > 0; 1451 }, 1452 resizeListener: function(splitterPosition) { 1453 // Refresh 2D/3D plan views on resize 1454 planView.revalidate(); 1455 view3D.revalidate(); 1456 } 1457 }; 1458 1459 this.plan3DViewSplitter = { 1460 element: plan3DViewSplitterElement, 1461 homePropertyName: HomePane.PLAN_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY, 1462 firstGroupElement: planView.getHTMLElement(), 1463 secondGroupElement: view3D.getHTMLElement(), 1464 isDisplayed: function() { 1465 return plan3DViewSplitterElement && plan3DViewSplitterElement.clientWidth > 0 && planView != null && view3D != null; 1466 }, 1467 resizeListener: function(splitterPosition) { 1468 // Refresh 2D/3D plan views on resize 1469 planView.revalidate(); 1470 view3D.revalidate(); 1471 } 1472 }; 1473 1474 this.catalogFurnitureSplitter = { 1475 element: catalogFurnitureSplitterElement, 1476 homePropertyName: HomePane.CATALOG_PANE_DIVIDER_LOCATION_VISUAL_PROPERTY, 1477 firstGroupElement: furnitureCatalogView.getHTMLElement(), 1478 secondGroupElement: furnitureView.getHTMLElement(), 1479 isDisplayed: function() { 1480 return catalogFurnitureSplitterElement && catalogFurnitureSplitterElement.clientWidth > 0 && furnitureCatalogView != null && furnitureView != null; 1481 } 1482 }; 1483 1484 this.updateSplitters(); 1485 1486 // Dispatch a resize window event to configure HTML elements in split panes and their children 1487 var resizeEvent = window.document.createEvent('UIEvents'); 1488 resizeEvent.initEvent('resize', true, true); 1489 window.dispatchEvent(resizeEvent); 1490 } 1491 1492 /** 1493 * @private 1494 */ 1495 HomePane.prototype.updateSplitters = function() { 1496 var planView = this.controller.getPlanController().getView(); 1497 var view3D = this.controller.getHomeController3D().getView(); 1498 var furnitureCatalogView = this.controller.getFurnitureCatalogController().getView(); 1499 // Plan 3D view splitter inverts its group depending on orientation 1500 if (furnitureCatalogView !== null 1501 && furnitureCatalogView.getHTMLElement().getBoundingClientRect().top > view3D.getHTMLElement().getBoundingClientRect().top + 10) { 1502 this.plan3DViewSplitter.firstGroupElement = view3D.getHTMLElement(); 1503 this.plan3DViewSplitter.secondGroupElement = planView.getHTMLElement(); 1504 } else { 1505 this.plan3DViewSplitter.firstGroupElement = planView.getHTMLElement(); 1506 this.plan3DViewSplitter.secondGroupElement = view3D.getHTMLElement(); 1507 } 1508 this.updateSplitter(this.plan3DViewSplitter); 1509 this.updateSplitter(this.furniturePlanSplitter); 1510 this.updateSplitter(this.catalogFurnitureSplitter); 1511 } 1512 1513 /** 1514 * Updates the given pane splitter. 1515 * @param {{ 1516 * element: HTMLElement, 1517 * homePropertyName: string, 1518 * firstGroupElement: HTMLElement, 1519 * secondGroupElement: HTMLElement, 1520 * isDisplayed: function(): boolean, 1521 * resizeListener?: function(splitterPosition: number) 1522 * }} splitter 1523 * @private 1524 */ 1525 HomePane.prototype.updateSplitter = function(splitter) { 1526 // Reset 1527 splitter.element.style.display = ''; 1528 splitter.element.style.top = ''; 1529 splitter.element.style.left = ''; 1530 splitter.firstGroupElement.style.left = ''; 1531 splitter.firstGroupElement.style.top = ''; 1532 splitter.firstGroupElement.style.width = ''; 1533 splitter.firstGroupElement.style.height = ''; 1534 splitter.secondGroupElement.style.left = ''; 1535 splitter.secondGroupElement.style.top = ''; 1536 splitter.secondGroupElement.style.width = ''; 1537 splitter.secondGroupElement.style.height = ''; 1538 1539 var displayed = splitter.isDisplayed(); 1540 if (displayed) { 1541 splitter.element.style.display = 'block'; 1542 } else { 1543 splitter.element.style.display = 'none'; 1544 } 1545 1546 if (splitter.mouseListener !== undefined 1547 && splitter.mouseListener.mousePressed) { 1548 splitter.element.removeEventListener("mousedown", splitter.mouseListener.mousePressed, true); 1549 splitter.element.removeEventListener("touchstart", splitter.mouseListener.mousePressed, true); 1550 window.removeEventListener("resize", splitter.mouseListener.windowResized); 1551 delete splitter.mouseListener; 1552 } 1553 1554 splitter.element.classList.remove("horizontal"); 1555 splitter.element.classList.remove("vertical"); 1556 var horizontal = splitter.element.clientWidth > splitter.element.clientHeight; 1557 if (horizontal) { 1558 splitter.element.classList.add("horizontal"); 1559 } else { 1560 splitter.element.classList.add("vertical"); 1561 } 1562 1563 var initialSplitterPosition = this.home.getNumericProperty(splitter.homePropertyName); 1564 var positionStyleProperty = horizontal ? "top" : "left"; 1565 var dimensionStyleProperty = horizontal ? "height" : "width"; 1566 var dimensionProperty = horizontal ? "clientHeight" : "clientWidth"; 1567 var pointerPositionProperty = horizontal ? "clientY" : "clientX"; 1568 var offsetParent = splitter.firstGroupElement.offsetParent; 1569 var offsetProperty = horizontal ? "offsetTop" : "offsetLeft"; 1570 var offsetTopFirst = offsetParent == document.body 1571 ? splitter.firstGroupElement[offsetProperty] - offsetParent[offsetProperty] 1572 : 0; 1573 var homePane = this; 1574 1575 var mouseListener = { 1576 getSplitterPosition: function(ev) { 1577 var pointerCoordinatesObject = ev.touches && ev.touches.length > 0 1578 ? ev.touches[0] : ev; 1579 return pointerCoordinatesObject[pointerPositionProperty] - offsetParent[offsetProperty]; 1580 }, 1581 setSplitterPosition: function(relativePosition) { 1582 // Prevent from moving splitter beyond limit (before first elements) 1583 if (relativePosition < offsetTopFirst) { 1584 relativePosition = offsetTopFirst; 1585 } 1586 // Prevent from moving splitter beyond limit (farther than parents width or height) 1587 if (relativePosition > offsetParent[dimensionProperty] - splitter.element[dimensionProperty]) { 1588 relativePosition = offsetParent[dimensionProperty] - splitter.element[dimensionProperty]; 1589 } 1590 // Elements in first groups grow or shrink 1591 splitter.firstGroupElement.style[dimensionStyleProperty] = (relativePosition - offsetTopFirst) + "px"; 1592 // Splitter moves to new mouse position 1593 splitter.element.style[positionStyleProperty] = relativePosition + "px"; 1594 // Elements in second groups move & grow / shrink 1595 splitter.secondGroupElement.style[positionStyleProperty] = (relativePosition + splitter.element[dimensionProperty]) + "px"; 1596 splitter.secondGroupElement.style[dimensionStyleProperty] = "calc(100% - " + (relativePosition + splitter.element[dimensionProperty]) + "px)"; 1597 }, 1598 mouseDragged: function(ev) { 1599 ev.stopImmediatePropagation(); 1600 mouseListener.currentPosition = mouseListener.getSplitterPosition(ev); 1601 mouseListener.setSplitterPosition(mouseListener.currentPosition); 1602 if (splitter.resizeListener !== undefined) { 1603 splitter.resizeListener(mouseListener.currentPosition); 1604 } 1605 }, 1606 mousePressed: function(ev) { 1607 ev.preventDefault(); 1608 ev.stopImmediatePropagation(); 1609 mouseListener.currentPosition = mouseListener.getSplitterPosition(ev); 1610 splitter.element.classList.add("moving"); 1611 window.addEventListener("mousemove", mouseListener.mouseDragged, true); 1612 window.addEventListener("touchmove", mouseListener.mouseDragged, true); 1613 window.addEventListener("mouseup", mouseListener.windowMouseReleased, true); 1614 window.addEventListener("touchend", mouseListener.windowMouseReleased, true); 1615 }, 1616 windowMouseReleased: function(ev) { 1617 ev.stopImmediatePropagation(); 1618 splitter.element.classList.remove("moving"); 1619 window.removeEventListener("mousemove", mouseListener.mouseDragged, true); 1620 window.removeEventListener("touchmove", mouseListener.mouseDragged, true); 1621 window.removeEventListener("mouseup", mouseListener.windowMouseReleased, true); 1622 window.removeEventListener("touchend", mouseListener.windowMouseReleased, true); 1623 homePane.controller.setHomeProperty(splitter.homePropertyName, mouseListener.currentPosition == null ? null : mouseListener.currentPosition.toString()); 1624 if (splitter.resizeListener !== undefined) { 1625 splitter.resizeListener(mouseListener.currentPosition); 1626 } 1627 }, 1628 windowResized: function(ev) { 1629 var splitterPosition = window.getComputedStyle(splitter.element)[positionStyleProperty]; 1630 if (splitterPosition == null) { 1631 splitterPosition = "0px"; 1632 } 1633 splitterPosition = splitterPosition.substring(0, splitterPosition.length - 2); 1634 if (splitterPosition > offsetParent[dimensionProperty] - splitter.element[dimensionProperty]) { 1635 mouseListener.setSplitterPosition(offsetParent[dimensionProperty] - splitter.element[dimensionProperty]); 1636 } 1637 } 1638 }; 1639 1640 if (initialSplitterPosition != null) { 1641 if (displayed) { 1642 mouseListener.setSplitterPosition(initialSplitterPosition); 1643 } 1644 if (splitter.resizeListener !== undefined) { 1645 splitter.resizeListener(initialSplitterPosition); 1646 } 1647 } 1648 splitter.element.addEventListener("mousedown", mouseListener.mousePressed, true); 1649 splitter.element.addEventListener("touchstart", mouseListener.mousePressed, true); 1650 // Ensure splitter doesn't disappear after a window resize 1651 window.addEventListener("resize", mouseListener.windowResized); 1652 splitter.mouseListener = mouseListener; 1653 } 1654 1655 /** 1656 * @private 1657 */ 1658 HomePane.prototype.addOrientationChangeListener = function() { 1659 var homePane = this; 1660 var orientationListener = function(ev) { 1661 var planView = homePane.controller.getPlanController().getView(); 1662 var view3D = homePane.controller.getHomeController3D().getView(); 1663 if (planView != null && view3D != null) { 1664 var splitter = document.getElementById("plan-3D-view-splitter"); 1665 splitter.removeAttribute("style"); 1666 planView.getHTMLElement().removeAttribute("style"); 1667 view3D.getHTMLElement().removeAttribute("style"); 1668 planView.revalidate(); 1669 view3D.revalidate(); 1670 } 1671 setTimeout(function() { 1672 homePane.updateSplitters(); 1673 }, 100); 1674 }; 1675 this.resizeListener = function(ev) { 1676 if (window.matchMedia("(hover: none), (pointer: coarse)").matches) { 1677 orientationListener(ev); 1678 } 1679 }; 1680 window.addEventListener("resize", this.resizeListener); 1681 } 1682 1683 /** 1684 * @private 1685 */ 1686 HomePane.prototype.startToolBarButtonGroup = function(toolBar) { 1687 var buttonGroup = document.createElement("span"); 1688 toolBar.appendChild(buttonGroup); 1689 buttonGroup.classList.add("toolbar-button-group"); 1690 } 1691 1692 /** 1693 * @private 1694 */ 1695 HomePane.prototype.addButtonToToolBar = function(toolBar, button) { 1696 if (toolBar.children.length === 0) { 1697 this.startToolBarButtonGroup(toolBar); 1698 } 1699 toolBar.children[toolBar.children.length - 1].appendChild(button); 1700 } 1701 1702 /** 1703 * Adds to tool bar the button matching the given <code>actionType</code> 1704 * and returns <code>true</code> if it was added. 1705 * @param {HomeView.ActionType} actionType 1706 * @param {javax.swing.JToolBar} toolBar 1707 * @private 1708 */ 1709 HomePane.prototype.addToggleActionToToolBar = function(actionType, toolBar, additionalClass) { 1710 var action = this.getAction(actionType); 1711 if (action.getValue(AbstractAction.NAME) != null) { 1712 var button = this.createToolBarButton(action, additionalClass); 1713 if (action.getValue(AbstractAction.SELECTED_KEY)) { 1714 button.classList.add("selected"); 1715 } 1716 action.addPropertyChangeListener(function(ev) { 1717 if (ev.getPropertyName() == AbstractAction.SELECTED_KEY) { 1718 if (ev.getNewValue()) { 1719 button.classList.add("selected"); 1720 } else { 1721 button.classList.remove("selected"); 1722 } 1723 } 1724 }); 1725 button.addEventListener("click", function() { 1726 var group = action.getValue(ResourceAction.TOGGLE_BUTTON_GROUP); 1727 action.putValue(AbstractAction.SELECTED_KEY, group ? true : !action.getValue(AbstractAction.SELECTED_KEY)); 1728 }); 1729 this.addButtonToToolBar(toolBar, button); 1730 } 1731 } 1732 1733 /** 1734 * Adds to tool bar the button matching the given <code>actionType</code>. 1735 * @param {HomeView.ActionType} actionType 1736 * @param {Object} toolBar 1737 * @param {string} otherClass additional CSS class 1738 * @private 1739 */ 1740 HomePane.prototype.addActionToToolBar = function(actionType, toolBar, additionalClass) { 1741 var action = this.getAction(actionType); 1742 if (action.getValue(AbstractAction.NAME) != null) { 1743 this.addButtonToToolBar(toolBar, this.createToolBarButton(action, additionalClass)); 1744 } 1745 } 1746 1747 /** 1748 * Returns a button configured from the given <code>action</code>. 1749 * @param {HomeView.ResourceAction} action 1750 * @param {string} [additionalClass] additional CSS class 1751 * @return {HTMLButton} 1752 * @private 1753 */ 1754 HomePane.prototype.createToolBarButton = function(action, additionalClass) { 1755 var button = document.createElement("button"); 1756 button.id = "toolbar-button-" + action.getValue(ResourceAction.RESOURCE_PREFIX); 1757 button.disabled = !action.isEnabled(); 1758 button.tabIndex = -1; 1759 // Modify action with a setAction method which is also invoked elsewhere 1760 button.setAction = function(newAction) { 1761 button.action = newAction; 1762 var iconUrl = newAction.getURL(ResourceAction.TOOL_BAR_ICON); 1763 if (!iconUrl) { 1764 iconUrl = newAction.getURL(AbstractAction.SMALL_ICON); 1765 } 1766 button.style.backgroundImage = "url('" + iconUrl + "')"; 1767 button.style.backgroundPosition = "center"; 1768 button.style.backgroundRepeat = "no-repeat"; 1769 var shortDescription = newAction.getValue(AbstractAction.SHORT_DESCRIPTION); 1770 if (shortDescription) { 1771 button.title = shortDescription; 1772 } 1773 }; 1774 button.setAction(action); 1775 button.classList.add("toolbar-button"); 1776 if (action.getValue(ResourceAction.TOGGLE_BUTTON_GROUP)) { 1777 button.classList.add("toggle"); 1778 } 1779 button.action = action; 1780 button.addEventListener("click", function(ev) { 1781 this.action.actionPerformed(ev); 1782 }); 1783 var listener = { 1784 propertyChange: function(ev) { 1785 if (ev.getPropertyName() == "enabled") { 1786 button.disabled = !ev.getNewValue(); 1787 } else if (ev.getPropertyName() == AbstractAction.SHORT_DESCRIPTION) { 1788 button.title = ev.getNewValue(); 1789 } 1790 } 1791 }; 1792 action.addPropertyChangeListener(listener); 1793 if (additionalClass) { 1794 button.classList.add(additionalClass); 1795 } 1796 return button; 1797 } 1798 1799 /** 1800 * @private 1801 */ 1802 HomePane.prototype.addSeparator = function(toolBar) { 1803 this.startToolBarButtonGroup(toolBar); 1804 } 1805 1806 /** 1807 * Enables or disables the action matching <code>actionType</code>. 1808 * @param {HomeView.ActionType} actionType 1809 * @param {boolean} enabled 1810 */ 1811 HomePane.prototype.setEnabled = function(actionType, enabled) { 1812 var action = this.getAction(actionType); 1813 if (action != null) { 1814 action.setEnabled(enabled); 1815 } 1816 } 1817 1818 /** 1819 * Enables or disables the action matching <code>actionType</code>. 1820 * @param {String} actionType 1821 * @param {boolean} enabled 1822 */ 1823 HomePane.prototype.setActionEnabled = function(actionType, enabled) { 1824 var action = this.getAction(actionType); 1825 if (action != null) { 1826 action.setEnabled(enabled); 1827 } 1828 } 1829 1830 /** 1831 * Sets the <code>NAME</code> and <code>SHORT_DESCRIPTION</code> properties value 1832 * of undo and redo actions. If a parameter is null, 1833 * the properties will be reset to their initial values. 1834 * @param {string} undoText 1835 * @param {string} redoText 1836 */ 1837 HomePane.prototype.setUndoRedoName = function(undoText, redoText) { 1838 // Localize undo / redo prefix 1839 this.setNameAndShortDescription(HomeView.ActionType.UNDO, 1840 undoText != null ? undoText.replace(/^Undo/, this.preferences.getLocalizedString("AbstractUndoableEdit", "undo.textAndMnemonic")) : null); 1841 this.setNameAndShortDescription(HomeView.ActionType.REDO, 1842 redoText != null ? redoText.replace(/^Redo/, this.preferences.getLocalizedString("AbstractUndoableEdit", "redo.textAndMnemonic")) : null); 1843 } 1844 1845 /** 1846 * Sets the <code>NAME</code> and <code>SHORT_DESCRIPTION</code> properties value 1847 * matching <code>actionType</code>. If <code>name</code> is null, 1848 * the properties will be reset to their initial values. 1849 * @param {HomeView.ActionType} actionType 1850 * @param {string} name 1851 * @private 1852 */ 1853 HomePane.prototype.setNameAndShortDescription = function(actionType, name) { 1854 var action = this.getAction(actionType); 1855 if (action != null) { 1856 if (name == null) { 1857 name = action.getValue(AbstractAction.DEFAULT); 1858 } 1859 action.putValue(AbstractAction.NAME, name); 1860 action.putValue(AbstractAction.SHORT_DESCRIPTION, name); 1861 } 1862 } 1863 1864 /** 1865 * Enables or disables transfer between components. 1866 * @param {boolean} enabled 1867 */ 1868 HomePane.prototype.setTransferEnabled = function(enabled) { 1869 var furnitureCatalogView = this.controller.getFurnitureCatalogController().getView(); 1870 if (enabled 1871 && !this.transferHandlerEnabled) { 1872 if (furnitureCatalogView != null) { 1873 if (this.furnitureCatalogDragAndDropListener == null) { 1874 this.furnitureCatalogDragAndDropListener = this.createFurnitureCatalogMouseListener(); 1875 } 1876 1877 var pieceContainers = furnitureCatalogView.getHTMLElement().querySelectorAll(".furniture"); 1878 if (OperatingSystem.isInternetExplorerOrLegacyEdge() 1879 && window.PointerEvent) { 1880 // Multi touch support for IE and Edge 1881 for (i = 0; i < pieceContainers.length; i++) { 1882 pieceContainers[i].addEventListener("pointerdown", this.furnitureCatalogDragAndDropListener.pointerPressed); 1883 } 1884 furnitureCatalogView.getHTMLElement().addEventListener("mousedown", this.furnitureCatalogDragAndDropListener.mousePressed); 1885 // Add pointermove and pointerup event listeners to window to capture pointer events out of the canvas 1886 window.addEventListener("pointermove", this.furnitureCatalogDragAndDropListener.windowPointerMoved); 1887 window.addEventListener("pointerup", this.furnitureCatalogDragAndDropListener.windowPointerReleased); 1888 } else { 1889 for (i = 0; i < pieceContainers.length; i++) { 1890 pieceContainers[i].addEventListener("touchstart", this.furnitureCatalogDragAndDropListener.mousePressed); 1891 } 1892 window.addEventListener("touchmove", this.furnitureCatalogDragAndDropListener.mouseDragged); 1893 window.addEventListener("touchend", this.furnitureCatalogDragAndDropListener.windowMouseReleased); 1894 furnitureCatalogView.getHTMLElement().addEventListener("mousedown", this.furnitureCatalogDragAndDropListener.mousePressed); 1895 window.addEventListener("mousemove", this.furnitureCatalogDragAndDropListener.mouseDragged); 1896 window.addEventListener("mouseup", this.furnitureCatalogDragAndDropListener.windowMouseReleased); 1897 } 1898 furnitureCatalogView.getHTMLElement().addEventListener("contextmenu", this.furnitureCatalogDragAndDropListener.contextMenuDisplayed); 1899 } 1900 var homePane = this; 1901 this.furnitureCatalogListener = function(ev) { 1902 if (ev.getType() === CollectionEvent.Type.ADD 1903 && !homePane.furnitureCatalogListener.updater) { 1904 // Add listeners later in case more than one piece was added 1905 homePane.furnitureCatalogListener.updater = function() { 1906 if (homePane.furnitureCatalogListener !== undefined) { 1907 var pieceContainers = furnitureCatalogView.getHTMLElement().querySelectorAll(".furniture"); 1908 if (OperatingSystem.isInternetExplorerOrLegacyEdge() 1909 && window.PointerEvent) { 1910 for (i = 0; i < pieceContainers.length; i++) { 1911 pieceContainers[i].addEventListener("pointerdown", homePane.furnitureCatalogDragAndDropListener.pointerPressed); 1912 } 1913 } else { 1914 for (i = 0; i < pieceContainers.length; i++) { 1915 pieceContainers[i].addEventListener("touchstart", homePane.furnitureCatalogDragAndDropListener.mousePressed); 1916 } 1917 } 1918 delete homePane.furnitureCatalogListener.updater; 1919 } 1920 }; 1921 setTimeout(homePane.furnitureCatalogListener.updater, 100); 1922 } 1923 }; 1924 this.preferences.getFurnitureCatalog().addFurnitureListener(this.furnitureCatalogListener); 1925 } else if (!enabled 1926 && this.transferHandlerEnabled) { 1927 if (furnitureCatalogView != null) { 1928 var pieceContainers = furnitureCatalogView.getHTMLElement().querySelectorAll(".furniture"); 1929 if (OperatingSystem.isInternetExplorerOrLegacyEdge() 1930 && window.PointerEvent) { 1931 for (i = 0; i < pieceContainers.length; i++) { 1932 pieceContainers[i].removeEventListener("pointerdown", this.furnitureCatalogDragAndDropListener.pointerPressed); 1933 } 1934 furnitureCatalogView.getHTMLElement().removeEventListener("mousedown", this.furnitureCatalogDragAndDropListener.mousePressed); 1935 // Add pointermove and pointerup event listeners to window to capture pointer events out of the canvas 1936 window.removeEventListener("pointermove", this.furnitureCatalogDragAndDropListener.windowPointerMoved); 1937 window.removeEventListener("pointerup", this.furnitureCatalogDragAndDropListener.windowPointerReleased); 1938 } else { 1939 for (i = 0; i < pieceContainers.length; i++) { 1940 pieceContainers[i].removeEventListener("touchstart", this.furnitureCatalogDragAndDropListener.mousePressed); 1941 } 1942 window.removeEventListener("touchmove", this.furnitureCatalogDragAndDropListener.mouseDragged); 1943 window.removeEventListener("touchend", this.furnitureCatalogDragAndDropListener.windowMouseReleased); 1944 furnitureCatalogView.getHTMLElement().removeEventListener("mousedown", this.furnitureCatalogDragAndDropListener.mousePressed); 1945 window.removeEventListener("mousemove", this.furnitureCatalogDragAndDropListener.mouseDragged); 1946 window.removeEventListener("mouseup", this.furnitureCatalogDragAndDropListener.windowMouseReleased); 1947 } 1948 furnitureCatalogView.getHTMLElement().removeEventListener("contextmenu", this.furnitureCatalogDragAndDropListener.contextMenuDisplayed); 1949 } 1950 this.preferences.getFurnitureCatalog().removeFurnitureListener(this.furnitureCatalogListener); 1951 delete this.furnitureCatalogListener; 1952 } 1953 this.transferHandlerEnabled = enabled; 1954 } 1955 1956 /** 1957 * Returns a mouse listener for catalog that acts as catalog view, furniture view and plan transfer handlers 1958 * for drag and drop operations. 1959 * @return {javax.swing.event.MouseInputAdapter} 1960 * @private 1961 */ 1962 HomePane.prototype.createFurnitureCatalogMouseListener = function() { 1963 var homePane = this; 1964 var mouseListener = { 1965 selectedPiece: null, 1966 previousCursor: null, 1967 previousView: null, 1968 escaped: false, 1969 draggedImage: null, 1970 pointerTouches: {}, 1971 actionStartedInFurnitureCatalog: false, 1972 contextMenuEventType: false, 1973 mousePressed: function(ev) { 1974 if (!mouseListener.contextMenuEventType 1975 && (ev.button === 0 || ev.targetTouches)) { 1976 if (!ev.target.classList.contains("selected")) { 1977 return; 1978 } 1979 ev.preventDefault(); 1980 ev.stopPropagation(); 1981 var selectedFurniture = homePane.controller.getFurnitureCatalogController().getSelectedFurniture(); 1982 if (selectedFurniture.length > 0) { 1983 mouseListener.selectedPiece = selectedFurniture[0]; 1984 mouseListener.previousCursor = null; 1985 mouseListener.previousView = null; 1986 mouseListener.escaped = false; 1987 1988 homePane.inputMap ["ESCAPE"] = "EscapeDragFromFurnitureCatalog"; 1989 } 1990 mouseListener.actionStartedInFurnitureCatalog = true; 1991 } 1992 }, 1993 mouseDragged: function(ev) { 1994 if (!mouseListener.contextMenuEventType 1995 && mouseListener.actionStartedInFurnitureCatalog 1996 && ((ev.buttons & 1) == 1 || ev.targetTouches) 1997 && mouseListener.selectedPiece != null) { 1998 ev.preventDefault(); 1999 ev.stopPropagation(); 2000 2001 if (!mouseListener.escaped) { 2002 if (mouseListener.draggedImage == null) { 2003 var img = document.createElement("img"); 2004 var originalIcon = homePane.controller.getFurnitureCatalogController().getView().getHTMLElement().querySelector(".furniture.selected .furniture-icon"); 2005 img.src = originalIcon.src; 2006 var style = window.getComputedStyle(originalIcon); 2007 img.style.width = style.width; 2008 img.style.height = style.height; 2009 img.style.position = "absolute"; 2010 img.style.opacity = 0.6; 2011 img.style.zIndex = 105; 2012 mouseListener.draggedImage = img; 2013 document.body.appendChild(img); 2014 } 2015 mouseListener.draggedImage.style.left = mouseListener.getCoordinates(ev).clientX + "px"; 2016 mouseListener.draggedImage.style.top = mouseListener.getCoordinates(ev).clientY + "px"; 2017 } 2018 2019 var selectedLevel = homePane.home.getSelectedLevel(); 2020 if (selectedLevel == null || selectedLevel.isViewable()) { 2021 var transferredFurniture = [homePane.controller.getFurnitureController().createHomePieceOfFurniture(mouseListener.selectedPiece)]; 2022 var view; 2023 var pointInView = mouseListener.getPointInPlanView(ev, transferredFurniture); 2024 if (pointInView != null) { 2025 view = homePane.controller.getPlanController().getView(); 2026 } else { 2027 view = homePane.controller.getFurnitureController().getView(); 2028 pointInView = mouseListener.getPointInFurnitureView(ev); 2029 } 2030 2031 if (mouseListener.previousView !== view) { 2032 if (mouseListener.previousView != null) { 2033 if (mouseListener.previousView === homePane.controller.getPlanController().getView() 2034 && !mouseListener.escaped) { 2035 homePane.controller.getPlanController().stopDraggedItems(); 2036 } 2037 var component = mouseListener.previousView; 2038 if (component && typeof component.setCursor === "function") { 2039 component.setCursor(mouseListener.previousCursor); 2040 } 2041 mouseListener.previousCursor = null; 2042 mouseListener.previousView = null; 2043 } 2044 if (view != null) { 2045 var component = view; 2046 mouseListener.previousCursor = "default"; 2047 mouseListener.previousView = view; 2048 if (!mouseListener.escaped) { 2049 if (typeof component.setCursor === "function") { 2050 component.setCursor("copy"); 2051 } 2052 if (view === homePane.controller.getPlanController().getView()) { 2053 homePane.controller.getPlanController().startDraggedItems(transferredFurniture, pointInView [0], pointInView [1]); 2054 } 2055 } 2056 } 2057 } else if (pointInView != null) { 2058 homePane.controller.getPlanController().moveMouse(pointInView [0], pointInView [1]); 2059 } 2060 } 2061 } 2062 }, 2063 getPointInPlanView: function(ev, transferredFurniture) { 2064 var planView = homePane.controller.getPlanController().getView(); 2065 if (planView != null) { 2066 var rect = planView.getHTMLElement().getBoundingClientRect(); 2067 var coords = mouseListener.getCoordinates(ev); 2068 if (coords.clientX >= rect.left 2069 && coords.clientX < rect.left + rect.width 2070 && coords.clientY >= rect.top 2071 && coords.clientY < rect.top + rect.height) { 2072 return [planView.convertXPixelToModel(coords.clientX - rect.left), planView.convertYPixelToModel(coords.clientY - rect.top)]; 2073 } 2074 } 2075 return null; 2076 }, 2077 getPointInView3D: function(ev) { 2078 var view3D = homePane.controller.getHomeController3D().getView(); 2079 if (view3D != null) { 2080 var rect = view3D.getHTMLElement().getBoundingClientRect(); 2081 var coords = mouseListener.getCoordinates(ev); 2082 if (coords.clientX >= rect.left 2083 && coords.clientX < rect.left + rect.width 2084 && coords.clientY >= rect.top 2085 && coords.clientY < rect.top + rect.height) { 2086 return [coords.clientX - rect.left, coords.clientY - rect.top]; 2087 } 2088 } 2089 return null; 2090 }, 2091 getCoordinates: function(ev) { 2092 if (ev.targetTouches) { 2093 if (ev.targetTouches.length === 1) { 2094 return { clientX: ev.targetTouches[0].clientX, clientY: ev.targetTouches[0].clientY }; 2095 } else if (ev.targetTouches.length === 0 && ev.changedTouches.length === 1) { 2096 return { clientX: ev.changedTouches[0].clientX, clientY: ev.changedTouches[0].clientY }; 2097 } 2098 } 2099 return ev; 2100 }, 2101 getPointInFurnitureView: function(ev) { 2102 var furnitureView = homePane.controller.getFurnitureController().getView(); 2103 if (furnitureView != null) { 2104 var rect = furnitureView.getHTMLElement().getBoundingClientRect(); 2105 var coords = mouseListener.getCoordinates(ev); 2106 if (coords.clientX >= rect.left && coords.clientX < rect.left + rect.width 2107 && coords.clientY >= rect.top && coords.clientY < rect.top + rect.height) { 2108 return [0, 0]; 2109 } 2110 } 2111 return null; 2112 }, 2113 contextMenuDisplayed: function(ev) { 2114 mouseListener.contextMenuEventType = true; 2115 }, 2116 windowMouseReleased: function(ev) { 2117 if (mouseListener.actionStartedInFurnitureCatalog) { 2118 if (mouseListener.draggedImage != null) { 2119 document.body.removeChild(mouseListener.draggedImage); 2120 mouseListener.draggedImage = null; 2121 } 2122 if (!mouseListener.contextMenuEventType) { 2123 if ((ev.button === 0 || ev.targetTouches) && mouseListener.selectedPiece != null) { 2124 ev.preventDefault(); 2125 if (!mouseListener.escaped) { 2126 var selectedLevel = homePane.home.getSelectedLevel(); 2127 if (selectedLevel == null || selectedLevel.isViewable()) { 2128 var transferredFurniture = [homePane.controller.getFurnitureController().createHomePieceOfFurniture(mouseListener.selectedPiece)]; 2129 var view; 2130 var pointInView = mouseListener.getPointInPlanView(ev, transferredFurniture); 2131 if (pointInView != null) { 2132 homePane.controller.getPlanController().stopDraggedItems(); 2133 view = homePane.controller.getPlanController().getView(); 2134 homePane.controller.drop(transferredFurniture, view, pointInView [0], pointInView [1]); 2135 var view = mouseListener.previousView; 2136 if (view && typeof view.setCursor === "function") { 2137 view.setCursor(this.previousCursor); 2138 } 2139 } else if (homePane.preferences.isEditingIn3DViewEnabled()) { 2140 pointInView3D = mouseListener.getPointInView3D(ev); 2141 if (pointInView3D !== null) { 2142 view = homePane.controller.getHomeController3D().getView(); 2143 var dropLevel = homePane.getDropModelLevel(view, pointInView3D); 2144 var dropLocation = homePane.getDropModelLocation(view, transferredFurniture, dropLevel, pointInView3D); 2145 homePane.controller.drop(transferredFurniture, view, dropLevel, 2146 dropLocation [0], dropLocation [1], dropLocation.length === 3 ? dropLocation [2] : null); 2147 } 2148 } 2149 } 2150 } 2151 } 2152 } 2153 } 2154 mouseListener.selectedPiece = null; 2155 mouseListener.actionStartedInFurnitureCatalog = false; 2156 mouseListener.contextMenuEventType = false; 2157 delete homePane.inputMap ["ESCAPE"]; 2158 }, 2159 pointerPressed : function(ev) { 2160 if (ev.pointerType != "mouse") { 2161 // Multi touch support for IE and Edge 2162 mouseListener.copyPointerToTargetTouches(ev); 2163 return; // Don't support drag and drop from catalog on touch screens under IE/Edge 2164 } 2165 mouseListener.mousePressed(ev); 2166 }, 2167 windowPointerMoved : function(ev) { 2168 if (ev.pointerType != "mouse") { 2169 // Multi touch support for IE and Edge 2170 mouseListener.copyPointerToTargetTouches(ev); 2171 return; // Don't support drag and drop from catalog on touch screens under IE/Edge 2172 } 2173 mouseListener.mouseDragged(ev); 2174 }, 2175 windowPointerReleased : function(ev) { 2176 if (ev.pointerType != "mouse") { 2177 delete mouseListener.pointerTouches [ev.pointerId]; 2178 return; // Don't support drag and drop from catalog on touch screens under IE/Edge 2179 } 2180 mouseListener.windowMouseReleased(ev); 2181 }, 2182 copyPointerToTargetTouches : function(ev) { 2183 // Copy the IE and Edge pointer location to ev.targetTouches 2184 mouseListener.pointerTouches [ev.pointerId] = {clientX : ev.clientX, clientY : ev.clientY}; 2185 ev.targetTouches = []; 2186 for (var attribute in mouseListener.pointerTouches) { 2187 if (mouseListener.pointerTouches.hasOwnProperty(attribute)) { 2188 ev.targetTouches.push(mouseListener.pointerTouches [attribute]); 2189 } 2190 } 2191 } 2192 }; 2193 2194 var escapeAction = { 2195 actionPerformed: function() { 2196 if (!mouseListener.escaped) { 2197 if (mouseListener.previousView != null) { 2198 if (mouseListener.previousView === homePane.controller.getPlanController().getView()) { 2199 homePane.controller.getPlanController().stopDraggedItems(); 2200 } 2201 if (mouseListener.previousCursor != null && typeof mouseListener.previousView.setCursor === "function") { 2202 mouseListener.previousView.setCursor(mouseListener.previousCursor); 2203 } 2204 } 2205 mouseListener.escaped = true; 2206 if (mouseListener.draggedImage != null) { 2207 document.body.removeChild(mouseListener.draggedImage); 2208 mouseListener.draggedImage = null; 2209 } 2210 } 2211 } 2212 }; 2213 this.getActionMap() ["EscapeDragFromFurnitureCatalog"] = escapeAction; 2214 2215 return mouseListener; 2216 } 2217 2218 /** 2219 * Returns the level where drop location should occur. 2220 * @private 2221 */ 2222 HomePane.prototype.getDropModelLevel = function(destination, dropLocation) { 2223 if (destination instanceof HomeComponent3D) { 2224 var view3D = destination; 2225 var closestItem = view3D.getClosestSelectableItemAt(dropLocation [0], dropLocation [1]); 2226 var selectedLevel = this.home.getSelectedLevel(); 2227 if (closestItem != null 2228 && typeof closestItem.isAtLevel === "function" // closestItem instanceof Elevatable 2229 && !closestItem.isAtLevel(selectedLevel)) { 2230 return closestItem.getLevel(); 2231 } 2232 } 2233 return this.home.getSelectedLevel(); 2234 } 2235 2236 /** 2237 * Returns the drop location converted in model coordinates space. 2238 * @private 2239 */ 2240 HomePane.prototype.getDropModelLocation = function(destination, transferedItems, dropLevel, dropLocation) { 2241 var floorLocation = [0, 0, 0]; 2242 if (destination instanceof HomeComponent3D) { 2243 var view3D = destination; 2244 var closestItem = view3D.getClosestSelectableItemAt(dropLocation [0], dropLocation [1]); 2245 var floorElevation = 0; 2246 if (dropLevel != null) { 2247 floorElevation = dropLevel.getElevation(); 2248 } 2249 if (closestItem instanceof HomePieceOfFurniture) { 2250 floorLocation = [closestItem.getX(), closestItem.getY()]; 2251 if (transferedItems.length === 1 2252 && transferedItems [0] instanceof HomePieceOfFurniture) { 2253 var pointOnFloor = view3D.getVirtualWorldPointAt(dropLocation [0], dropLocation [1], floorElevation); 2254 var intersectionWithPieceMiddle = this.computeIntersection(pointOnFloor [0], pointOnFloor [1], this.home.getCamera().getX(), this.home.getCamera().getY(), 2255 floorLocation [0], floorLocation [1], floorLocation [0] + Math.cos(closestItem.getAngle()), floorLocation [1] + Math.sin(closestItem.getAngle())); 2256 if (java.awt.geom.Point2D.distance(intersectionWithPieceMiddle [0], intersectionWithPieceMiddle [1], closestItem.getX(), closestItem.getY()) < closestItem.getWidth() / 2) { 2257 floorLocation = intersectionWithPieceMiddle; 2258 } 2259 var transferedPiece = transferedItems [0]; 2260 floorLocation [0] -= transferedPiece.getWidth() / 2; 2261 floorLocation [1] -= transferedPiece.getDepth() / 2; 2262 var elevation; 2263 if (closestItem instanceof HomeShelfUnit) { 2264 var camera = this.home.getCamera(); 2265 var distancePointOnFloorToCamera = java.awt.geom.Point2D.distance(pointOnFloor [0], pointOnFloor [1], camera.getX(), camera.getY()); 2266 var distancePointOnFloorToLocation = java.awt.geom.Point2D.distance(pointOnFloor [0], pointOnFloor [1], floorLocation [0], floorLocation [1]); 2267 var elevation = (camera.getZ() - (this.home.getSelectedLevel() !== null ? this.home.getSelectedLevel().getElevation() : 0)) 2268 / distancePointOnFloorToCamera * distancePointOnFloorToLocation; 2269 } else if (closestItem.isHorizontallyRotated()) { 2270 elevation = closestItem.getElevation() + closestItem.getHeightInPlan(); 2271 } else if (closestItem.getDropOnTopElevation() >= 0) { 2272 elevation = closestItem.getElevation() + closestItem.getHeight() * closestItem.getDropOnTopElevation(); 2273 } else { 2274 elevation = 0; 2275 } 2276 floorLocation = [floorLocation [0], floorLocation [1], elevation]; 2277 } 2278 } else if (closestItem instanceof Wall 2279 && closestItem.getArcExtent() === null 2280 && transferedItems.length === 1) { 2281 var pointOnFloor = view3D.getVirtualWorldPointAt(dropLocation [0], dropLocation [1], floorElevation); 2282 // Compute intersection between camera - pointOnFloor line and left/right sides of the wall 2283 var wall = closestItem; 2284 var wallPoints = wall.getPoints(); 2285 var leftSideIntersection = this.computeIntersection(pointOnFloor [0], pointOnFloor [1], this.home.getCamera().getX(), this.home.getCamera().getY(), 2286 wallPoints [0][0], wallPoints [0][1], wallPoints [1][0], wallPoints [1][1]); 2287 var rightSideIntersection = this.computeIntersection(pointOnFloor [0], pointOnFloor [1], this.home.getCamera().getX(), this.home.getCamera().getY(), 2288 wallPoints [3][0], wallPoints [3][1], wallPoints [2][0], wallPoints [2][1]); 2289 if (java.awt.geom.Point2D.distanceSq(this.home.getCamera().getX(), this.home.getCamera().getY(), leftSideIntersection [0], leftSideIntersection [1]) 2290 < java.awt.geom.Point2D.distanceSq(this.home.getCamera().getX(), this.home.getCamera().getY(), rightSideIntersection [0], rightSideIntersection [1])) { 2291 floorLocation = leftSideIntersection; 2292 } else { 2293 floorLocation = rightSideIntersection; 2294 } 2295 if (transferedItems [0] instanceof HomePieceOfFurniture) { 2296 var transferedPiece = transferedItems [0]; 2297 var wallYawAngle = Math.atan((wall.getYEnd() - wall.getYStart()) / (wall.getXEnd() - wall.getXStart())); 2298 floorLocation [0] -= transferedPiece.getWidth() / 2 * Math.cos(wallYawAngle); 2299 floorLocation [1] -= transferedPiece.getWidth() / 2 * Math.sin(wallYawAngle); 2300 } 2301 } else if (!this.home.isEmpty()) { 2302 floorLocation = view3D.getVirtualWorldPointAt(dropLocation [0], dropLocation [1], floorElevation); 2303 floorLocation = [floorLocation [0], floorLocation [1]]; 2304 if (transferedItems.length === 1 2305 && transferedItems [0] instanceof HomePieceOfFurniture) { 2306 var transferedPiece = transferedItems [0]; 2307 floorLocation [0] -= transferedPiece.getWidth() / 2; 2308 floorLocation [1] -= transferedPiece.getDepth() / 2; 2309 } 2310 } 2311 } 2312 return floorLocation; 2313 } 2314 2315 /** 2316 * Returns the intersection point between the line joining the first two points and 2317 * the line joining the two last points. 2318 * @private 2319 */ 2320 HomePane.prototype.computeIntersection = function(xPoint1, yPoint1, xPoint2, yPoint2, 2321 xPoint3, yPoint3, xPoint4, yPoint4) { 2322 var x = xPoint2; 2323 var y = yPoint2; 2324 var alpha1 = (yPoint2 - yPoint1) / (xPoint2 - xPoint1); 2325 var alpha2 = (yPoint4 - yPoint3) / (xPoint4 - xPoint3); 2326 // If the two lines are not parallel 2327 if (alpha1 !== alpha2) { 2328 // If first line is vertical 2329 if (Math.abs(alpha1) > 4000) { 2330 if (Math.abs(alpha2) < 4000) { 2331 x = xPoint1; 2332 var beta2 = yPoint4 - alpha2 * xPoint4; 2333 y = alpha2 * x + beta2; 2334 } 2335 // If second line is vertical 2336 } else if (Math.abs(alpha2) > 4000) { 2337 if (Math.abs(alpha1) < 4000) { 2338 x = xPoint3; 2339 var beta1 = yPoint2 - alpha1 * xPoint2; 2340 y = alpha1 * x + beta1; 2341 } 2342 } else { 2343 var sameSignum = alpha1 > 0 && alpha2 > 0 || alpha1 < 0 && alpha2 < 0; 2344 if (Math.abs(alpha1 - alpha2) > 1E-5 2345 && (!sameSignum || (Math.abs(alpha1) > Math.abs(alpha2) ? alpha1 / alpha2 : alpha2 / alpha1) > 1.004)) { 2346 var beta1 = yPoint2 - alpha1 * xPoint2; 2347 var beta2 = yPoint4 - alpha2 * xPoint4; 2348 x = (beta2 - beta1) / (alpha1 - alpha2); 2349 y = alpha1 * x + beta1; 2350 } 2351 } 2352 } 2353 return [x, y]; 2354 } 2355 2356 /** 2357 * Detaches the given <code>view</code> from home view. 2358 * @param {Object} view 2359 * @ignore 2360 */ 2361 HomePane.prototype.detachView = function(view) { 2362 } 2363 2364 /** 2365 * Attaches the given <code>view</code> to home view. 2366 * @param {Object} view 2367 * @ignore 2368 */ 2369 HomePane.prototype.attachView = function(view) { 2370 } 2371 2372 /** 2373 * Displays a content chooser open dialog to choose the name of a home. 2374 * @return {string} 2375 * @ignore 2376 */ 2377 HomePane.prototype.showOpenDialog = function() { 2378 } 2379 2380 /** 2381 * Displays a dialog to let the user choose a home example. 2382 * @return {string} 2383 * @ignore 2384 */ 2385 HomePane.prototype.showNewHomeFromExampleDialog = function() { 2386 } 2387 2388 /** 2389 * Displays a dialog that lets user choose what he wants to do with a damaged home he tries to open it. 2390 * @return {HomeView.OpenDamagedHomeAnswer} {@link com.eteks.sweethome3d.viewcontroller.HomeView.OpenDamagedHomeAnswer#REMOVE_DAMAGED_ITEMS} 2391 * if the user chose to remove damaged items, 2392 * {@link com.eteks.sweethome3d.viewcontroller.HomeView.OpenDamagedHomeAnswer#REPLACE_DAMAGED_ITEMS} 2393 * if he doesn't want to replace damaged items by red images and red boxes, 2394 * or {@link com.eteks.sweethome3d.viewcontroller.HomeView.OpenDamagedHomeAnswer#DO_NOT_OPEN_HOME} 2395 * if he doesn't want to open damaged home. 2396 * @param {string} homeName 2397 * @param {Home} damagedHome 2398 * @param {Object[]} invalidContent 2399 * @ignore 2400 */ 2401 HomePane.prototype.confirmOpenDamagedHome = function(homeName, damagedHome, invalidContent) { 2402 return true; 2403 } 2404 2405 /** 2406 * Displays a content chooser open dialog to choose a language library. 2407 * @return {string} 2408 * @ignore 2409 */ 2410 HomePane.prototype.showImportLanguageLibraryDialog = function() { 2411 } 2412 2413 /** 2414 * Displays a dialog that lets user choose whether he wants to overwrite 2415 * an existing language library or not. 2416 * @param {string} languageLibraryName 2417 * @return {boolean} 2418 * @ignore 2419 */ 2420 HomePane.prototype.confirmReplaceLanguageLibrary = function(languageLibraryName) { 2421 return true; 2422 } 2423 2424 /** 2425 * Displays a content chooser open dialog to choose a furniture library. 2426 * @return {string} 2427 * @ignore 2428 */ 2429 HomePane.prototype.showImportFurnitureLibraryDialog = function() { 2430 } 2431 2432 /** 2433 * Displays a dialog that lets user choose whether he wants to overwrite 2434 * an existing furniture library or not. 2435 * @param {string} furnitureLibraryName 2436 * @return {boolean} 2437 * @ignore 2438 */ 2439 HomePane.prototype.confirmReplaceFurnitureLibrary = function(furnitureLibraryName) { 2440 return true; 2441 } 2442 2443 /** 2444 * Displays a content chooser open dialog to choose a textures library. 2445 * @return {string} 2446 * @ignore 2447 */ 2448 HomePane.prototype.showImportTexturesLibraryDialog = function() { 2449 } 2450 2451 /** 2452 * Displays a dialog that lets user choose whether he wants to overwrite 2453 * an existing textures library or not. 2454 * @param {string} texturesLibraryName 2455 * @return {boolean} 2456 * @ignore 2457 */ 2458 HomePane.prototype.confirmReplaceTexturesLibrary = function(texturesLibraryName) { 2459 return true; 2460 } 2461 2462 /** 2463 * Displays a dialog that lets user choose whether he wants to overwrite 2464 * an existing plug-in or not. 2465 * @param {string} pluginName 2466 * @return {boolean} 2467 * @ignore 2468 */ 2469 HomePane.prototype.confirmReplacePlugin = function(pluginName) { 2470 return true; 2471 } 2472 2473 /** 2474 * Displays a content chooser save dialog to choose the name of a home. 2475 * @param {string} homeName 2476 * @return {string} 2477 * @ignore 2478 */ 2479 HomePane.prototype.showSaveDialog = function(homeName) { 2480 return null; 2481 } 2482 2483 /** 2484 * Displays <code>message</code> in an error message box. 2485 * @param {string} message 2486 * @ignore 2487 */ 2488 HomePane.prototype.showError = function(message) { 2489 alert(message.indexOf("<html>") < 0 ? message : message.replace(/\<\/?\w+(\s+\w+\=[\"\'][^\"\']+[\"\'])*\>/g, " ").replace(/\s+/g, " ")); 2490 } 2491 2492 /** 2493 * Displays <code>message</code> in a message box. 2494 * @param {string} message 2495 * @ignore 2496 */ 2497 HomePane.prototype.showMessage = function(message) { 2498 alert(message.indexOf("<html>") < 0 ? message : message.replace(/\<\/?\w+(\s+\w+\=[\"\'][^\"\']+[\"\'])*\>/g, " ").replace(/\s+/g, " ")); 2499 } 2500 2501 /** 2502 * Displays the tip matching <code>actionTipKey</code> and 2503 * returns <code>true</code> if the user chose not to display again the tip. 2504 * @param {string} actionTipKey 2505 * @return {boolean} 2506 * @ignore 2507 */ 2508 HomePane.prototype.showActionTipMessage = function(actionTipKey) { 2509 return false; 2510 } 2511 2512 /** 2513 * Displays a dialog that lets user choose whether he wants to save 2514 * the current home or not. 2515 * @return {@link com.eteks.sweethome3d.viewcontroller.HomeView.SaveAnswer#CANCEL} 2516 * @param {string} homeName 2517 * @param {function} saveHome callback with a boolean parameter equal to true if the user confirmed to save 2518 * @ignore 2519 */ 2520 HomePane.prototype.confirmSave = function(homeName, saveHome) { 2521 var message; 2522 if (homeName != null) { 2523 message = this.preferences.getLocalizedString("HomePane", "confirmSave.message", '"' + homeName + '"'); 2524 } else { 2525 message = this.preferences.getLocalizedString("HomePane", "confirmSave.message", " "); 2526 } 2527 2528 var confirmSavingDialog = new JSDialog(this.preferences, 2529 this.preferences.getLocalizedString("HomePane", "confirmSave.title"), 2530 message.replace(/\<br\>/, " ") + "</font>", 2531 { 2532 size: "small", 2533 applier: function() { 2534 saveHome(true); 2535 } 2536 }); 2537 confirmSavingDialog.findElement(".dialog-ok-button").innerHTML = 2538 this.preferences.getLocalizedString("HomePane", "confirmSave.save"); 2539 var cancelButton = confirmSavingDialog.findElement(".dialog-cancel-button"); 2540 cancelButton.innerHTML = this.preferences.getLocalizedString("HomePane", "confirmSave.cancel"); 2541 var doNotSaveButton = document.createElement("button"); 2542 doNotSaveButton.innerHTML = this.preferences.getLocalizedString("HomePane", "confirmSave.doNotSave"); 2543 confirmSavingDialog.registerEventListener(doNotSaveButton, "click", function() { 2544 confirmSavingDialog.close(); 2545 saveHome(false); 2546 }); 2547 cancelButton.parentElement.insertBefore(doNotSaveButton, cancelButton); 2548 confirmSavingDialog.displayView(); 2549 return HomeView.SaveAnswer.CANCEL; 2550 } 2551 2552 /** 2553 * Displays a dialog that let user choose whether he wants to save 2554 * a home that was created with a newer version of Sweet Home 3D. 2555 * @return {boolean} <code>true</code> if user confirmed to save. 2556 * @param {string} homeName 2557 * @ignore 2558 */ 2559 HomePane.prototype.confirmSaveNewerHome = function(homeName) { 2560 return true; 2561 } 2562 2563 /** 2564 * Displays a dialog that let user choose whether he wants to exit 2565 * application or not. 2566 * @return {boolean} <code>true</code> if user confirmed to exit. 2567 * @ignore 2568 */ 2569 HomePane.prototype.confirmExit = function() { 2570 return true; 2571 } 2572 2573 /** 2574 * Displays an about dialog. 2575 */ 2576 HomePane.prototype.showAboutDialog = function() { 2577 var message = this.preferences.getLocalizedString("HomePane", "about.message", this.controller.getVersion()); 2578 var template = "<table><tr><td><img src='"+ ZIPTools.getScriptFolder() + this.preferences.getLocalizedString("HomePane", "about.icon") + "'></td>" 2579 + "<td>" + message + "</td></tr></table>"; 2580 var aboutDialog = new JSDialog(this.preferences, 2581 this.preferences.getLocalizedString("HomePane", "about.title"), 2582 template, { size: "medium" }); 2583 aboutDialog.getHTMLElement().classList.add("about-dialog"); 2584 aboutDialog.displayView(); 2585 } 2586 2587 /** 2588 * Displays the given message and returns <code>false</code> if the user 2589 * doesn't want to be informed of the shown updates anymore. 2590 * @param {string} updatesMessage the message to display 2591 * @param {boolean} showOnlyMessage if <code>false</code> a check box proposing not to display 2592 * again shown updates will be shown. 2593 * @return {boolean} 2594 * @ignore 2595 */ 2596 HomePane.prototype.showUpdatesMessage = function(updatesMessage, showOnlyMessage) { 2597 return false; 2598 } 2599 2600 /** 2601 * Shows a print dialog to print the home displayed by this pane. 2602 * @return {function(): Object} a print task to execute or <code>null</code> if the user canceled print. 2603 * The <code>call</code> method of the returned task may throw a 2604 * {@link RecorderException} exception if print failed 2605 * or an {@link InterruptedRecorderException} 2606 * exception if it was interrupted. 2607 * @ignore 2608 */ 2609 HomePane.prototype.showPrintDialog = function() { 2610 return null; 2611 } 2612 2613 /** 2614 * Shows a content chooser save dialog to print a home in a PDF file. 2615 * @param {string} homeName 2616 * @return {string} 2617 * @ignore 2618 */ 2619 HomePane.prototype.showPrintToPDFDialog = function(homeName) { 2620 return null; 2621 } 2622 2623 /** 2624 * Prints a home to a given PDF file. This method may be overridden 2625 * to write to another kind of output stream. 2626 * @param {string} pdfFile 2627 * @ignore 2628 */ 2629 HomePane.prototype.printToPDF = function(pdfFile) { 2630 } 2631 2632 /** 2633 * Shows a content chooser save dialog to export furniture list in a CSV file. 2634 * @param {string} homeName 2635 * @return {string} 2636 * @ignore 2637 */ 2638 HomePane.prototype.showExportToCSVDialog = function(homeName) { 2639 return null; 2640 } 2641 2642 /** 2643 * Exports furniture list to a given CSV file. 2644 * @param {string} csvFile 2645 * @ignore 2646 */ 2647 HomePane.prototype.exportToCSV = function(csvFile) { 2648 } 2649 2650 /** 2651 * Shows a content chooser save dialog to export a home plan in a SVG file. 2652 * @param {string} homeName 2653 * @return {string} 2654 * @ignore 2655 */ 2656 HomePane.prototype.showExportToSVGDialog = function(homeName) { 2657 return null; 2658 } 2659 2660 /** 2661 * Exports the plan objects to a given SVG file. 2662 * @param {string} svgFile 2663 * @ignore 2664 */ 2665 HomePane.prototype.exportToSVG = function(svgFile) { 2666 } 2667 2668 /** 2669 * Shows a content chooser save dialog to export a 3D home in a OBJ file. 2670 * @param {string} homeName 2671 * @return {string} 2672 * @ignore 2673 */ 2674 HomePane.prototype.showExportToOBJDialog = function(homeName) { 2675 return null; 2676 } 2677 2678 /** 2679 * Exports to an OBJ file the objects of the 3D view created with the given factory. 2680 * @param {string} objFile 2681 * @param {Object} object3dFactory 2682 * @ignore 2683 */ 2684 HomePane.prototype.exportToOBJ = function(objFile, object3dFactory) { 2685 } 2686 2687 2688 /** 2689 * Displays a dialog that let user choose whether he wants to delete 2690 * the selected furniture from catalog or not. 2691 * @return {boolean} <code>true</code> if user confirmed to delete. 2692 * @ignore 2693 */ 2694 HomePane.prototype.confirmDeleteCatalogSelection = function() { 2695 return true; 2696 } 2697 2698 /** 2699 * Displays a dialog that lets the user choose a name for the current camera. 2700 * @return {null} the chosen name or <code>null</code> if the user canceled. 2701 * @param {string} cameraName default name 2702 * @ignore 2703 */ 2704 HomePane.prototype.showStoreCameraDialog = function(cameraName) { 2705 return prompt(this.preferences.getLocalizedString("HomePane", "showStoreCameraDialog.message"), cameraName); 2706 } 2707 2708 /** 2709 * Displays a dialog showing the list of cameras stored in home 2710 * and returns <code>null</code> to delete selected cameras asynchronously. 2711 */ 2712 HomePane.prototype.showDeletedCamerasDialog = function() { 2713 var homePane = this; 2714 var storedCameras = this.home.getStoredCameras(); 2715 2716 function JSConfirmDeleteCamerasDialog() { 2717 JSDialog.call(this, homePane.preferences, 2718 "@{HomePane.showDeletedCamerasDialog.title}", 2719 "<div>@{HomePane.confirmDeleteCameras.message}</div>", 2720 { 2721 applier: function(dialog) { 2722 homePane.controller.getHomeController3D().deleteCameras(dialog.selectedCameras); 2723 }, 2724 }); 2725 2726 var confirmDialog = this; 2727 var cancelButton = this.findElement(".dialog-cancel-button"); 2728 this.registerEventListener(cancelButton, "click", function(ev) { 2729 confirmDialog.cancel(); 2730 }); 2731 var okButtons = this.findElements(".dialog-ok-button"); 2732 this.registerEventListener(okButtons, "click", function(ev) { 2733 confirmDialog.validate(); 2734 }); 2735 } 2736 JSConfirmDeleteCamerasDialog.prototype = Object.create(JSDialog.prototype); 2737 JSConfirmDeleteCamerasDialog.prototype.constructor = JSConfirmDeleteCamerasDialog; 2738 2739 JSConfirmDeleteCamerasDialog.prototype.appendButtons = function(buttonsPanel) { 2740 buttonsPanel.innerHTML = JSComponent.substituteWithLocale(this.preferences, 2741 "<button class='dialog-cancel-button'>@{HomePane.confirmDeleteCameras.cancel}</button>" + 2742 "<button class='dialog-ok-button'>@{HomePane.confirmDeleteCameras.delete}</button>"); 2743 } 2744 2745 var html = "<div>@{HomePane.showDeletedCamerasDialog.message}</div><br />"; 2746 for (var i = 0; i < storedCameras.length; i++) { 2747 html += "<div><label><input type='checkbox' value='" + i + "' />" + storedCameras[i].getName() + "</label></div>"; 2748 } 2749 2750 function JSDeleteCamerasDialog() { 2751 JSDialog.call(this, homePane.preferences, 2752 "@{HomePane.showDeletedCamerasDialog.title}", 2753 html, 2754 { 2755 applier: function(dialog) { 2756 var checkboxes = dialog.findElements("input[type='checkbox']:checked"); 2757 var selectedCameras = []; 2758 for (var i = 0; i < checkboxes.length; i++) { 2759 var cameraIndex = parseInt(checkboxes[i].value); 2760 var camera = storedCameras[cameraIndex]; 2761 selectedCameras.push(camera); 2762 } 2763 2764 if (selectedCameras.length > 0) { 2765 var confirmDialog = new JSConfirmDeleteCamerasDialog(); 2766 confirmDialog.selectedCameras = selectedCameras; 2767 confirmDialog.displayView(); 2768 } 2769 }, 2770 }); 2771 } 2772 JSDeleteCamerasDialog.prototype = Object.create(JSDialog.prototype); 2773 JSDeleteCamerasDialog.prototype.constructor = JSDeleteCamerasDialog; 2774 2775 var dialog = new JSDeleteCamerasDialog(); 2776 dialog.displayView(); 2777 return null; 2778 } 2779 2780 /** 2781 * Returns <code>true</code> if clipboard doesn't contain data that 2782 * components are able to handle. 2783 * @return {boolean} 2784 */ 2785 HomePane.prototype.isClipboardEmpty = function() { 2786 return this.clipboardEmpty; 2787 } 2788 2789 /** 2790 * Returns the list of selectable items that are currently in clipboard 2791 * or <code>null</code> if clipboard doesn't contain any selectable item. 2792 * @return {Object[]} 2793 */ 2794 HomePane.prototype.getClipboardItems = function() { 2795 return this.clipboard; 2796 } 2797 2798 /** 2799 * Execute <code>runnable</code> asynchronously in the thread 2800 * that manages toolkit events. 2801 * @param {function} runnable 2802 * @ignore 2803 */ 2804 HomePane.prototype.invokeLater = function(runnable) { 2805 setTimeout(runnable); 2806 } 2807 2808 /** 2809 * Removes components added to this pane and their listeners. 2810 */ 2811 HomePane.prototype.dispose = function() { 2812 this.setTransferEnabled(false); 2813 2814 var furnitureCatalogView = this.controller.getFurnitureCatalogController().getView(); 2815 var furnitureView = this.controller.getFurnitureController().getView(); 2816 var planView = this.controller.getPlanController().getView(); 2817 var view3D = this.controller.getHomeController3D().getView(); 2818 if (view3D != null) { 2819 view3D.dispose(); 2820 } 2821 if (planView != null) { 2822 planView.dispose(); 2823 } 2824 if (furnitureView != null) { 2825 furnitureView.dispose(); 2826 } 2827 if (furnitureCatalogView != null) { 2828 furnitureCatalogView.dispose(); 2829 } 2830 2831 if (this.view3DPopupMenu != null) { 2832 document.body.removeChild(this.view3DPopupMenu.getHTMLElement()); 2833 } 2834 if (this.planPopupMenu != null) { 2835 document.body.removeChild(this.planPopupMenu.getHTMLElement()); 2836 } 2837 if (this.furniturePopupMenu != null) { 2838 document.body.removeChild(this.furniturePopupMenu.getHTMLElement()); 2839 } 2840 if (this.furnitureCatalogPopupMenu != null) { 2841 document.body.removeChild(this.furnitureCatalogPopupMenu.getHTMLElement()); 2842 } 2843 2844 if (this.levelSelector) { 2845 while (this.levelSelector.children.length > 0) { 2846 this.levelSelector.removeChild(this.levelSelector.children[0]); 2847 } 2848 this.levelSelector.removeEventListener("change", this.levelSelectorChangeListener); 2849 } 2850 2851 document.removeEventListener("keydown", this.keydownListener); 2852 2853 window.removeEventListener("resize", this.resizeListener); 2854 var splitters = [this.catalogFurnitureSplitter, this.furniturePlanSplitter, this.plan3DViewSplitter]; 2855 for (var i = 0; i < splitters.length; i++) { 2856 var splitter = splitters [i]; 2857 splitter.element.removeEventListener("mousedown", splitter.mouseListener.mousePressed, true); 2858 splitter.element.removeEventListener("touchstart", splitter.mouseListener.mousePressed, true); 2859 window.removeEventListener("resize", splitter.mouseListener.windowResized); 2860 } 2861 var applicationMenuToolBar = document.getElementById("application-menu-toolbar"); 2862 if (applicationMenuToolBar != null) { 2863 var toolBarChildren = applicationMenuToolBar.children; 2864 for (var i = toolBarChildren.length - 1; i >= 0; i--) { 2865 applicationMenuToolBar.removeChild(toolBarChildren [i]); 2866 } 2867 } 2868 var toolBar = document.getElementById("home-pane-toolbar"); 2869 toolBarChildren = toolBar.children; 2870 for (var i = toolBarChildren.length - 1; i >= 0; i--) { 2871 if (this.toolBarDefaultChildren.indexOf(toolBarChildren [i]) < 0) { 2872 toolBar.removeChild(toolBarChildren [i]); 2873 } 2874 } 2875 this.getHTMLElement().removeEventListener("focusin", this.focusListener); 2876 this.preferences.removePropertyChangeListener("VALUE_ADDED_TAX_ENABLED", this.preferencesChangeListener); 2877 this.preferences.removePropertyChangeListener("CURRENCY", this.preferencesChangeListener); 2878 if (this.furnitureCatalogListener != null) { 2879 this.preferences.getFurnitureCatalog().removeFurnitureListener(this.furnitureCatalogListener); 2880 } 2881 } 2882