View Javadoc

1   /*
2    *  File: SmileyCellRenderer.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 javax.swing.BoundedRangeModel;
14  import javax.swing.DefaultBoundedRangeModel;
15  
16  import org.eclipse.swt.SWT;
17  import org.eclipse.swt.graphics.Color;
18  import org.eclipse.swt.graphics.Device;
19  import org.eclipse.swt.graphics.GC;
20  import org.eclipse.swt.graphics.Path;
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.IRow;
28  
29  /***
30   * Fun renderer rendering an integer as a smiley.
31   * 
32   * @TODO Printing
33   * 
34   * @author Peter Kliem
35   * @version $Id: SmileyCellRenderer.java 179 2007-01-07 17:37:50Z olk $
36   */
37  public class SmileyCellRenderer extends CellRendererBase implements ICellRenderer {
38      private BoundedRangeModel _brModel = new DefaultBoundedRangeModel(50, 0, 0, 100);
39      private boolean _eyeBrows = true;
40      private boolean _colorChange = true;
41      /*** if true, rendering will be alwa limited to a maximal square, forcing the smiley to be a circle. */
42      private boolean _forceCircle = true;
43  
44      private Color _neutral;
45      private Color _positive;
46      private Color _negative;
47      private Color _currentColor;
48      private Color _black;
49  
50      private double _currentValue;
51  
52      public SmileyCellRenderer(Printer printer) {
53          super(printer);
54          if (printer != null) {
55              _neutral = printer.getSystemColor(SWT.COLOR_YELLOW);
56              _positive = printer.getSystemColor(SWT.COLOR_GREEN);
57              _negative = printer.getSystemColor(SWT.COLOR_RED);
58              _black = printer.getSystemColor(SWT.COLOR_BLACK);
59  
60          }
61      }
62  
63      public SmileyCellRenderer() {
64          super(null);
65          _neutral = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
66          _positive = Display.getCurrent().getSystemColor(SWT.COLOR_GREEN);
67          _negative = Display.getCurrent().getSystemColor(SWT.COLOR_RED);
68          _black = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
69      }
70  
71      /***
72       * {@inheritDoc}
73       */
74      public void draw(GC gc, JaretTable jaretTable, ICellStyle cellStyle, Rectangle drawingArea, IRow row,
75              IColumn column, boolean drawFocus, boolean selected, boolean printing) {
76          drawBackground(gc, drawingArea, cellStyle, selected, printing);
77          Rectangle drect = drawBorder(gc, cellStyle, drawingArea, printing);
78          Rectangle rect = applyInsets(drect);
79          Object value = column.getValue(row);
80          if (value != null) {
81              saveGCAttributes(gc);
82              int val = ((Integer) value).intValue();
83              _brModel.setValue(val);
84              calcSmileFactor();
85  
86              if (_forceCircle) {
87                  int a = Math.min(rect.width, rect.height);
88                  Rectangle nrect = new Rectangle(0, 0, a, a);
89                  nrect.x = rect.x + (rect.width - a) / 2;
90                  nrect.y = rect.y + (rect.height - a) / 2;
91                  rect = nrect;
92              }
93  
94              int width = rect.width;
95              int height = rect.height;
96              int offx = rect.x;
97              int offy = rect.y;
98              float foffx = (float) offx;
99              float foffy = (float) offy;
100 
101             int lineWidth = height / 40;
102             if (!_colorChange) {
103                 gc.setBackground(_neutral);
104             } else {
105                 if (_currentValue >= 0) { // positive
106                     gc.setBackground(calcColor(_positive, printing));
107                 } else { // negative
108                     gc.setBackground(calcColor(_negative, printing));
109                 }
110             }
111 
112             Device device = printing ? _printer : Display.getCurrent();
113             Path p = new Path(device);
114             p.addArc(foffx + 0 + lineWidth / 2, foffy + 0 + lineWidth / 2, width - 1 - lineWidth, height - 1
115                     - lineWidth, 0, 360);
116             gc.fillPath(p);
117             gc.setForeground(_black);
118             gc.setLineWidth(lineWidth);
119             gc.drawPath(p);
120             p.dispose();
121             // eyes
122             int y = height / 3;
123             int x1 = width / 3;
124             int x2 = width - width / 3;
125             int r = width / 30;
126             // eyes have a minimal size
127             if (r == 0) {
128                 r = 1;
129             }
130             gc.setBackground(_black);
131             gc.fillOval(offx + x1 - r, offy + y - r, 2 * r, 2 * r);
132             gc.fillOval(offx + x2 - r, offy + y - r, 2 * r, 2 * r);
133             // eye brows
134             if (_eyeBrows) {
135                 gc.setLineWidth(lineWidth / 2);
136                 int ebWidth = width / 10;
137                 int yDist = height / 13;
138                 int yOff = (int) (_currentValue * (double) height / 30);
139                 int xShift = (int) (_currentValue * (double) width / 90);
140                 p = new Path(device);
141                 p.moveTo(foffx + x1 - ebWidth / 2 + xShift, foffy + y - yDist + yOff);
142                 p.lineTo(foffx + x1 + ebWidth / 2 - xShift, foffy + y - yDist - yOff);
143                 gc.drawPath(p);
144                 p.dispose();
145 
146                 p = new Path(device);
147                 p.moveTo(foffx + x2 - ebWidth / 2 + xShift, foffy + y - yDist - yOff);
148                 p.lineTo(foffx + x2 + ebWidth / 2 - xShift, foffy + y - yDist + yOff);
149                 gc.drawPath(p);
150                 p.dispose();
151             }
152             // mouth
153             gc.setLineWidth(lineWidth);
154             x1 = (int) (width / 4.5);
155             x2 = width - x1;
156             y = height - height / 3;
157             int midX = width / 2;
158             int offset = (int) (_currentValue * (double) height / 3);
159             p = new Path(Display.getCurrent());
160             p.moveTo(foffx + x1, foffy + y);
161             p.quadTo(foffx + midX, foffy + y + offset, foffx + x2, foffy + y);
162             gc.drawPath(p);
163             p.dispose();
164             restoreGCAttributes(gc);
165         }
166         if (drawFocus) {
167             drawFocus(gc, drect);
168         }
169         drawSelection(gc, drawingArea, cellStyle, selected, printing);
170 
171     }
172 
173     /***
174      * Scales the BoundedRangeModel to [-1, 1]
175      */
176     private void calcSmileFactor() {
177         int range = _brModel.getMaximum() - _brModel.getMinimum();
178         int mid = _brModel.getMinimum() + range / 2;
179         int value = _brModel.getValue();
180         _currentValue = (double) (value - mid) / (double) (range / 2);
181         // due to rounding errors the smileFactor may be over 1
182         if (_currentValue > 1) {
183             _currentValue = 1;
184         } else if (_currentValue < -1) {
185             _currentValue = -1;
186         }
187     }
188 
189     /***
190      * Calculates the color beetween _neutral and the specified color
191      * 
192      * @param destColor
193      * @return the mixed color
194      */
195     private Color calcColor(Color destColor, boolean printing) {
196         int rDiff = destColor.getRed() - _neutral.getRed();
197         int gDiff = destColor.getGreen() - _neutral.getGreen();
198         int bDiff = destColor.getBlue() - _neutral.getBlue();
199         double factor = Math.abs(_currentValue);
200         int r = (int) ((double) rDiff * factor);
201         int g = (int) ((double) gDiff * factor);
202         int b = (int) ((double) bDiff * factor);
203 
204         if (_currentColor != null) {
205             _currentColor.dispose();
206         }
207         if (!printing) {
208             _currentColor = new Color(Display.getCurrent(), _neutral.getRed() + r, _neutral.getGreen() + g, _neutral
209                     .getBlue()
210                     - b);
211         } else {
212             _currentColor = new Color(_printer, _neutral.getRed() + r, _neutral.getGreen() + g, _neutral.getBlue() - b);
213         }
214         return _currentColor;
215     }
216 
217     /***
218      * {@inheritDoc}
219      */
220     public void dispose() {
221         if (_currentColor != null) {
222             _currentColor.dispose();
223         }
224     }
225 
226     /***
227      * {@inheritDoc}
228      */
229     public ICellRenderer createPrintRenderer(Printer printer) {
230         // return new SmileyCellRenderer(printer);
231         // TODO there is a printing problem with using path on a printer, so use a text cell renderer instead
232         return new TextCellRenderer(printer);
233     }
234 }