View Javadoc
1   package org.opentrafficsim.editor;
2   
3   import java.awt.BorderLayout;
4   import java.awt.Component;
5   import java.awt.Dimension;
6   import java.awt.FlowLayout;
7   import java.util.List;
8   
9   import javax.swing.ImageIcon;
10  import javax.swing.JButton;
11  import javax.swing.JDialog;
12  import javax.swing.JOptionPane;
13  import javax.swing.JPanel;
14  import javax.swing.JScrollPane;
15  import javax.swing.JTable;
16  import javax.swing.border.EmptyBorder;
17  import javax.swing.table.AbstractTableModel;
18  import javax.swing.table.DefaultTableCellRenderer;
19  import javax.swing.table.DefaultTableColumnModel;
20  import javax.swing.table.TableColumn;
21  import javax.swing.table.TableColumnModel;
22  import javax.swing.table.TableModel;
23  
24  /**
25   * Shows a modal dialog to edit properties (of the main XML tag).
26   * <p>
27   * Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
28   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
29   * </p>
30   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
31   */
32  public class PropertiesDialog extends JDialog
33  {
34  
35      /** */
36      private static final long serialVersionUID = 20250918L;
37  
38      /**
39       * Constructor.
40       * @param owner owner
41       * @param properties list of properties (keys even indices, values at uneven)
42       * @param questionMark question mark icon
43       */
44      public PropertiesDialog(final OtsEditor owner, final List<String> properties, final ImageIcon questionMark)
45      {
46          super(owner, "Properties", true);
47  
48          // main panel
49          JPanel panel = new JPanel();
50          panel.setLayout(new BorderLayout());
51          // columns
52          TableColumnModel columns = new DefaultTableColumnModel();
53          TableColumn column1 = new TableColumn(0, 200);
54          column1.setHeaderValue("Property");
55          columns.addColumn(column1);
56          TableColumn column2 = new TableColumn(1, 600);
57          column2.setHeaderValue("Value");
58          columns.addColumn(column2);
59          // model
60          TableModel model = new AbstractTableModel()
61          {
62              /** */
63              private static final long serialVersionUID = 20240314L;
64  
65              @Override
66              public int getRowCount()
67              {
68                  return properties.size() / 2;
69              }
70  
71              @Override
72              public int getColumnCount()
73              {
74                  return 2;
75              }
76  
77              @Override
78              public Object getValueAt(final int rowIndex, final int columnIndex)
79              {
80                  return properties.get(rowIndex * 2 + columnIndex);
81              }
82  
83              @Override
84              public boolean isCellEditable(final int rowIndex, final int columnIndex)
85              {
86                  return columnIndex == 1;
87              }
88  
89              @Override
90              public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex)
91              {
92                  properties.set(rowIndex * 2 + columnIndex, aValue.toString());
93                  owner.setUnsavedChanges(true);
94              }
95          };
96          // table
97          JTable table = new JTable(model, columns);
98          DefaultTableCellRenderer renderer = new DefaultTableCellRenderer()
99          {
100             /** */
101             private static final long serialVersionUID = 20240314L;
102 
103             @Override
104             public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected,
105                     final boolean hasFocus, final int row, final int column)
106             {
107                 Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
108                 if (table.convertColumnIndexToModel(column) == 0)
109                 {
110                     setOpaque(true);
111                 }
112                 else
113                 {
114                     setOpaque(false);
115                 }
116                 return component;
117             }
118         };
119         renderer.setBackground(panel.getBackground()); // for editable cells
120         table.setDefaultRenderer(Object.class, renderer);
121         JScrollPane scroll = new JScrollPane(table); // put table in scroll window, also makes the header visible
122         scroll.setBorder(new EmptyBorder(0, 0, 0, 0));
123         panel.add(scroll, BorderLayout.CENTER);
124         // dialog
125         setMinimumSize(new Dimension(250, 150));
126         setPreferredSize(new Dimension(800, 200));
127         // buttons
128         JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
129         JButton defaults = new JButton("Set defaults...");
130         defaults.addActionListener((a) ->
131         {
132             boolean set = JOptionPane.showConfirmDialog(PropertiesDialog.this, "Are you sure? This will reset all properties.",
133                     "Are you sure?", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
134                     questionMark) == JOptionPane.OK_OPTION;
135             if (set)
136             {
137                 table.getDefaultEditor(Object.class).stopCellEditing();
138                 owner.setDefaultProperties();
139                 table.updateUI();
140                 owner.setUnsavedChanges(true);
141             }
142         });
143         buttons.add(defaults);
144         JButton ok = new JButton("Ok");
145         ok.addActionListener((a) ->
146         {
147             table.getDefaultEditor(Object.class).stopCellEditing();
148             dispose();
149         });
150         buttons.add(ok);
151         panel.add(buttons, BorderLayout.PAGE_END);
152         // pack and visualize
153         getContentPane().add(panel);
154         pack();
155         setLocationRelativeTo(this);
156         setVisible(true);
157     }
158 
159 }