View Javadoc

1   /*
2    *  File: DefaultGridRenderer.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.renderer;
21  
22  import java.util.Calendar;
23  
24  import org.eclipse.swt.graphics.Color;
25  import org.eclipse.swt.graphics.GC;
26  import org.eclipse.swt.graphics.RGB;
27  import org.eclipse.swt.graphics.Rectangle;
28  import org.eclipse.swt.printing.Printer;
29  
30  import de.jaret.util.date.DateUtils;
31  import de.jaret.util.date.JaretDate;
32  import de.jaret.util.date.holidayenumerator.HolidayEnumerator;
33  import de.jaret.util.ui.timebars.TickScaler;
34  import de.jaret.util.ui.timebars.TickScaler.Range;
35  import de.jaret.util.ui.timebars.TimeBarViewerDelegate;
36  import de.jaret.util.ui.timebars.TimeBarViewerInterface;
37  import de.jaret.util.ui.timebars.strategy.ITickProvider;
38  
39  /**
40   * Simple default grid renderer for the timebar viewer. Uses a holiday enumerator (jaretutils) to color the days.
41   * 
42   * @author Peter Kliem
43   * @version $Id: DefaultGridRenderer.java 1073 2010-11-22 21:25:33Z kliem $
44   */
45  public class DefaultGridRenderer extends AbstractGridRenderer {
46      /** default value (pps) for coloring days. */
47      private static final double DEFAULT_UPPERPPSMARKLIMIT = 0.01;
48  
49      /** default color for the major grid (r,g,b). */
50      private static final RGB MAJORGRID_COLOR = new RGB(200, 200, 200);
51      /** default color for the minor grid (r,g,b). */
52      private static final RGB MINORGRID_COLOR = new RGB(230, 230, 230);
53      /** default color for saturdays (r,g,b). */
54      private static final RGB SATURDAY_COLOR = new RGB(255, 230, 230);
55      /** default color for sundays (r,g,b). */
56      private static final RGB SUNDAY_COLOR = new RGB(255, 200, 200);
57      /** default color for special days (r,g,b). */
58      private static final RGB SPECIALDAY_COLOR = new RGB(255, 255, 207);
59  
60      /** color of the major grid. */
61      private Color _colorMajorGrid;
62  
63      /** color of the minor grid. */
64      private Color _colorMinorGrid;
65  
66      /** color for saturdays. */
67      private Color _colorSaturday;
68  
69      /** color for sundays. */
70      private Color _colorSunday;
71  
72      /** color for special days. */
73      private Color _colorSpecialDay;
74  
75      /** holiday enumerator for coloring days. */
76      private HolidayEnumerator _holidayEnumerator;
77  
78      /** if true weekend days are colored. */
79      private boolean _markWeekends = true;
80  
81      /** if true, special day according to the holiday enumerator are marked. */
82      private boolean _markSpecialdays = true;
83  
84      /** if true, holidays according to the holiday enumerator are marked. */
85      private boolean _markHolidays = true;
86  
87      /** limit for coloring days. */
88      private double _upperPPSMarkLimit = DEFAULT_UPPERPPSMARKLIMIT;
89  
90      /** external tick provider. */
91      protected ITickProvider _tickProvider = null;
92  
93      /**
94       * Create a DefaultGridRenderer for a printer.
95       * 
96       * @param printer printer device
97       */
98      public DefaultGridRenderer(Printer printer) {
99          super(printer);
100     }
101 
102     /**
103      * Create a DefaultGridRenderer for the screen.
104      */
105     public DefaultGridRenderer() {
106         super(null);
107     }
108 
109     /**
110      * Set a tick provider to determine the ticks to be drawn. If no tick provider is set the defaulst by the tick
111      * scaler will be used.
112      * 
113      * @param tickProvider tick provider to be used or <code>null</code>.
114      */
115     public void setTickProvider(ITickProvider tickProvider) {
116         _tickProvider = tickProvider;
117     }
118 
119     /**
120      * Initialize the colors using the device in the gc.
121      * 
122      * @param gc GC carrying the device
123      */
124     private void initializeColors(GC gc) {
125         _colorMajorGrid = new Color(gc.getDevice(), MAJORGRID_COLOR);
126         _colorMinorGrid = new Color(gc.getDevice(), MINORGRID_COLOR);
127         _colorSaturday = new Color(gc.getDevice(), SATURDAY_COLOR);
128         _colorSunday = new Color(gc.getDevice(), SUNDAY_COLOR);
129         _colorSpecialDay = new Color(gc.getDevice(), SPECIALDAY_COLOR);
130     }
131 
132     /**
133      * Set the holiday enumerator to be used for coloring days.
134      * 
135      * @param he HolidayEnumerator to be used
136      */
137     public void setHolidayEnumerator(HolidayEnumerator he) {
138         _holidayEnumerator = he;
139     }
140 
141     /**
142      * If mark weekends is set to true, weekend days will be colored.
143      * 
144      * @param mark true for week end coloring
145      */
146     public void setMarkWeekends(boolean mark) {
147         _markWeekends = mark;
148     }
149 
150     /**
151      * If mark special days is set to true, days that are special days according to the holiday enumerator are colored.
152      * 
153      * @param mark true for coloring spcial days
154      */
155     public void setMarkSpecialDays(boolean mark) {
156         _markSpecialdays = mark;
157     }
158 
159     /**
160      * If mark holidaysdays is set to true, days that are holidays days according to the holiday enumerator are colored.
161      * 
162      * @param mark true for coloring holidays
163      */
164     public void setMarkHolidays(boolean mark) {
165         _markHolidays = mark;
166     }
167 
168     /**
169      * Set the limit for the pixPerSecond (scale) for marking days.
170      * 
171      * @param limit pixPerSecond limit (upper bound)
172      */
173     public void setUpperPPSMarkLimit(double limit) {
174         _upperPPSMarkLimit = limit;
175     }
176 
177     /**
178      * {@inheritDoc}
179      */
180     public void draw(GC gc, TimeBarViewerDelegate delegate, Rectangle drawingArea, boolean printing) {
181         // lazy initialize the used colors
182         if (_colorMajorGrid == null) {
183             initializeColors(gc);
184         }
185         boolean horizontal = delegate.getOrientation() == TimeBarViewerInterface.Orientation.HORIZONTAL;
186 
187         if (_tickProvider == null) {
188             drawIntern(gc, delegate, drawingArea, printing, horizontal);
189         } else {
190             drawIntern(gc, delegate, drawingArea, printing, horizontal, _tickProvider);
191         }
192 
193     }
194 
195     public void drawIntern(GC gc, TimeBarViewerDelegate delegate, Rectangle drawingArea, boolean printing,
196             boolean horizontal, ITickProvider tickProvider) {
197         int ox = drawingArea.x;
198         int oy = drawingArea.y;
199         int width = drawingArea.width;
200         int height = drawingArea.height;
201 
202         Color fg = gc.getForeground();
203 
204         if (printing) {
205             _upperPPSMarkLimit = _upperPPSMarkLimit * getScaleX();
206         }
207 
208         // first date
209         JaretDate date = delegate.getStartDate().copy();
210         date.setTime(0, 0, 0);
211 
212         int max = horizontal ? (ox + width) : (oy + height);
213 
214         // draw day backgroud if configured
215         if (_markHolidays || _markSpecialdays || _markWeekends) {
216             Color bg = gc.getBackground();
217             if (delegate.getPixelPerSecond() < _upperPPSMarkLimit) {
218                 // only valid if no variable xaxis is used, see below
219                 int daywidth = (int) (delegate.getPixelPerSecond() * 24.0 * 60.0 * 60.0);
220                 while (delegate.xForDate(date) < max) {
221                     int x = delegate.xForDate(date);
222                     Color mark = null;
223                     if (_holidayEnumerator != null) {
224                         if (_markHolidays && _holidayEnumerator.isHoliday(date.getDate())) {
225                             mark = _colorSunday;
226                         } else if (_markSpecialdays && _holidayEnumerator.isSpecialDay(date.getDate())) {
227                             mark = _colorSpecialDay;
228                         }
229                     }
230                     if (mark == null && _markWeekends) {
231                         if (date.getDayOfWeek() == Calendar.SATURDAY) {
232                             mark = _colorSaturday;
233                         } else if (date.getDayOfWeek() == Calendar.SUNDAY) {
234                             mark = _colorSunday;
235                         }
236                     }
237                     if (mark != null) {
238                         gc.setBackground(mark);
239                         // if the viewer uses a variable x scale, calculate the width of the day dynamically
240                         if (delegate.hasVariableXScale()) {
241                             int x2 = delegate.xForDate(date.copy().advanceDays(1));
242                             daywidth = x2 - x;
243                         }
244                         if (horizontal) {
245                             gc.fillRectangle(x, oy, daywidth, height);
246                         } else {
247                             // TODO CHECK
248                             gc.fillRectangle(ox, x, width, daywidth);
249                         }
250                     }
251                     date.advanceDays(1);
252                 }
253 
254             }
255 
256             gc.setBackground(bg);
257         }
258 
259         // correct line width for printing
260         if (printing) {
261             gc.setLineWidth(getDefaultLineWidth());
262         }
263         // draw the minor grid
264         gc.setForeground(_colorMinorGrid);
265         for (JaretDate d : tickProvider.getMinorTicks(delegate)) {
266             int x = delegate.xForDate(d);
267             if (horizontal) {
268                 gc.drawLine(x, oy, x, oy + height);
269             } else {
270                 gc.drawLine(ox, x, ox + width, x);
271             }
272         }
273 
274         // draw the major grid
275         gc.setForeground(_colorMajorGrid);
276         for (JaretDate d : tickProvider.getMajorTicks(delegate)) {
277             int x = delegate.xForDate(d);
278             if (horizontal) {
279                 gc.drawLine(x, oy, x, oy + height);
280             } else {
281                 gc.drawLine(ox, x, ox + width, x);
282             }
283         }
284         gc.setLineWidth(1);
285         gc.setForeground(fg);
286     }
287 
288     public void drawIntern(GC gc, TimeBarViewerDelegate delegate, Rectangle drawingArea, boolean printing,
289             boolean horizontal) {
290 
291         int ox = drawingArea.x;
292         int oy = drawingArea.y;
293         int width = drawingArea.width;
294         int height = drawingArea.height;
295 
296         Color fg = gc.getForeground();
297 
298         int idx;
299         if (!printing) {
300             idx = TickScaler.getTickIdx(delegate.getPixelPerSecond() / getScaleX());
301         } else {
302             idx = TickScaler.getTickIdx(delegate.getPixelPerSecond() / getScaleX());
303             _upperPPSMarkLimit = _upperPPSMarkLimit * getScaleX();
304         }
305         int majTick = TickScaler.getMajorTickMinutes(idx);
306         int minTick = TickScaler.getMinorTickMinutes(idx);
307         Range range = TickScaler.getRange(idx);
308 
309         // first date
310         JaretDate date = delegate.getStartDate().copy();
311 
312         // clean starting date on a major tick minute position (starting with a
313         // day)
314         date.setMinutes(0);
315         date.setHours(0);
316         date.setSeconds(0);
317         // if range is week take a week starting point
318         if (range == Range.WEEK) {
319             while (date.getDayOfWeek() != DateUtils.getFirstDayOfWeek()) {
320                 date.backDays(1);
321             }
322         } else if (range == Range.MONTH) {
323             // month -> month starting point
324             date.setDay(1);
325         }
326         JaretDate save = date.copy();
327 
328         int max = horizontal ? (ox + width) : (oy + height);
329 
330         // draw day backgroud if configured
331         if (_markHolidays || _markSpecialdays || _markWeekends) {
332             Color bg = gc.getBackground();
333             if (range == Range.DAY || range == Range.WEEK
334                     || (range == Range.HOUR && delegate.getPixelPerSecond() < _upperPPSMarkLimit)) {
335                 // only valid if no variable xaxis is used, see below
336                 int daywidth = (int) (delegate.getPixelPerSecond() * 24.0 * 60.0 * 60.0);
337                 while (delegate.xForDate(date) < max) {
338                     int x = delegate.xForDate(date);
339                     Color mark = null;
340                     if (_holidayEnumerator != null) {
341                         if (_markHolidays && _holidayEnumerator.isHoliday(date.getDate())) {
342                             mark = _colorSunday;
343                         } else if (_markSpecialdays && _holidayEnumerator.isSpecialDay(date.getDate())) {
344                             mark = _colorSpecialDay;
345                         }
346                     }
347                     if (mark == null && _markWeekends) {
348                         if (date.getDayOfWeek() == Calendar.SATURDAY) {
349                             mark = _colorSaturday;
350                         } else if (date.getDayOfWeek() == Calendar.SUNDAY) {
351                             mark = _colorSunday;
352                         }
353                     }
354                     if (mark != null) {
355                         gc.setBackground(mark);
356                         // if the viewer uses a variable x scale, calculate the width of the day dynamically
357                         if (delegate.hasVariableXScale()) {
358                             int x2 = delegate.xForDate(date.copy().advanceDays(1));
359                             daywidth = x2 - x;
360                         }
361                         if (horizontal) {
362                             gc.fillRectangle(x, oy, daywidth, height);
363                         } else {
364                             // TODO CHECK
365                             gc.fillRectangle(ox, x, width, daywidth);
366                         }
367                     }
368                     date.advanceDays(1);
369                 }
370 
371             }
372 
373             gc.setBackground(bg);
374         }
375 
376         date = save.copy();
377         // draw the minor grid
378         if (printing) {
379             gc.setLineWidth(getDefaultLineWidth());
380         }
381         gc.setForeground(_colorMinorGrid);
382         while (delegate.xForDate(date) < max) {
383             int x = delegate.xForDate(date);
384             if (horizontal) {
385                 gc.drawLine(x, oy, x, oy + height);
386             } else {
387                 gc.drawLine(ox, x, ox + width, x);
388             }
389 
390             if (range == Range.MONTH) {
391                 int adv = Math.round((float) minTick / (float) (24 * 60 * 7 * 4));
392                 if (adv == 0) {
393                     adv = 1;
394                 }
395                 date.advanceMonths(adv);
396             } else {
397                 date.advanceMinutes(minTick);
398             }
399         }
400 
401         date = save.copy();
402         // draw the major grid
403         gc.setForeground(_colorMajorGrid);
404         while (delegate.xForDate(date) < ox + width) {
405             int x = delegate.xForDate(date);
406             if (horizontal) {
407                 gc.drawLine(x, oy, x, oy + height);
408             } else {
409                 gc.drawLine(ox, x, ox + width, x);
410             }
411             if (range == Range.MONTH) {
412                 int adv = Math.round((float) majTick / (float) (24 * 60 * 7 * 4));
413                 if (adv == 0) {
414                     adv = 1;
415                 }
416                 date.advanceMonths(adv);
417             } else {
418                 date.advanceMinutes(majTick);
419             }
420         }
421         gc.setLineWidth(1);
422         gc.setForeground(fg);
423     }
424 
425     /**
426      * {@inheritDoc}
427      */
428     public void dispose() {
429         super.dispose();
430         if (_colorMajorGrid != null) {
431             _colorMajorGrid.dispose();
432             _colorMinorGrid.dispose();
433             _colorSaturday.dispose();
434             _colorSpecialDay.dispose();
435             _colorSunday.dispose();
436         }
437     }
438 
439     /**
440      * {@inheritDoc}
441      */
442     public GridRenderer createPrintRenderer(Printer printer) {
443         DefaultGridRenderer renderer = new DefaultGridRenderer(printer);
444         renderer.setHolidayEnumerator(_holidayEnumerator);
445         renderer.setMarkHolidays(_markHolidays);
446         renderer.setMarkSpecialDays(_markSpecialdays);
447         renderer.setMarkWeekends(_markWeekends);
448         renderer.setTickProvider(_tickProvider);
449         return renderer;
450     }
451 
452 }