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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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",
  340. item -> 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. }
  461. if (t.getRowNumber() % 4 == 3
  462. && c.getCaption().equals("Column 1")) {
  463. return null;
  464. }
  465. return c.getCaption().replaceAll(" ", "_");
  466. })));
  467. addGridMethodMenu(cellStyleMenu, CELL_STYLE_GENERATOR_NULL,
  468. (StyleGenerator<DataObject>) t -> null,
  469. sg -> grid.getColumns().forEach(c -> c.setStyleGenerator(sg)));
  470. }
  471. private <T> void addGridMethodMenu(MenuItem parent, String name, T value,
  472. Consumer<T> method) {
  473. parent.addItem(name, menuItem -> method.accept(value));
  474. }
  475. private void createBodyMenu(MenuItem rowMenu) {
  476. rowMenu.addItem("Toggle first row selection", menuItem -> {
  477. DataObject item = data.get(0);
  478. if (grid.getSelectionModel().isSelected(item)) {
  479. grid.getSelectionModel().deselect(item);
  480. } else {
  481. grid.getSelectionModel().select(item);
  482. }
  483. });
  484. rowMenu.addItem("Deselect all",
  485. menuItem -> grid.getSelectionModel().deselectAll());
  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 -> switchToMultiSelect());
  502. selectionModelItem.addItem("none", menuItem -> {
  503. selectionListenerRegistration.remove();
  504. grid.setSelectionMode(SelectionMode.NONE);
  505. });
  506. selectionModelItem.addItem("Select All", menuItem -> {
  507. switchToMultiSelect();
  508. ((MultiSelectionModel<DataObject>) grid.getSelectionModel())
  509. .selectAll();
  510. });
  511. selectionModelItem.addItem("Deselect All", menuItem -> {
  512. switchToMultiSelect();
  513. ((MultiSelectionModel<DataObject>) grid.getSelectionModel())
  514. .deselectAll();
  515. });
  516. selectionModelItem.addItem("SelectAllCheckbox: Visible", menuItem -> {
  517. switchToMultiSelect();
  518. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  519. .setSelectAllCheckBoxVisibility(
  520. SelectAllCheckBoxVisibility.VISIBLE);
  521. });
  522. selectionModelItem.addItem("SelectAllCheckbox: Hidden", menuItem -> {
  523. switchToMultiSelect();
  524. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  525. .setSelectAllCheckBoxVisibility(
  526. SelectAllCheckBoxVisibility.HIDDEN);
  527. });
  528. selectionModelItem.addItem("SelectAllCheckbox: Default", menuItem -> {
  529. switchToMultiSelect();
  530. ((MultiSelectionModelImpl<DataObject>) grid.getSelectionModel())
  531. .setSelectAllCheckBoxVisibility(
  532. SelectAllCheckBoxVisibility.DEFAULT);
  533. });
  534. }
  535. private void switchToMultiSelect() {
  536. if (!(grid.getSelectionModel() instanceof MultiSelectionModel)) {
  537. selectionListenerRegistration.remove();
  538. MultiSelectionModelImpl<DataObject> model = (MultiSelectionModelImpl<DataObject>) grid
  539. .setSelectionMode(SelectionMode.MULTI);
  540. model.addMultiSelectionListener(this::onMultiSelect);
  541. grid.asMultiSelect().setReadOnly(isUserSelectionDisallowed);
  542. selectionListenerRegistration = model
  543. .addMultiSelectionListener(this::onMultiSelect);
  544. }
  545. }
  546. private void createHeaderMenu(MenuItem headerMenu) {
  547. headerMenu.addItem("Toggle header visibility",
  548. menuitem -> grid.setHeaderVisible(!grid.isHeaderVisible()));
  549. headerMenu.addItem("Append header row", menuItem -> {
  550. HeaderRow row = grid.appendHeaderRow();
  551. int i = 0;
  552. for (Column<?, ?> column : grid.getColumns()) {
  553. row.getCell(column).setText("Header cell " + i++);
  554. }
  555. });
  556. headerMenu.addItem("Prepend header row", menuItem -> {
  557. HeaderRow row = grid.prependHeaderRow();
  558. int i = 0;
  559. for (Column<?, ?> column : grid.getColumns()) {
  560. row.getCell(column).setText("Header cell " + i++);
  561. }
  562. });
  563. headerMenu.addItem("Remove first header row",
  564. menuItem -> grid.removeHeaderRow(0));
  565. headerMenu.addItem("Set first row as default",
  566. menuItem -> grid.setDefaultHeaderRow(grid.getHeaderRow(0)));
  567. headerMenu.addItem("Set no default row",
  568. menuItem -> grid.setDefaultHeaderRow(null));
  569. headerMenu.addItem("Merge Header Cells [0,0..1]",
  570. menuItem -> mergeHeaderСells(0, "0+1", 0, 1));
  571. headerMenu.addItem("Merge Header Cells [1,1..3]",
  572. menuItem -> mergeHeaderСells(1, "1+2+3", 1, 2, 3));
  573. headerMenu.addItem("Merge Header Cells [0,6..7]",
  574. menuItem -> mergeHeaderСells(0, "6+7", 6, 7));
  575. MenuItem rowHeight = headerMenu.addItem("Header Row Height", null);
  576. Stream.of(-1, 20, 50, 100).forEach(i -> rowHeight.addItem("" + i,
  577. menuItem -> grid.setHeaderRowHeight(i)));
  578. }
  579. private void mergeHeaderСells(int rowIndex, String jointCellText,
  580. int... columnIndexes) {
  581. HeaderRow headerRow = grid.getHeaderRow(rowIndex);
  582. List<Column<DataObject, ?>> columns = grid.getColumns();
  583. Set<HeaderCell> toMerge = new HashSet<>();
  584. for (int columnIndex : columnIndexes) {
  585. toMerge.add(headerRow.getCell(columns.get(columnIndex)));
  586. }
  587. headerRow.join(toMerge).setText(jointCellText);
  588. }
  589. private void mergeFooterСells(int rowIndex, String jointCellText,
  590. int... columnIndexes) {
  591. FooterRow footerRow = grid.getFooterRow(rowIndex);
  592. List<Column<DataObject, ?>> columns = grid.getColumns();
  593. Set<FooterCell> toMerge = new HashSet<>();
  594. for (int columnIndex : columnIndexes) {
  595. toMerge.add(footerRow.getCell(columns.get(columnIndex)));
  596. }
  597. footerRow.join(toMerge).setText(jointCellText);
  598. }
  599. private void createFooterMenu(MenuItem footerMenu) {
  600. footerMenu.addItem("Toggle footer visibility",
  601. menuitem -> grid.setFooterVisible(!grid.isFooterVisible()));
  602. footerMenu.addItem("Add default footer row", menuItem -> {
  603. FooterRow defaultFooter = grid.appendFooterRow();
  604. grid.getColumns().forEach(
  605. column -> defaultFooter.getCell(column).setText(grid
  606. .getDefaultHeaderRow().getCell(column).getText()));
  607. footerMenu.removeChild(menuItem);
  608. });
  609. footerMenu.addItem("Append footer row", menuItem -> {
  610. FooterRow row = grid.appendFooterRow();
  611. int i = 0;
  612. for (Column<?, ?> column : grid.getColumns()) {
  613. row.getCell(column).setText("Footer cell " + i++);
  614. }
  615. });
  616. footerMenu.addItem("Prepend footer row", menuItem -> {
  617. FooterRow row = grid.prependFooterRow();
  618. int i = 0;
  619. for (Column<?, ?> column : grid.getColumns()) {
  620. row.getCell(column).setText("Footer cell " + i++);
  621. }
  622. });
  623. footerMenu.addItem("Remove first footer row",
  624. menuItem -> grid.removeFooterRow(0));
  625. footerMenu.addItem("Merge Footer Cells [0,0..1]",
  626. menuItem -> mergeFooterСells(0, "0+1", 0, 1));
  627. footerMenu.addItem("Merge Footer Cells [1,1..3]",
  628. menuItem -> mergeFooterСells(1, "1+2+3", 1, 2, 3));
  629. footerMenu.addItem("Merge Footer Cells [0,6..7]",
  630. menuItem -> mergeFooterСells(0, "6+7", 6, 7));
  631. MenuItem rowHeight = footerMenu.addItem("Footer Row Height", null);
  632. Stream.of(-1, 20, 50, 100).forEach(i -> rowHeight.addItem("" + i,
  633. menuItem -> grid.setFooterRowHeight(i)));
  634. }
  635. /* DetailsGenerator related things */
  636. private void createDetailsMenu(MenuItem detailsMenu) {
  637. MenuItem generatorsMenu = detailsMenu.addItem("Generators", null);
  638. generators.forEach((name, gen) -> generatorsMenu.addItem(name,
  639. item -> grid.setDetailsGenerator(gen)));
  640. generatorsMenu.addItem("- Change Component",
  641. persistingDetails::changeDetailsComponent);
  642. detailsMenu.addItem("Toggle First", item -> {
  643. DataObject first = data.get(0);
  644. openOrCloseDetails(first);
  645. openOrCloseDetails(first);
  646. });
  647. detailsMenu.addItem("Open First", item -> {
  648. DataObject object = data.get(0);
  649. openOrCloseDetails(object);
  650. });
  651. detailsMenu.addItem("Open 1", item -> {
  652. DataObject object = data.get(1);
  653. openOrCloseDetails(object);
  654. });
  655. detailsMenu.addItem("Open 995", item -> {
  656. DataObject object = data.get(995);
  657. openOrCloseDetails(object);
  658. });
  659. }
  660. private void createEditorMenu(MenuItem editorMenu) {
  661. editorMenu
  662. .addItem("Enabled",
  663. i -> grid.getEditor().setEnabled(i.isChecked()))
  664. .setCheckable(true);
  665. MenuItem bufferedMode = editorMenu.addItem("Buffered mode",
  666. i -> grid.getEditor().setBuffered(i.isChecked()));
  667. bufferedMode.setCheckable(true);
  668. bufferedMode.setChecked(true);
  669. editorMenu.addItem("Save", i -> grid.getEditor().save());
  670. editorMenu.addItem("Cancel edit", i -> grid.getEditor().cancel());
  671. Stream.of(0, 5, 100).forEach(i -> editorMenu.addItem("Edit row " + i,
  672. menuItem -> grid.getEditor().editRow(i)));
  673. editorMenu.addItem("Edit last row", menuItem -> grid.getEditor()
  674. .editRow(grid.getDataCommunicator().getDataProviderSize() - 1));
  675. editorMenu.addItem("Change save caption",
  676. e -> grid.getEditor().setSaveCaption("ǝʌɐS"));
  677. editorMenu.addItem("Change cancel caption",
  678. e -> grid.getEditor().setCancelCaption("ʃǝɔuɐↃ"));
  679. }
  680. private void openOrCloseDetails(DataObject dataObj) {
  681. grid.setDetailsVisible(dataObj, !grid.isDetailsVisible(dataObj));
  682. }
  683. }