View Javadoc

1   /*
2   Canvas for GWT
3   Copyright (C) 2006 Alexei Sokolov http://gwt.components.googlepages.com/
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  
19  */
20  
21  package com.gwt.components.client;
22  
23  import com.google.gwt.core.client.JavaScriptObject;
24  import com.google.gwt.user.client.DOM;
25  import com.google.gwt.user.client.Element;
26  import com.google.gwt.user.client.Event;
27  import com.google.gwt.user.client.ui.FocusWidget;
28  import com.google.gwt.user.client.ui.Image;
29  import com.google.gwt.user.client.ui.KeyboardListener;
30  import com.google.gwt.user.client.ui.MouseListener;
31  import com.google.gwt.user.client.ui.MouseListenerCollection;
32  import com.google.gwt.user.client.ui.MouseWheelListener;
33  import com.google.gwt.user.client.ui.MouseWheelListenerCollection;
34  import com.google.gwt.user.client.ui.SourcesMouseEvents;
35  import com.google.gwt.user.client.ui.SourcesMouseWheelEvents;
36  import com.google.gwt.user.client.ui.impl.FocusImpl;
37  
38  public class Canvas extends FocusWidget implements 
39  SourcesMouseEvents, SourcesMouseWheelEvents {
40  
41      public static class DrawingStyle extends JavaScriptObject {
42          protected DrawingStyle() {
43              super();
44          }
45      }
46  
47      public static class Gradient extends DrawingStyle {
48      	protected Gradient() {
49              super();
50          }
51  
52          protected static native void addColorStop(JavaScriptObject obj,
53                  float offset, String color) /*-{
54           obj.addColorStop(offset, color);
55          }-*/;
56      }
57  
58      public static class LinearGradient extends Gradient {
59      	protected LinearGradient() {
60              super();
61          }
62  
63          public final LinearGradient addColorStop(float offset, String color) {
64              Gradient.addColorStop(this, offset, color);
65              return this;
66          }
67      }
68  
69      public static class RadialGradient extends Gradient {
70      	protected RadialGradient() {
71              super();
72          }
73  
74          public final RadialGradient addColorStop(float offset, String color) {
75              Gradient.addColorStop(this, offset, color);
76              return this;
77          }
78      }
79  
80      public static class Pattern extends DrawingStyle {
81          protected Pattern() {
82              super();
83          }
84  
85      }
86  
87      private JavaScriptObject context;
88      private Element canvas;
89      protected int modifiers;
90      private MouseListenerCollection mouseListeners;
91      private MouseWheelListenerCollection mouseWheelListeners;
92      
93      public Canvas(int width, int height) {
94          setElement(DOM.createDiv());
95          sinkEvents(Event.MOUSEEVENTS|Event.KEYEVENTS|Event.ONMOUSEWHEEL);
96          canvas = DOM.createElement("canvas");
97          setWidth(width);
98          setHeight(height);
99          DOM.appendChild(getElement(), canvas);
100         setStyleName("gwt-Canvas");
101 		Element focusable = FocusImpl.getFocusImplForPanel().createFocusable();
102 		DOM.appendChild(getElement(), focusable);
103 
104         init();
105 
106         setFillStyle("black");
107         setStrokeStyle("black");
108     }
109     
110     public int getWidth() {
111     	return DOM.getIntAttribute(canvas, "width");
112     }
113     public void setWidth(int width) {
114         DOM.setAttribute(canvas, "width", String.valueOf(width));
115     }
116     public int getHeight() {
117     	return DOM.getIntAttribute(canvas, "height");
118     }    
119     public void setHeight(int height) {
120         DOM.setAttribute(canvas, "height", String.valueOf(height));
121     }
122     
123     public void resize(int width, int height) {
124         setWidth(width);
125         setHeight(height);
126 		setSize(width + "px", height + "px");
127     }
128         
129     public native static boolean isEmulation() /*-{
130      return (typeof $wnd.G_vmlCanvasManager != "undefined");
131     }-*/;
132 
133     protected native void init() /*-{
134      var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()().firstChild;
135      if (typeof $wnd.G_vmlCanvasManager != "undefined") {
136        var parent = el.parent;
137      
138        el = $wnd.G_vmlCanvasManager.fixElement_(el);
139        el.getContext = function () {
140          if (this.context_) {
141            return this.context_;
142          }
143          return this.context_ = new $wnd.CanvasRenderingContext2D(el);
144        };
145 
146        el.attachEvent("onpropertychange", function (e) {
147          // we need to watch changes to width and height
148          switch (e.propertyName) {
149            case "width":
150            case "height":
151              // coord size changed?
152              break;
153            }
154        });
155 
156        // if style.height is set
157 
158        var attrs = el.attributes;
159        if (attrs.width && attrs.width.specified) {
160          // TODO: use runtimeStyle and coordsize
161          // el.getContext().setWidth_(attrs.width.nodeValue);
162          el.style.width = attrs.width.nodeValue + "px";
163        }
164        if (attrs.height && attrs.height.specified) {
165          // TODO: use runtimeStyle and coordsize
166          // el.getContext().setHeight_(attrs.height.nodeValue);
167          el.style.height = attrs.height.nodeValue + "px";
168        }
169      }
170      this.@com.gwt.components.client.Canvas::context = el.getContext("2d");
171     }-*/;
172     
173 
174 
175 	public void addMouseListener(MouseListener listener) {
176 		if (mouseListeners == null) {
177 			mouseListeners = new MouseListenerCollection();
178 		}
179 		mouseListeners.add(listener);
180 	}
181 
182 	public void onBrowserEvent(Event event) {
183 		switch (DOM.eventGetType(event)) {
184 			case Event.ONMOUSEDOWN:
185 			case Event.ONMOUSEUP:
186 			case Event.ONMOUSEMOVE:
187 			case Event.ONMOUSEOVER:
188 			case Event.ONMOUSEOUT: {
189 				if (mouseListeners != null) {
190 					modifiers = (DOM.eventGetShiftKey(event) ? KeyboardListener.MODIFIER_SHIFT : 0)
191 					  | (DOM.eventGetMetaKey(event) ? KeyboardListener.MODIFIER_META : 0)
192 				      | (DOM.eventGetCtrlKey(event) ? KeyboardListener.MODIFIER_CTRL : 0)
193 				      | (DOM.eventGetAltKey(event) ? KeyboardListener.MODIFIER_ALT : 0);
194 					mouseListeners.fireMouseEvent(this, event);
195 				}
196 				break;
197 			}
198 			case Event.ONMOUSEWHEEL: {
199 				if (mouseWheelListeners != null) {
200 					modifiers = (DOM.eventGetShiftKey(event) ? KeyboardListener.MODIFIER_SHIFT : 0)
201 					  | (DOM.eventGetMetaKey(event) ? KeyboardListener.MODIFIER_META : 0)
202 				      | (DOM.eventGetCtrlKey(event) ? KeyboardListener.MODIFIER_CTRL : 0)
203 				      | (DOM.eventGetAltKey(event) ? KeyboardListener.MODIFIER_ALT : 0);
204 					mouseWheelListeners.fireMouseWheelEvent(this, event);
205 				}
206 				break;
207 			}
208 			case Event.ONKEYDOWN:
209 			case Event.ONKEYPRESS:
210 			case Event.ONKEYUP:
211 				super.onBrowserEvent(event);
212 		}
213 	}
214 
215 	public void removeMouseListener(MouseListener listener) {
216 		if (mouseListeners != null) {
217 			mouseListeners.remove(listener);
218 		}
219 	}
220 	
221 	public int getModifiers() {
222 		return modifiers;
223 	}
224 
225 	public void addMouseWheelListener(MouseWheelListener listener) {
226 		if (mouseWheelListeners == null) {
227 			mouseWheelListeners = new MouseWheelListenerCollection();
228 		}
229 		mouseWheelListeners.add(listener);
230 	}
231 
232 	public void removeMouseWheelListener(MouseWheelListener listener) {
233 		if (mouseWheelListeners != null) {
234 			mouseWheelListeners.remove(listener);
235 		}
236 	}
237 
238     public native void saveContext() /*-{
239      this.@com.gwt.components.client.Canvas::context.save();
240     }-*/;
241 
242     public native void restoreContext() /*-{
243      this.@com.gwt.components.client.Canvas::context.restore();
244     }-*/;
245 
246     public native void scale(float x, float y) /*-{
247      this.@com.gwt.components.client.Canvas::context.scale(x, y);   
248     }-*/;
249 
250     public native void rotate(float angle)/*-{
251      this.@com.gwt.components.client.Canvas::context.rotate(angle);   
252     }-*/;
253 
254     public native void translate(float x, float y) /*-{
255      this.@com.gwt.components.client.Canvas::context.translate(x, y);   
256     }-*/;
257 
258     public native void transform(float m11, float m12, float m21, float m22,
259             float dx, float dy) /*-{
260      this.@com.gwt.components.client.Canvas::context.transform(
261       m11, m12, m21, m22, dx, dy);   
262     }-*/;
263 
264     public native void setTransform(float m11, float m12, float m21, float m22,
265             float dx, float dy) /*-{
266      this.@com.gwt.components.client.Canvas::context.setTransform(
267       m11, m12, m21, m22, dx, dy);   
268     }-*/;
269 
270     public native float getGlobalAlpha() /*-{
271      return this.@com.gwt.components.client.Canvas::context.globalAlpha;
272     }-*/;
273 
274     public native void setGlobalAlpha(float alpha) /*-{
275      this.@com.gwt.components.client.Canvas::context.globalAlpha = alpha;
276     }-*/;
277 
278     public native String getGlobalCompositeOperation() /*-{
279      return this.@com.gwt.components.client.Canvas::context.globalCompositeOperation;
280     }-*/;
281 
282     public native void setGlobalCompositeOperation(String operation) /*-{
283      this.@com.gwt.components.client.Canvas::context.globalCompositeOperation = 
284       operation;
285     }-*/;
286 
287     public native Object getStrokeStyle() /*-{
288     return this.@com.gwt.components.client.Canvas::context.strokeStyle;
289 	}-*/;
290 
291     public native Object getFillStyle() /*-{
292         return this.@com.gwt.components.client.Canvas::context.fillStyle;
293     }-*/;
294 
295     /**
296      * @param style
297      * Can be either a java.lang.String valued to a valid CSS color or
298      * a DrawingStyle
299      */
300     public native void setStrokeStyle(String style) /*-{
301      this.@com.gwt.components.client.Canvas::context.strokeStyle = style;
302     }-*/;
303     public native void setStrokeStyle(DrawingStyle style) /*-{
304     this.@com.gwt.components.client.Canvas::context.strokeStyle = style;
305    }-*/;
306 
307     /**
308      * @param style
309      * Can be either a java.lang.String valued to a valid CSS color or
310      * a DrawingStyle
311      */
312     public native void setFillStyle(String style) /*-{
313      this.@com.gwt.components.client.Canvas::context.fillStyle = style;
314     }-*/;
315     public native void setFillStyle(DrawingStyle style) /*-{
316      this.@com.gwt.components.client.Canvas::context.fillStyle = style;
317     }-*/;
318 
319     public native LinearGradient createLinearGradient(float x0, float y0,
320             float x1, float y1) /*-{
321      return this.@com.gwt.components.client.Canvas::context.createLinearGradient(
322       x0, y0, x1, y1);   
323     }-*/;
324 
325     public native RadialGradient createRadialGradient(float x0, float y0,
326             float r0, float x1, float y1, float r1) /*-{
327      return this.@com.gwt.components.client.Canvas::context.createRadialGradient(
328       x0, y0, r0, x1, y1, r1);   
329     }-*/;
330 
331     public native Pattern createPattern(Image img, String repetition) /*-{
332      var elem = img.@com.google.gwt.user.client.ui.UIObject::getElement()();
333      var ctx = this.@com.gwt.components.client.Canvas::context;
334      if (ctx.createPattern)
335      return ctx.createPattern(elem, repetition);
336      return null;   
337     }-*/;
338 
339     public native float getLineWidth() /*-{
340      return this.@com.gwt.components.client.Canvas::context.lineWidth;
341     }-*/;
342 
343     public native void setLineWidth(float lineWidth) /*-{
344      this.@com.gwt.components.client.Canvas::context.lineWidth = lineWidth;
345     }-*/;
346 
347     public native String getLineCap() /*-{
348      return this.@com.gwt.components.client.Canvas::context.lineCap;
349     }-*/;
350 
351     public native void setLineCap(String lineCap) /*-{
352      this.@com.gwt.components.client.Canvas::context.lineCap = lineCap;
353     }-*/;
354 
355     public native String getLineJoin() /*-{
356      return this.@com.gwt.components.client.Canvas::context.lineJoin;
357     }-*/;
358 
359     public native void setLineJoin(String lineJoin) /*-{
360      this.@com.gwt.components.client.Canvas::context.lineJoin = lineJoin;
361     }-*/;
362 
363     public native float getMiterLimit() /*-{
364      return this.@com.gwt.components.client.Canvas::context.miterLimit;
365     }-*/;
366 
367     public native void setMiterLimit(float miterLimit) /*-{
368      this.@com.gwt.components.client.Canvas::context.miterLimit = miterLimit;
369     }-*/;
370 
371     public native float getShadowOffsetX() /*-{
372      return this.@com.gwt.components.client.Canvas::context.shadowOffsetX;
373     }-*/;
374 
375     public native void setShadowOffsetX(float x) /*-{
376      this.@com.gwt.components.client.Canvas::context.shadowOffsetX = x;
377     }-*/;
378 
379     public native float getShadowOffsetY() /*-{
380      return this.@com.gwt.components.client.Canvas::context.shadowOffsetY;
381     }-*/;
382 
383     public native void setShadowOffsetY(float y) /*-{
384      this.@com.gwt.components.client.Canvas::context.shadowOffsetY = y;
385     }-*/;
386 
387     public native float getShadowBlur() /*-{
388      return this.@com.gwt.components.client.Canvas::context.shadowBlur;
389     }-*/;
390 
391     public native void setShadowBlur(float blur) /*-{
392      this.@com.gwt.components.client.Canvas::context.shadowBlur = blur;
393     }-*/;
394 
395     public native String getShadowColor() /*-{
396      return this.@com.gwt.components.client.Canvas::context.shadowColor;
397     }-*/;
398 
399     public native void setShadowColor(String style) /*-{
400      this.@com.gwt.components.client.Canvas::context.shadowColor = style;
401     }-*/;
402 
403     public native void clearRect(float x, float y, float w, float h) /*-{
404      var ctx = this.@com.gwt.components.client.Canvas::context;
405      if (typeof $wnd.G_vmlCanvasManager != "undefined") {
406        var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()();
407        if (el.currentStyle) {
408          var color = el.currentStyle['background-color'];
409          if (!color) {
410            color = '#ffffff';
411          }
412          ctx.save();
413          ctx.fillStyle = color;
414          ctx.fillRect(x, y, w, h);
415          ctx.restore();
416        }
417      } else {
418        ctx.clearRect(x, y, w, h);
419      }
420     }-*/;
421 
422     public native void fillRect(float x, float y, float w, float h) /*-{
423      this.@com.gwt.components.client.Canvas::context.fillRect(x, y, w, h);
424     }-*/;
425 
426     public native void strokeRect(float x, float y, float w, float h) /*-{
427      this.@com.gwt.components.client.Canvas::context.strokeRect(x, y, w, h);
428     }-*/;
429 
430     public native void beginPath() /*-{
431      this.@com.gwt.components.client.Canvas::context.beginPath();
432     }-*/;
433 
434     public native void closePath() /*-{
435      this.@com.gwt.components.client.Canvas::context.closePath();
436     }-*/;
437 
438     public native void moveTo(float x, float y) /*-{
439      this.@com.gwt.components.client.Canvas::context.moveTo(x,y);
440     }-*/;
441 
442     public native void lineTo(float x, float y) /*-{
443      this.@com.gwt.components.client.Canvas::context.lineTo(x,y);
444     }-*/;
445 
446     public native void quadraticCurveTo(float cpx, float cpy, float x, float y) /*-{
447      this.@com.gwt.components.client.Canvas::context.quadraticCurveTo(cpx, cpy, x, y);
448     }-*/;
449 
450     public native void bezierCurveTo(float cp1x, float cp1y, float cp2x,
451             float cp2y, float x, float y) /*-{
452      this.@com.gwt.components.client.Canvas::context.bezierCurveTo(
453       cp1x, cp1y, cp2x, cp2y, x, y);
454     }-*/;
455 
456     public native void arcTo(float x1, float y1, float x2, float y2,
457             float radius) /*-{
458      this.@com.gwt.components.client.Canvas::context.arcTo(x1, y1, x2, y2, radius);
459     }-*/;
460 
461     public native void rect(float x, float y, float w, float h) /*-{
462      this.@com.gwt.components.client.Canvas::context.rect(x, y, w, h);
463     }-*/;
464 
465     public native void arc(float x, float y, float radius, float startAngle,
466             float endAngle, boolean anticlockwise) /*-{
467      this.@com.gwt.components.client.Canvas::context.arc(
468       x, y, radius, startAngle, endAngle, anticlockwise);
469     }-*/;
470 
471     public native void fill() /*-{
472      this.@com.gwt.components.client.Canvas::context.fill();
473     }-*/;
474 
475     public native void stroke() /*-{
476      this.@com.gwt.components.client.Canvas::context.stroke();
477     }-*/;
478 
479     public native void clip() /*-{
480      this.@com.gwt.components.client.Canvas::context.clip();
481     }-*/;
482 
483     public native boolean isPointInPath(float x, float y) /*-{
484      return this.@com.gwt.components.client.Canvas::context.isPointInPath(x, y);
485     }-*/;
486 
487 }