View Javadoc
1   package fr.ifremer.quadrige3.ui.swing.table;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: UI Swing Common
6    * %%
7    * Copyright (C) 2017 - 2019 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Affero General Public License as published by
11   * the Free Software Foundation, either version 3 of the License, or
12   * (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU Affero General Public License
20   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21   * #L%
22   */
23  
24  import fr.ifremer.quadrige3.core.dao.technical.Assert;
25  import org.jdesktop.swingx.table.TableColumnExt;
26  
27  import javax.swing.event.*;
28  import java.awt.event.MouseEvent;
29  import java.awt.event.MouseListener;
30  import java.beans.PropertyChangeEvent;
31  import java.beans.PropertyChangeListener;
32  import java.util.Arrays;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  /*
37   *	Use a JTable as a renderer for row numbers of a given mainTable table.
38   *  This table must be added to the row header of the scrollpane that
39   *  contains the main table.
40   */
41  public class FixedSwingTable extends SwingTable
42      implements PropertyChangeListener, TableModelListener, RowSorterListener, MouseListener {
43  
44      private final SwingTable mainTable;
45  
46      private Map<Integer, Integer> modelIndexTransposeMap = new HashMap<>();
47  
48      public FixedSwingTable(SwingTable table) {
49          Assert.notNull(table, "A FixedSwingTable must have a main table");
50          mainTable = table;
51  
52          // Set component name
53          setName(mainTable.getName() + "_fixed");
54  
55          // Affect the main model
56          setModel(mainTable.getTableModel());
57  
58          // init table
59          setAutoCreateColumnsFromModel(false);
60          setSelectionModel(mainTable.getSelectionModel());
61          setRowSorter(mainTable.getRowSorter());
62          setRowHeight(mainTable.getRowHeight());
63          getTableHeader().setReorderingAllowed(false);
64          setAutoResizeMode(SwingTable.AUTO_RESIZE_OFF);
65  
66          // add listeners
67          addMouseListener(this);
68          mainTable.addPropertyChangeListener(this);
69          mainTable.getModel().addTableModelListener(this);
70      }
71  
72      public void addColumnModelTransposition(int fixedColumnModelIndex, int mainColumnModelIndex) {
73          modelIndexTransposeMap.put(fixedColumnModelIndex, mainColumnModelIndex);
74      }
75  
76      public void removeColumnModelTransposition(int fixedColumnModelIndex) {
77          modelIndexTransposeMap.remove(fixedColumnModelIndex);
78      }
79  
80      public Integer getMainColumnModelIndex(int fixedColumnModelIndex) {
81          return modelIndexTransposeMap.getOrDefault(fixedColumnModelIndex, fixedColumnModelIndex);
82      }
83  
84      public Integer getFixedColumnModelIndex(int mainColumnModelIndex) {
85          return modelIndexTransposeMap.entrySet().stream().filter(entry -> entry.getValue().equals(mainColumnModelIndex)).findFirst().map(Map.Entry::getKey).orElse(mainColumnModelIndex);
86      }
87  
88      public int getColumnModelIndex(ColumnIdentifier<?> identifier) {
89          TableColumnExt column = getColumnExt(identifier);
90          Assert.notNull(column);
91          return getMainColumnModelIndex(column.getModelIndex());
92      }
93  
94      @Override
95      public int convertColumnIndexToModel(int viewColumnIndex) {
96          return getMainColumnModelIndex(super.convertColumnIndexToModel(viewColumnIndex));
97      }
98  
99      @Override
100     public int convertColumnIndexToView(int modelColumnIndex) {
101         return getFixedColumnModelIndex(super.convertColumnIndexToView(modelColumnIndex));
102     }
103 
104     /*
105      *  Keep the row table in sync with the mainTable table
106      */
107     @Override
108     public void propertyChange(PropertyChangeEvent e) {
109         if ("selectionModel".equals(e.getPropertyName())) {
110             setSelectionModel(mainTable.getSelectionModel());
111         } else if ("rowSorter".equals(e.getPropertyName())) {
112             setRowSorter(mainTable.getRowSorter());
113         } else if ("rowHeight".equals(e.getPropertyName())) {
114             repaint();
115         } else if (SwingTable.PROPERTY_ROW_FILTER.equals(e.getPropertyName())
116             || SwingTable.PROPERTY_SORTED.equals(e.getPropertyName())) {
117             revalidate();
118         }
119     }
120 
121     /*
122      *  Implement the TableModelListener
123      */
124     @Override
125     public void tableChanged(TableModelEvent e) {
126         revalidate();
127     }
128 
129     @Override
130     public void columnAdded(TableColumnModelEvent e) {
131         super.columnAdded(e);
132         updateViewportSize();
133     }
134 
135     @Override
136     public void columnRemoved(TableColumnModelEvent e) {
137         super.columnRemoved(e);
138         updateViewportSize();
139     }
140 
141     @Override
142     public void columnMarginChanged(ChangeEvent e) {
143         super.columnMarginChanged(e);
144         updateViewportSize();
145     }
146 
147     private void updateViewportSize() {
148         setPreferredScrollableViewportSize(getPreferredSize());
149     }
150 
151     @Override
152     public void mouseClicked(MouseEvent e) {
153         // propagate mouseClicked event to main table (ie. allows popup on right click)
154         if (mainTable.getMouseListeners() != null)
155             Arrays.stream(mainTable.getMouseListeners()).forEach(mouseListener -> mouseListener.mouseClicked(e));
156     }
157 
158     @Override
159     public void mousePressed(MouseEvent e) {
160 
161     }
162 
163     @Override
164     public void mouseReleased(MouseEvent e) {
165 
166     }
167 
168     @Override
169     public void mouseEntered(MouseEvent e) {
170 
171     }
172 
173     @Override
174     public void mouseExited(MouseEvent e) {
175 
176     }
177 }