View Javadoc

1   /*
2    *  File: TableHierarchyRenderer.java 
3    *  Copyright (c) 2004-2007  Peter Kliem (Peter.Kliem@jaret.de)
4    *  A commercial license is available, see http://www.jaret.de.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Common Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/cpl-v10.html
10   */
11  package de.jaret.util.ui.table.renderer;
12  
13  import java.util.List;
14  
15  import org.eclipse.jface.viewers.ILabelProvider;
16  import org.eclipse.swt.SWT;
17  import org.eclipse.swt.graphics.Color;
18  import org.eclipse.swt.graphics.GC;
19  import org.eclipse.swt.graphics.Image;
20  import org.eclipse.swt.graphics.Point;
21  import org.eclipse.swt.graphics.Rectangle;
22  import org.eclipse.swt.printing.Printer;
23  import org.eclipse.swt.widgets.Display;
24  
25  import de.jaret.util.ui.table.JaretTable;
26  import de.jaret.util.ui.table.model.IColumn;
27  import de.jaret.util.ui.table.model.IHierarchicalTableViewState;
28  import de.jaret.util.ui.table.model.IRow;
29  import de.jaret.util.ui.table.model.ITableNode;
30  import de.jaret.util.ui.table.model.StdHierarchicalTableModel;
31  
32  /***
33   * A renderer for rendering the hierarchy (as a tree) of a hierarchical tree model.
34   * 
35   * @author Peter Kliem
36   * @version $Id: TableHierarchyRenderer.java 1077 2010-12-17 12:03:27Z kliem $
37   */
38  public class TableHierarchyRenderer extends CellRendererBase implements IHierarchyRenderer {
39      /*** size of the plus/minus signs. */
40      protected int SIZE = 12;
41  
42      protected int SIGNINSETS = 3;
43  
44      protected boolean _drawTree = true;
45  
46      protected int _levelWidth = 30;
47  
48      protected boolean _drawIcons = false;
49  
50      protected boolean _drawLabels = false;
51      
52      protected boolean _drawBorder = false;
53      
54      protected boolean _drawFullSelection = true;
55  
56      protected ILabelProvider _labelProvider = null;
57  
58      /*** type of nodemarks to draw: 0 none, 1 +/-, 2 triangles. */
59      protected int _nodeMarkType = 2;
60  
61      /***
62       * Create the renderer for a printer device.
63       * @param printer printer device
64       */
65      public TableHierarchyRenderer(Printer printer) {
66          super(printer);
67          SIZE = scaleX(SIZE);
68          SIGNINSETS = scaleX(SIGNINSETS);
69      }
70  
71      /***
72       * Create the renderer for use with the display.
73       */
74      public TableHierarchyRenderer() {
75          super(null);
76      }
77  
78      /***
79       * {@inheritDoc}
80       */
81      public void draw(GC gc, JaretTable jaretTable, ICellStyle cellStyle, Rectangle drawingArea, IRow row,
82              IColumn column, boolean drawFocus, boolean selected, boolean printing) {
83          int offx;
84          offx = scaleX(_levelWidth);
85          ITableNode node = (ITableNode) row;
86          int level = node.getLevel();
87          boolean leaf = node.getChildren().size() == 0;
88          boolean expanded = ((IHierarchicalTableViewState) jaretTable.getTableViewState()).isExpanded(node);
89  
90          int x = drawingArea.x + offx * level + SIZE / 2;
91  
92          int y = drawingArea.y + (drawingArea.height - SIZE) / 2;
93  
94          if (leaf && !_drawIcons) {
95              drawLeaf(gc, SIZE, x, y);
96          } else if (expanded && !leaf) {
97              if (_nodeMarkType == 1) {
98                  drawMinus(gc, SIZE, x, y);
99              } else if (_nodeMarkType == 2) {
100                 drawTriangleDown(gc, SIZE, x, y);
101             }
102         } else if (!leaf) {
103             if (_nodeMarkType == 1) {
104                 drawPlus(gc, SIZE, x, y);
105             } else if (_nodeMarkType == 2) {
106                 drawTriangleRight(gc, SIZE, x, y);
107             }
108         }
109         if (_nodeMarkType != 0) {
110             x += SIZE + 4;
111         }
112 
113         if (_drawBorder) {
114             gc.drawRectangle(drawingArea);
115         }
116         
117         // default for drawing selection
118         Rectangle labelrect = drawingArea;
119 
120         if (_labelProvider != null && (_drawIcons || _drawLabels)) {
121             int labelx = x;
122             String label = _labelProvider.getText(row);
123             labelrect = new Rectangle(x, y, 0, 0);
124             if (label != null) {
125                 Point extent = gc.stringExtent(label);
126                 labelrect.y = drawingArea.y+(drawingArea.height-extent.y)/2;
127 //                labelrect.y-=extent.y/2;
128                 labelrect.width += extent.x;
129                 labelrect.height = Math.max(labelrect.height, extent.y);
130             }
131             
132             
133             if (_drawIcons) {
134                 Image img = _labelProvider.getImage(row);
135                 if (img != null) {
136                     if (!printing) {
137                         gc.drawImage(img, x, y);
138                         labelx += img.getBounds().width;
139                         labelrect.width += img.getBounds().width;
140                         labelrect.height = img.getBounds().height;
141                     } else {
142                         gc.drawImage(img, 0, 0, img.getBounds().width, img.getBounds().height, x, y, scaleX(img
143                                 .getBounds().width), scaleY(img.getBounds().height));
144                         labelx += scaleX(img.getBounds().width);
145                         labelrect.width += scaleX(img.getBounds().width);
146                         labelrect.height = scaleY(img.getBounds().height);
147                     }
148                 }
149             }
150             if (_drawLabels) {
151                 gc.drawString(label, labelx, labelrect.y);
152             }
153         }
154 
155         // draw tree connections
156         if (_drawTree) {
157             // TimeBarNode node = (TimeBarNode) row;
158             if (printing) {
159                 gc.setLineWidth(3);
160             }
161             gc.setLineStyle(SWT.LINE_DOT);
162             int midy = drawingArea.y + ((drawingArea.height - SIZE) / 2) + SIZE / 2;
163             int icoy = drawingArea.y + ((drawingArea.height - SIZE) / 2) + SIZE;
164             int icox = drawingArea.x + offx * (level) + SIZE - SIZE / 2;
165             int midx = drawingArea.x + +offx * (level) + SIZE;
166             int beginx = drawingArea.x + offx * (level - 1) + SIZE;
167             int endx = drawingArea.x + offx * (level + 1) + SIZE;
168 
169             // connection
170             gc.drawLine(beginx, midy, icox, midy);
171 
172             // uplink
173             gc.drawLine(beginx, drawingArea.y, beginx, midy);
174 
175             // downlink
176             if ((!leaf && expanded)) {
177                 gc.drawLine(midx, icoy, midx, drawingArea.y + drawingArea.height);
178             }
179 
180             boolean hasMoreSiblings = true;
181             if (jaretTable.getTableModel() instanceof StdHierarchicalTableModel) {
182                 StdHierarchicalTableModel model = (StdHierarchicalTableModel) jaretTable.getTableModel();
183                 hasMoreSiblings = model.moreSiblings(node, node.getLevel());
184             }
185 
186             // // downlink on begin
187             // // if has more siblings
188             // if (hasMoreSiblings) {
189             // // gc.drawLine(beginx, icoy, beginx,
190             // drawingArea.y+drawingArea.height);
191             // }
192 
193             // level lines
194             if (jaretTable.getTableModel() instanceof StdHierarchicalTableModel) {
195                 StdHierarchicalTableModel model = (StdHierarchicalTableModel) jaretTable.getTableModel();
196                 for (int i = 0; i < level; i++) {
197                     if (model.moreSiblings(node, i)) {
198                         x = drawingArea.x + offx * i + SIZE;
199                         gc.drawLine(x, drawingArea.y, x, drawingArea.y + drawingArea.height);
200                     }
201                 }
202             }
203 
204             gc.setLineStyle(SWT.LINE_SOLID);
205             gc.setLineWidth(1);
206         }
207         
208         Rectangle selectionRect = labelrect;
209         if (_drawFullSelection) {
210             selectionRect = drawingArea;
211         }
212         
213         if (drawFocus) {
214             drawFocus(gc, selectionRect);
215         }
216         drawSelection(gc, selectionRect, cellStyle, selected, printing);
217 
218     }
219 
220     protected void drawPlus(GC gc, int size, int x, int y) {
221         gc.drawLine(x + SIGNINSETS, y + size / 2, x + size - SIGNINSETS, y + size / 2);
222         gc.drawLine(x + size / 2, y + SIGNINSETS, x + size / 2, y + size - SIGNINSETS);
223         gc.drawRectangle(x, y, size, size);
224     }
225 
226     protected void drawMinus(GC gc, int size, int x, int y) {
227         gc.drawLine(x + SIGNINSETS, y + size / 2, x + size - SIGNINSETS, y + size / 2);
228         gc.drawRectangle(x, y, size, size);
229     }
230 
231     protected void drawTriangleDown(GC gc, int size, int x, int y) {
232         Color bg = gc.getBackground();
233         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
234         int[] pArray = new int[] { x, y, x + size, y, x + size / 2, y + size - 3 };
235         gc.fillPolygon(pArray);
236         gc.setBackground(bg);
237     }
238 
239     protected void drawTriangleRight(GC gc, int size, int x, int y) {
240         Color bg = gc.getBackground();
241         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
242         int[] pArray = new int[] { x, y, x + size - 3, y + size / 2, x, y + size };
243         gc.fillPolygon(pArray);
244         gc.setBackground(bg);
245     }
246 
247     protected void drawLeaf(GC gc, int size, int x, int y) {
248         Color bg = gc.getBackground();
249         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
250         gc.fillOval(x + size / 2, y + size / 2, size / 2, size / 2);
251         gc.setBackground(bg);
252     }
253 
254     /***
255      * {@inheritDoc}
256      */
257     public boolean contains(Rectangle drawingArea, int x, int y) {
258         return true;
259     }
260 
261     /***
262      * {@inheritDoc}
263      */
264     public int getPreferredWidth() {
265         return scaleX(SIZE + 4);
266     }
267 
268     /***
269      * {@inheritDoc}
270      */
271     public void dispose() {
272         if (_labelProvider != null) {
273             _labelProvider.dispose();
274         }
275     }
276 
277     /***
278      * @return Returns the labelProvider.
279      */
280     public ILabelProvider getLabelProvider() {
281         return _labelProvider;
282     }
283 
284     /***
285      * @param labelProvider The labelProvider to set.
286      */
287     public void setLabelProvider(ILabelProvider labelProvider) {
288         _labelProvider = labelProvider;
289     }
290 
291     /***
292      * @return Returns the levelWidth.
293      */
294     public int getLevelWidth() {
295         return _levelWidth;
296     }
297 
298     /***
299      * @param levelWidth The levelWidth to set.
300      */
301     public void setLevelWidth(int levelWidth) {
302         _levelWidth = levelWidth;
303     }
304 
305     /***
306      * @return Returns the drawIcons.
307      */
308     public boolean getDrawIcons() {
309         return _drawIcons;
310     }
311 
312     /***
313      * @param drawIcons The drawIcons to set.
314      */
315     public void setDrawIcons(boolean drawIcons) {
316         this._drawIcons = drawIcons;
317     }
318 
319     /***
320      * @return Returns the drawLabels.
321      */
322     public boolean getDrawLabels() {
323         return _drawLabels;
324     }
325 
326     /***
327      * @param drawLabels The drawLabels to set.
328      */
329     public void setDrawLabels(boolean drawLabels) {
330         this._drawLabels = drawLabels;
331     }
332 
333     /***
334      * {@inheritDoc}
335      */
336     public ICellRenderer createPrintRenderer(Printer printer) {
337         TableHierarchyRenderer r = new TableHierarchyRenderer(printer);
338         r.setDrawIcons(_drawIcons);
339         r.setDrawLabels(_drawLabels);
340         r.setLevelWidth(_levelWidth);
341         r.setLabelProvider(_labelProvider);
342         return r;
343     }
344 
345     /***
346      * {@inheritDoc}
347      */
348     public int getPreferredWidth(List<IRow> rows, IColumn column) {
349         return -1;
350     }
351 
352     /***
353      * {@inheritDoc}
354      */
355     public int getPreferredHeight(IRow row, IColumn column) {
356         return -1;
357     }
358 
359     /***
360      * {@inheritDoc}
361      */
362     public boolean isInActiveArea(IRow row, Rectangle drawingArea, int xx, int yy) {
363         int offx = scaleX(_levelWidth);
364         ITableNode node = (ITableNode) row;
365         int level = node.getLevel();
366         boolean leaf = node.getChildren().size() == 0;
367         // leaves can not be toggled
368         if (leaf) {
369             return false;
370         }
371 
372         int x = drawingArea.x + offx * level + SIZE / 2;
373         int y = drawingArea.y + (drawingArea.height - SIZE) / 2;
374 
375         return x <= xx && xx <= x + SIZE && y <= yy && yy <= y + SIZE;
376     }
377     
378     public boolean getDrawBorder() {
379         return _drawBorder;
380     }
381 
382     public void setDrawBorder(boolean drawBorder) {
383         _drawBorder = drawBorder;
384     }
385 
386     public boolean getDrawTree() {
387         return _drawTree;
388     }
389 
390     public void setDrawTree(boolean drawTree) {
391         _drawTree = drawTree;
392     }
393 
394     public boolean getDrawFullSelection() {
395         return _drawFullSelection;
396     }
397 
398     public void setDrawFUllSelection(boolean drawFullSelection) {
399         _drawFullSelection = drawFullSelection;
400     }
401 
402 }