1 /* 2 * Copyright (c) 2008, 2015, 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 modena; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 import javafx.application.Platform; 38 import javafx.collections.FXCollections; 39 import javafx.collections.ObservableList; 40 import javafx.css.PseudoClass; 41 import javafx.geometry.Insets; 42 import javafx.geometry.Orientation; 43 import javafx.geometry.Pos; 44 import javafx.geometry.Side; 45 import javafx.scene.Group; 46 import javafx.scene.Node; 47 import javafx.scene.control.Accordion; 48 import javafx.scene.control.Button; 49 import javafx.scene.control.CheckMenuItem; 50 import javafx.scene.control.ContextMenu; 51 import javafx.scene.control.Label; 52 import javafx.scene.control.ListView; 53 import javafx.scene.control.Menu; 54 import javafx.scene.control.MenuBar; 55 import javafx.scene.control.MenuItem; 56 import javafx.scene.control.RadioMenuItem; 57 import javafx.scene.control.Pagination; 58 import javafx.scene.control.SelectionMode; 59 import javafx.scene.control.Separator; 60 import javafx.scene.control.SeparatorMenuItem; 61 import javafx.scene.control.SplitPane; 62 import javafx.scene.control.TabPane; 63 import javafx.scene.control.Tab; 64 import javafx.scene.control.TitledPane; 65 import javafx.scene.control.TextField; 66 import javafx.scene.control.ToolBar; 67 import javafx.scene.image.Image; 68 import javafx.scene.image.ImageView; 69 import javafx.scene.input.KeyCharacterCombination; 70 import javafx.scene.input.KeyCombination; 71 import javafx.scene.layout.HBox; 72 import javafx.scene.layout.StackPane; 73 import javafx.scene.paint.Color; 74 import javafx.scene.shape.Line; 75 import javafx.scene.shape.Rectangle; 76 77 /** 78 * Helper static methods for Sample Page 79 */ 80 public class SamplePageHelpers { 81 82 static <T extends Node> T withState(T node, String state) { 83 if (node != null && state != null) { 84 // stop user from being able to change state 85 node.setMouseTransparent(true); 86 node.setFocusTraversable(false); 87 // set state to chosen state 88 final String[] pseudoClasses = (state).split("[\\s,]+"); 89 for (String pseudoClass : pseudoClasses) { 90 node.pseudoClassStateChanged(PseudoClass.getPseudoClass(pseudoClass), true); 91 } 92 } 93 return node; 94 } 95 96 static <T extends Node> T withState(final T node, final String state, final String subNodeStyleClass, final String subNodeState) { 97 withState(node, state); 98 Platform.runLater(() -> withState(node.lookup(subNodeStyleClass), subNodeState)); 99 return node; 100 } 101 102 private static final String[] LETTERS = new String[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; 103 104 static ObservableList<String> sampleItems() { 105 return sampleItems(7); 106 } 107 108 static ObservableList<String> sampleItems(int numberOfItems) { 109 ArrayList<String> items = new ArrayList<String>(); 110 if (numberOfItems < 26) { 111 for(int i=0; i<numberOfItems; i++) { 112 items.add("Item "+LETTERS[i]); 113 } 114 } else { 115 for(int i=0; i<numberOfItems; i++) { 116 items.add("Item "+i); 117 } 118 } 119 return FXCollections.observableArrayList(items); 120 } 121 122 static Node scrollPaneContent() { 123 Line l1 = new Line(); 124 l1.setEndX(200); 125 l1.setEndY(200); 126 l1.setStroke(Color.DODGERBLUE); 127 Line l2 = new Line(); 128 l2.setStartX(200); 129 l2.setStartY(0); 130 l2.setEndY(200); 131 l2.setStroke(Color.DODGERBLUE); 132 return new Group(new Rectangle(200, 200, Color.PALETURQUOISE), l1, l2); 133 } 134 135 static Node createTabPane(int numOfTabs, int prefWidth, int prefHeight, String firstTabText, boolean floating, boolean disableFirst, Side side) { 136 TabPane tabPane = new TabPane(); 137 tabPane.setSide(side); 138 if (floating) tabPane.getStyleClass().add("floating"); 139 for (int i=1; i<=numOfTabs; i++) { 140 Tab tab = new Tab("Tab "+i); 141 tab.setDisable(i==1 && disableFirst); 142 tab.setContent(new Label((i==1 && firstTabText!=null)? firstTabText :"Tab "+i+" Content")); 143 tabPane.getTabs().add(tab); 144 } 145 if (disableFirst) tabPane.getSelectionModel().select(1); 146 tabPane.setPrefWidth(prefWidth); 147 tabPane.setPrefHeight(prefHeight); 148 return tabPane; 149 } 150 151 static Node wrapBdr(Node node) { 152 StackPane sp = new StackPane(node); 153 sp.setStyle("-fx-border-color: black; -fx-border-width: 3;"); 154 return sp; 155 } 156 157 static ToolBar createToolBar(Side side, boolean overFlow, boolean disabled) { 158 final boolean vertical = side == Side.LEFT || side == Side.RIGHT; 159 ToolBar toolBar = new ToolBar(); 160 if (vertical) toolBar.setOrientation(Orientation.VERTICAL); 161 if (side == Side.BOTTOM) toolBar.getStyleClass().add("bottom"); 162 if (side == Side.RIGHT) toolBar.getStyleClass().add("right"); 163 if (disabled) toolBar.setDisable(true); 164 toolBar.getItems().addAll( 165 new Button("A"), 166 new Button("B"), 167 new Separator() 168 ); 169 if (vertical) { 170 toolBar.getItems().addAll( 171 new Button("C"), 172 new Button("D") 173 ); 174 } else { 175 Label searchLabel = new Label("Search:"); 176 HBox searchBox = new HBox(10, searchLabel, new TextField()); 177 searchBox.setAlignment(Pos.BASELINE_LEFT); 178 toolBar.getItems().addAll(searchBox); 179 } 180 if (overFlow) { 181 if (vertical) { 182 toolBar.setPrefHeight(80); 183 } else { 184 toolBar.setPrefWidth(80); 185 } 186 } 187 return toolBar; 188 } 189 190 static Accordion createAccordion() { 191 Accordion accordian = new Accordion(); 192 accordian.getPanes().addAll( 193 new TitledPane("Title 1", new Label("Content\nLine2.")), 194 new TitledPane("Title 2", new Label("Content\nLine2.")), 195 new TitledPane("Title 3", new Label("Content\nLine2.")) 196 ); 197 return accordian; 198 } 199 200 static SplitPane createSplitPane(int numOfItems, boolean vertical, Node firstItem) { 201 SplitPane splitPane = new SplitPane(); 202 if(vertical) splitPane.setOrientation(Orientation.VERTICAL); 203 if (firstItem != null) splitPane.getItems().add(firstItem); 204 for (int i=1; i<=numOfItems; i++) { 205 splitPane.getItems().add(new Label("Item "+i)); 206 } 207 splitPane.setPrefSize(150, 150); 208 return splitPane; 209 } 210 211 static Pagination createPagination(int numOfPages, boolean bullet, boolean arrows) { 212 Pagination pagination = new Pagination(numOfPages); 213 if (bullet) pagination.getStyleClass().add("bullet"); 214 if (!arrows) pagination.setStyle("-fx-arrows-visible:false;"); 215 pagination.setPageFactory(param -> new Label("Page Label "+param)); 216 return pagination; 217 } 218 219 static ListView<String> createListView(int numOfItems, boolean multipleSelection, boolean disable, boolean horiz) { 220 ListView<String> listView = new ListView<String>(); 221 if (horiz) listView.setOrientation(Orientation.HORIZONTAL); 222 listView.setPrefHeight((24*7)+4); 223 listView.setPrefWidth(horiz ? 200 : 140); 224 listView.getItems().addAll(sampleItems(numOfItems)); 225 listView.setDisable(disable); 226 if (multipleSelection) { 227 listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 228 listView.getSelectionModel().selectRange(1, 5); 229 } else { 230 listView.getSelectionModel().select(1); 231 } 232 return listView; 233 } 234 235 static MenuItem[] createMenuItems(int numberOfItems) { 236 ArrayList<MenuItem> items = new ArrayList<MenuItem>(); 237 if (numberOfItems < 26) { 238 for(int i=0; i<numberOfItems; i++) { 239 items.add(new MenuItem("Item "+LETTERS[i])); 240 } 241 } else { 242 for(int i=0; i<numberOfItems; i++) { 243 items.add(new MenuItem("Item "+i)); 244 } 245 } 246 return items.toArray(new MenuItem[items.size()]); 247 } 248 249 static MenuBar createMenuBar() { 250 final MenuBar mb = new MenuBar(); 251 mb.getMenus().addAll( 252 createMenu("File"), 253 createMenu("Edit"), 254 createMenu("View"), 255 createMenu("Help") 256 ); 257 Platform.runLater(() -> new ArrayList<Node>(mb.lookupAll(".menu")).get(1).pseudoClassStateChanged(PseudoClass.getPseudoClass("hover"), true)); 258 return mb; 259 } 260 261 static Menu createMenu(String name) { 262 Menu m = new Menu(name); 263 m.getStyleClass().add(name); 264 m.getItems().addAll(createMenuContents()); 265 return m; 266 } 267 268 static Node createContextMenu() { 269 Button b = new Button("ContextMenu Right Click Me"); 270 b.setContextMenu(new ContextMenu(createMenuContents())); 271 return b; 272 } 273 274 static Node createInlineMenu(final boolean selectAll) { 275 // create a context menu so we can put it inline in our test page 276 final ContextMenu menu = new ContextMenu(createMenuContents()); 277 // create a place holder container 278 final StackPane contextMenu = new StackPane(); 279 // show context menu then steal and place inline 280 Platform.runLater(() -> { 281 menu.show(contextMenu,-1000,-1000); 282 menu.hide(); 283 Platform.runLater(() -> { 284 final Node menuContent = menu.getSkin().getNode(); 285 contextMenu.getChildren().add(menuContent); 286 menuContent.setMouseTransparent(true); 287 // System.out.println("menuContent = " + menuContent); 288 // System.out.println("menuContent.lookupAll(\".menu-item\") = " + menuContent.lookupAll(".menu-item")); 289 290 // Platform.runLater(new Runnable() { 291 // @Override public void run() { 292 //// if (selectAll) { 293 //// for (Node n: menuContent.lookupAll(".menu-item")) { 294 //// n.pseudoClassStateChanged(PseudoClass.getPseudoClass("hover"), true); 295 //// } 296 //// } else { 297 // new ArrayList<Node>(menuContent.lookupAll(".menu-item")).get(2) 298 // .pseudoClassStateChanged(PseudoClass.getPseudoClass("hover"), true); 299 //// } 300 // } 301 // }); 302 }); 303 }); 304 return contextMenu; 305 } 306 307 static MenuItem[] createMenuContents() { 308 List<MenuItem> menuItems = new ArrayList<>(); 309 final Menu menu11 = new Menu("_New"); 310 MenuItem menu12 = new MenuItem("_Open"); 311 menu12.getStyleClass().add("OpenMenuItem"); 312 menu12.setAccelerator(new KeyCharacterCombination("]", 313 KeyCombination.SHIFT_DOWN, KeyCombination.META_DOWN)); 314 Menu menu13 = new Menu("_Submenu"); 315 MenuItem menu15 = new MenuItem("E_xit"); 316 final String change[] = {"Change Text", "Change Back"}; 317 final MenuItem menu16 = new MenuItem(change[0]); 318 menu16.setAccelerator(KeyCombination.keyCombination("Shortcut+C")); 319 menuItems.add(menu11); 320 menuItems.add(menu12); 321 menuItems.add(menu13); 322 menuItems.add(menu16); 323 menuItems.add(new SeparatorMenuItem()); 324 325 menuItems.add(new CheckMenuItem("Check")); 326 CheckMenuItem checkMenuItem = new CheckMenuItem("Check Selected"); 327 checkMenuItem.setSelected(true); 328 menuItems.add(checkMenuItem); 329 menuItems.add(new SeparatorMenuItem()); 330 menuItems.add(new RadioMenuItem("Radio")); 331 RadioMenuItem radioMenuItem = new RadioMenuItem("Radio Selected"); 332 radioMenuItem.setSelected(true); 333 menuItems.add(radioMenuItem); 334 menuItems.add(new SeparatorMenuItem()); 335 menuItems.add(menu15); 336 337 // --- Menu 11 submenu 338 final MenuItem menu111 = new MenuItem("blah"); 339 final MenuItem menu112 = new MenuItem("foo"); 340 final CheckMenuItem menu113 = new CheckMenuItem("Show \"foo\" item"); 341 menu113.setSelected(true); 342 menu113.selectedProperty().addListener(valueModel -> { 343 menu112.setVisible(menu113.isSelected()); 344 System.err.println("MenuItem \"foo\" is now " + (menu112.isVisible() ? "" : "not") + " visible."); 345 }); 346 menu11.getItems().addAll(menu111, menu112, menu113); 347 348 // --- Menu 13 submenu 349 MenuItem menu131 = new MenuItem("Item _1"); 350 MenuItem menu132 = new MenuItem("Item _2"); 351 menu13.getItems().addAll(menu131, menu132); 352 353 return menuItems.toArray(new MenuItem[menuItems.size()]); 354 } 355 356 static final Image recorder48 = new Image(SamplePageHelpers.class.getResource("recorder-icon-48.png").toExternalForm()); 357 358 static ImageView createGraphic() { 359 return new ImageView(recorder48); 360 } 361 362 static Node createGreyButton(double percentageGrey) { 363 int grey = (int)(percentageGrey*255); 364 int percentage = (int)(percentageGrey * 100); 365 StackPane sp = new StackPane(); 366 sp.setStyle("-fx-base: rgba("+grey+","+grey+","+grey+",1); -fx-background-color: -fx-background;"); 367 sp.setPadding(new Insets(8)); 368 sp.getChildren().add(new Button(percentage+"%")); 369 return sp; 370 } 371 }