View Javadoc

1   /*
2    *  File: RenderDelegate.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    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation; either version 2 of the License, or
9    *  (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *  GNU General Public License for more details.
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */
20  package de.jaret.util.ui.timebars.swt;
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.eclipse.swt.graphics.Color;
26  import org.eclipse.swt.graphics.GC;
27  import org.eclipse.swt.graphics.Rectangle;
28  
29  import de.jaret.util.date.Interval;
30  import de.jaret.util.date.JaretDate;
31  import de.jaret.util.ui.timebars.TimeBarMarker;
32  import de.jaret.util.ui.timebars.TimeBarViewerDelegate;
33  import de.jaret.util.ui.timebars.TimeBarViewerInterface;
34  import de.jaret.util.ui.timebars.model.TimeBarNode;
35  import de.jaret.util.ui.timebars.model.TimeBarRow;
36  import de.jaret.util.ui.timebars.model.TimeBarRowHeader;
37  import de.jaret.util.ui.timebars.strategy.OverlapInfo;
38  import de.jaret.util.ui.timebars.swt.renderer.GridRenderer;
39  import de.jaret.util.ui.timebars.swt.renderer.HeaderRenderer;
40  import de.jaret.util.ui.timebars.swt.renderer.HierarchyRenderer;
41  import de.jaret.util.ui.timebars.swt.renderer.TimeBarGapRenderer;
42  import de.jaret.util.ui.timebars.swt.renderer.TimeBarMarkerRenderer;
43  import de.jaret.util.ui.timebars.swt.renderer.TimeBarRenderer;
44  import de.jaret.util.ui.timebars.swt.renderer.TimeBarRenderer2;
45  import de.jaret.util.ui.timebars.swt.renderer.TimeScaleRenderer;
46  import de.jaret.util.ui.timebars.swt.renderer.TitleRenderer;
47  
48  /**
49   * This class contains the actual methods used for rendering a time bar viewer. They have been factored out to support
50   * both printing (headless) and painting on the screen.
51   * 
52   * @author Peter Kliem
53   * @version $Id: RenderDelegate.java 803 2008-12-28 19:30:23Z kliem $
54   */
55  public class RenderDelegate {
56  
57      /**
58       * Draw a timebar row (used by the timebar printer).
59       * 
60       * @param delegate the delegate
61       * @param tbPrinter timebar printer
62       * @param headerRenderer header renderer
63       * @param hierarchyRenderer renderer for the hierarchy
64       * @param printing tru for printing
65       * @param gc GC to use
66       * @param row row to draw
67       * @param y begin y
68       * @param selected true if the row is selected
69       */
70      public static void drawRowSimple(TimeBarViewerDelegate delegate, TimeBarPrinter tbPrinter,
71              HeaderRenderer headerRenderer, HierarchyRenderer hierarchyRenderer, boolean printing, GC gc,
72              TimeBarRow row, int y, boolean selected) {
73          // first of all draw the row header
74          if (row.getRowHeader() != null) {
75              drawRowHeaderHorizontal(delegate, headerRenderer, printing, gc, y, row.getRowHeader(), selected, row);
76          }
77  
78          // the draw the hierarchy display if configured
79          if (hierarchyRenderer != null && delegate.getHierarchyWidth() > 0) {
80              drawHierarchy(delegate, hierarchyRenderer, printing, gc, y, row, selected);
81          }
82  
83          int rowHeight = delegate.getTimeBarViewState().getRowHeight(row);
84  
85          Rectangle clipSave = gc.getClipping();
86          gc.setClipping(TimeBarViewer.convertRect(delegate.getDiagramRect()));
87  
88          // row grid if configured
89          if (delegate.getDrawRowGrid()) {
90              Color fg = gc.getForeground();
91              // check whether the line is inside the diagram rect
92              int ly = y + rowHeight - 1;
93              if (delegate.getDiagramRect().y + delegate.getDiagramRect().height > ly) {
94                  gc.drawLine(delegate.getDiagramRect().x, ly, delegate.getDiagramRect().x
95                          + delegate.getDiagramRect().width, ly);
96              }
97              gc.setForeground(fg);
98          }
99  
100         // use the clipping bounds to reduce the painted intervals
101         JaretDate start = delegate.getStartDate();
102         JaretDate end = delegate.getEndDate();
103         if (gc.isClipped()) {
104             start = delegate.dateForCoord(gc.getClipping().x);
105             end = delegate.dateForCoord(gc.getClipping().x + gc.getClipping().width);
106         }
107         List<Interval> intervals = row.getIntervals(start, end);
108         for (Interval i : intervals) {
109             // apply filter on intervals if set
110             if (delegate.getIntervalFilter() == null || delegate.getIntervalFilter().isInResult(i)) {
111                 // get the renderer for that interval
112                 TimeBarRenderer renderer = tbPrinter.getRenderer(i.getClass());
113                 if (delegate.getTimeBarViewState().getDrawOverlapping(row)) {
114                     drawIntervalHorizontal(delegate, renderer, printing, gc, y, i, null, row);
115                 } else {
116                     drawIntervalHorizontal(delegate, renderer, printing, gc, y, i, delegate.getOverlapStrategy()
117                             .getOverlapInfo(row, i), row);
118                 }
119             }
120         }
121         gc.setClipping(clipSave);
122     }
123 
124     /**
125      * Render the row gaps horizontal.
126      * 
127      * @param delegate the delegate
128      * @param renderer the gap renderer to use
129      * @param printing true for printing
130      * @param gc GC
131      * @param x begin x
132      * @param y begin y
133      * @param row row to draw the gaps for
134      * @param selected true if the row is selected
135      */
136     public static void drawRowGaps(TimeBarViewerDelegate delegate, TimeBarGapRenderer renderer, boolean printing,
137             GC gc, int x, int y, TimeBarRow row, boolean selected) {
138         // TODO VERTICAL
139         // use the clip bounds (if given) to shorten the region to be
140         // painted
141         JaretDate start = delegate.getStartDate();
142         JaretDate end = delegate.getEndDate();
143         if (gc.isClipped()) {
144             start = delegate.dateForXY(gc.getClipping().x, gc.getClipping().y);
145             end = delegate.dateForXY(gc.getClipping().x + gc.getClipping().width, gc.getClipping().y
146                     + gc.getClipping().height);
147         }
148         // for the gaps we need a minimum of two intervals
149         // those has to be in the displayed intervals, so we apply the
150         // filter first (if set) and do the selction
151         // ourself. The alogorithm is highly dependet on the rodering of the
152         // list! This should be guaranteed by the model
153         List<Interval> intervals = new ArrayList<Interval>();
154         Interval firstInterval = null;
155 
156         for (Interval interval : row.getIntervals()) {
157             if (delegate.getIntervalFilter() == null || delegate.getIntervalFilter().isInResult(interval)) {
158                 if (interval.getEnd().compareTo(start) < 0) {
159                     // before the starting date: remember the nearest
160                     // interval
161                     if (firstInterval == null
162                             || start.diffMilliSeconds(interval.getEnd()) < start.diffMilliSeconds(firstInterval
163                                     .getEnd())) {
164                         firstInterval = interval;
165                     }
166                 } else if (interval.contains(start)) {
167                     // direct hit
168                     firstInterval = interval;
169                 } else {
170                     // in or after the starting date: copy the intervals
171                     // until we have one behind the end date or
172                     // a direct hit
173                     // First of all, add the firstInterval to the resulting
174                     // list once
175                     if (firstInterval != null) {
176                         intervals.add(firstInterval);
177                         firstInterval = null; // we don't need the reference
178                         // and by setting it to null
179                         // we do not add it twice
180                     }
181                     if (interval.contains(end)) {
182                         // direct hit
183                         intervals.add(interval);
184                         break; // finished
185                     }
186                     if (interval.getBegin().compareTo(end) > 0) {
187                         intervals.add(interval);
188                         break; // found an interval beginning behind the end
189                         // date
190                     } else {
191                         // all between: add
192                         intervals.add(interval);
193                     }
194                 }
195             }
196         }
197         Interval lastInterval = null;
198         for (Interval i : intervals) {
199             // draw gap if there is lastInterval
200             if (lastInterval != null) {
201                 RenderDelegate.drawGap(delegate, renderer, false, gc, row, x, y, lastInterval, i);
202             }
203             // remember last interval for next turn
204             lastInterval = i;
205         }
206     }
207 
208     /**
209      * Render a single interval.
210      * 
211      * @param delegate th edelegate
212      * @param renderer renderer to use
213      * @param printing true for printing
214      * @param gc GC
215      * @param y begin y
216      * @param interval the interval to render
217      * @param selected true if the intervals should be drawn selected
218      */
219     // public static void drawIntervalX(TimeBarViewerDelegate delegate, TimeBarRenderer renderer, boolean printing, GC
220     // gc,
221     // int y, Interval interval, boolean selected) {
222     // if (renderer != null) {
223     // int x = delegate.xForDate(interval.getBegin());
224     // int x2 = delegate.xForDate(interval.getEnd());
225     // int width = x2 - x;
226     // if (x2 < delegate.getDiagramRect().x) {
227     // // if the end is not shown, simply return
228     // return;
229     // }
230     // int height = delegate.getRowHeight();
231     // Rectangle drawingArea = new Rectangle(x, y, width, height);
232     //
233     // // calculate height for clipping
234     // if (y + height > delegate.getDiagramRect().y + delegate.getDiagramRect().height) {
235     // height = height - (y + height - (delegate.getDiagramRect().y + delegate.getDiagramRect().height));
236     // }
237     // // calc x clipping and set clipping rect
238     // Rectangle clip = new Rectangle(x < delegate.getDiagramRect().x ? delegate.getDiagramRect().x : x, y, width,
239     // height);
240     //
241     // Rectangle clipSave = gc.getClipping();
242     // gc.setClipping(clip.intersection(clipSave));
243     // renderer.draw(gc, drawingArea, delegate, interval, selected, printing, false);
244     // gc.setClipping(clipSave);
245     // }
246     // }
247     /**
248      * Draws a single interval.
249      * 
250      * @param delegate delegate
251      * @param renderer renderer to use
252      * @param printing true if this rendering is for a printer
253      * @param gc GC to paint on
254      * @param y y coordinate of the row
255      * @param interval interval to be painted
256      * @param oi overlap information (may be null when drawing overlapped)
257      * @param row of the interval beeing rendered
258      */
259     public static void drawIntervalHorizontal(TimeBarViewerDelegate delegate, TimeBarRenderer renderer,
260             boolean printing, GC gc, int y, Interval interval, OverlapInfo oi, TimeBarRow row) {
261         if (renderer != null) {
262             int rowHeight = delegate.getTimeBarViewState().getRowHeight(row);
263             int maxOverlapping = 1;
264             int oiPos = 0;
265             if (oi != null) {
266                 maxOverlapping = oi.maxOverlapping + 1;
267                 oiPos = oi.pos;
268             }
269 
270             int height = 0;
271             if (!delegate.getUseUniformHeight()){
272                 height = rowHeight / maxOverlapping;
273             } else {
274                 height = rowHeight / delegate.getOverlapStrategy().getMaxOverlapCount(row);
275             }
276             y = y + oiPos * height;
277             
278             int x = delegate.xForDate(interval.getBegin());
279             int x2 = delegate.xForDate(interval.getEnd());
280             int width = x2 - x;
281             Rectangle intervalArea = new Rectangle(x, y, width, height);
282 
283             boolean selected = delegate.getSelectionModel().isSelected(interval);
284             boolean overlapping = oi != null ? oi.overlappingCount > 0 : false;
285 
286             Rectangle drawingArea = new Rectangle(intervalArea.x, intervalArea.y, intervalArea.width,
287                     intervalArea.height);
288             if (renderer instanceof TimeBarRenderer2) {
289                 drawingArea = ((TimeBarRenderer2) renderer).getPreferredDrawingBounds(intervalArea, delegate, interval,
290                         selected, printing, overlapping);
291             }
292 
293             // check whether any portion of the targeted area is in the dirty range
294             if (!gc.getClipping().intersects(drawingArea)) {
295                 // nothing to do
296                 return;
297             }
298 
299             // calculate height for clipping
300             if (drawingArea.y + drawingArea.height > delegate.getDiagramRect().y + delegate.getDiagramRect().height) {
301                 height = height
302                         - (drawingArea.y + drawingArea.height - (delegate.getDiagramRect().y + delegate
303                                 .getDiagramRect().height));
304             }
305             // calc x clipping and set clipping rect
306             Rectangle clip = new Rectangle(drawingArea.x < delegate.getDiagramRect().x ? delegate.getDiagramRect().x
307                     : drawingArea.x, drawingArea.y, drawingArea.width, height);
308 
309             Rectangle clipSave = gc.getClipping();
310             gc.setClipping(clip.intersection(clipSave));
311             renderer.draw(gc, intervalArea, delegate, interval, selected, printing, overlapping);
312             gc.setClipping(clipSave);
313         }
314     }
315 
316     /**
317      * Draws a single interval (Vertical orientation).
318      * 
319      * @param delegate delegate
320      * @param renderer renderer to use
321      * @param printing true if this rendering is for a printer
322      * @param gc GC tio paint on
323      * @param x x coordinate of the row
324      * @param interval interval to be painted
325      * @param oi overlap information (may be null when drawing overlapped)
326      * @param row of the interval beeing rendered
327      */
328     public static void drawIntervalVertical(TimeBarViewerDelegate delegate, TimeBarRenderer renderer, boolean printing,
329             GC gc, int x, Interval interval, OverlapInfo oi, TimeBarRow row) {
330         if (renderer != null) {
331             int rowHeight = delegate.getTimeBarViewState().getRowHeight(row);
332             int maxOverlapping = 1;
333             int oiPos = 0;
334             if (oi != null) {
335                 maxOverlapping = oi.maxOverlapping + 1;
336                 oiPos = oi.pos;
337             }
338 
339             int width = 0;
340             if (!delegate.getUseUniformHeight()){
341                 width = rowHeight / maxOverlapping;
342             } else {
343                 width = rowHeight / delegate.getOverlapStrategy().getMaxOverlapCount(row);
344             }
345             x = x + oiPos * width;
346             int y = delegate.xForDate(interval.getBegin());
347             int y2 = delegate.xForDate(interval.getEnd());
348             int height = y2 - y;
349             Rectangle intervalArea = new Rectangle(x, y, width, height);
350 
351             boolean selected = delegate.getSelectionModel().isSelected(interval);
352             boolean overlapping = oi != null ? oi.overlappingCount > 0 : false;
353 
354             Rectangle drawingArea = new Rectangle(intervalArea.x, intervalArea.y, intervalArea.width,
355                     intervalArea.height);
356             if (renderer instanceof TimeBarRenderer2) {
357                 drawingArea = ((TimeBarRenderer2) renderer).getPreferredDrawingBounds(intervalArea, delegate, interval,
358                         selected, printing, overlapping);
359             }
360 
361             // check whether any portion of the targeted area is in the dirty range
362             if (!gc.getClipping().intersects(drawingArea)) {
363                 // nothing to do
364                 return;
365             }
366 
367             // calculate width for clipping
368             if (drawingArea.x + drawingArea.width > delegate.getDiagramRect().x + delegate.getDiagramRect().width) {
369                 width = width
370                         - (drawingArea.x + drawingArea.width - (delegate.getDiagramRect().x + delegate.getDiagramRect().width));
371             }
372             // calc y clipping and set clipping rect
373             Rectangle clip = new Rectangle(drawingArea.x, drawingArea.y < delegate.getDiagramRect().y ? delegate
374                     .getDiagramRect().y : drawingArea.y, width, drawingArea.height);
375 
376             // // calculate width for clipping
377             // if (x + width > delegate.getDiagramRect().x + delegate.getDiagramRect().width) {
378             // width = width - (x + width - (delegate.getDiagramRect().x + delegate.getDiagramRect().width));
379             // }
380             // // calc y clipping and set clipping rect
381             // Rectangle clip = new Rectangle(x, y < delegate.getDiagramRect().y ? delegate.getDiagramRect().y : y,
382             // width,
383             // height);
384 
385             Rectangle clipSave = gc.getClipping();
386             gc.setClipping(clip.intersection(clipSave));
387             renderer.draw(gc, intervalArea, delegate, interval, delegate.getSelectionModel().isSelected(interval),
388                     printing, oi.overlappingCount > 0);
389             gc.setClipping(clipSave);
390         }
391     }
392 
393     /**
394      * Draw a row header (horizontal orientation).
395      * 
396      * @param delegate the delegate
397      * @param renderer renderer to use
398      * @param printing true for printing
399      * @param gc GC
400      * @param y begin y
401      * @param header header to draw
402      * @param selected true for selected
403      * @param row of the header beeing rendered
404      */
405     public static void drawRowHeaderHorizontal(TimeBarViewerDelegate delegate, HeaderRenderer renderer,
406             boolean printing, GC gc, int y, TimeBarRowHeader header, boolean selected, TimeBarRow row) {
407         if (renderer != null && delegate.getYAxisWidth() > 0) {
408             int x = delegate.getYAxisRect().x;
409             int width = delegate.getYAxisWidth() - 1;
410             int rowHeight = delegate.getTimeBarViewState().getRowHeight(row);
411             Rectangle drawingArea = new Rectangle(x, y, width, rowHeight);
412 
413             int clipheight = rowHeight;
414             if (y + rowHeight > delegate.getDiagramRect().y + delegate.getDiagramRect().height) {
415                 clipheight = clipheight
416                         - (y + clipheight - (delegate.getDiagramRect().y + delegate.getDiagramRect().height));
417             }
418             Rectangle clip = new Rectangle(x, y, width, clipheight);
419             Rectangle clipSave = gc.getClipping();
420             gc.setClipping(clip.intersection(clipSave));
421             renderer.draw(gc, drawingArea, delegate, header, selected, printing);
422             gc.setClipping(clipSave);
423         }
424     }
425 
426     /**
427      * Draw a row header (vertical orientation).
428      * 
429      * @param delegate the delegate
430      * @param renderer renderer to use
431      * @param printing true for printing
432      * @param gc GC
433      * @param x begin x
434      * @param header header to draw
435      * @param selected true for selected
436      * @param row of the header beeing rendered
437      */
438     public static void drawRowHeaderVertical(TimeBarViewerDelegate delegate, HeaderRenderer renderer, boolean printing,
439             GC gc, int x, TimeBarRowHeader header, boolean selected, TimeBarRow row) {
440         if (renderer != null && delegate.getYAxisWidth() > 0) {
441             int y = delegate.getYAxisRect().y;
442             int height = delegate.getYAxisWidth() - 1;
443             int rowWidth = delegate.getTimeBarViewState().getRowHeight(row);
444             Rectangle drawingArea = new Rectangle(x, y, rowWidth, height);
445 
446             int clipwidth = rowWidth;
447             if (x + rowWidth > delegate.getDiagramRect().x + delegate.getDiagramRect().width) {
448                 clipwidth = clipwidth
449                         - (x + clipwidth - (delegate.getDiagramRect().x + delegate.getDiagramRect().width));
450             }
451             Rectangle clip = new Rectangle(x, y, clipwidth, height);
452             Rectangle clipSave = gc.getClipping();
453             gc.setClipping(clip.intersection(clipSave));
454             renderer.draw(gc, drawingArea, delegate, header, selected, printing);
455             gc.setClipping(clipSave);
456         }
457     }
458 
459     /**
460      * Draw hierarchy element.
461      * 
462      * @param delegate the delegate
463      * @param renderer the renderer to use
464      * @param printing true for printing
465      * @param gc GC
466      * @param y begin y
467      * @param row the element is for
468      * @param selected true for selected
469      */
470     public static void drawHierarchy(TimeBarViewerDelegate delegate, HierarchyRenderer renderer, boolean printing,
471             GC gc, int y, TimeBarRow row, boolean selected) {
472         if (renderer != null) {
473             int rowHeight = delegate.getTimeBarViewState().getRowHeight(row);
474             int level = 0;
475             int depth = 0;
476             boolean expanded = false;
477             boolean leaf = true;
478             if (row instanceof TimeBarNode) {
479                 TimeBarNode node = (TimeBarNode) row;
480                 if (delegate.getHierarchicalViewState().isExpanded(node)) {
481                     expanded = true;
482                 }
483                 leaf = node.getChildren().size() == 0;
484                 level = node.getLevel();
485                 depth = delegate.getHierarchicalModel().getDepth();
486             }
487 
488             int x = delegate.getHierarchyRect().x;
489             int width = delegate.getHierarchyWidth() - 1;
490             Rectangle drawingArea = new Rectangle(x, y, width, rowHeight);
491 
492             int clipheight = rowHeight;
493             if (y + rowHeight > delegate.getDiagramRect().y + delegate.getDiagramRect().height) {
494                 clipheight = clipheight
495                         - (y + clipheight - (delegate.getDiagramRect().y + delegate.getDiagramRect().height));
496             }
497             Rectangle clip = new Rectangle(x, y, width, clipheight);
498             Rectangle clipSave = gc.getClipping();
499             gc.setClipping(clip.intersection(clipSave));
500             // draw!
501             renderer.draw(gc, drawingArea, delegate, row, selected, expanded, leaf, level, depth, printing);
502             gc.setClipping(clipSave);
503         }
504     }
505 
506     /**
507      * Draw hierarchy element (vertical orientation).
508      * 
509      * @param delegate the delegate
510      * @param renderer the renderer to use
511      * @param printing true for printing
512      * @param gc GC
513      * @param x begin x
514      * @param row the element is for
515      * @param selected true for selected
516      */
517     public static void drawHierarchyVertical(TimeBarViewerDelegate delegate, HierarchyRenderer renderer,
518             boolean printing, GC gc, int x, TimeBarRow row, boolean selected) {
519         if (renderer != null) {
520             int level = 0;
521             int depth = 0;
522             boolean expanded = false;
523             boolean leaf = true;
524             if (row instanceof TimeBarNode) {
525                 TimeBarNode node = (TimeBarNode) row;
526                 if (delegate.getHierarchicalViewState().isExpanded(node)) {
527                     expanded = true;
528                 }
529                 leaf = node.getChildren().size() == 0;
530                 level = node.getLevel();
531                 depth = delegate.getHierarchicalModel().getDepth();
532             }
533 
534             int y = delegate.getHierarchyRect().y;
535             int height = delegate.getHierarchyWidth() - 1;
536             int rowWidth = delegate.getTimeBarViewState().getRowHeight(row);
537             Rectangle drawingArea = new Rectangle(x, y, rowWidth, height);
538 
539             int clipwidth = rowWidth;
540             if (x + rowWidth > delegate.getDiagramRect().x + delegate.getDiagramRect().width) {
541                 clipwidth = clipwidth
542                         - (x + clipwidth - (delegate.getDiagramRect().x + delegate.getDiagramRect().width));
543             }
544             Rectangle clip = new Rectangle(x, y, clipwidth, height);
545             Rectangle clipSave = gc.getClipping();
546             gc.setClipping(clip.intersection(clipSave));
547             // draw!
548             renderer.draw(gc, drawingArea, delegate, row, selected, expanded, leaf, level, depth, printing);
549             gc.setClipping(clipSave);
550 
551         }
552     }
553 
554     /**
555      * Draw the xaxis (timescale).
556      * 
557      * @param delegate the delegate
558      * @param renderer the renderer
559      * @param printing true for printing
560      * @param gc GC
561      */
562     public static void drawXAxis(TimeBarViewerDelegate delegate, TimeScaleRenderer renderer, boolean printing, GC gc) {
563         if (renderer != null && delegate.getTimeScalePosition() != TimeBarViewerInterface.TIMESCALE_POSITION_NONE) {
564             Rectangle clipSave = gc.getClipping();
565             gc.setClipping(convertRect(delegate.getXAxisRect()).intersection(clipSave));
566             renderer.draw(gc, convertRect(delegate.getXAxisRect()), delegate,
567                     delegate.getTimeScalePosition() == TimeBarViewerInterface.TIMESCALE_POSITION_TOP, printing);
568             gc.setClipping(clipSave);
569         }
570     }
571 
572     /**
573      * Render the grid (background).
574      * 
575      * @param delegate delegate
576      * @param gridRenderer the renderer to use
577      * @param printing true for printing
578      * @param gc GC
579      */
580     public static void drawGrid(TimeBarViewerDelegate delegate, GridRenderer gridRenderer, boolean printing, GC gc) {
581         if (gridRenderer != null) {
582             Rectangle clipSave = gc.getClipping();
583             gc.setClipping(convertRect(delegate.getDiagramRect()).intersection(clipSave));
584             gridRenderer.draw(gc, delegate, convertRect(delegate.getDiagramRect()), printing);
585             gc.setClipping(clipSave);
586         }
587     }
588 
589     /**
590      * Render the title area.
591      * 
592      * @param delegate the delegate
593      * @param titleRenderer the renderer
594      * @param printing true for printing
595      * @param gc GC
596      */
597     public static void drawTitle(TimeBarViewerDelegate delegate, TitleRenderer titleRenderer, boolean printing, GC gc) {
598         if (titleRenderer != null && delegate.getTimeScalePosition() != TimeBarViewerInterface.TIMESCALE_POSITION_NONE) {
599             Rectangle clipSave = gc.getClipping();
600             gc.setClipping(convertRect(delegate.getTitleRect()).intersection(clipSave));
601             titleRenderer.draw(gc, convertRect(delegate.getTitleRect()), delegate, delegate.getTitle(), printing);
602             gc.setClipping(clipSave);
603         }
604     }
605 
606     /**
607      * Draws all markers for the diagram. If a marker is not currently displayed it will not be painted.
608      * 
609      * @param delegate the delegate
610      * @param renderer the renderer to use
611      * @param printing true for printing
612      * @param gc GC
613      */
614     public static void drawMarkers(TimeBarViewerDelegate delegate, TimeBarMarkerRenderer renderer, boolean printing,
615             GC gc) {
616         if (delegate.getMarkers() != null) {
617             for (TimeBarMarker marker : delegate.getMarkers()) {
618                 if (delegate.isDisplayed(marker.getDate())) {
619                     drawMarker(delegate, renderer, printing, gc, marker);
620                 }
621             }
622         }
623     }
624 
625     /**
626      * Draw a single marker.
627      * 
628      * @param delegate the delegate
629      * @param renderer renderer to use
630      * @param printing true for printing
631      * @param gc GC
632      * @param marker the marker
633      */
634     public static void drawMarker(TimeBarViewerDelegate delegate, TimeBarMarkerRenderer renderer, boolean printing,
635             GC gc, TimeBarMarker marker) {
636         if (renderer != null) {
637             boolean isDragged = false;
638             if (delegate.getDraggedMarker() == marker) {
639                 isDragged = true;
640             }
641             renderer.draw(gc, delegate, marker, isDragged, printing);
642         }
643     }
644 
645     /**
646      * Draw a gap beetween two intervals.
647      * 
648      * @param delegate the delegate
649      * @param renderer the renderer to use
650      * @param printing true for printing
651      * @param gc GC
652      * @param row the row of both intervals
653      * @param xx begin x
654      * @param y begin y
655      * @param i1 first interval
656      * @param i2 second interval
657      */
658     public static void drawGap(TimeBarViewerDelegate delegate, TimeBarGapRenderer renderer, boolean printing, GC gc,
659             TimeBarRow row, int xx, int y, Interval i1, Interval i2) {
660         if (renderer != null) {
661             if (delegate.getOrientation() == TimeBarViewerInterface.Orientation.HORIZONTAL) {
662                 int x = delegate.xForDate(i1.getEnd());
663                 int width = delegate.xForDate(i2.getBegin()) - x;
664                 int height = delegate.getTimeBarViewState().getRowHeight(row);
665                 Rectangle drawingArea = new Rectangle(x, y, width, height);
666                 // calculate height for clipping
667                 if (y + height > delegate.getDiagramRect().y + delegate.getDiagramRect().height) {
668                     height = height - (y + height - (delegate.getDiagramRect().y + delegate.getDiagramRect().height));
669                 }
670                 // calc x clipping and set clipping rect
671                 Rectangle clip = new Rectangle(x < delegate.getDiagramRect().x ? delegate.getDiagramRect().x : x, y,
672                         width, height);
673                 Rectangle clipSave = gc.getClipping();
674                 gc.setClipping(clip.intersection(clipSave));
675                 renderer.draw(gc, delegate, row, i1, i2, drawingArea, printing);
676                 gc.setClipping(clipSave);
677             } else {
678                 // vertical
679                 int yy = delegate.xForDate(i1.getEnd());
680                 int height = delegate.xForDate(i2.getBegin()) - yy;
681                 int width = delegate.getTimeBarViewState().getRowHeight(row);
682                 Rectangle drawingArea = new Rectangle(xx, yy, width, height);
683                 // calculate width for clipping
684                 if (xx + width > delegate.getDiagramRect().x + delegate.getDiagramRect().width) {
685                     width = width - (xx + width - (delegate.getDiagramRect().x + delegate.getDiagramRect().width));
686                 }
687                 // calc y clipping and set clipping rect
688                 Rectangle clip = new Rectangle(xx, yy < delegate.getDiagramRect().y ? delegate.getDiagramRect().y : yy,
689                         width, height);
690                 Rectangle clipSave = gc.getClipping();
691                 gc.setClipping(clip.intersection(clipSave));
692                 renderer.draw(gc, delegate, row, i1, i2, drawingArea, printing);
693                 gc.setClipping(clipSave);
694             }
695         }
696     }
697 
698     /**
699      * Convert a java.awt.Rectangle to an swt one.
700      * 
701      * @param rect awt.graphics.Rectangle
702      * @return swt.graphics.Rectangle
703      */
704     private static Rectangle convertRect(java.awt.Rectangle rect) {
705         return new Rectangle(rect.x, rect.y, rect.width, rect.height);
706     }
707 
708 }