123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- package ui.view.inspector;
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Container;
- import java.awt.Dimension;
- import java.math.RoundingMode;
- import java.text.NumberFormat;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Locale;
- import java.util.Optional;
- import java.util.Set;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- import javax.swing.BorderFactory;
- import javax.swing.Box;
- import javax.swing.BoxLayout;
- import javax.swing.ImageIcon;
- import javax.swing.JButton;
- import javax.swing.JCheckBox;
- import javax.swing.JComboBox;
- import javax.swing.JFormattedTextField;
- import javax.swing.JLabel;
- import javax.swing.JPanel;
- import javax.swing.JTextField;
- import javax.swing.text.NumberFormatter;
- import classes.AbstractCanvasObject;
- import classes.GroupNode;
- import classes.HolonElement;
- import classes.HolonElement.Priority;
- import classes.HolonObject;
- import net.miginfocom.swing.MigLayout;
- import ui.controller.Control;
- import ui.view.component.TrippleCheckBox;
- import ui.view.component.TrippleCheckBox.State;
- import utility.ImageImport;
- import utility.events.Action;
- import utility.events.SimpleDocumentListener;
- public class InspectorTable extends JPanel {
- private List<ElementRow> elementRows = new ArrayList<ElementRow>();
- private Control control;
- private final int columnHeight = 20;
- //UI
- private final TrippleCheckBox selectAllCheckBox = new TrippleCheckBox();
- private final JButton addButton = new JButton();
- private final JButton duplicateButton = new JButton();
- private final JButton deleteButton = new JButton();
- private final JPanel buttonPanel = new JPanel();
- private final static NumberFormatter doubleFormatter = generateNumberFormatter();
-
- //Colors
- private final static Color selectedColor = new Color(126, 186, 255);
- private final static Color borderColor = new Color(171, 173, 179);
- //Events
- public Action<Set<HolonElement>> OnElementSelectionChanged = new Action<>();
- public InspectorTable(Control control) {
- control.OnSelectionChanged.addListener(() -> update_ui());
- this.control = control;
- init();
- generateHeader();
- }
- private void init() {
- MigLayout layout = new MigLayout("insets 0,gap 0,wrap 7", // Layout Constraints
- "[][fill, grow][][fill, grow][fill, grow][][]", // Column constraints
- "[25!][20:20:20]"); // Row constraints
- this.setLayout(layout);
- initSelectAllCheckBox();
- initButtonPanel();
- }
- private static NumberFormatter generateNumberFormatter() {
- NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
- doubleFormat.setMinimumFractionDigits(1);
- doubleFormat.setMaximumFractionDigits(10);
- doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
- doubleFormat.setGroupingUsed(false);
- NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat);
- doubleFormatter.setCommitsOnValidEdit(true);
- doubleFormatter.setValueClass(Double.class);
- return doubleFormatter;
- }
- private void generateHeader() {
- this.add(selectAllCheckBox);
- this.add(generateHeaderColumnTitle("Object"));
- this.add(generateHeaderColumnTitle("Id "));
- this.add(generateHeaderColumnTitle("Device"));
- this.add(generateHeaderColumnTitle("Energy"));
- this.add(generateHeaderColumnTitle("Priority"));
- this.add(generateHeaderColumnTitle("Activ"));
- }
- private void initSelectAllCheckBox() {
- selectAllCheckBox.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
- // Pixel Perfect alignment
- selectAllCheckBox.setBorder(BorderFactory.createEmptyBorder(2, 3, 0, 0));
- selectAllCheckBox.addActionListener(clicked -> {
- switch (selectAllCheckBox.getSelectionState()) {
- case mid_state_selection:
- case selected: {
- for (ElementRow row : elementRows) {
- row.setSelected(false);
- }
- duplicateButton.setEnabled(false);
- deleteButton.setEnabled(false);
- }
- break;
- case unselected:
- if(!elementRows.isEmpty()) {
- for (ElementRow row : elementRows) {
- row.setSelected(true);
- }
- duplicateButton.setEnabled(true);
- deleteButton.setEnabled(true);
- }
- default:
- break;
- }
- updateElementSelection();
- });
- }
- private JLabel generateHeaderColumnTitle(String string) {
- JLabel columnTitleLabel = new JLabel(string);
- columnTitleLabel.setToolTipText(string);
- columnTitleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
- return columnTitleLabel;
- }
- private void initButtonPanel() {
- buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
- buttonPanel.add(Box.createRigidArea(new Dimension(2, 0)));
- addButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/plus.png", 16, 16)));
- addButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
- addButton.addActionListener(clicked -> {
- Optional<HolonObject> last = control.getModel().getSelectedObjects().stream()
- .filter(obj -> obj instanceof HolonObject).reduce((prev, next) -> next)
- .map(obj -> (HolonObject) obj);
- last.ifPresent(obj -> {
- obj.addElement(new HolonElement(obj, "Element", 0.0f));
- control.calculateStateAndVisualForCurrentTimeStep();
- update_ui();
- });
- });
- buttonPanel.add(addButton);
- duplicateButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/duplicate.png", 16, 16)));
- duplicateButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
- duplicateButton.addActionListener(clicked -> {
- for (ElementRow row : elementRows) {
- if(row.isSelected()) {
- row.element.parentObject.addElement(new HolonElement(row.element));
- }
- }
- control.calculateStateAndVisualForCurrentTimeStep();
- update_ui();
- });
- buttonPanel.add(duplicateButton);
- deleteButton.setIcon(new ImageIcon(ImageImport.loadImage("Images/minus.png", 16, 16)));
- deleteButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
- deleteButton.addActionListener(clicked -> {
- for (ElementRow row : elementRows) {
- if(row.isSelected()) {
- row.element.parentObject.removeElement(row.element);
- }
- }
- control.calculateStateAndVisualForCurrentTimeStep();
- update_ui();
- });
- buttonPanel.add(deleteButton);
- }
- private void update_ui() {
- Stream<HolonElement> elements = extractElements(control.getModel().getSelectedObjects());
- // TODO Pooling
- this.removeAll();
- elementRows.clear();
- generateHeader();
- elements.forEach(element -> elementRows.add(new ElementRow(element)));
- this.add(buttonPanel, "span");
- boolean isAtLeastOneHolonObjectSelected =
- control.getModel().getSelectedObjects().stream().anyMatch(object -> object instanceof HolonObject);
- this.addButton.setEnabled(isAtLeastOneHolonObjectSelected);
- duplicateButton.setEnabled(false);
- deleteButton.setEnabled(false);
- selectAllCheckBox.setSelectionState(State.unselected);
- revalidate();
- repaint();
- this.OnElementSelectionChanged.broadcast(new HashSet<HolonElement>());
- }
- private void updateElementSelection() {
- Set<HolonElement> eleSet = elementRows.stream().filter(ele -> ele.isSelected()).map(row -> row.element).collect(Collectors.toSet());
- this.OnElementSelectionChanged.broadcast(eleSet);
- }
- private void updateButtonAppearance() {
- long count = elementRows.stream().filter(ele -> ele.isSelected()).count();
- if (count == elementRows.size()) {
- selectAllCheckBox.setSelectionState(State.selected);
- } else if (count == 0) {
- selectAllCheckBox.setSelectionState(State.unselected);
- } else {
- selectAllCheckBox.setSelectionState(State.mid_state_selection);
- }
- duplicateButton.setEnabled(count != 0);
- deleteButton.setEnabled(count != 0);
- }
- // Extract elements from a list of AbstractCanvasObjects
- static Stream<HolonElement> extractElements(Collection<AbstractCanvasObject> toInspect) {
- Stream<HolonElement> recursiveLayer = toInspect.stream().filter(object ->object instanceof GroupNode).flatMap(obj -> extractElements(((GroupNode)obj).getNodes()));
- Stream<HolonElement> thisLayer = toInspect.stream().filter(obj -> obj instanceof HolonObject).flatMap(obj -> {
- HolonObject ho = (HolonObject) obj;
- return ho.getElements().stream();
- });
- return Stream.concat(thisLayer, recursiveLayer);
- }
-
-
-
-
- private class ElementRow {
- HolonElement element;
- private JCheckBox selectionBox;
- Container[] cellsInRow = new Container[7];
- ElementRow(HolonElement element) {
- this.element = element;
- this.createEditFields();
- addContainerToInspector();
- }
- private void addContainerToInspector() {
- for (Container cell : cellsInRow) {
- InspectorTable.this.add(cell);
- }
- }
- public void setSelected(boolean value) {
- selectionBox.setSelected(value);
- // Color row
- for (Container cell : cellsInRow) {
- cell.setBackground(selectionBox.isSelected() ? selectedColor : Color.white);
- }
- }
- public boolean isSelected() {
- return selectionBox.isSelected();
- }
- private void createEditFields() {
- // Selected
- JPanel selectedColumnPanel = new JPanel(new BorderLayout());
- selectedColumnPanel.setBackground(Color.white);
- selectedColumnPanel.setBorder(BorderFactory.createLineBorder(borderColor));
- selectionBox = new JCheckBox();
- selectionBox.addActionListener(clicked -> {
- setSelected(selectionBox.isSelected());
- updateButtonAppearance();
- updateElementSelection();
- });
- selectedColumnPanel.setMinimumSize(new Dimension(columnHeight, columnHeight));
- selectedColumnPanel.setPreferredSize(new Dimension(columnHeight, columnHeight));
- selectedColumnPanel.setMaximumSize(new Dimension(columnHeight, columnHeight));
- selectionBox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
- selectionBox.setOpaque(false);
- selectedColumnPanel.add(selectionBox, BorderLayout.CENTER);
- cellsInRow[0] = selectedColumnPanel;
- // ObjectName and ID
- JTextField objectNameTextField = new JTextField(this.element.parentObject.getName());
- objectNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
- this.element.parentObject.setName(objectNameTextField.getText());
- });
- objectNameTextField.addActionListener(ae -> update_ui());
- cellsInRow[1] = objectNameTextField;
- JTextField idObjectTextField = new JTextField(Integer.toString(this.element.parentObject.getId()));
- idObjectTextField.setMinimumSize(idObjectTextField.getPreferredSize());
- idObjectTextField.setBackground(Color.white);
- idObjectTextField.setEditable(false);
- idObjectTextField.setEnabled(false);
- cellsInRow[2] = idObjectTextField;
- // Name
- JTextField elementNameTextField = new JTextField(this.element.getEleName());
- elementNameTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> {
- this.element.setEleName(elementNameTextField.getText());
- });
- elementNameTextField.setBackground(Color.white);
- cellsInRow[3] = elementNameTextField;
- // Energy
- JFormattedTextField energyTextField = new JFormattedTextField(doubleFormatter);
- energyTextField.setInputVerifier(getInputVerifier());
- energyTextField.setValue(this.element.getEnergy());
- energyTextField.setBackground(Color.white);
- energyTextField.addPropertyChangeListener(actionEvent -> {
- try {
- float energy = Float.parseFloat(energyTextField.getText());
- if (this.element.getEnergy() != energy) {
- this.element.setEnergyPerElement(energy);
- control.calculateStateAndVisualForCurrentTimeStep();
- }
- } catch (NumberFormatException e) {
- // Dont Update
- }
- });
- cellsInRow[4] = energyTextField;
- // Priority
- JComboBox<Priority> comboBox = new JComboBox<Priority>(Priority.values());
- comboBox.setSelectedItem(this.element.getPriority());
- comboBox.setBackground(Color.white);
- comboBox.setEditable(false);
- comboBox.addActionListener(ae -> {
- this.element.setPriority((Priority) comboBox.getSelectedItem());
- });
- cellsInRow[5] = comboBox;
- JPanel checkBoxWrapperPanel = new JPanel(new BorderLayout());
- checkBoxWrapperPanel.setBorder(BorderFactory.createLineBorder(borderColor));
- checkBoxWrapperPanel.setBackground(Color.white);
- checkBoxWrapperPanel.setMinimumSize(new Dimension(columnHeight, columnHeight));
- checkBoxWrapperPanel.setMaximumSize(new Dimension(columnHeight, columnHeight));
- // Active
- JCheckBox checkbox = new JCheckBox();
- checkbox.setSelected(this.element.isActive());
- checkbox.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
- checkbox.setOpaque(false);
- checkbox.addActionListener(actionEvent -> {
- this.element.setActive(checkbox.isSelected());
- control.calculateStateAndVisualForCurrentTimeStep();
- });
- checkBoxWrapperPanel.add(checkbox, BorderLayout.CENTER);
- cellsInRow[6] = checkBoxWrapperPanel;
- }
- }
- }
|