View Javadoc
1   package nl.tudelft.simulation.dsol.swing.introspection.gui;
2   
3   import java.awt.Insets;
4   import java.awt.Window;
5   import java.awt.event.ActionEvent;
6   import java.awt.event.ActionListener;
7   import java.lang.reflect.Constructor;
8   
9   import javax.swing.JButton;
10  import javax.swing.JTable;
11  import javax.swing.SwingUtilities;
12  
13  import org.djutils.logger.CategoryLogger;
14  
15  import nl.tudelft.simulation.dsol.swing.introspection.mapping.CellPresentationConfiguration;
16  import nl.tudelft.simulation.dsol.swing.introspection.mapping.DefaultConfiguration;
17  import nl.tudelft.simulation.introspection.Introspector;
18  import nl.tudelft.simulation.introspection.Property;
19  
20  /**
21   * A table-element that spawns an introspection dialog for a property. In the new dialog, the property has become the
22   * introspected object.
23   * <p>
24   * Copyright (c) 2002-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
25   * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
26   * project is distributed under a three-clause BSD-style license, which can be found at
27   * <a href="https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
28   * </p>
29   * @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs</a>.
30   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>.
31   * @author Niels Lang.
32   * @since 1.5
33   */
34  public class ExpandButton extends JButton
35  {
36      /** */
37      private static final long serialVersionUID = 20140831L;
38  
39      /** the JTable in which this button is actually displayed. */
40      private JTable myTable;
41  
42      /** the property */
43      private final Property PROPERTY;
44  
45      /** the model. */
46      private final IntrospectingTableModelInterface MODEL;
47  
48      /**
49       * constructs a new ExpandButton.
50       * @param property Property; the property
51       * @param model IntrospectingTableModelInterface; the model
52       */
53      public ExpandButton(final Property property, final IntrospectingTableModelInterface model)
54      {
55          super("+");
56          this.setMargin(new Insets(0, 0, 0, 0));
57          this.PROPERTY = property;
58          this.MODEL = model;
59  
60          ActionListener al = new ActionListener()
61          {
62              @Override
63              public void actionPerformed(final ActionEvent e)
64              {
65                  showTable();
66              }
67          };
68  
69          this.addActionListener(al);
70      }
71  
72      /**
73       * Sets the JTable in which this button is actually displayed. The reference is used to facilitate dialog creation.
74       * @param table JTable; the table
75       */
76      public void setMyJTable(final JTable table)
77      {
78          this.myTable = table;
79      }
80  
81      /**
82       * Shows a new table introspecing the property.
83       */
84      public void showTable()
85      {
86          if (this.PROPERTY.getValue() == null)
87          {
88              return;
89          }
90          if (this.myTable != null)
91          {
92              Window parentWindow = SwingUtilities.getWindowAncestor(this);
93              new IntrospectionDialog(parentWindow, this.PROPERTY.getName() + ", " + this.PROPERTY.getValue(),
94                      instantiateTable());
95          }
96          else
97          {
98              new IntrospectionDialog(this.PROPERTY.getName() + ", " + this.PROPERTY.getValue(), instantiateTable());
99          }
100     }
101 
102     /**
103      * instantiates a JTable with an object model of the property.
104      * @return the JTable
105      */
106     private JTable instantiateTable()
107     {
108         IntrospectingTableModelInterface newModel = null;
109         ModelManager manager = this.MODEL.getModelManager();
110         Introspector introspector = this.MODEL.getIntrospector();
111         try
112         {
113             Class<?> modelClass = null;
114             if (this.PROPERTY.getComposedType().isArray())
115             {
116                 modelClass = manager.getDefaultCollectionObjectTableModel();
117                 Constructor<?> c = modelClass.getConstructor(new Class[] {Property.class, Introspector.class});
118                 newModel = (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY, introspector});
119             }
120             else if (this.PROPERTY.getComposedType().isCollection())
121             {
122                 modelClass = manager.getDefaultCollectionObjectTableModel();
123                 Constructor<?> c = modelClass.getConstructor(new Class[] {Property.class, Introspector.class});
124                 newModel = (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY, introspector});
125             }
126             else if (this.PROPERTY.getComposedType().isImmutableCollection())
127             {
128                 modelClass = manager.getDefaultCollectionObjectTableModel();
129                 Constructor<?> c = modelClass.getConstructor(new Class[] {Property.class, Introspector.class});
130                 newModel = (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY, introspector});
131             }
132             else if (this.PROPERTY.getComposedType().isMap())
133             {
134                 modelClass = manager.getDefaultMapObjectTableModel();
135                 Constructor<?> c = modelClass.getConstructor(new Class[] {Property.class, Introspector.class});
136                 newModel = (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY, introspector});
137             }
138             else if (this.PROPERTY.getComposedType().isImmutableMap())
139             {
140                 modelClass = manager.getDefaultMapObjectTableModel();
141                 Constructor<?> c = modelClass.getConstructor(new Class[] {Property.class, Introspector.class});
142                 newModel = (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY, introspector});
143             }
144             else
145             {
146                 modelClass = manager.getDefaultObjectTableModel();
147                 Constructor<?> c = modelClass.getConstructor(new Class[] {Object.class, Introspector.class});
148                 newModel =
149                         (IntrospectingTableModelInterface) c.newInstance(new Object[] {this.PROPERTY.getValue(), introspector});
150             }
151         }
152         catch (Exception exception)
153         {
154             CategoryLogger.always().warn(exception, "instantiate: could not instantiate parent tablemodel, using default");
155             if (this.PROPERTY.getComposedType().isArray())
156             {
157                 newModel = new CollectionTableModel(this.PROPERTY);
158             }
159             else if (this.PROPERTY.getComposedType().isCollection())
160             {
161                 newModel = new CollectionTableModel(this.PROPERTY);
162             }
163             else if (this.PROPERTY.getComposedType().isImmutableCollection())
164             {
165                 newModel = new ImmutableCollectionTableModel(this.PROPERTY);
166             }
167             else if (this.PROPERTY.getComposedType().isMap())
168             {
169                 newModel = new MapTableModel(this.PROPERTY);
170             }
171             else if (this.PROPERTY.getComposedType().isImmutableMap())
172             {
173                 newModel = new MapTableModel(this.PROPERTY);
174             }
175             else
176             {
177                 newModel = new ObjectTableModel(this.PROPERTY.getValue());
178             }
179         }
180         // Propagate CellPresentation configuration.
181         CellPresentationConfiguration config = DefaultConfiguration.getDefaultConfiguration();
182         if (this.myTable instanceof ICellPresentationConfigProvider)
183             config = ((ICellPresentationConfigProvider) this.myTable).getCellPresentationConfiguration();
184         JTable result = new ObjectJTable(newModel, config);
185         // Propagate model settings
186         newModel.getModelManager().setDefaultCollectionObjectTableModel(manager.getDefaultCollectionObjectTableModel());
187         newModel.getModelManager().setDefaultObjectTableModel(manager.getDefaultObjectTableModel());
188         result.repaint();
189         return result;
190     }
191 
192     @Override
193     public String toString()
194     {
195         return "ExpandButton [PROPERTY=" + this.PROPERTY + ", MODEL=" + this.MODEL + "]";
196     }
197 }