View Javadoc
1   package fr.ifremer.allegro.obsdeb.ui.swing.util.treetable;
2   
3   /*
4    * #%L
5    * SIH Allegro ObsDeb :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2013 - 2014 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  import com.google.common.collect.Lists;
26  import jaxx.runtime.swing.nav.treetable.NavTreeTableHelper;
27  import jaxx.runtime.swing.nav.treetable.NavTreeTableModel;
28  import org.apache.commons.collections4.CollectionUtils;
29  import org.jdesktop.swingx.JXTreeTable;
30  
31  import javax.swing.*;
32  import java.util.Enumeration;
33  import java.util.List;
34  
35  /**
36   * abstract helper class to manage treetable (model/node/data provider)
37   *
38   * @author Ludovic Pecquot (ludovic.pecquot@e-is.pro)
39   * @param <H> type of AbstractObsdebTreeTableUIHandler
40   * @param <NM> type of NodeUIModel
41   * @param <TN> type of TreeTableNode
42   * @param <P> type of TreeTableDataProvider
43   */
44  public abstract class AbstractObsdebTreeTableHelper<H extends AbstractObsdebTreeTableUIHandler,
45          NM extends AbstractObsdebNodeUIModel, TN extends AbstractObsdebTreeTableNode<NM, TN>, P extends AbstractObsdebTreeTableDataProvider<NM>>
46      extends NavTreeTableHelper<TN> {
47  
48      protected final H handler;
49  
50      /**
51       * Creates a new node when moving to next editable cell / row ?
52       */
53      protected final boolean createNewNode;
54  
55      public AbstractObsdebTreeTableHelper(H handler, P dataProvider, boolean createNewNode) {
56          setDataProvider(dataProvider);
57          this.handler = handler;
58          this.createNewNode = createNewNode;
59      }
60  
61      @Override
62      public P getDataProvider() {
63          return (P) super.getDataProvider();
64      }
65  
66      public boolean isCreateNewNode() {
67          return createNewNode;
68      }
69  
70      public NavTreeTableModel createModel(AbstractObsdebTreeTableModel delegate) {
71  
72          // create the root node
73          TN root = getNewRootNode();
74  
75          NavTreeTableModel model = createModel(root, delegate);
76  
77          // populate children's root
78          root.populateChilds(getBridge(), getDataProvider());
79  
80          return model;
81      }
82  
83      public AbstractObsdebTreeTableModel getTreeTableModel() {
84          return (AbstractObsdebTreeTableModel) getModel().getDelegate();
85      }
86  
87      /**
88       * get the new root node to build the tree
89       *
90       * @return a tree table node
91       */
92      protected abstract TN getNewRootNode();
93  
94      /**
95       * get a new node to insert in root
96       *
97       * @return a tree table node
98       */
99      protected abstract TN getNewNode();
100 
101     public void modelChanged() {
102 
103         // hack to empty the root's children, otherwise, the children are duplicated
104         getRootNode().setAllowsChildren(false);
105         getRootNode().setAllowsChildren(true);
106 
107         // reload new children
108         getDataProvider().prepareData();
109         getRootNode().populateNode(getBridge(), getDataProvider(), true);
110 
111         // redraw tree table
112         getModel().getModelSupport().fireNewRoot();
113         getTreeTable().expandAll();
114 
115         // reselect last node
116 //        reselectLastNode();
117         handler.onModelRowsChanged();
118     }
119 
120 //    private void reselectLastNode() {
121 ////        final TN lastNode = (TN) getTreeTableModel().getLastSelectedNode();
122 //        final Integer lastRowIndex = getTreeTableModel().getLastRowIndex();
123 //        final Integer lastColmunIndex = getTreeTableModel().getLastColumnIndex();
124 //        if (lastRowIndex != null && lastColmunIndex != null) {
125 //            SwingUtilities.invokeLater(new Runnable() {
126 //
127 //                @Override
128 //                public void run() {
129 ////                    TreePath path = new TreePath(lastNode);
130 ////                    setSelectionPath(path);
131 //                    getTreeTable().setRowSelectionInterval(lastRowIndex, lastRowIndex);
132 //                    getTreeTable().setColumnSelectionInterval(lastColmunIndex, lastColmunIndex);
133 //                    getTreeTableModel().setLastCellIndexes(null, null);
134 //                }
135 //            });
136 //        }
137 //    }
138     public void flushModel() {
139         getDataProvider().flushData();
140     }
141 
142     public void addNewNode() {
143         // add empty row on root
144         TN newNode = getNewNode();
145         insertNode(getRootNode(), newNode);
146         selectNode(newNode);
147     }
148 
149     public void removeSelectedRows() {
150 
151         List<TN> selectedNodes = getSelectedNodes();
152 
153         if (CollectionUtils.isNotEmpty(selectedNodes)) {
154 
155             // remove each node
156             for (TN node : selectedNodes) {
157 
158                 getDataProvider().removeRow(node.getUserObject());
159                 removeNode(node);
160 
161             }
162 
163             // nodes/lines have been removed and parent/child relation has changed, let reload the model
164             flushModel();
165             modelChanged();
166 
167         }
168     }
169 
170     public void refreshRow(NM row) {
171         // find the node containing the row
172         TN node = findNode(getRootNode(), row.getNodeId());
173         refreshNode(node, false);
174     }
175 
176     public void refreshAll() {
177         // try to refresh all nodes and treetable itself for repaint
178         refreshNode(getRootNode(), true);
179 //        getTreeTable().repaint();
180     }
181 
182     public void duplicateSelectedNode() {
183         NM rowToDuplicate = getSelectedNode().getUserObject();
184         NM newRow = getDataProvider().getNewRow();
185 
186         duplicateRow(newRow, rowToDuplicate);
187 
188         flushModel();
189         modelChanged();
190     }
191 
192     /**
193      *
194      * @param newRow
195      * @param rowToDuplicate
196      */
197     protected void duplicateRow(NM newRow, NM rowToDuplicate) {
198         // do nothing by default
199     }
200 
201     public JXTreeTable getTreeTable() {
202         return getUI();
203     }
204 
205     @Override
206     public TN getSelectedNode() {
207         return super.getSelectedNode();
208     }
209 
210     @Override
211     public List<TN> getSelectedNodes() {
212 
213         if (getTreeTable().getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) {
214 
215             // find selected node models
216             return findSelectedNodeModels(getRootNode());
217         }
218 
219         // return selected nodes if selection mode is not single
220         return super.getSelectedNodes();
221     }
222 
223     private List<TN> findSelectedNodeModels(TN rootNode) {
224 
225         List<TN> selectedNodes = Lists.newArrayList();
226 
227         Enumeration<TN> e = rootNode.children();
228         while (e.hasMoreElements()) {
229             TN node = e.nextElement();
230             if (node.isSelected()) {
231                 selectedNodes.add(node);
232             }
233             if (node.getChildCount() > 0) {
234                 selectedNodes.addAll(findSelectedNodeModels(node));
235             }
236         }
237         return selectedNodes;
238     }
239 
240     @Override
241     public TN findNode(TN node, String... ids) {
242         return super.findNode(node, ids);
243     }
244 
245 }