1 /* 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.oracle.javafx.scenebuilder.kit.editor.util; 33 34 import com.oracle.javafx.scenebuilder.kit.editor.EditorController; 35 import com.oracle.javafx.scenebuilder.kit.editor.EditorController.ControlAction; 36 import com.oracle.javafx.scenebuilder.kit.editor.EditorController.EditAction; 37 import com.oracle.javafx.scenebuilder.kit.editor.i18n.I18N; 38 import com.oracle.javafx.scenebuilder.kit.editor.selection.AbstractSelectionGroup; 39 import com.oracle.javafx.scenebuilder.kit.editor.selection.GridSelectionGroup; 40 import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup; 41 import com.oracle.javafx.scenebuilder.kit.editor.selection.Selection; 42 import com.oracle.javafx.scenebuilder.kit.fxom.FXOMObject; 43 44 import javafx.beans.value.ChangeListener; 45 import javafx.collections.ObservableList; 46 import javafx.event.ActionEvent; 47 import javafx.event.Event; 48 import javafx.event.EventHandler; 49 import javafx.scene.control.ContextMenu; 50 import javafx.scene.control.Menu; 51 import javafx.scene.control.MenuItem; 52 import javafx.scene.control.RadioMenuItem; 53 import javafx.scene.control.SeparatorMenuItem; 54 import javafx.scene.layout.GridPane; 55 import javafx.stage.WindowEvent; 56 57 /** 58 * Controller used to handle contextual menu in hierarchy and content view. 59 */ 60 public class ContextMenuController { 61 62 private final EditorController editorController; 63 private ContextMenu contextMenu; // Initialized lazily 64 65 private MenuItem cutMenuItem; 66 private MenuItem copyMenuItem; 67 private MenuItem pasteMenuItem; 68 private MenuItem pasteIntoMenuItem; 69 private MenuItem duplicateMenuItem; 70 private MenuItem deleteMenuItem; 71 private MenuItem selectParentMenuItem; 72 private MenuItem fitToParentMenuItem; 73 private MenuItem useComputedSizesMenuItem; 74 private MenuItem editIncludedFileMenuItem; 75 private MenuItem revealIncludedFileMenuItem; 76 private MenuItem bringToFrontMenuItem; 77 private MenuItem sendToBackMenuItem; 78 private MenuItem bringForwardMenuItem; 79 private MenuItem sendBackwardMenuItem; 80 private Menu wrapInMenu; 81 private MenuItem wrapInAnchorPaneMenuItem; 82 private MenuItem wrapInBorderPaneMenuItem; 83 private MenuItem wrapInButtonBarMenuItem; 84 private MenuItem wrapInDialogPaneMenuItem; 85 private MenuItem wrapInFlowPaneMenuItem; 86 private MenuItem wrapInGridPaneMenuItem; 87 private MenuItem wrapInGroupMenuItem; 88 private MenuItem wrapInHBoxMenuItem; 89 private MenuItem wrapInPaneMenuItem; 90 private MenuItem wrapInScrollPaneMenuItem; 91 private MenuItem wrapInSplitPaneMenuItem; 92 private MenuItem wrapInStackPaneMenuItem; 93 private MenuItem wrapInTabPaneMenuItem; 94 private MenuItem wrapInTextFlowMenuItem; 95 private MenuItem wrapInTilePaneMenuItem; 96 private MenuItem wrapInTitledPaneMenuItem; 97 private MenuItem wrapInToolBarMenuItem; 98 private MenuItem wrapInVBoxMenuItem; 99 private MenuItem unwrapMenuItem; 100 private Menu gridPaneMenu; 101 private MenuItem moveRowAboveMenuItem; 102 private MenuItem moveRowBelowMenuItem; 103 private MenuItem moveColumnBeforeMenuItem; 104 private MenuItem moveColumnAfterMenuItem; 105 private MenuItem addRowAboveMenuItem; 106 private MenuItem addRowBelowMenuItem; 107 private MenuItem addColumnBeforeMenuItem; 108 private MenuItem addColumnAfterMenuItem; 109 private MenuItem increaseRowSpan; 110 private MenuItem decreaseRowSpan; 111 private MenuItem increaseColumnSpan; 112 private MenuItem decreaseColumnSpan; 113 114 private final EventHandler<Event> onShowingMenuEventHandler 115 = t -> { 116 assert t.getSource() instanceof Menu; 117 final Menu menu = (Menu) t.getSource(); 118 handleOnShowing(menu.getItems()); 119 }; 120 121 private final EventHandler<WindowEvent> onShowingContextMenuEventHandler 122 = t -> { 123 assert t.getSource() instanceof ContextMenu; 124 final ContextMenu contextMenu = (ContextMenu) t.getSource(); 125 handleOnShowing(contextMenu.getItems()); 126 }; 127 128 private final EventHandler<ActionEvent> onActionEventHandler 129 = t -> { 130 assert t.getSource() instanceof MenuItem; 131 handleOnActionMenu((MenuItem) t.getSource()); 132 }; 133 134 private final ChangeListener<Number> jobManagerRevisionListener 135 = (observable, oldValue, newValue) -> jobManagerRevisionDidChange(); 136 137 public ContextMenuController(final EditorController editorController) { 138 this.editorController = editorController; 139 this.editorController.getJobManager().revisionProperty().addListener(jobManagerRevisionListener); 140 } 141 142 public ContextMenu getContextMenu() { 143 if (contextMenu == null) { 144 // Initialization of context menu 145 contextMenu = new ContextMenu(); 146 contextMenu.setConsumeAutoHidingEvents(false); 147 contextMenu.setOnShowing(onShowingContextMenuEventHandler); 148 } 149 return contextMenu; 150 } 151 152 /** 153 * Updates the context menu items depending on the selection. 154 */ 155 public void updateContextMenuItems() { 156 157 // Lazely initialization of context menu items 158 if (copyMenuItem == null) { 159 initializeMenuItems(); 160 } 161 getContextMenu().getItems().clear(); 162 163 final Selection selection = editorController.getSelection(); 164 if (selection.isEmpty() == false) { 165 final AbstractSelectionGroup asg = selection.getGroup(); 166 if (asg instanceof ObjectSelectionGroup) { 167 168 // Common editing actions 169 getContextMenu().getItems().addAll( 170 cutMenuItem, 171 copyMenuItem, 172 pasteMenuItem, 173 pasteIntoMenuItem, 174 duplicateMenuItem, 175 deleteMenuItem, 176 new SeparatorMenuItem(), 177 selectParentMenuItem, 178 new SeparatorMenuItem(), 179 fitToParentMenuItem, 180 useComputedSizesMenuItem); 181 // GridPane specific actions 182 if (canPerformGridPaneActions() || canPerformGridPaneChildActions()) { 183 updateGridPaneMenuItems(); 184 getContextMenu().getItems().add(gridPaneMenu); 185 } 186 // Common editing actions on going 187 getContextMenu().getItems().addAll( 188 editIncludedFileMenuItem, 189 revealIncludedFileMenuItem, 190 new SeparatorMenuItem(), 191 bringToFrontMenuItem, 192 sendToBackMenuItem, 193 bringForwardMenuItem, 194 sendBackwardMenuItem, 195 new SeparatorMenuItem(), 196 wrapInMenu, 197 unwrapMenuItem); 198 199 } else { 200 assert asg instanceof GridSelectionGroup; 201 getContextMenu().getItems().addAll( 202 deleteMenuItem, 203 new SeparatorMenuItem(), 204 moveRowAboveMenuItem, 205 moveRowBelowMenuItem, 206 moveColumnBeforeMenuItem, 207 moveColumnAfterMenuItem, 208 new SeparatorMenuItem(), 209 addRowAboveMenuItem, 210 addRowBelowMenuItem, 211 addColumnBeforeMenuItem, 212 addColumnAfterMenuItem); 213 } 214 } 215 } 216 217 private void handleOnShowing(final ObservableList<MenuItem> menuItems) { 218 for (MenuItem menuItem : menuItems) { 219 final boolean disable, selected; 220 final String title; 221 if (menuItem.getUserData() instanceof MenuItemController) { 222 final MenuItemController c = (MenuItemController) menuItem.getUserData(); 223 disable = !c.canPerform(); 224 title = c.getTitle(); 225 selected = c.isSelected(); 226 } else { 227 if (menuItem instanceof Menu) { 228 disable = false; 229 selected = false; 230 title = null; 231 } else { 232 disable = true; 233 selected = false; 234 title = null; 235 } 236 } 237 menuItem.setDisable(disable); 238 if (title != null) { 239 menuItem.setText(title); 240 } 241 if (menuItem instanceof RadioMenuItem) { 242 final RadioMenuItem ri = (RadioMenuItem) menuItem; 243 ri.setSelected(selected); 244 } 245 } 246 } 247 248 private void handleOnActionMenu(MenuItem i) { 249 assert i.getUserData() instanceof MenuItemController; 250 final MenuItemController c = (MenuItemController) i.getUserData(); 251 c.perform(); 252 } 253 254 private void jobManagerRevisionDidChange() { 255 // FXOMDocument has been modified by a job. 256 if (contextMenu != null && contextMenu.isShowing()) { 257 contextMenu.hide(); 258 } 259 } 260 261 262 /** 263 * Returns true if all the selected items are GridPanes. 264 * 265 * @return 266 */ 267 private boolean canPerformGridPaneActions() { 268 boolean result = false; 269 final Selection selection = editorController.getSelection(); 270 final AbstractSelectionGroup asg = selection.getGroup(); 271 272 if (asg instanceof ObjectSelectionGroup) { 273 final ObjectSelectionGroup osg = (ObjectSelectionGroup) asg; 274 result = true; 275 for (FXOMObject obj : osg.getItems()) { 276 if ((obj.getSceneGraphObject() instanceof GridPane) == false) { 277 result = false; 278 break; 279 } 280 } 281 } 282 return result; 283 } 284 285 /** 286 * Returns true if all the selected items are children of 1 or more GridPanes. 287 * 288 * @return 289 */ 290 private boolean canPerformGridPaneChildActions() { 291 boolean result = false; 292 final Selection selection = editorController.getSelection(); 293 final AbstractSelectionGroup asg = selection.getGroup(); 294 295 if (asg instanceof ObjectSelectionGroup) { 296 final ObjectSelectionGroup osg = (ObjectSelectionGroup) asg; 297 result = true; 298 for (FXOMObject obj : osg.getItems()) { 299 final FXOMObject parent = obj.getParentObject(); 300 if (parent == null 301 || (parent.getSceneGraphObject() instanceof GridPane) == false) { 302 result = false; 303 break; 304 } 305 } 306 } 307 return result; 308 } 309 310 private void updateGridPaneMenuItems() { 311 assert canPerformGridPaneActions() || canPerformGridPaneChildActions(); 312 gridPaneMenu.getItems().clear(); 313 // Add actions on the GridPane rows/columns 314 if (canPerformGridPaneActions()) { 315 gridPaneMenu.getItems().addAll( 316 moveRowAboveMenuItem, 317 moveRowBelowMenuItem, 318 moveColumnBeforeMenuItem, 319 moveColumnAfterMenuItem, 320 new SeparatorMenuItem(), 321 addRowAboveMenuItem, 322 addRowBelowMenuItem, 323 addColumnBeforeMenuItem, 324 addColumnAfterMenuItem); 325 } 326 // Add actions on the GridPane row/column span 327 if (canPerformGridPaneChildActions()) { 328 // The selection is a GridPane child of another GridPane 329 if (gridPaneMenu.getItems().isEmpty() == false) { 330 gridPaneMenu.getItems().add(new SeparatorMenuItem()); 331 } 332 gridPaneMenu.getItems().addAll( 333 increaseRowSpan, 334 decreaseRowSpan, 335 increaseColumnSpan, 336 decreaseColumnSpan); 337 } 338 } 339 340 private void initializeMenuItems() { 341 342 copyMenuItem = new MenuItem(I18N.getString("menu.title.copy")); 343 copyMenuItem.setOnAction(onActionEventHandler); 344 copyMenuItem.setUserData(new ControlActionController(ControlAction.COPY)); 345 selectParentMenuItem = new MenuItem(I18N.getString("menu.title.select.parent")); 346 selectParentMenuItem.setOnAction(onActionEventHandler); 347 selectParentMenuItem.setUserData(new ControlActionController(ControlAction.SELECT_PARENT)); 348 editIncludedFileMenuItem = new MenuItem(I18N.getString("menu.title.edit.included.default")); 349 editIncludedFileMenuItem.setOnAction(onActionEventHandler); 350 editIncludedFileMenuItem.setUserData(new ControlActionController(ControlAction.EDIT_INCLUDED_FILE)); 351 revealIncludedFileMenuItem = new MenuItem(I18N.getString("menu.title.reveal.included.default")); 352 revealIncludedFileMenuItem.setOnAction(onActionEventHandler); 353 revealIncludedFileMenuItem.setUserData(new ControlActionController(ControlAction.REVEAL_INCLUDED_FILE)); 354 cutMenuItem = new MenuItem(I18N.getString("menu.title.cut")); 355 cutMenuItem.setOnAction(onActionEventHandler); 356 cutMenuItem.setUserData(new EditActionController(EditAction.CUT)); 357 pasteMenuItem = new MenuItem(I18N.getString("menu.title.paste")); 358 pasteMenuItem.setOnAction(onActionEventHandler); 359 pasteMenuItem.setUserData(new EditActionController(EditAction.PASTE)); 360 pasteIntoMenuItem = new MenuItem(I18N.getString("menu.title.paste.into")); 361 pasteIntoMenuItem.setOnAction(onActionEventHandler); 362 pasteIntoMenuItem.setUserData(new EditActionController(EditAction.PASTE_INTO)); 363 duplicateMenuItem = new MenuItem(I18N.getString("menu.title.duplicate")); 364 duplicateMenuItem.setOnAction(onActionEventHandler); 365 duplicateMenuItem.setUserData(new EditActionController(EditAction.DUPLICATE)); 366 deleteMenuItem = new MenuItem(I18N.getString("menu.title.delete")); 367 deleteMenuItem.setOnAction(onActionEventHandler); 368 deleteMenuItem.setUserData(new EditActionController(EditAction.DELETE)); 369 fitToParentMenuItem = new MenuItem(I18N.getString("menu.title.fit")); 370 fitToParentMenuItem.setOnAction(onActionEventHandler); 371 fitToParentMenuItem.setUserData(new EditActionController(EditAction.FIT_TO_PARENT)); 372 useComputedSizesMenuItem = new MenuItem(I18N.getString("menu.title.use.computed.sizes")); 373 useComputedSizesMenuItem.setOnAction(onActionEventHandler); 374 useComputedSizesMenuItem.setUserData(new EditActionController(EditAction.USE_COMPUTED_SIZES)); 375 bringToFrontMenuItem = new MenuItem(I18N.getString("menu.title.front")); 376 bringToFrontMenuItem.setOnAction(onActionEventHandler); 377 bringToFrontMenuItem.setUserData(new EditActionController(EditAction.BRING_TO_FRONT)); 378 sendToBackMenuItem = new MenuItem(I18N.getString("menu.title.back")); 379 sendToBackMenuItem.setOnAction(onActionEventHandler); 380 sendToBackMenuItem.setUserData(new EditActionController(EditAction.SEND_TO_BACK)); 381 bringForwardMenuItem = new MenuItem(I18N.getString("menu.title.forward")); 382 bringForwardMenuItem.setOnAction(onActionEventHandler); 383 bringForwardMenuItem.setUserData(new EditActionController(EditAction.BRING_FORWARD)); 384 sendBackwardMenuItem = new MenuItem(I18N.getString("menu.title.backward")); 385 sendBackwardMenuItem.setOnAction(onActionEventHandler); 386 sendBackwardMenuItem.setUserData(new EditActionController(EditAction.SEND_BACKWARD)); 387 wrapInMenu = new Menu(I18N.getString("menu.title.wrap")); 388 wrapInAnchorPaneMenuItem = new MenuItem("AnchorPane"); 389 wrapInAnchorPaneMenuItem.setOnAction(onActionEventHandler); 390 wrapInAnchorPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_ANCHOR_PANE)); 391 wrapInBorderPaneMenuItem = new MenuItem("BorderPane"); 392 wrapInBorderPaneMenuItem.setOnAction(onActionEventHandler); 393 wrapInBorderPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_BORDER_PANE)); 394 wrapInButtonBarMenuItem = new MenuItem("ButtonBar"); 395 wrapInButtonBarMenuItem.setOnAction(onActionEventHandler); 396 wrapInButtonBarMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_BUTTON_BAR)); 397 wrapInDialogPaneMenuItem = new MenuItem("DialogPane"); 398 wrapInDialogPaneMenuItem.setOnAction(onActionEventHandler); 399 wrapInDialogPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_DIALOG_PANE)); 400 wrapInFlowPaneMenuItem = new MenuItem("FlowPane"); 401 wrapInFlowPaneMenuItem.setOnAction(onActionEventHandler); 402 wrapInFlowPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_FLOW_PANE)); 403 wrapInGridPaneMenuItem = new MenuItem("GridPane"); 404 wrapInGridPaneMenuItem.setOnAction(onActionEventHandler); 405 wrapInGridPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_GRID_PANE)); 406 wrapInHBoxMenuItem = new MenuItem("HBox"); 407 wrapInHBoxMenuItem.setOnAction(onActionEventHandler); 408 wrapInHBoxMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_HBOX)); 409 wrapInPaneMenuItem = new MenuItem("Pane"); 410 wrapInPaneMenuItem.setOnAction(onActionEventHandler); 411 wrapInPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_PANE)); 412 wrapInScrollPaneMenuItem = new MenuItem("ScrollPane"); 413 wrapInScrollPaneMenuItem.setOnAction(onActionEventHandler); 414 wrapInScrollPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_SCROLL_PANE)); 415 wrapInSplitPaneMenuItem = new MenuItem("SplitPane"); 416 wrapInSplitPaneMenuItem.setOnAction(onActionEventHandler); 417 wrapInSplitPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_SPLIT_PANE)); 418 wrapInStackPaneMenuItem = new MenuItem("StackPane"); 419 wrapInStackPaneMenuItem.setOnAction(onActionEventHandler); 420 wrapInStackPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_STACK_PANE)); 421 wrapInTabPaneMenuItem = new MenuItem("TabPane"); 422 wrapInTabPaneMenuItem.setOnAction(onActionEventHandler); 423 wrapInTabPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_TAB_PANE)); 424 wrapInTilePaneMenuItem = new MenuItem("TilePane"); 425 wrapInTilePaneMenuItem.setOnAction(onActionEventHandler); 426 wrapInTilePaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_TILE_PANE)); 427 wrapInTextFlowMenuItem = new MenuItem("TextFlow"); 428 wrapInTextFlowMenuItem.setOnAction(onActionEventHandler); 429 wrapInTextFlowMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_TEXT_FLOW)); 430 wrapInTitledPaneMenuItem = new MenuItem("TitledPane"); 431 wrapInTitledPaneMenuItem.setOnAction(onActionEventHandler); 432 wrapInTitledPaneMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_TITLED_PANE)); 433 wrapInToolBarMenuItem = new MenuItem("ToolBar"); 434 wrapInToolBarMenuItem.setOnAction(onActionEventHandler); 435 wrapInToolBarMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_TOOL_BAR)); 436 wrapInVBoxMenuItem = new MenuItem("VBox"); 437 wrapInVBoxMenuItem.setOnAction(onActionEventHandler); 438 wrapInVBoxMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_VBOX)); 439 wrapInGroupMenuItem = new MenuItem("Group"); 440 wrapInGroupMenuItem.setOnAction(onActionEventHandler); 441 wrapInGroupMenuItem.setUserData(new EditActionController(EditAction.WRAP_IN_GROUP)); 442 wrapInMenu.getItems().setAll( 443 wrapInAnchorPaneMenuItem, 444 wrapInBorderPaneMenuItem, 445 wrapInButtonBarMenuItem, 446 wrapInDialogPaneMenuItem, 447 wrapInFlowPaneMenuItem, 448 wrapInGridPaneMenuItem, 449 wrapInGroupMenuItem, 450 wrapInHBoxMenuItem, 451 wrapInPaneMenuItem, 452 wrapInScrollPaneMenuItem, 453 wrapInSplitPaneMenuItem, 454 wrapInStackPaneMenuItem, 455 wrapInTabPaneMenuItem, 456 wrapInTextFlowMenuItem, 457 wrapInTilePaneMenuItem, 458 wrapInTitledPaneMenuItem, 459 wrapInToolBarMenuItem, 460 wrapInVBoxMenuItem); 461 unwrapMenuItem = new MenuItem(I18N.getString("menu.title.unwrap")); 462 unwrapMenuItem.setOnAction(onActionEventHandler); 463 unwrapMenuItem.setUserData(new EditActionController(EditAction.UNWRAP)); 464 // GridPane specifics 465 gridPaneMenu = new Menu(I18N.getString("menu.title.grid")); 466 moveRowAboveMenuItem = new MenuItem(I18N.getString("menu.title.grid.move.row.above")); 467 moveRowAboveMenuItem.setOnAction(onActionEventHandler); 468 moveRowAboveMenuItem.setUserData(new EditActionController(EditAction.MOVE_ROW_ABOVE)); 469 moveRowBelowMenuItem = new MenuItem(I18N.getString("menu.title.grid.move.row.below")); 470 moveRowBelowMenuItem.setOnAction(onActionEventHandler); 471 moveRowBelowMenuItem.setUserData(new EditActionController(EditAction.MOVE_ROW_BELOW)); 472 moveColumnBeforeMenuItem = new MenuItem(I18N.getString("menu.title.grid.move.column.before")); 473 moveColumnBeforeMenuItem.setOnAction(onActionEventHandler); 474 moveColumnBeforeMenuItem.setUserData(new EditActionController(EditAction.MOVE_COLUMN_BEFORE)); 475 moveColumnAfterMenuItem = new MenuItem(I18N.getString("menu.title.grid.move.column.after")); 476 moveColumnAfterMenuItem.setOnAction(onActionEventHandler); 477 moveColumnAfterMenuItem.setUserData(new EditActionController(EditAction.MOVE_COLUMN_AFTER)); 478 addRowAboveMenuItem = new MenuItem(I18N.getString("menu.title.grid.add.row.above")); 479 addRowAboveMenuItem.setOnAction(onActionEventHandler); 480 addRowAboveMenuItem.setUserData(new EditActionController(EditAction.ADD_ROW_ABOVE)); 481 addRowBelowMenuItem = new MenuItem(I18N.getString("menu.title.grid.add.row.below")); 482 addRowBelowMenuItem.setOnAction(onActionEventHandler); 483 addRowBelowMenuItem.setUserData(new EditActionController(EditAction.ADD_ROW_BELOW)); 484 addColumnBeforeMenuItem = new MenuItem(I18N.getString("menu.title.grid.add.column.before")); 485 addColumnBeforeMenuItem.setOnAction(onActionEventHandler); 486 addColumnBeforeMenuItem.setUserData(new EditActionController(EditAction.ADD_COLUMN_BEFORE)); 487 addColumnAfterMenuItem = new MenuItem(I18N.getString("menu.title.grid.add.column.after")); 488 addColumnAfterMenuItem.setOnAction(onActionEventHandler); 489 addColumnAfterMenuItem.setUserData(new EditActionController(EditAction.ADD_COLUMN_AFTER)); 490 increaseRowSpan = new MenuItem(I18N.getString("menu.title.grid.increase.row.span")); 491 increaseRowSpan.setOnAction(onActionEventHandler); 492 increaseRowSpan.setUserData(new EditActionController(EditAction.INCREASE_ROW_SPAN)); 493 decreaseRowSpan = new MenuItem(I18N.getString("menu.title.grid.decrease.row.span")); 494 decreaseRowSpan.setOnAction(onActionEventHandler); 495 decreaseRowSpan.setUserData(new EditActionController(EditAction.DECREASE_ROW_SPAN)); 496 increaseColumnSpan = new MenuItem(I18N.getString("menu.title.grid.increase.column.span")); 497 increaseColumnSpan.setOnAction(onActionEventHandler); 498 increaseColumnSpan.setUserData(new EditActionController(EditAction.INCREASE_COLUMN_SPAN)); 499 decreaseColumnSpan = new MenuItem(I18N.getString("menu.title.grid.decrease.column.span")); 500 decreaseColumnSpan.setOnAction(onActionEventHandler); 501 decreaseColumnSpan.setUserData(new EditActionController(EditAction.DECREASE_COLUMN_SPAN)); 502 503 wrapInMenu.setOnShowing(onShowingMenuEventHandler); 504 gridPaneMenu.setOnShowing(onShowingMenuEventHandler); 505 } 506 507 class EditActionController extends MenuItemController { 508 509 private final EditAction editAction; 510 511 public EditActionController(EditAction editAction) { 512 this.editAction = editAction; 513 } 514 515 @Override 516 public boolean canPerform() { 517 boolean result; 518 if (editorController.getFxomDocument() == null) { 519 result = false; 520 } else { 521 result = editorController.canPerformEditAction(editAction); 522 } 523 return result; 524 } 525 526 @Override 527 public void perform() { 528 assert canPerform() : "editAction=" + editAction; 529 editorController.performEditAction(editAction); 530 } 531 } 532 533 class ControlActionController extends MenuItemController { 534 535 private final ControlAction controlAction; 536 537 public ControlActionController(ControlAction controlAction) { 538 this.controlAction = controlAction; 539 } 540 541 @Override 542 public boolean canPerform() { 543 boolean result; 544 if (editorController.getFxomDocument() == null) { 545 result = false; 546 } else { 547 result = editorController.canPerformControlAction(controlAction); 548 } 549 return result; 550 } 551 552 @Override 553 public void perform() { 554 assert canPerform() : "controlAction=" + controlAction; 555 editorController.performControlAction(controlAction); 556 } 557 } 558 559 abstract class MenuItemController { 560 561 public abstract boolean canPerform(); 562 563 public abstract void perform(); 564 565 public String getTitle() { 566 return null; 567 } 568 569 public boolean isSelected() { 570 return false; 571 } 572 } 573 }