001    /* AbstractLayoutCache.java --
002       Copyright (C) 2002, 2004, 2006,  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing.tree;
040    
041    import java.awt.Rectangle;
042    import java.util.Enumeration;
043    
044    import javax.swing.event.TreeModelEvent;
045    
046    /**
047     * class AbstractLayoutCache
048     *
049     * @author Andrew Selkirk
050     */
051    public abstract class AbstractLayoutCache
052      implements RowMapper
053    {
054      /**
055       * class NodeDimensions
056       */
057      public abstract static class NodeDimensions
058      {
059        /**
060         * Creates <code>NodeDimensions</code> object.
061         */
062        public NodeDimensions()
063        {
064          // Do nothing here.
065        }
066    
067       /**
068        * Get the node dimensions. The NodeDimensions property must be set (unless
069        * the method is overridden, like if {@link FixedHeightLayoutCache}. If the
070        * method is not overridden and the property is not set, the InternalError is
071        * thrown.
072        *
073        * @param value the last node in the path
074        * @param row the node row
075        * @param depth the indentation depth
076        * @param expanded true if this node is expanded, false otherwise
077        * @param bounds the area where the tree is displayed
078        */
079        public abstract Rectangle getNodeDimensions(Object value, int row,
080                                                    int depth, boolean expanded,
081                                                    Rectangle bounds);
082      }
083    
084      /**
085       * nodeDimensions
086       */
087      protected NodeDimensions nodeDimensions;
088    
089      /**
090       * treeModel
091       */
092      protected TreeModel treeModel;
093    
094      /**
095       * treeSelectionModel
096       */
097      protected TreeSelectionModel treeSelectionModel;
098    
099      /**
100       * rootVisible
101       */
102      protected boolean rootVisible;
103    
104      /**
105       * rowHeight
106       */
107      protected int rowHeight;
108    
109      /**
110       * Constructor AbstractLayoutCache
111       */
112      public AbstractLayoutCache()
113      {
114        // Do nothing here.
115      }
116    
117      /**
118       * setNodeDimensions
119       *
120       * @param dimensions TODO
121       */
122      public void setNodeDimensions(NodeDimensions dimensions)
123      {
124        nodeDimensions = dimensions;
125      }
126    
127      /**
128       * getNodeDimensions
129       *
130       * @return NodeDimensions
131       */
132      public NodeDimensions getNodeDimensions()
133      {
134        return nodeDimensions;
135      }
136    
137     /**
138      * Get the node dimensions. The NodeDimensions property must be set
139      * (unless the method is overridden, like if
140      * {@link FixedHeightLayoutCache}. If the method is not overridden and
141      * the property is not set, the InternalError is thrown.
142      *
143      * @param value the last node in the path
144      * @param row the node row
145      * @param depth the indentation depth
146      * @param expanded true if this node is expanded, false otherwise
147      * @param bounds the area where the tree is displayed
148      */
149      protected Rectangle getNodeDimensions(Object value, int row, int depth,
150                                            boolean expanded, Rectangle bounds)
151      {
152        Rectangle d = null;
153        if (nodeDimensions != null)
154          d = nodeDimensions.getNodeDimensions(value, row, depth, expanded,
155                                               bounds);
156        return d;
157      }
158    
159      /**
160       * Sets the model that provides the tree data.
161       *
162       * @param model the model
163       */
164      public void setModel(TreeModel model)
165      {
166        treeModel = model;
167      }
168    
169      /**
170       * Returns the model that provides the tree data.
171       *
172       * @return the model
173       */
174      public TreeModel getModel()
175      {
176        return treeModel;
177      }
178    
179      /**
180       * setRootVisible
181       *
182       * @param visible <code>true</code> if root should be visible,
183       * <code>false</code> otherwise
184       */
185      public void setRootVisible(boolean visible)
186      {
187        rootVisible = visible;
188      }
189    
190      /**
191       * isRootVisible
192       *
193       * @return <code>true</code> if root is visible,
194       * <code>false</code> otherwise
195       */
196      public boolean isRootVisible()
197      {
198        return rootVisible;
199      }
200    
201      /**
202       * setRowHeight
203       *
204       * @param height the row height
205       */
206      public void setRowHeight(int height)
207      {
208        rowHeight = height;
209        invalidateSizes();
210      }
211    
212      /**
213       * getRowHeight
214       *
215       * @return the row height
216       */
217      public int getRowHeight()
218      {
219        return rowHeight;
220      }
221    
222      /**
223       * setSelectionModel
224       *
225       * @param model the model
226       */
227      public void setSelectionModel(TreeSelectionModel model)
228      {
229        if (treeSelectionModel != null)
230          treeSelectionModel.setRowMapper(null);
231        treeSelectionModel = model;
232        if (treeSelectionModel != null)
233          treeSelectionModel.setRowMapper(this);
234    
235      }
236    
237      /**
238       * getSelectionModel
239       *
240       * @return the model
241       */
242      public TreeSelectionModel getSelectionModel()
243      {
244        return treeSelectionModel;
245      }
246    
247      /**
248       * Get the sum of heights for all rows. This class provides a general not
249       * optimized implementation that is overridded in derived classes
250       * ({@link VariableHeightLayoutCache}, {@link FixedHeightLayoutCache}) for
251       * the better performance.
252       */
253      public int getPreferredHeight()
254      {
255        int height = 0;
256        int n = getRowCount();
257        Rectangle r = new Rectangle();
258        for (int i = 0; i < n; i++)
259          {
260            TreePath path = getPathForRow(i);
261            height += getBounds(path, r).height;
262          }
263        return height;
264      }
265    
266      /**
267       * Get the maximal width. This class provides a general not
268       * optimized implementation that is overridded in derived classes
269       * ({@link VariableHeightLayoutCache}, {@link FixedHeightLayoutCache}) for
270       * the better performance.
271       *
272       * @param rect the rectangle that is used during the method work
273       */
274      public int getPreferredWidth(Rectangle rect)
275      {
276        int maximalWidth = 0;
277        Rectangle r = new Rectangle();
278        int n = getRowCount();
279        for (int i = 0; i < n; i++)
280          {
281            TreePath path = getPathForRow(i);
282            r.setBounds(0, 0, 0, 0);
283            r = getBounds(path, r);
284            if (r.x + r.width > maximalWidth)
285              maximalWidth = r.x + r.width;
286            // Invalidate the cached value as this may be the very early call
287            // before the heigth is properly set (the vertical coordinate may
288            // not be correct).
289            invalidatePathBounds(path);
290          }
291        return maximalWidth;
292      }
293      /**
294       * isExpanded
295       *
296       * @param value0 TODO
297       *
298       * @return boolean
299       */
300      public abstract boolean isExpanded(TreePath value0);
301    
302      /**
303       * getBounds
304       *
305       * @param value0 TODO
306       * @param value1 TODO
307       *
308       * @return Rectangle
309       */
310      public abstract Rectangle getBounds(TreePath value0, Rectangle value1);
311    
312      /**
313       * getPathForRow
314       *
315       * @param row the row
316       *
317       * @return the tree path
318       */
319      public abstract TreePath getPathForRow(int row);
320    
321      /**
322       * getRowForPath
323       *
324       * @param path the tree path
325       *
326       * @return the row
327       */
328      public abstract int getRowForPath(TreePath path);
329    
330      /**
331       * getPathClosestTo
332       *
333       * @param value0 TODO
334       * @param value1 TODO
335       *
336       * @return the tree path
337       */
338      public abstract TreePath getPathClosestTo(int value0, int value1);
339    
340      /**
341       * getVisiblePathsFrom
342       *
343       * @param path the tree path
344       *
345       * @return Enumeration
346       */
347      public abstract Enumeration<TreePath> getVisiblePathsFrom(TreePath path);
348    
349      /**
350       * getVisibleChildCount
351       *
352       * @param path the tree path
353       *
354       * @return int
355       */
356      public abstract int getVisibleChildCount(TreePath path);
357    
358      /**
359       * setExpandedState
360       *
361       * @param value0 TODO
362       *
363       * @param value1 TODO
364       */
365      public abstract void setExpandedState(TreePath value0, boolean value1);
366    
367      /**
368       * getExpandedState
369       *
370       * @param path the tree path
371       *
372       * @return boolean
373       */
374      public abstract boolean getExpandedState(TreePath path);
375    
376      /**
377       * getRowCount
378       *
379       * @return the number of rows
380       */
381      public abstract int getRowCount();
382    
383      /**
384       * invalidateSizes
385       */
386      public abstract void invalidateSizes();
387    
388      /**
389       * invalidatePathBounds
390       *
391       * @param path the tree path
392       */
393      public abstract void invalidatePathBounds(TreePath path);
394    
395      /**
396       * treeNodesChanged
397       *
398       * @param event the event to send
399       */
400      public abstract void treeNodesChanged(TreeModelEvent event);
401    
402      /**
403       * treeNodesInserted
404       *
405       * @param event the event to send
406       */
407      public abstract void treeNodesInserted(TreeModelEvent event);
408    
409      /**
410       * treeNodesRemoved
411       *
412       * @param event the event to send
413       */
414      public abstract void treeNodesRemoved(TreeModelEvent event);
415    
416      /**
417       * treeStructureChanged
418       *
419       * @param event the event to send
420       */
421      public abstract void treeStructureChanged(TreeModelEvent event);
422    
423      /**
424       * Get the tree row numbers for the given pathes. This method performs
425       * the "bulk" conversion that may be faster than mapping pathes one by
426       * one. To have the benefit from the bulk conversion, the method must be
427       * overridden in the derived classes. The default method delegates work
428       * to the {@link #getRowForPath(TreePath)}.
429       *
430       * @param paths the tree paths the array of the tree pathes.
431       * @return the array of the matching tree rows.
432       */
433      public int[] getRowsForPaths(TreePath[] paths)
434      {
435        int[] rows = null;
436        if (paths != null)
437          {
438            rows = new int[paths.length];
439            for (int i = 0; i < rows.length; i++)
440              rows[i] = getRowForPath(paths[i]);
441          }
442        return rows;
443      }
444    
445      /**
446       * Returns true if this layout supposes that all rows have the fixed
447       * height.
448       *
449       * @return boolean true if all rows in the tree must have the fixed
450       * height (false by default).
451       */
452      protected boolean isFixedRowHeight()
453      {
454        return rowHeight > 0;
455      }
456    }