View Javadoc

1   /*
2    *  File: OldDefaultTimeScaleRenderer.java 
3    *  Copyright (c) 2004-2009  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.renderer;
21  
22  import org.eclipse.swt.graphics.GC;
23  import org.eclipse.swt.graphics.Rectangle;
24  import org.eclipse.swt.printing.Printer;
25  
26  import de.jaret.util.date.DateUtils;
27  import de.jaret.util.date.JaretDate;
28  import de.jaret.util.date.holidayenumerator.HolidayEnumerator;
29  import de.jaret.util.swt.SwtGraphicsHelper;
30  import de.jaret.util.ui.timebars.TickScaler;
31  import de.jaret.util.ui.timebars.TickScaler.Range;
32  import de.jaret.util.ui.timebars.TimeBarViewerDelegate;
33  import de.jaret.util.ui.timebars.TimeBarViewerInterface;
34  import de.jaret.util.ui.timebars.swt.TimeBarViewer;
35  
36  /**
37   * A default timescale renderer using the TickScaler to render a readable scale for use cases taht display something in
38   * the range of hours and more in the timebar viewer. A holiday enumerator is used to display special and holidays in
39   * the tooltip. Suports horizontal and ertical orientation.
40   * 
41   * @author Peter Kliem
42   * @version $Id: OldDefaultTimeScaleRenderer.java 1086 2011-07-30 20:28:05Z kliem $
43   */
44  public class OldDefaultTimeScaleRenderer extends RendererBase implements TimeScaleRenderer {
45  
46      /** preferred height. */
47      protected static final int PREFERREDHEIGHT = 50;
48  
49      /** aproximate number of seconds in one month. */
50      private static final long APPROXSECONDSINMONTH = (24 * 60 * 7 * 4);
51  
52      /** length of minor ticks. */
53      protected static final int MINORLENGTH = 5;
54      /** length of major ticks. */
55      protected static final int MAJORLENGTH = 10;
56  
57      /** remember tha last range for tooltip display. */
58      private Range _lastRange = Range.DAY;
59  
60      /** holiday enumeratotr for tooltips. */
61      protected HolidayEnumerator _holidayEnumerator;
62  
63      /**
64       * Construct the renderer for a prinetr device.
65       * 
66       * @param printer printer device
67       */
68      public OldDefaultTimeScaleRenderer(Printer printer) {
69          super(printer);
70      }
71  
72      /**
73       * Default constructor.
74       */
75      public OldDefaultTimeScaleRenderer() {
76          super(null);
77      }
78  
79      /**
80       * Set a holidayenumerator for diasplaying special days as tooltip.
81       * 
82       * @param he holidayenumerator to use
83       */
84      public void setHolidayEnumerator(HolidayEnumerator he) {
85          _holidayEnumerator = he;
86      }
87  
88      /**
89       * {@inheritDoc}
90       */
91      public void draw(GC gc, Rectangle drawingArea, TimeBarViewerDelegate delegate, boolean top, boolean printing) {
92          if (delegate.getOrientation() == TimeBarViewerInterface.Orientation.HORIZONTAL) {
93              drawHorizontal(gc, drawingArea, delegate, top, printing);
94          } else {
95              drawVertical(gc, drawingArea, delegate, top, printing);
96          }
97      }
98  
99      /**
100      * Draw the horizontal scale.
101      * 
102      * @param gc GC
103      * @param drawingArea drawing area
104      * @param delegate the timebar viewer delegate
105      * @param top true for top position
106      * @param printing true if printing
107      */
108     public void drawHorizontal(GC gc, Rectangle drawingArea, TimeBarViewerDelegate delegate, boolean top,
109             boolean printing) {
110         int ox = drawingArea.x;
111 
112         int basey;
113         int minorOff;
114         int majorOff;
115         int majorLabelOff;
116         int dayOff;
117 
118         if (!top) {
119             basey = drawingArea.y;
120             minorOff = scaleY(MINORLENGTH);
121             majorOff = scaleY(MAJORLENGTH);
122             majorLabelOff = scaleY(22);
123             dayOff = scaleY(34);
124         } else {
125             basey = drawingArea.y + drawingArea.height - 1;
126             minorOff = scaleY(-MINORLENGTH);
127             majorOff = scaleY(-MAJORLENGTH);
128             majorLabelOff = scaleY(-10);
129             dayOff = scaleY(-22);
130         }
131         int oy = basey;
132 
133         int width = drawingArea.width;
134         JaretDate date = delegate.getStartDate().copy();
135 
136         int idx;
137         if (!printing) {
138             idx = TickScaler.getTickIdx(delegate.getPixelPerSecond() / getScaleX());
139         } else {
140             idx = TickScaler.getTickIdx(delegate.getPixelPerSecond() / getScaleX());
141         }
142         int majTick = TickScaler.getMajorTickMinutes(idx);
143         int minTick = TickScaler.getMinorTickMinutes(idx);
144         TickScaler.Range range = TickScaler.getRange(idx);
145         _lastRange = range;
146 
147         // clean starting date on a major tick minute position (starting with a
148         // day)
149         date.setMinutes(0);
150         date.setHours(0);
151         date.setSeconds(0);
152 
153         // if range is week take a week starting point
154         if (range == Range.WEEK) {
155             while (date.getDayOfWeek() != DateUtils.getFirstDayOfWeek()) {
156                 date.backDays(1.0);
157             }
158         } else if (range == Range.MONTH) {
159             // month -> month starting point
160             date.setDay(1);
161         }
162         JaretDate save = date.copy();
163 
164         if (printing) {
165             gc.setLineWidth(1);
166         }
167         // draw top/bottom line
168         gc.drawLine(ox, oy, ox + width, oy);
169 
170         // draw the minor ticks
171         while (delegate.xForDate(date) < ox + width) {
172             int x = delegate.xForDate(date);
173             gc.drawLine(x, oy, x, oy + minorOff);
174             if (range == Range.MONTH) {
175                 int adv = Math.round(minTick / APPROXSECONDSINMONTH);
176                 if (adv == 0) {
177                     adv = 1;
178                 }
179                 date.advanceMonths(adv);
180             } else {
181                 date.advanceMinutes(minTick);
182             }
183         }
184 
185         date = save.copy();
186         // draw the major ticks
187         while (delegate.xForDate(date) < ox + width) {
188             int x = delegate.xForDate(date);
189             gc.drawLine(x, oy, x, oy + majorOff);
190             if (range == Range.MONTH) {
191                 int adv = Math.round(majTick / APPROXSECONDSINMONTH);
192                 if (adv == 0) {
193                     adv = 1;
194                 }
195                 date.advanceMonths(adv);
196             } else {
197                 date.advanceMinutes(majTick);
198             }
199         }
200 
201         gc.setLineWidth(1);
202 
203         // labels: draw every two major ticks
204         date = save.copy();
205         int lastDay = date.getDay();
206         boolean second = true;
207         int count = 0;
208         boolean third = true;
209         // Labels are drawn beyond the width. Otherwise when the beginning of
210         // the labels
211         // would not be drawn when the tick itself is out of sight
212         while (delegate.xForDate(date) < drawingArea.x + drawingArea.width) {
213             int x = delegate.xForDate(date);
214             if (date.getMinutes() % (majTick * 2) == 0) {
215                 // Second line
216                 String str = null;
217                 if (range == Range.HOUR) {
218                     // time
219                     str = date.toDisplayStringTime();
220                 } else if (range == Range.DAY) {
221                     // day
222                     str = date.getShortDayOfWeekString();
223                 } else if (range == Range.WEEK) {
224                     // week
225                     str = "KW" + date.getWeekOfYear();
226                 } else if (range == Range.MONTH) {
227                     // month
228                     str = Integer.toString(date.getYear());
229                 }
230                 // draw
231                 if (x > SwtGraphicsHelper.getStringDrawingWidth(gc, str) / 2) {
232                     SwtGraphicsHelper.drawStringCentered(gc, str, x, oy + majorLabelOff);
233                 }
234                 // first line
235                 if (range == Range.HOUR) {
236                     if (date.getDay() != lastDay) {
237                         str = date.getDay() + ". (" + date.getDayOfWeekString() + ")";
238                     } else {
239                         str = "";
240                     }
241                     lastDay = date.getDay();
242                 } else if (range == Range.DAY || range == Range.WEEK) {
243                     str = date.getDay() + "." + (third ? date.getShortMonthString() : "");
244                 } else if (range == Range.MONTH) {
245                     str = date.getMonthString();
246                 }
247                 second = !second;
248                 third = count++ % 3 == 0;
249                 SwtGraphicsHelper.drawStringCentered(gc, str, x, oy + dayOff);
250             }
251             if (range == Range.MONTH) {
252                 int adv = Math.round(majTick / APPROXSECONDSINMONTH);
253                 if (adv == 0) {
254                     adv = 1;
255                 }
256                 date.advanceMonths(adv);
257             } else {
258                 date.advanceMinutes(majTick);
259             }
260         }
261     }
262 
263     /**
264      * Draw the vertical scale.
265      * 
266      * @param gc GC
267      * @param drawingArea drawing area
268      * @param delegate the timebar viewer delegate
269      * @param top true for left position
270      * @param printing true if printing
271      */
272     private void drawVertical(GC gc, Rectangle drawingArea, TimeBarViewerDelegate delegate, boolean top,
273             boolean printing) {
274         int oy = drawingArea.y;
275 
276         int basex;
277         int minorOff;
278         int majorOff;
279         int majorLabelOff;
280         int dayOff;
281 
282         if (!top) {
283             basex = drawingArea.x;
284             minorOff = scaleX(MINORLENGTH);
285             majorOff = scaleX(MAJORLENGTH);
286             majorLabelOff = scaleX(22);
287             dayOff = scaleX(34);
288         } else {
289             basex = drawingArea.x + drawingArea.width - 1;
290             minorOff = scaleX(-MINORLENGTH);
291             majorOff = scaleX(-MAJORLENGTH);
292             majorLabelOff = scaleX(-10);
293             dayOff = scaleX(-22);
294         }
295         int ox = basex;
296 
297         int height = drawingArea.height;
298         JaretDate date = delegate.getStartDate().copy();
299 
300         int idx = TickScaler.getTickIdx(delegate.getPixelPerSecond() / getScaleY());
301 
302         int majTick = TickScaler.getMajorTickMinutes(idx);
303         int minTick = TickScaler.getMinorTickMinutes(idx);
304         TickScaler.Range range = TickScaler.getRange(idx);
305         _lastRange = range;
306 
307         // clean starting date on a major tick minute position (starting with a
308         // day)
309         date.setMinutes(0);
310         date.setHours(0);
311         date.setSeconds(0);
312 
313         // if range is week take a week starting point
314         if (range == Range.WEEK) {
315             while (date.getDayOfWeek() != DateUtils.getFirstDayOfWeek()) {
316                 date.backDays(1.0);
317             }
318         } else if (range == Range.MONTH) {
319             // month -> month starting point
320             date.setDay(1);
321         }
322         JaretDate save = date.copy();
323 
324         if (printing) {
325             gc.setLineWidth(1);
326         }
327         // draw top/bottom line
328         gc.drawLine(ox, oy, ox, oy + height);
329 
330         // draw the minor ticks
331         while (delegate.xForDate(date) < oy + height) {
332             int y = delegate.xForDate(date);
333             gc.drawLine(ox, y, ox + minorOff, y);
334             if (range == Range.MONTH) {
335                 int adv = Math.round(minTick / APPROXSECONDSINMONTH);
336                 if (adv == 0) {
337                     adv = 1;
338                 }
339                 date.advanceMonths(adv);
340             } else {
341                 date.advanceMinutes(minTick);
342             }
343         }
344 
345         date = save.copy();
346         // draw the major ticks
347         while (delegate.xForDate(date) < oy + height) {
348             int y = delegate.xForDate(date);
349             gc.drawLine(ox, y, ox + majorOff, y);
350             if (range == Range.MONTH) {
351                 int adv = Math.round(majTick / APPROXSECONDSINMONTH);
352                 if (adv == 0) {
353                     adv = 1;
354                 }
355                 date.advanceMonths(adv);
356             } else {
357                 date.advanceMinutes(majTick);
358             }
359         }
360 
361         gc.setLineWidth(1);
362 
363         // labels: draw every two major ticks
364         date = save.copy();
365         // Labels are drawn beyond the width. Otherwise when the beginning of
366         // the labels
367         // would not be drawn when the tick itself is out of sight
368         while (delegate.xForDate(date) < drawingArea.y + drawingArea.height + 50) {
369             int y = delegate.xForDate(date);
370             if (date.getMinutes() % (majTick * 2) == 0) {
371                 // Second line
372                 String str = null;
373                 if (range == Range.HOUR) {
374                     // time
375                     str = date.toDisplayStringTime();
376                 } else if (range == Range.DAY) {
377                     // day
378                     str = date.getShortDayOfWeekString();
379                 } else if (range == Range.WEEK) {
380                     // week
381                     str = "KW" + date.getWeekOfYear();
382                 } else if (range == Range.MONTH) {
383                     // month
384                     str = Integer.toString(date.getYear());
385                 }
386                 // draw
387                 if (top) {
388                     SwtGraphicsHelper.drawStringRightAlignedVCenter(gc, str, drawingArea.x + drawingArea.width
389                             + majorOff, y);
390                 } else {
391                     SwtGraphicsHelper.drawStringLeftAlignedVCenter(gc, str, drawingArea.x + majorOff, y);
392                 }
393                 // // first line
394                 // if (range == Range.HOUR) {
395                 // if (date.getDay() != lastDay) {
396                 // str = date.getDay() + ". (" + date.getDayOfWeekString() + ")";
397                 // } else {
398                 // str = "";
399                 // }
400                 // lastDay = date.getDay();
401                 // } else if (range == Range.DAY || range == Range.WEEK) {
402                 // str = date.getDay() + "." + (third ? date.getShortMonthString() : "");
403                 // } else if (range == Range.MONTH) {
404                 // str = date.getMonthString();
405                 // }
406                 // second = !second;
407                 // third = count++ % 3 == 0;
408                 // SwtGraphicsHelper.drawStringCentered(gc, str, x, oy + dayOff);
409             }
410             if (range == Range.MONTH) {
411                 int adv = Math.round(majTick / APPROXSECONDSINMONTH);
412                 if (adv == 0) {
413                     adv = 1;
414                 }
415                 date.advanceMonths(adv);
416             } else {
417                 date.advanceMinutes(majTick);
418             }
419         }
420     }
421 
422     /**
423      * {@inheritDoc}
424      */
425     public String getToolTipText(TimeBarViewer tbv, Rectangle drawingArea, int x, int y) {
426 
427         TimeBarViewerDelegate delegate = (TimeBarViewerDelegate) tbv.getData("delegate");
428         JaretDate date = null;
429         if (delegate.getOrientation() == TimeBarViewerInterface.Orientation.HORIZONTAL) {
430             date = tbv.dateForX(x);
431         } else {
432             date = tbv.dateForX(y);
433         }
434 
435         String str = getToolTipTextForDate(date, _lastRange);
436         if (_holidayEnumerator != null) {
437             if (_holidayEnumerator.isHoliday(date.getDate()) || _holidayEnumerator.isSpecialDay(date.getDate())) {
438                 str += "\n" + _holidayEnumerator.getDayName(date.getDate());
439             }
440         }
441         return str;
442     }
443 
444     /**
445      * Convert date to string for tooltip display.
446      * 
447      * @param date date
448      * @param range last range
449      * @return string for displaying as tooltip
450      */
451     protected String getToolTipTextForDate(JaretDate date, Range range) {
452         String str;
453         if (range == Range.HOUR) {
454             str = date.toDisplayString();
455         } else {
456             str = date.toDisplayStringDate();
457         }
458         return str;
459     }
460 
461     /**
462      * {@inheritDoc}
463      */
464     public int getHeight() {
465         if (_printer == null) {
466             return PREFERREDHEIGHT;
467         } else {
468             return scaleY(PREFERREDHEIGHT);
469         }
470     }
471 
472     /**
473      * {@inheritDoc}
474      */
475     public void dispose() {
476         // nothing to dispose
477     }
478 
479     /**
480      * {@inheritDoc}
481      */
482     public TimeScaleRenderer createPrintRenderer(Printer printer) {
483         OldDefaultTimeScaleRenderer dtsr = new OldDefaultTimeScaleRenderer(printer);
484         dtsr.setHolidayEnumerator(_holidayEnumerator);
485         return dtsr;
486     }
487 
488     /**
489      * {@inheritDoc}
490      */
491     public boolean supportsOptimizedScrolling() {
492         return true;
493     }
494 
495 }