You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GridBasics.java 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. package com.vaadin.tests.components.grid.basics;
  2. import java.text.DecimalFormat;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.HashMap;
  6. import java.util.HashSet;
  7. import java.util.LinkedHashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Optional;
  11. import java.util.Set;
  12. import java.util.function.Consumer;
  13. import java.util.stream.Stream;
  14. import com.vaadin.annotations.Theme;
  15. import com.vaadin.annotations.Widgetset;
  16. import com.vaadin.data.Binder;
  17. import com.vaadin.data.Binder.Binding;
  18. import com.vaadin.data.converter.StringToIntegerConverter;
  19. import com.vaadin.event.selection.MultiSelectionEvent;
  20. import com.vaadin.event.selection.SingleSelectionEvent;
  21. import com.vaadin.server.VaadinRequest;
  22. import com.vaadin.shared.Registration;
  23. import com.vaadin.shared.data.sort.SortDirection;
  24. import com.vaadin.shared.ui.grid.ColumnResizeMode;
  25. import com.vaadin.shared.ui.grid.HeightMode;
  26. import com.vaadin.tests.components.AbstractTestUIWithLog;
  27. import com.vaadin.ui.Button;
  28. import com.vaadin.ui.Component;
  29. import com.vaadin.ui.Grid;
  30. import com.vaadin.ui.Grid.Column;
  31. import com.vaadin.ui.Grid.SelectionMode;
  32. import com.vaadin.ui.Label;
  33. import com.vaadin.ui.MenuBar;
  34. import com.vaadin.ui.MenuBar.Command;
  35. import com.vaadin.ui.MenuBar.MenuItem;
  36. import com.vaadin.ui.MultiSelect;
  37. import com.vaadin.ui.Notification;
  38. import com.vaadin.ui.Panel;
  39. import com.vaadin.ui.SingleSelect;
  40. import com.vaadin.ui.StyleGenerator;
  41. import com.vaadin.ui.TextField;
  42. import com.vaadin.ui.VerticalLayout;
  43. import com.vaadin.ui.components.grid.DetailsGenerator;
  44. import com.vaadin.ui.components.grid.FooterCell;
  45. import com.vaadin.ui.components.grid.FooterRow;
  46. import com.vaadin.ui.components.grid.HeaderCell;
  47. import com.vaadin.ui.components.grid.HeaderRow;
  48. import com.vaadin.ui.components.grid.MultiSelectionModel;
  49. import com.vaadin.ui.components.grid.MultiSelectionModel.SelectAllCheckBoxVisibility;
  50. import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
  51. import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
  52. import com.vaadin.ui.renderers.DateRenderer;
  53. import com.vaadin.ui.renderers.HtmlRenderer;
  54. import com.vaadin.ui.renderers.NumberRenderer;
  55. import com.vaadin.ui.renderers.ProgressBarRenderer;
  56. @Widgetset("com.vaadin.DefaultWidgetSet")
  57. @Theme("tests-valo-disabled-animations")
  58. public class GridBasics extends AbstractTestUIWithLog {
  59. public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4 = "Row numbers for 3/4";
  60. public static final String ROW_STYLE_GENERATOR_NONE = "None";
  61. public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS = "Row numbers";
  62. public static final String ROW_STYLE_GENERATOR_EMPTY = "Empty string";
  63. public static final String ROW_STYLE_GENERATOR_NULL = "Null";
  64. public static final String CELL_STYLE_GENERATOR_NONE = "None";
  65. public static final String CELL_STYLE_GENERATOR_PROPERTY_TO_STRING = "Property to string";
  66. public static final String CELL_STYLE_GENERATOR_SPECIAL = "Special for 1/4 Column 1";
  67. public static final String CELL_STYLE_GENERATOR_EMPTY = "Empty string";
  68. public static final String CELL_STYLE_GENERATOR_NULL = "Null";
  69. private boolean isUserSelectionDisallowed;
  70. public static final String[] COLUMN_CAPTIONS = { "Column 0", "Column 1",
  71. "Column 2", "Row Number", "Date", "HTML String", "Big Random",
  72. "Small Random" };
  73. private final Command toggleReorderListenerCommand = new Command() {
  74. private Registration registration = null;
  75. @Override
  76. public void menuSelected(MenuItem selectedItem) {
  77. removeRegistration();
  78. if (selectedItem.isChecked()) {
  79. registration = grid.addColumnReorderListener(event -> {
  80. List<String> columnCaptions = new ArrayList<>();
  81. for (Column<DataObject, ?> column : grid.getColumns()) {
  82. columnCaptions.add(column.getCaption());
  83. }
  84. log("Columns reordered, userOriginated: "
  85. + event.isUserOriginated());
  86. log("Column order: " + columnCaptions);
  87. });
  88. log("Registered a column reorder listener.");
  89. }
  90. }
  91. private void removeRegistration() {
  92. if (registration != null) {
  93. registration.remove();
  94. registration = null;
  95. log("Removed a column reorder listener.");
  96. }
  97. }
  98. };
  99. private static class DetailedDetailsGenerator
  100. implements DetailsGenerator<DataObject> {
  101. @Override
  102. public Component apply(DataObject dataObj) {
  103. VerticalLayout cssLayout = new VerticalLayout();
  104. cssLayout.setHeight("200px");
  105. cssLayout.setWidth("100%");
  106. cssLayout.addComponent(
  107. new Label("Row Number: " + dataObj.getRowNumber()));
  108. cssLayout.addComponent(new Label("Date: " + dataObj.getDate()));
  109. cssLayout.addComponent(
  110. new Label("Big Random: " + dataObj.getBigRandom()));
  111. cssLayout.addComponent(
  112. new Label("Small Random: " + dataObj.getSmallRandom()));
  113. cssLayout
  114. .addComponent(new Button("Press me",
  115. e -> Notification.show("You clicked on the "
  116. + "button in the details for " + "row "
  117. + dataObj.getRowNumber())));
  118. return cssLayout;
  119. }
  120. }
  121. private static class PersistingDetailsGenerator
  122. implements DetailsGenerator<DataObject> {
  123. private Map<DataObject, Panel> detailsMap = new HashMap<>();
  124. @Override
  125. public Component apply(DataObject dataObj) {
  126. if (!detailsMap.containsKey(dataObj)) {
  127. Panel panel = new Panel();
  128. panel.setContent(new Label("One"));
  129. detailsMap.put(dataObj, panel);
  130. }
  131. return detailsMap.get(dataObj);
  132. }
  133. public void changeDetailsComponent(MenuItem item) {
  134. for (DataObject id : detailsMap.keySet()) {
  135. Panel panel = detailsMap.get(id);
  136. Label label = (Label) panel.getContent();
  137. if (label.getValue().equals("One")) {
  138. panel.setContent(new Label("Two"));
  139. } else {
  140. panel.setContent(new Label("One"));
  141. }
  142. }
  143. }
  144. }
  145. private Grid<DataObject> grid;
  146. private Map<String, DetailsGenerator<DataObject>> generators = new LinkedHashMap<>();
  147. private List<DataObject> data;
  148. private int watchingCount = 0;
  149. private PersistingDetailsGenerator persistingDetails;
  150. private List<Column<DataObject, ?>> initialColumnOrder;
  151. private Registration selectionListenerRegistration;
  152. public GridBasics() {
  153. generators.put("NULL", null);
  154. generators.put("Detailed", new DetailedDetailsGenerator());
  155. generators
  156. .put("\"Watching\"",
  157. dataObj -> new Label("You are watching item id "
  158. + dataObj.getRowNumber() + " ("
  159. + watchingCount++ + ")"));
  160. persistingDetails = new PersistingDetailsGenerator();
  161. generators.put("Persisting", persistingDetails);
  162. }
  163. @Override
  164. protected void setup(VaadinRequest request) {
  165. data = DataObject.generateObjects();
  166. VerticalLayout layout = new VerticalLayout();
  167. layout.setSpacing(true);
  168. layout.setSizeFull();
  169. // Create grid
  170. grid = new Grid<>();
  171. grid.setItems(data);
  172. grid.setSizeFull();
  173. Binder<DataObject> binder = grid.getEditor().getBinder();
  174. TextField html = new TextField();
  175. TextField smallRandom = new TextField();
  176. TextField coordinates = new TextField();
  177. TextField rowNumber = new TextField();
  178. Binding<DataObject, Integer> smallRandomBinding = binder
  179. .forField(smallRandom)
  180. .withConverter(new StringToIntegerConverter(
  181. "Could not convert value to Integer"))
  182. .withValidator(i -> i >= 0 && i < 5,
  183. "Small random needs to be in range [0..5)")
  184. .bind(DataObject::getSmallRandom, DataObject::setSmallRandom);
  185. Binding<DataObject, Integer> rowNumberBinding = binder
  186. .forField(rowNumber)
  187. .withConverter(new StringToIntegerConverter(
  188. "Could not convert value to Integer"))
  189. .bind(DataObject::getRowNumber, DataObject::setRowNumber);
  190. grid.addColumn(DataObject::getCoordinates)
  191. .setCaption(COLUMN_CAPTIONS[0])
  192. .setEditorComponent(coordinates, DataObject::setCoordinates);
  193. grid.addColumn(dataObj -> "(" + dataObj.getRowNumber() + ", 1)")
  194. .setCaption(COLUMN_CAPTIONS[1]);
  195. grid.addColumn(dataObj -> "(" + dataObj.getRowNumber() + ", 2)")
  196. .setCaption(COLUMN_CAPTIONS[2]);
  197. grid.addColumn(DataObject::getRowNumber, new NumberRenderer())
  198. .setCaption(COLUMN_CAPTIONS[3])
  199. .setEditorBinding(rowNumberBinding);
  200. grid.addColumn(DataObject::getDate, new DateRenderer())
  201. .setCaption(COLUMN_CAPTIONS[4]);
  202. grid.addColumn(DataObject::getHtmlString, new HtmlRenderer())
  203. .setCaption(COLUMN_CAPTIONS[5])
  204. .setEditorComponent(html, DataObject::setHtmlString);
  205. grid.addColumn(DataObject::getBigRandom, new NumberRenderer())
  206. .setCaption(COLUMN_CAPTIONS[6]);
  207. grid.addColumn(data -> data.getSmallRandom() / 5d,
  208. new ProgressBarRenderer()).setCaption(COLUMN_CAPTIONS[7])
  209. .setEditorBinding(smallRandomBinding);
  210. selectionListenerRegistration = ((SingleSelectionModelImpl<DataObject>) grid
  211. .getSelectionModel())
  212. .addSingleSelectionListener(this::onSingleSelect);
  213. grid.addColumnResizeListener(
  214. event -> log("ColumnResizeEvent: isUserOriginated? "
  215. + event.isUserOriginated()));
  216. grid.addSortListener(event -> log(
  217. "SortEvent: isUserOriginated? " + event.isUserOriginated()));
  218. layout.addComponent(
  219. createMenu());
  220. layout.addComponent(grid);
  221. addComponent(layout);
  222. }
  223. private void onSingleSelect(SingleSelectionEvent<DataObject> event) {
  224. log("SingleSelectionEvent: Selected: "
  225. + (event.getSelectedItem().isPresent()
  226. ? event.getSelectedItem().get().toString()
  227. : "none"));
  228. }
  229. private void onMultiSelect(MultiSelectionEvent<DataObject> event) {
  230. Optional<DataObject> firstAdded = event.getAddedSelection().stream()
  231. .findFirst();
  232. Optional<DataObject> firstRemoved = event.getRemovedSelection().stream()
  233. .findFirst();
  234. String addedRow = firstAdded.isPresent() ? firstAdded.get().toString()
  235. : "none";
  236. String removedRow = firstRemoved.isPresent()
  237. ? firstRemoved.get().toString()
  238. : "none";
  239. log("SelectionEvent: Added " + addedRow + ", Removed " + removedRow);
  240. }
  241. private Component createMenu() {
  242. MenuBar menu = new MenuBar();
  243. menu.setErrorHandler(error -> log("Exception occurred, "
  244. + error.getThrowable().getClass().getName() + ": "
  245. + error.getThrowable().getMessage()));
  246. MenuItem componentMenu = menu.addItem("Component", null);
  247. createStateMenu(componentMenu.addItem("State", null));
  248. createSizeMenu(componentMenu.addItem("Size", null));
  249. createDetailsMenu(componentMenu.addItem("Details", null));
  250. createBodyMenu(componentMenu.addItem("Body rows", null));
  251. createHeaderMenu(componentMenu.addItem("Header", null));
  252. createFooterMenu(componentMenu.addItem("Footer", null));
  253. createColumnsMenu(componentMenu.addItem("Columns", null));
  254. createEditorMenu(componentMenu.addItem("Editor", null));
  255. return menu;
  256. }
  257. @SuppressWarnings("unchecked")
  258. private void createColumnsMenu(MenuItem columnsMenu) {
  259. for (Column<DataObject, ?> col : grid.getColumns()) {
  260. MenuItem columnMenu = columnsMenu.addItem(col.getCaption(), null);
  261. columnMenu.addItem("Move left", selectedItem -> {
  262. int index = grid.getColumns().indexOf(col);
  263. if (index > 0) {
  264. List<Column<DataObject, ?>> columnOrder = new ArrayList<>(
  265. grid.getColumns());
  266. Collections.swap(columnOrder, index, index - 1);
  267. grid.setColumnOrder(columnOrder
  268. .toArray(new Column[columnOrder.size()]));
  269. }
  270. });
  271. columnMenu.addItem("Move right", selectedItem -> {
  272. int index = grid.getColumns().indexOf(col);
  273. if (index < grid.getColumns().size() - 1) {
  274. List<Column<DataObject, ?>> columnOrder = new ArrayList<>(
  275. grid.getColumns());
  276. Collections.swap(columnOrder, index, index + 1);
  277. grid.setColumnOrder(columnOrder
  278. .toArray(new Column[columnOrder.size()]));
  279. }
  280. });
  281. MenuItem headerTypeMenu = columnMenu.addItem("Header Type", null);
  282. headerTypeMenu.addItem("Text Header", selectedItem -> grid
  283. .getDefaultHeaderRow().getCell(col).setText("Text Header"));
  284. headerTypeMenu.addItem("HTML Header",
  285. selectedItem -> grid.getDefaultHeaderRow().getCell(col)
  286. .setHtml("<b>HTML Header</b>"));
  287. headerTypeMenu.addItem("Widget Header", selectedItem -> {
  288. final Button button = new Button("Button Header");
  289. button.addClickListener(clickEvent -> log("Button clicked!"));
  290. grid.getDefaultHeaderRow().getCell(col).setComponent(button);
  291. });
  292. MenuItem footerTypeMenu = columnMenu.addItem("Footer Type", null);
  293. footerTypeMenu.addItem("Text Footer", selectedItem -> grid
  294. .getFooterRow(0).getCell(col).setText("Text Footer"));
  295. footerTypeMenu.addItem("HTML Footer",
  296. selectedItem -> grid.getFooterRow(0).getCell(col)
  297. .setHtml("<b>HTML Footer</b>"));
  298. footerTypeMenu.addItem("Widget Footer", selectedItem -> {
  299. final Button button = new Button("Button Footer");
  300. button.addClickListener(clickEvent -> log("Button clicked!"));
  301. grid.getFooterRow(0).getCell(col).setComponent(button);
  302. });
  303. columnMenu
  304. .addItem("Sortable",
  305. selectedItem -> col
  306. .setSortable(selectedItem.isChecked()))
  307. .setCheckable(true);
  308. columnMenu
  309. .addItem("Hidable",
  310. selectedItem -> col
  311. .setHidable(selectedItem.isChecked()))
  312. .setCheckable(true);
  313. columnMenu
  314. .addItem("Hidden",
  315. selectedItem -> col
  316. .setHidden(selectedItem.isChecked()))
  317. .setCheckable(true);
  318. columnMenu.addItem("Remove",
  319. selectedItem -> grid.removeColumn(col));
  320. columnMenu.addItem("Sort ASC", item -> grid.sort(col));
  321. columnMenu.addItem("Sort DESC",
  322. item -> grid.sort(col, SortDirection.DESCENDING));
  323. }
  324. columnsMenu.addItem("Clear sort", item -> grid.clearSortOrder());
  325. columnsMenu
  326. .addItem("Simple resize mode",
  327. item -> grid.setColumnResizeMode(
  328. item.isChecked() ? ColumnResizeMode.SIMPLE
  329. : ColumnResizeMode.ANIMATED))
  330. .setCheckable(true);
  331. }
  332. private void createSizeMenu(MenuItem sizeMenu) {
  333. MenuItem heightByRows = sizeMenu.addItem("Height by Rows", null);
  334. DecimalFormat df = new DecimalFormat("0.00");
  335. Stream.of(0.33, 0.67, 1.00, 1.33, 1.67, 2.00, 2.33, 2.67, 3.00, 3.33,
  336. 3.67, 4.00, 4.33, 4.67)
  337. .forEach(d -> addGridMethodMenu(heightByRows,
  338. df.format(d) + " rows", d, grid::setHeightByRows));
  339. sizeMenu.addItem("HeightMode Row", item -> {
  340. grid.setHeightMode(
  341. item.isChecked() ? HeightMode.ROW : HeightMode.CSS);
  342. }).setCheckable(true);
  343. MenuItem heightMenu = sizeMenu.addItem("Height", null);
  344. Stream.of(50, 100, 200, 400).map(i -> i + "px").forEach(
  345. i -> addGridMethodMenu(heightMenu, i, i, grid::setHeight));
  346. MenuItem rowHeightMenu = sizeMenu.addItem("Row Height", null);
  347. Stream.of(-1, 20, 40, 100).forEach(i -> addGridMethodMenu(rowHeightMenu,
  348. String.valueOf(i), (double) i, grid::setRowHeight));
  349. }
  350. private void createStateMenu(MenuItem stateMenu) {
  351. MenuItem tabIndexMenu = stateMenu.addItem("Tab index", null);
  352. addGridMethodMenu(tabIndexMenu, "0", 0, grid::setTabIndex);
  353. addGridMethodMenu(tabIndexMenu, "-1", -1, grid::setTabIndex);
  354. addGridMethodMenu(tabIndexMenu, "10", 10, grid::setTabIndex);
  355. MenuItem frozenColMenu = stateMenu.addItem("Frozen column count", null);
  356. for (int i = -1; i < 3; ++i) {
  357. addGridMethodMenu(frozenColMenu, "" + i, i,
  358. grid::setFrozenColumnCount);
  359. }
  360. createRowStyleMenu(stateMenu.addItem("Row style generator", null));
  361. createCellStyleMenu(stateMenu.addItem("Cell style generator", null));
  362. stateMenu.addItem("Row description generator",
  363. item -> grid.setDescriptionGenerator(item.isChecked()
  364. ? t -> "Row tooltip for row " + t.getRowNumber()
  365. : null))
  366. .setCheckable(true);
  367. stateMenu.addItem("Cell description generator",
  368. item -> grid.getColumns().stream().findFirst().ifPresent(
  369. c -> c.setDescriptionGenerator(item.isChecked()
  370. ? t -> "Cell tooltip for row "
  371. + t.getRowNumber() + ", Column 0"
  372. : null)))
  373. .setCheckable(true);
  374. stateMenu.addItem("Item click listener", new Command() {
  375. private Registration registration = null;
  376. @Override
  377. public void menuSelected(MenuItem selectedItem) {
  378. removeRegistration();
  379. if (selectedItem.isChecked()) {
  380. registration = grid.addItemClickListener(e -> {
  381. grid.setDetailsVisible(e.getItem(),
  382. !grid.isDetailsVisible(e.getItem()));
  383. log("Item click on row " + e.getItem().getRowNumber()
  384. + ", Column '" + e.getColumn().getCaption()
  385. + "'");
  386. });
  387. log("Registered an item click listener.");
  388. }
  389. }
  390. private void removeRegistration() {
  391. if (registration != null) {
  392. registration.remove();
  393. registration = null;
  394. log("Removed an item click listener.");
  395. }
  396. }
  397. }).setCheckable(true);
  398. MenuItem selectionAllowedItem = stateMenu
  399. .addItem("Disallow user selection", item -> {
  400. isUserSelectionDisallowed = !isUserSelectionDisallowed;
  401. if (grid.getSelectionModel() instanceof MultiSelectionModelImpl) {
  402. MultiSelect<DataObject> multiSelect = grid
  403. .asMultiSelect();
  404. multiSelect.setReadOnly(isUserSelectionDisallowed);
  405. }
  406. if (grid.getSelectionModel() instanceof SingleSelectionModelImpl) {
  407. SingleSelect<DataObject> singleSelect = grid
  408. .asSingleSelect();
  409. singleSelect.setReadOnly(isUserSelectionDisallowed);
  410. }
  411. });
  412. selectionAllowedItem.setChecked(false);
  413. selectionAllowedItem.setCheckable(true);
  414. stateMenu.addItem("Column reorder listener",
  415. toggleReorderListenerCommand).setCheckable(true);
  416. stateMenu
  417. .addItem("Column Reordering", selectedItem -> grid
  418. .setColumnReorderingAllowed(selectedItem.isChecked()))
  419. .setCheckable(true);
  420. MenuItem enableItem = stateMenu.addItem("Enabled",
  421. e -> grid.setEnabled(e.isChecked()));
  422. enableItem.setCheckable(true);
  423. enableItem.setChecked(true);
  424. createSelectionMenu(stateMenu);
  425. stateMenu.addItem("Set focus", item -> grid.focus());
  426. }
  427. private void createRowStyleMenu(MenuItem rowStyleMenu) {
  428. addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_NONE,
  429. (StyleGenerator<DataObject>) t -> null,
  430. grid::setStyleGenerator);
  431. addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_ROW_NUMBERS,
  432. t -> "row" + t.getRowNumber(), grid::setStyleGenerator);
  433. addGridMethodMenu(rowStyleMenu,
  434. ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4,
  435. t -> t.getRowNumber() % 4 != 0 ? "row" + t.getRowNumber()
  436. : null,
  437. grid::setStyleGenerator);
  438. addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_EMPTY, t -> "",
  439. grid::setStyleGenerator);
  440. addGridMethodMenu(rowStyleMenu, ROW_STYLE_GENERATOR_NULL, t -> null,
  441. grid::setStyleGenerator);
  442. }
  443. private void createCellStyleMenu(MenuItem cellStyleMenu) {
  444. addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_NONE,
  445. (StyleGenerator<DataObject>) t -> null,
  446. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
  447. addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_EMPTY,
  448. (StyleGenerator<DataObject>) t -> "",
  449. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
  450. addGridMethodMenu(cellStyleMenu,
  451. CELL_STYLE_GENERATOR_PROPERTY_TO_STRING,
  452. (StyleGenerator<DataObject>) t -> null,
  453. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(
  454. t -> c.getCaption().replaceAll(" ", "-"))));
  455. addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_SPECIAL,
  456. (StyleGenerator<DataObject>) t -> null,
  457. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(t -> {
  458. if (t.getRowNumber() % 4 == 1) {
  459. return null;
  460. } else if (t.getRowNumber() % 4 == 3
  461. && c.getCaption().equals("Column 1")) {
  462. return null;
  463. }
  464. return c.getCaption().replaceAll(" ", "_");
  465. })));
  466. addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_NULL,
  467. (StyleGenerator<DataObject>) t -> null,
  468. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
  469. }
  470. private <T> void addGridMethodMenu(MenuItem parent, String name, T value,
  471. Consumer<T> method) {
  472. parent.addItem(name, menuItem -> method.accept(value));
  473. }
  474. private void createBodyMenu(MenuItem rowMenu) {
  475. rowMenu.addItem("Toggle first row selection", menuItem -> {
  476. DataObject item = data.get(0);
  477. if (grid.getSelectionModel().isSelected(item)) {
  478. grid.getSelectionModel().deselect(item);
  479. } else {
  480. grid.getSelectionModel().select(item);
  481. }
  482. });
  483. rowMenu.addItem("Deselect all", menuItem -> {
  484. grid.getSelectionModel().deselectAll();
  485. });
  486. MenuItem rowHeight = rowMenu.addItem("Body Row Height", null);
  487. Stream.of(-1, 20, 50, 100).forEach(i -> rowHeight.addItem("" + i,
  488. menuItem -> grid.setBodyRowHeight(i)));
  489. }
  490. private void createSelectionMenu(MenuItem stateItem) {
  491. MenuItem selectionModelItem = stateItem.addItem("Selection model",
  492. null);
  493. selectionModelItem.addItem("single", menuItem -> {
  494. selectionListenerRegistration.remove();
  495. grid.setSelectionMode(SelectionMode.SINGLE);
  496. selectionListenerRegistration = ((SingleSelectionModelImpl<DataObject>) grid
  497. .getSelectionModel())
  498. .addSingleSelectionListener(this::onSingleSelect);
  499. grid.asSingleSelect().setReadOnly(isUserSelectionDisallowed);
  500. });
  501. selectionModelItem.addItem("multi", menuItem -> {
  502. switchToMultiSelect();
  503. });
  504. selectionModelItem.addItem("none", menuItem -> {
  505. selectionListenerRegistration.remove();
  506. grid.setSelectionMode(SelectionMode.NONE);
  507. });
  508. selectionModelItem.addItem("Select All", menuItem -> {
  509. switchToMultiSelect();
  510. ((MultiSelectionModel<DataObject>) grid.getSelectionModel())
  511. .selectAll();
  512. });
  513. selectionModelItem.addItem("Deselect All", menuItem -> {
  514. switchToMultiSelect();
  515. ((MultiSelectionModel<DataObject>) grid.getSelectionModel())
  516. .deselectAll();
  517. });
  518. selectionModelItem.addItem("SelectAllCheckbox: Visible", menuItem -> {
  519. switchToMultiSelect();
  520. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  521. .setSelectAllCheckBoxVisibility(
  522. SelectAllCheckBoxVisibility.VISIBLE);
  523. });
  524. selectionModelItem.addItem("SelectAllCheckbox: Hidden", menuItem -> {
  525. switchToMultiSelect();
  526. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  527. .setSelectAllCheckBoxVisibility(
  528. SelectAllCheckBoxVisibility.HIDDEN);
  529. });
  530. selectionModelItem.addItem("SelectAllCheckbox: Default", menuItem -> {
  531. switchToMultiSelect();
  532. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  533. .setSelectAllCheckBoxVisibility(
  534. SelectAllCheckBoxVisibility.DEFAULT);
  535. });
  536. }
  537. private void switchToMultiSelect() {
  538. if (!(grid.getSelectionModel() instanceof MultiSelectionModel)) {
  539. selectionListenerRegistration.remove();
  540. MultiSelectionModelImpl<DataObject> model = (MultiSelectionModelImpl<DataObject>) grid
  541. .setSelectionMode(SelectionMode.MULTI);
  542. model.addMultiSelectionListener(this::onMultiSelect);
  543. grid.asMultiSelect().setReadOnly(isUserSelectionDisallowed);
  544. selectionListenerRegistration = model
  545. .addMultiSelectionListener(this::onMultiSelect);
  546. }
  547. }
  548. private void createHeaderMenu(MenuItem headerMenu) {
  549. headerMenu.addItem("Toggle header visibility",
  550. menuitem -> grid.setHeaderVisible(!grid.isHeaderVisible()));
  551. headerMenu.addItem("Append header row", menuItem -> {
  552. HeaderRow row = grid.appendHeaderRow();
  553. int i = 0;
  554. for (Column<?, ?> column : grid.getColumns()) {
  555. row.getCell(column).setText("Header cell " + i++);
  556. }
  557. });
  558. headerMenu.addItem("Prepend header row", menuItem -> {
  559. HeaderRow row = grid.prependHeaderRow();
  560. int i = 0;
  561. for (Column<?, ?> column : grid.getColumns()) {
  562. row.getCell(column).setText("Header cell " + i++);
  563. }
  564. });
  565. headerMenu.addItem("Remove first header row", menuItem -> {
  566. grid.removeHeaderRow(0);
  567. });
  568. headerMenu.addItem("Set first row as default", menuItem -> {
  569. grid.setDefaultHeaderRow(grid.getHeaderRow(0));
  570. });
  571. headerMenu.addItem("Set no default row", menuItem -> {
  572. grid.setDefaultHeaderRow(null);
  573. });
  574. headerMenu.addItem("Merge Header Cells [0,0..1]", menuItem -> {
  575. mergeHeaderСells(0, "0+1", 0, 1);
  576. });
  577. headerMenu.addItem("Merge Header Cells [1,1..3]", menuItem -> {
  578. mergeHeaderСells(1, "1+2+3", 1, 2, 3);
  579. });
  580. headerMenu.addItem("Merge Header Cells [0,6..7]", menuItem -> {
  581. mergeHeaderСells(0, "6+7", 6, 7);
  582. });
  583. MenuItem rowHeight = headerMenu.addItem("Header Row Height", null);
  584. Stream.of(-1, 20, 50, 100).forEach(i -> rowHeight.addItem("" + i,
  585. menuItem -> grid.setHeaderRowHeight(i)));
  586. }
  587. private void mergeHeaderСells(int rowIndex, String jointCellText,
  588. int... columnIndexes) {
  589. HeaderRow headerRow = grid.getHeaderRow(rowIndex);
  590. List<Column<DataObject, ?>> columns = grid.getColumns();
  591. Set<HeaderCell> toMerge = new HashSet<>();
  592. for (int columnIndex : columnIndexes) {
  593. toMerge.add(headerRow.getCell(columns.get(columnIndex)));
  594. }
  595. headerRow.join(toMerge).setText(jointCellText);
  596. }
  597. private void mergeFooterСells(int rowIndex, String jointCellText,
  598. int... columnIndexes) {
  599. FooterRow footerRow = grid.getFooterRow(rowIndex);
  600. List<Column<DataObject, ?>> columns = grid.getColumns();
  601. Set<FooterCell> toMerge = new HashSet<>();
  602. for (int columnIndex : columnIndexes) {
  603. toMerge.add(footerRow.getCell(columns.get(columnIndex)));
  604. }
  605. footerRow.join(toMerge).setText(jointCellText);
  606. }
  607. private void createFooterMenu(MenuItem footerMenu) {
  608. footerMenu.addItem("Toggle footer visibility",
  609. menuitem -> grid.setFooterVisible(!grid.isFooterVisible()));
  610. footerMenu.addItem("Add default footer row", menuItem -> {
  611. FooterRow defaultFooter = grid.appendFooterRow();
  612. grid.getColumns().forEach(
  613. column -> defaultFooter.getCell(column).setText(grid
  614. .getDefaultHeaderRow().getCell(column).getText()));
  615. footerMenu.removeChild(menuItem);
  616. });
  617. footerMenu.addItem("Append footer row", menuItem -> {
  618. FooterRow row = grid.appendFooterRow();
  619. int i = 0;
  620. for (Column<?, ?> column : grid.getColumns()) {
  621. row.getCell(column).setText("Footer cell " + i++);
  622. }
  623. });
  624. footerMenu.addItem("Prepend footer row", menuItem -> {
  625. FooterRow row = grid.prependFooterRow();
  626. int i = 0;
  627. for (Column<?, ?> column : grid.getColumns()) {
  628. row.getCell(column).setText("Footer cell " + i++);
  629. }
  630. });
  631. footerMenu.addItem("Remove first footer row", menuItem -> {
  632. grid.removeFooterRow(0);
  633. });
  634. footerMenu.addItem("Merge Footer Cells [0,0..1]", menuItem -> {
  635. mergeFooterСells(0, "0+1", 0, 1);
  636. });
  637. footerMenu.addItem("Merge Footer Cells [1,1..3]", menuItem -> {
  638. mergeFooterСells(1, "1+2+3", 1, 2, 3);
  639. });
  640. footerMenu.addItem("Merge Footer Cells [0,6..7]", menuItem -> {
  641. mergeFooterСells(0, "6+7", 6, 7);
  642. });
  643. MenuItem rowHeight = footerMenu.addItem("Footer Row Height", null);
  644. Stream.of(-1, 20, 50, 100).forEach(i -> rowHeight.addItem("" + i,
  645. menuItem -> grid.setFooterRowHeight(i)));
  646. }
  647. /* DetailsGenerator related things */
  648. private void createDetailsMenu(MenuItem detailsMenu) {
  649. MenuItem generatorsMenu = detailsMenu.addItem("Generators", null);
  650. generators.forEach((name, gen) -> generatorsMenu.addItem(name,
  651. item -> grid.setDetailsGenerator(gen)));
  652. generatorsMenu.addItem("- Change Component",
  653. persistingDetails::changeDetailsComponent);
  654. detailsMenu.addItem("Toggle First", item -> {
  655. DataObject first = data.get(0);
  656. openOrCloseDetails(first);
  657. openOrCloseDetails(first);
  658. });
  659. detailsMenu.addItem("Open First", item -> {
  660. DataObject object = data.get(0);
  661. openOrCloseDetails(object);
  662. });
  663. detailsMenu.addItem("Open 1", item -> {
  664. DataObject object = data.get(1);
  665. openOrCloseDetails(object);
  666. });
  667. detailsMenu.addItem("Open 995", item -> {
  668. DataObject object = data.get(995);
  669. openOrCloseDetails(object);
  670. });
  671. }
  672. private void createEditorMenu(MenuItem editorMenu) {
  673. editorMenu
  674. .addItem("Enabled",
  675. i -> grid.getEditor().setEnabled(i.isChecked()))
  676. .setCheckable(true);
  677. MenuItem bufferedMode = editorMenu.addItem("Buffered mode",
  678. i -> grid.getEditor().setBuffered(i.isChecked()));
  679. bufferedMode.setCheckable(true);
  680. bufferedMode.setChecked(true);
  681. editorMenu.addItem("Save", i -> grid.getEditor().save());
  682. editorMenu.addItem("Cancel edit", i -> grid.getEditor().cancel());
  683. Stream.of(0, 5, 100).forEach(i -> editorMenu.addItem("Edit row " + i,
  684. menuItem -> grid.getEditor().editRow(i)));
  685. editorMenu.addItem("Edit last row", menuItem -> grid.getEditor()
  686. .editRow(grid.getDataCommunicator().getDataProviderSize() - 1));
  687. editorMenu.addItem("Change save caption",
  688. e -> grid.getEditor().setSaveCaption("ǝʌɐS"));
  689. editorMenu.addItem("Change cancel caption",
  690. e -> grid.getEditor().setCancelCaption("ʃǝɔuɐↃ"));
  691. }
  692. private void openOrCloseDetails(DataObject dataObj) {
  693. grid.setDetailsVisible(dataObj, !grid.isDetailsVisible(dataObj));
  694. }
  695. }