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