InspectorTable.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. package ui.view.inspector;
  2. import java.awt.BorderLayout;
  3. import java.awt.Color;
  4. import java.awt.Container;
  5. import java.awt.Dimension;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.InputEvent;
  8. import java.awt.event.KeyEvent;
  9. import java.math.RoundingMode;
  10. import java.text.NumberFormat;
  11. import java.util.Collection;
  12. import java.util.Comparator;
  13. import java.util.HashSet;
  14. import java.util.List;
  15. import java.util.Locale;
  16. import java.util.Optional;
  17. import java.util.Set;
  18. import java.util.stream.Collectors;
  19. import java.util.stream.Stream;
  20. import java.util.ArrayList;
  21. import javax.swing.AbstractAction;
  22. import javax.swing.BorderFactory;
  23. import javax.swing.Box;
  24. import javax.swing.BoxLayout;
  25. import javax.swing.ImageIcon;
  26. import javax.swing.JButton;
  27. import javax.swing.JCheckBox;
  28. import javax.swing.JComboBox;
  29. import javax.swing.JFormattedTextField;
  30. import javax.swing.JLabel;
  31. import javax.swing.JPanel;
  32. import javax.swing.JTextField;
  33. import javax.swing.KeyStroke;
  34. import javax.swing.SwingConstants;
  35. import javax.swing.text.NumberFormatter;
  36. import classes.AbstractCanvasObject;
  37. import classes.GroupNode;
  38. import classes.HolonElement;
  39. import classes.HolonElement.Priority;
  40. import classes.HolonObject;
  41. import net.miginfocom.swing.MigLayout;
  42. import ui.controller.Control;
  43. import ui.view.component.TrippleCheckBox;
  44. import ui.view.component.TrippleCheckBox.State;
  45. import utility.ImageImport;
  46. import utility.Pool;
  47. import utility.events.Action;
  48. import utility.listener.SimpleDocumentListener;
  49. public class InspectorTable extends JPanel {
  50. private Pool<ElementRow> rowPool = new Pool<ElementRow>() {
  51. @Override
  52. public ElementRow create() {
  53. return new ElementRow();
  54. }
  55. };
  56. private final int maxDisplayedRowsNumber = 100;
  57. private int actualPage = 0;
  58. private int maxPageNumberForThisSelection = 0;
  59. private Control control;
  60. private final int columnHeight = 20;
  61. // UI
  62. private final TrippleCheckBox selectAllCheckBox = new TrippleCheckBox();
  63. private final JButton addButton = new JButton();
  64. private final JButton duplicateButton = new JButton();
  65. private final JButton deleteButton = new JButton();
  66. private final JPanel buttonPanel = new JPanel();
  67. private final JButton pageIncreaseButton = new JButton();
  68. private final JButton pageDecreaseButton = new JButton();
  69. private final JLabel pageInformationLabel = new JLabel();
  70. private final JPanel pageSelectionPanel = new JPanel();
  71. private ArrayList<SortButton<ElementRow>> headerButtonList = new ArrayList<>();
  72. private final static NumberFormatter doubleFormatter = generateNumberFormatter();
  73. //sorting
  74. private Comparator<ElementRow> actual_comp = (ElementRow a, ElementRow b) -> Float.compare(a.element.getEnergy(), b.element.getEnergy());
  75. // Colors
  76. private final static Color selectedColor = new Color(126, 186, 255);
  77. private final static Color borderColor = new Color(171, 173, 179);
  78. // Events
  79. public Action<Set<HolonElement>> OnElementSelectionChanged = new Action<>();
  80. private Thread populateRowsThread;
  81. private boolean abortThread = false;
  82. public InspectorTable(Control control) {
  83. control.OnSelectionChanged.addListener(() -> updateInspectorUi());
  84. this.control = control;
  85. init();
  86. addHeader();
  87. }
  88. private void init() {
  89. MigLayout layout = new MigLayout("insets 0,gap 0,wrap 7", // Layout Constraints
  90. "[][fill, grow][fill][fill, grow][fill, grow][][fill]", // Column constraints
  91. "[25!][20:20:20]"); // Row constraints
  92. this.setLayout(layout);
  93. initSelectAllCheckBox();
  94. initButtons();
  95. initKeyControls();
  96. initHeaderButtons();
  97. }
  98. private void initKeyControls() {
  99. this.getInputMap(WHEN_IN_FOCUSED_WINDOW)
  100. .put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK), "PageRight");
  101. this.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK),
  102. "PageLeft");
  103. this.getActionMap().put("PageRight", new AbstractAction() {
  104. @Override
  105. public void actionPerformed(ActionEvent e) {
  106. performPageAction(PageAction.Increase);
  107. }
  108. });
  109. this.getActionMap().put("PageLeft", new AbstractAction() {
  110. @Override
  111. public void actionPerformed(ActionEvent e) {
  112. performPageAction(PageAction.Decrease);
  113. }
  114. });
  115. }
  116. private enum PageAction {
  117. Increase, Decrease
  118. };
  119. private void performPageAction(PageAction action) {
  120. int newPageNumber;
  121. switch (action) {
  122. case Decrease:
  123. newPageNumber = Math.max(actualPage - 1, 0);
  124. break;
  125. case Increase:
  126. default:
  127. newPageNumber = Math.min(actualPage + 1, maxPageNumberForThisSelection);
  128. break;
  129. }
  130. if (newPageNumber != actualPage) {
  131. actualPage = newPageNumber;
  132. updateTableUi();
  133. updatePageButtonAppearance();
  134. }
  135. }
  136. private void updatePageButtonAppearance() {
  137. this.pageDecreaseButton.setEnabled(actualPage != 0);
  138. this.pageIncreaseButton.setEnabled(actualPage != maxPageNumberForThisSelection);
  139. }
  140. private static NumberFormatter generateNumberFormatter() {
  141. NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
  142. doubleFormat.setMinimumFractionDigits(1);
  143. doubleFormat.setMaximumFractionDigits(10);
  144. doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
  145. doubleFormat.setGroupingUsed(false);
  146. NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat);
  147. doubleFormatter.setCommitsOnValidEdit(true);
  148. doubleFormatter.setValueClass(Double.class);
  149. return doubleFormatter;
  150. }
  151. private void initHeaderButtons() {
  152. Comparator<ElementRow> objectComp = (ElementRow a, ElementRow b) -> a.element.parentObject.getName().compareTo(b.element.parentObject.getName());
  153. Comparator<ElementRow> idComp = (ElementRow a, ElementRow b) -> Integer.compare(a.element.parentObject.getId(), b.element.parentObject.getId());
  154. Comparator<ElementRow> deviceComp = (ElementRow a, ElementRow b) -> a.element.getName().compareTo(b.element.getName());
  155. Comparator<ElementRow> energyComp = (ElementRow a, ElementRow b) -> Float.compare(a.element.getEnergy(), b.element.getEnergy());
  156. Comparator<ElementRow> priorityComp = (ElementRow a, ElementRow b) -> a.element.getPriority().compareTo(b.element.getPriority());
  157. Comparator<ElementRow> activeComp = (ElementRow a, ElementRow b) -> Boolean.compare(a.element.isActive(), b.element.isActive());
  158. ;
  159. headerButtonList.add(new SortButton<ElementRow>("Object", objectComp));
  160. headerButtonList.add(new SortButton<ElementRow>("Id", idComp));
  161. headerButtonList.add(new SortButton<ElementRow>("Device", deviceComp));
  162. headerButtonList.add(new SortButton<ElementRow>("Energy", energyComp));
  163. headerButtonList.add(new SortButton<ElementRow>("Priority", priorityComp));
  164. headerButtonList.add(new SortButton<ElementRow>("Activ", activeComp));
  165. }
  166. private void addHeader() {
  167. this.add(selectAllCheckBox);
  168. for(SortButton<ElementRow> button : headerButtonList) {
  169. this.add(button);
  170. }
  171. }
  172. private void initSelectAllCheckBox() {
  173. selectAllCheckBox.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
  174. // Pixel Perfect alignment
  175. selectAllCheckBox.setBorder(BorderFactory.createEmptyBorder(2, 3, 0, 0));
  176. selectAllCheckBox.addActionListener(clicked -> {
  177. switch (selectAllCheckBox.getSelectionState()) {
  178. case mid_state_selection:
  179. case selected: {
  180. rowPool.getBorrowedStream().forEach(row -> row.setSelected(false));
  181. duplicateButton.setEnabled(false);
  182. deleteButton.setEnabled(false);
  183. }
  184. break;
  185. case unselected:
  186. // TODO maybe select only current page
  187. if (rowPool.getBorrowedCount() != 0) {
  188. rowPool.getBorrowedStream().forEach(row -> row.setSelected(true));
  189. duplicateButton.setEnabled(true);
  190. deleteButton.setEnabled(true);
  191. }
  192. default:
  193. break;
  194. }
  195. updateElementSelection();
  196. });
  197. }
  198. private void initButtons() {
  199. buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
  200. buttonPanel.add(Box.createRigidArea(new Dimension(2, 0)));
  201. addButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/plus.png", 16, 16)));
  202. addButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  203. addButton.addActionListener(clicked -> {
  204. Optional<HolonObject> last = control.getModel().getSelectedObjects().stream()
  205. .filter(obj -> obj instanceof HolonObject).reduce((prev, next) -> next)
  206. .map(obj -> (HolonObject) obj);
  207. last.ifPresent(obj -> {
  208. obj.addElement(new HolonElement(obj, "Element", 0.0f));
  209. control.calculateStateAndVisualForCurrentTimeStep();
  210. updateInspectorUi();
  211. });
  212. });
  213. buttonPanel.add(addButton);
  214. duplicateButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/duplicate.png", 16, 16)));
  215. duplicateButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  216. duplicateButton.addActionListener(clicked -> {
  217. rowPool.getBorrowedStream().forEach(row -> {
  218. if (row.isSelected()) {
  219. row.element.parentObject.addElement(new HolonElement(row.element));
  220. }
  221. });
  222. control.calculateStateAndVisualForCurrentTimeStep();
  223. updateInspectorUi();
  224. });
  225. buttonPanel.add(duplicateButton);
  226. deleteButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/minus.png", 16, 16)));
  227. deleteButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  228. deleteButton.addActionListener(clicked -> {
  229. rowPool.getBorrowedStream().forEach(row -> {
  230. if (row.isSelected()) {
  231. row.element.parentObject.removeElement(row.element);
  232. }
  233. });
  234. control.calculateStateAndVisualForCurrentTimeStep();
  235. updateInspectorUi();
  236. });
  237. buttonPanel.add(deleteButton);
  238. pageIncreaseButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/page_increase.png", 16, 16)));
  239. ;
  240. pageIncreaseButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  241. pageIncreaseButton.addActionListener(clicked -> this.performPageAction(PageAction.Increase));
  242. pageDecreaseButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/page_decrease.png", 16, 16)));
  243. pageDecreaseButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  244. pageDecreaseButton.addActionListener(clicked -> this.performPageAction(PageAction.Decrease));
  245. pageInformationLabel.setForeground(Color.gray);
  246. pageSelectionPanel.setLayout(new BoxLayout(pageSelectionPanel, BoxLayout.LINE_AXIS));
  247. pageSelectionPanel.add(Box.createRigidArea(new Dimension(2, 0)));
  248. pageSelectionPanel.add(this.pageInformationLabel);
  249. pageSelectionPanel.add(Box.createHorizontalGlue());
  250. pageSelectionPanel.add(this.pageDecreaseButton);
  251. pageSelectionPanel.add(this.pageIncreaseButton);
  252. }
  253. private void assignElementsToRowPool(Set<AbstractCanvasObject> selection) {
  254. List<HolonElement> elementList = extractElements(selection).toList();
  255. rowPool.clear();
  256. for (HolonElement element : elementList) {
  257. ElementRow row = rowPool.get();
  258. row.setElement(element);
  259. }
  260. actualPage = 0;
  261. this.maxPageNumberForThisSelection = elementList.size() / this.maxDisplayedRowsNumber;
  262. updatePageButtonAppearance();
  263. }
  264. private void updateTableUi() {
  265. // Maybe abort current thread and join them
  266. if (populateRowsThread != null) {
  267. try {
  268. abortThread = true;
  269. populateRowsThread.join();
  270. populateRowsThread.join();
  271. abortThread = false;
  272. } catch (InterruptedException e) {
  273. e.printStackTrace();
  274. }
  275. }
  276. populateRowsThread = new Thread(() -> {
  277. int numberOfRows = rowPool.getBorrowedCount();
  278. this.removeAll();
  279. addHeader();
  280. rowPool.getBorrowedStream().sorted(actual_comp).skip(actualPage * maxDisplayedRowsNumber).limit(maxDisplayedRowsNumber)
  281. .takeWhile(row -> !abortThread).forEach(row -> {
  282. row.addContainerToInspector();
  283. });
  284. if (numberOfRows > maxDisplayedRowsNumber) {
  285. int lastDisplayedElementNumber = Math.min(numberOfRows, (actualPage + 1) * maxDisplayedRowsNumber);
  286. pageInformationLabel.setText(String.format("%d - %d from %d", 1 + actualPage * maxDisplayedRowsNumber,
  287. lastDisplayedElementNumber, numberOfRows));
  288. this.add(pageSelectionPanel, "span, grow");
  289. }
  290. this.add(buttonPanel, "span");
  291. boolean isAtLeastOneHolonObjectSelected = control.getModel().getSelectedObjects().stream()
  292. .anyMatch(object -> object instanceof HolonObject);
  293. this.addButton.setEnabled(isAtLeastOneHolonObjectSelected);
  294. duplicateButton.setEnabled(false);
  295. deleteButton.setEnabled(false);
  296. selectAllCheckBox.setSelectionState(State.unselected);
  297. revalidate();
  298. repaint();
  299. this.OnElementSelectionChanged.broadcast(new HashSet<HolonElement>());
  300. });
  301. populateRowsThread.start();
  302. }
  303. private void updateInspectorUi() {
  304. // clone for concurrency
  305. Set<AbstractCanvasObject> selection = new HashSet<>(control.getModel().getSelectedObjects());
  306. assignElementsToRowPool(selection);
  307. updateTableUi();
  308. }
  309. private void updateElementSelection() {
  310. Set<HolonElement> eleSet = rowPool.getBorrowedStream().filter(ele -> ele.isSelected()).map(row -> row.element)
  311. .collect(Collectors.toSet());
  312. this.OnElementSelectionChanged.broadcast(eleSet);
  313. }
  314. private void updateButtonAppearance() {
  315. long count = rowPool.getBorrowedStream().filter(ele -> ele.isSelected()).count();
  316. if (count == rowPool.getBorrowedCount()) {
  317. selectAllCheckBox.setSelectionState(State.selected);
  318. } else if (count == 0) {
  319. selectAllCheckBox.setSelectionState(State.unselected);
  320. } else {
  321. selectAllCheckBox.setSelectionState(State.mid_state_selection);
  322. }
  323. duplicateButton.setEnabled(count != 0);
  324. deleteButton.setEnabled(count != 0);
  325. }
  326. // Extract elements from a list of AbstractCanvasObjects
  327. static Stream<HolonElement> extractElements(Collection<AbstractCanvasObject> toInspect) {
  328. Stream<HolonElement> recursiveLayer = toInspect.stream().filter(object -> object instanceof GroupNode)
  329. .flatMap(obj -> extractElements(((GroupNode) obj).getNodes()));
  330. Stream<HolonElement> thisLayer = toInspect.stream().filter(obj -> obj instanceof HolonObject).flatMap(obj -> {
  331. HolonObject ho = (HolonObject) obj;
  332. return ho.getElements().stream();
  333. });
  334. return Stream.concat(thisLayer, recursiveLayer);
  335. }
  336. private class ElementRow {
  337. private HolonElement element = null;
  338. private Container[] cellsInRow = new Container[7];
  339. // TextBoxes
  340. private JTextField elementNameTextField;
  341. private JCheckBox selectionBox;
  342. private JTextField idObjectTextField;
  343. private JFormattedTextField energyTextField;
  344. private JComboBox<Priority> comboBox;
  345. private JCheckBox activeCheckBox;
  346. private JTextField objectNameTextField;
  347. public ElementRow() {
  348. this.createEditFields();
  349. }
  350. public void addContainerToInspector() {
  351. for (Container cell : cellsInRow) {
  352. InspectorTable.this.add(cell);
  353. }
  354. }
  355. public void setSelected(boolean value) {
  356. selectionBox.setSelected(value);
  357. // Color row
  358. for (Container cell : cellsInRow) {
  359. cell.setBackground(selectionBox.isSelected() ? selectedColor : Color.white);
  360. }
  361. }
  362. public boolean isSelected() {
  363. return selectionBox.isSelected();
  364. }
  365. public void setElement(HolonElement element) {
  366. this.element = element;
  367. setSelected(false);
  368. objectNameTextField.setText(this.element.parentObject.getName());
  369. idObjectTextField.setText(Integer.toString(this.element.parentObject.getId()));
  370. elementNameTextField.setText(this.element.getName());
  371. energyTextField.setValue(this.element.getEnergy());
  372. comboBox.setSelectedItem(this.element.getPriority());
  373. activeCheckBox.setSelected(this.element.isActive());
  374. }
  375. private void createEditFields() {
  376. // Selected
  377. JPanel selectedColumnPanel = new JPanel(new BorderLayout());
  378. selectedColumnPanel.setBackground(Color.white);
  379. selectedColumnPanel.setBorder(BorderFactory.createLineBorder(borderColor));
  380. selectionBox = new JCheckBox();
  381. selectionBox.addActionListener(clicked -> {
  382. setSelected(selectionBox.isSelected());
  383. updateButtonAppearance();
  384. updateElementSelection();
  385. });
  386. selectedColumnPanel.setMinimumSize(new Dimension(columnHeight, columnHeight));
  387. selectedColumnPanel.setPreferredSize(new Dimension(columnHeight, columnHeight));
  388. selectedColumnPanel.setMaximumSize(new Dimension(columnHeight, columnHeight));
  389. selectionBox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
  390. selectionBox.setOpaque(false);
  391. selectedColumnPanel.add(selectionBox, BorderLayout.CENTER);
  392. cellsInRow[0] = selectedColumnPanel;
  393. // ObjectName and ID
  394. objectNameTextField = new JTextField();
  395. objectNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
  396. this.element.parentObject.setName(objectNameTextField.getText());
  397. });
  398. objectNameTextField.addActionListener(ae -> updateInspectorUi());
  399. cellsInRow[1] = objectNameTextField;
  400. idObjectTextField = new JTextField();
  401. idObjectTextField.setMinimumSize(idObjectTextField.getPreferredSize());
  402. idObjectTextField.setBackground(Color.white);
  403. idObjectTextField.setEditable(false);
  404. idObjectTextField.setEnabled(false);
  405. cellsInRow[2] = idObjectTextField;
  406. // Name
  407. elementNameTextField = new JTextField();
  408. elementNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
  409. this.element.setEleName(elementNameTextField.getText());
  410. });
  411. elementNameTextField.setBackground(Color.white);
  412. cellsInRow[3] = elementNameTextField;
  413. // Energy
  414. energyTextField = new JFormattedTextField(doubleFormatter);
  415. energyTextField.setInputVerifier(getInputVerifier());
  416. energyTextField.setBackground(Color.white);
  417. energyTextField.addPropertyChangeListener(actionEvent -> {
  418. try {
  419. float energy = Float.parseFloat(energyTextField.getText());
  420. if (this.element.getEnergy() != energy) {
  421. this.element.setEnergyPerElement(energy);
  422. control.calculateStateAndVisualForCurrentTimeStep();
  423. }
  424. } catch (NumberFormatException e) {
  425. // Dont Update
  426. }
  427. });
  428. cellsInRow[4] = energyTextField;
  429. // Priority
  430. comboBox = new JComboBox<Priority>(Priority.values());
  431. comboBox.setBackground(Color.white);
  432. comboBox.setEditable(false);
  433. comboBox.addActionListener(ae -> {
  434. this.element.setPriority((Priority) comboBox.getSelectedItem());
  435. });
  436. cellsInRow[5] = comboBox;
  437. JPanel checkBoxWrapperPanel = new JPanel(new BorderLayout());
  438. checkBoxWrapperPanel.setBorder(BorderFactory.createLineBorder(borderColor));
  439. checkBoxWrapperPanel.setBackground(Color.white);
  440. checkBoxWrapperPanel.setMinimumSize(new Dimension(columnHeight, columnHeight));
  441. checkBoxWrapperPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, columnHeight));
  442. // Active
  443. activeCheckBox = new JCheckBox();
  444. activeCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
  445. activeCheckBox.setOpaque(false);
  446. activeCheckBox.addActionListener(actionEvent -> {
  447. this.element.setActive(activeCheckBox.isSelected());
  448. control.calculateStateAndVisualForCurrentTimeStep();
  449. });
  450. checkBoxWrapperPanel.add(activeCheckBox, BorderLayout.CENTER);
  451. cellsInRow[6] = checkBoxWrapperPanel;
  452. }
  453. }
  454. private enum SortState {
  455. None, Descending, Ascending
  456. };
  457. private class SortButton<T> extends JButton {
  458. private SortState state = SortState.None;
  459. private Comparator<T> comp;
  460. public SortButton(String text, Comparator<T> comp) {
  461. super(text);
  462. this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  463. this.setContentAreaFilled(false);
  464. this.setBorderPainted(false);
  465. this.setFocusPainted(false);
  466. this.setHorizontalAlignment(SwingConstants.LEFT);
  467. this.comp = comp;
  468. this.addActionListener(onClick -> changeStateOnClick());
  469. }
  470. @SuppressWarnings("unchecked")
  471. private void changeStateOnClick() {
  472. setState((this.state == SortState.Ascending) ? SortState.Descending : SortState.Ascending);
  473. headerButtonList.stream().filter(button -> (button !=this)).forEach(button -> button.setState(SortState.None));
  474. actual_comp = (Comparator<ElementRow>) getComp();
  475. updateInspectorUi();
  476. }
  477. public void setState(SortState state) {
  478. this.state = state;
  479. String text = this.getText();
  480. // remove order symbols from text
  481. text = text.replaceAll("\u25bc|\u25b2", "");
  482. // update text
  483. switch (state) {
  484. case Descending:
  485. this.setText(text + "\u25bc");
  486. break;
  487. case Ascending:
  488. this.setText(text + "\u25b2");
  489. break;
  490. case None:
  491. default:
  492. this.setText(text);
  493. break;
  494. }
  495. }
  496. public Comparator<T> getComp(){
  497. switch(state){
  498. case Descending:
  499. return comp.reversed();
  500. case Ascending:
  501. case None:
  502. default:
  503. return comp;
  504. }
  505. }
  506. }
  507. }