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 36KB

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