001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.ui.vect;
021 
022 import js.ArrayLike;
023 import js.Id;
024 import js.Initializer;
025 import js.Js;
026 import js.ObjectLike;
027 import js.Vars;
028 import jsx.Configurable;
029 import jsx.client.Browser;
030 import jsx.core.ObjectLikes;
031 import jsx.dom.Styles;
032 import jsx.graphic.SVG;
033 import jsx.graphic.VML;
034 import jsx.motion.Motion;
035 import jsx.motion.reg.Uniform;
036 import jsx.ui.Component;
037 import jsx.ui.Widget;
038 import jsx.ui.event.OnRender;
039 import jsx.ui.event.OnStyle;
040 import jsx.ui.event.Render;
041 import jsx.ui.event.Style;
042 
043 /**
044  * <p>A base class for widgets that wrap HTML vector graphics elements.</p>
045  * <p>This class provides basic functionalities to manipulate the underlying vector 
046  * graphics element, which is either a VML element for IE or a SVG element for other 
047  * browsers, eliminating the browser dependencies.</p>
048  * <p>A {@link Graphic} widget is {@link Configurable} and is also an event source 
049  * which fires {@link jsx.ui.Widget.Event} events.</p>
050  * 
051  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
052  * @see SVG
053  * @see VML
054  */
055 public class Graphic extends Widget implements OnRender, OnStyle
056 {
057     private final static Id<Component> GRAPHIC = new Id<Component>();
058 
059     /**
060      * <p>The default constructor to create widgets of this type.</p>
061      * <p>This constructor simply invokes the typical constructor of this class passing 
062      * a newly created graphic component, which wraps a HTML <tt>&lt;div&gt</tt> element, 
063      * as argument.</p>
064      * @since 1.0
065      */
066     public Graphic() {
067         this(Component.div());
068     }
069 
070     /**
071      * <p>A typical constructor that constructs widgets of this type and forces 
072      * constructors of subclasses to pass a graphic component.</p>
073      * <p>This constructor invokes the typical constructor of the superclass passing 
074      * the specified graphic component as argument and registers the wrapper widget being 
075      * constructed as an event listener to listen {@link Render} and {@link Style} events 
076      * fired from the underlying graphic component.</p>
077      * @param e The underlying graphic component which is a component that wraps an HTML 
078      * <tt>&lt;div&gt</tt> element that is containing either a VML element for IE or a 
079      * SVG element for other browsers.
080      * @since 1.0
081      */
082     public Graphic(Component e) {
083         super(e);
084         init(this);
085         e.addListener(Render.class, this);
086         e.addListener(Style.class, this);
087     }
088 
089     /**
090      * <p>Gets the graphic component currently wrapped by the wrapper widget.</p>
091      * @return The graphic component currently wrapped by the wrapper widget.
092      * @since 1.0
093      */
094     public final Component getGraphic() {
095         return ini(this).var(GRAPHIC);
096     }
097 
098     /**
099      * <p>Deletes the graphic component wrapped by the specified graphic widget.</p>
100      * @param g The current graphic widget.
101      * @since 1.0
102      */
103     public static final void removeGraphic(Graphic g) {
104         if (g.isRendered()) {
105             Component ge = g.getGraphic();
106             if (Js.be(ge)) {
107                 Component.detach(ge);
108             }
109         }
110         ObjectLikes.delete(ini(g), GRAPHIC);
111     }
112 
113     /**
114      * <p>Sets the graphic component of the specified graphic widget.</p>
115      * @param g The current graphic widget.
116      * @param ge The graphic component is to be wrapped by the specified graphic wrapper.
117      * @since 1.0
118      */
119     public static final void setGraphic(Graphic g, Component ge) {
120         removeGraphic(g);
121         Component.appendChild(g.unwrap(), ge);
122         ini(g).var(GRAPHIC, ge);
123         init(g);
124     }
125 
126     private static final void init(Graphic g) {
127         if (g.isRendered()) {
128             Component e = g.unwrap();
129             Component ge = g.getGraphic();
130             if (Js.not(ge)) {
131                 ge = graphic();
132                 ini(g).var(GRAPHIC, ge);
133                 Component.appendChild(e, ge);
134             }
135             int cl = (int)Component.contentLeft  (e);
136             int ct = (int)Component.contentTop   (e);
137             int cw = (int)Component.contentWidth (e);
138             int ch = (int)Component.contentHeight(e);
139             ObjectLike s = Component.style(ge);
140             Styles.position(s, "absolute");
141             Styles.left(s, Styles.px(cl));
142             Styles.top (s, Styles.px(ct));
143             if (Browser.isIE) {
144                 VML.coordSize(ge, cw, ch);
145                 Styles.width (s, Styles.px(cw));
146                 Styles.height(s, Styles.px(ch));
147             } else {
148                 SVG.viewBox(ge, 0, 0, cw, ch);
149                 Component.setAttribute(ge, SVG.WIDTH , cw);
150                 Component.setAttribute(ge, SVG.HEIGHT, ch);
151             }
152         }
153     }
154 
155     /**
156      * <p>Performs an action on the dispatched event.</p>
157      * <p>This method initializes the current graphic widget.</p>
158      * @param evt The event dispatched to this listener.
159      * @since 1.0
160      */
161     public void onEvent(Render evt) {
162         init(this);
163     }
164 
165     /**
166      * <p>Performs an action on the dispatched event.</p>
167      * <p>This method initializes the current graphic widget.</p>
168      * @param evt The event dispatched to this listener.
169      * @since 1.0
170      */
171     public void onEvent(Style evt) {
172         init(this);
173     }
174 
175     /**
176      * <p>Sets the size of the specified graphic widget, eliminating the browser 
177      * dependencies.</p>
178      * @param g The current graphic wrapper.
179      * @param w The X dimension of the graphic widget.
180      * @param h The Y dimension of the graphic widget.
181      * @since 1.0
182      */
183     public static final void setSize(Graphic g, double w, double h) {
184         ObjectLike s = new Initializer().var();
185         Styles.position(s, "absolute");
186         Styles.left(s, "100px");
187         Styles.top(s, "100px");
188         Styles.width (s, Styles.px(w));
189         Styles.height(s, Styles.px(h));
190         Component.applyStyle(g.unwrap(), s);
191     }
192 
193     /**
194      * <p>Appends a graphic component to the underlying graphic element of the specified 
195      * graphic widget, eliminating the browser dependencies.</p>
196      * @param g The current graphic wrapper.
197      * @param ge The graphic component to be appended which is either a VML component 
198      * for IE or a SVG component for other browsers.
199      * @since 1.0
200      */
201     public static final void add(Graphic g, Component ge) {
202         if (Browser.isIE) {
203             Component e = g.unwrap();
204             ObjectLike s = Component.style(ge);
205             Styles.position(s, "absolute");
206             if (!VML.isStyled(ge)) {
207                 int cl = (int)Component.contentLeft(e);
208                 int ct = (int)Component.contentTop (e);
209                 Styles.left(s, Js.toString(cl));
210                 Styles.top (s, Js.toString(ct));
211             }
212             VML.appendChild(g.getGraphic(), ge);
213         } else {
214             Component.appendChild(g.getGraphic(), ge);
215         }
216     }
217 
218     /**
219      * <p>Creates and returns a root graphic component, eliminating the browser dependencies.</p>
220      * @return The newly created root graphic component which is either a VML group 
221      * component for IE or a SVG component wrapping an HTML <tt>&lt;svg:svg&gt;</tt> 
222      * element for other browsers.
223      * @since 1.0
224      * @see SVG#svg()
225      * @see VML#group()
226      */
227     public static final Component graphic() {
228         return Browser.isIE ? VML.group() : SVG.svg();
229     }
230 
231     /**
232      * <p>Defines the outline data of a path component, eliminating the browser dependencies.</p>
233      * @param v A path component which is either a VML shape component for IE or a SVG 
234      * path component for other browsers.
235      * @param commands An array of path commands.
236      * @since 1.0
237      * @see #path()
238      * @see SVG#path(Component, ArrayLike)
239      * @see VML#path(Component, ArrayLike)
240      */
241     public static final void path(Component v, ArrayLike<String> commands) {
242         if (Browser.isIE) {
243             VML.path(v, commands);
244         } else {
245             SVG.path(v, commands);
246         }
247     }
248 
249     /**
250      * <p>Creates a path component, eliminating the browser dependencies.</p>
251      * @param commands An array of path commands.
252      * @return The newly created path component which is either a VML shape component 
253      * for IE or a SVG path component for other browsers.
254      * @since 1.0
255      * @see SVG#path(ArrayLike)
256      * @see VML#path(ArrayLike)
257      */
258     public static final Component path(ArrayLike<String> commands) {
259         return Browser.isIE ? VML.path(commands) : SVG.path(commands);
260     }
261 
262     /**
263      * <p>Creates a path component, eliminating the browser dependencies.</p>
264      * @return The newly created path component which is either a VML shape component 
265      * for IE or a SVG path component for other browsers.
266      * @since 1.0
267      * @see SVG#path()
268      * @see VML#shape()
269      */
270     public static final Component path() {
271         return Browser.isIE ? VML.shape() : SVG.path();
272     }
273 
274     /**
275      * <p>Creates an absolute move-to path command, eliminating the browser dependencies.</p>
276      * @param x The X coordinate of the point to move to.
277      * @param y The Y coordinate of the point to move to.
278      * @return A string value of the newly created path command.
279      * @since 1.0
280      * @see SVG#moveTo(double, double)
281      * @see VML#moveTo(int, int)
282      */
283     public static final String moveTo(Number x, Number y) {
284         return Browser.isIE ? VML.moveTo(x.intValue(), y.intValue()) : SVG.moveTo(x.doubleValue(), y.doubleValue());
285     }
286 
287     /**
288      * <p>Creates an absolute line-to path command, eliminating the browser dependencies.</p>
289      * @param x The X coordinate of the point to line to.
290      * @param y The Y coordinate of the point to line to.
291      * @return A string value of the newly created path command.
292      * @since 1.0
293      * @see SVG#lineTo(double, double)
294      * @see VML#lineTo(int, int)
295      */
296     public static final String lineTo(Number x, Number y) {
297         return Browser.isIE ? VML.lineTo(x.intValue(), y.intValue()) : SVG.lineTo(x.doubleValue(), y.doubleValue());
298     }
299 
300     /**
301      * <p>Creates an relative move-to path command, eliminating the browser dependencies.</p>
302      * @param x The relative X coordinate of the point to move to.
303      * @param y The relative Y coordinate of the point to move to.
304      * @return A string value of the newly created path command.
305      * @since 1.0
306      * @see SVG#moveto(double, double)
307      * @see VML#moveto(int, int)
308      */
309     public static final String moveto(Number x, Number y) {
310         return Browser.isIE ? VML.moveTo(x.intValue(), y.intValue()) : SVG.moveTo(x.doubleValue(), y.doubleValue());
311     }
312 
313     /**
314      * <p>Creates an relative line-to path command, eliminating the browser dependencies.</p>
315      * @param x The relative X coordinate of the point to line to.
316      * @param y The relative Y coordinate of the point to line to.
317      * @return A string value of the newly created path command.
318      * @since 1.0
319      * @see SVG#lineto(double, double)
320      * @see VML#lineto(int, int)
321      */
322     public static final String lineto(Number x, Number y) {
323         return Browser.isIE ? VML.lineTo(x.intValue(), y.intValue()) : SVG.lineTo(x.doubleValue(), y.doubleValue());
324     }
325 
326     /**
327      * <p>Creates a close-path command, eliminating the browser dependencies.</p>
328      * @return A string value of the newly created path command.
329      * @since 1.0
330      * @see SVG#closePath()
331      * @see VML#close()
332      */
333     public static final String close() {
334         return Browser.isIE ? VML.close() : SVG.closePath();
335     }
336 
337     /**
338      * <p>Fills a specified graphic component with a CSS color, eliminating the browser dependencies.</p>
339      * @param v A graphic component which is either a VML component for IE or a SVG 
340      * component for other browsers.
341      * @param color A string of CSS color value.
342      * @since 1.0
343      * @see SVG#fill(Component, String)
344      * @see VML#fillColor(Component, String)
345      */
346     public static final void fill(Component v, String color) {
347         if (Browser.isIE) {
348             VML.fillColor(v, color);
349         } else {
350             SVG.fill(v, color);
351         }
352     }
353 
354     /**
355      * <p>Defines stroke color of a specified graphic component, eliminating the browser dependencies.</p>
356      * @param v A graphic component which is either a VML component for IE or a SVG 
357      * component for other browsers.
358      * @param color A string of CSS color value.
359      * @since 1.0
360      * @see SVG#stroke(Component, String)
361      * @see VML#strokeColor(Component, String)
362      */
363     public static final void stroke(Component v, String color) {
364         if (Browser.isIE) {
365             VML.strokeColor(v, color);
366         } else {
367             SVG.stroke(v, color);
368         }
369     }
370 
371     /**
372      * <p>Defines stroke width of a specified graphic component, eliminating the browser dependencies.</p>
373      * @param v A graphic component which is either a VML component for IE or a SVG 
374      * component for other browsers.
375      * @param w A number or string value of stroke width.
376      * @since 1.0
377      * @see SVG#strokeWidth(Component, Object)
378      * @see VML#strokeWeight(Component, Object)
379      */
380     public static final void strokeWidth(Component v, Object w) {
381         if (Browser.isIE) {
382             VML.strokeWeight(v, w);
383         } else {
384             SVG.strokeWidth(v, w);
385         }
386     }
387 
388     /**
389      * <p>Creates graphic rectangle component, eliminating the browser dependencies.</p>
390      * @return The newly created rectangle component which is either a VML rounded 
391      * rectangle component for IE or a SVG rectangle component for other browsers.
392      * @since 1.0
393      * @see SVG#rect()
394      * @see VML#roundrect()
395      * @see #rectFrom(Component, double, double)
396      * @see #rectSize(Component, double, double)
397      * @see #rectRound(Component, double)
398      */
399     public static final Component rect() {
400         return Browser.isIE ? VML.roundrect() : SVG.rect();
401     }
402 
403     /**
404      * <p>Defines the base point of a rectangle component, eliminating the browser dependencies.</p>
405      * @param v The current rectangle component which is either a VML rounded rectangle 
406      * component for IE or a SVG rectangle component for other browsers.
407      * @param x The X coordinate of the base point.
408      * @param y The Y coordinate of the base point.
409      * @since 1.0
410      * @see SVG#rectFrom(Component, double, double)
411      * @see VML#roundrect()
412      * @see #rect()
413      * @see #rectSize(Component, double, double)
414      * @see #rectRound(Component, double)
415      */
416     public static final void rectFrom(Component v, double x, double y) {
417         if (Browser.isIE) {
418             ObjectLike s = Component.style(v);
419             Styles.left(s, Js.toString(x));
420             Styles.top (s, Js.toString(y));
421         } else {
422             SVG.rectFrom(v, x, y);
423         }
424     }
425 
426     /**
427      * <p>Defines the size of a rectangle component, eliminating the browser dependencies.</p>
428      * @param v The current rectangle component which is either a VML rounded rectangle 
429      * component for IE or a SVG rectangle component for other browsers.
430      * @param w The X dimension.
431      * @param h The Y dimension.
432      * @since 1.0
433      * @see SVG#rectSize(Component, double, double)
434      * @see VML#roundrect()
435      * @see #rect()
436      * @see #rectFrom(Component, double, double)
437      * @see #rectRound(Component, double)
438      */
439     public static final void rectSize(Component v, double w, double h) {
440         if (Browser.isIE) {
441             ObjectLike s = Component.style(v);
442             Styles.width (s, Js.toString(w));
443             Styles.height(s, Js.toString(h));
444         } else {
445             SVG.rectSize(v, w, h);
446         }
447     }
448 
449     /**
450      * <p>Rounds off the corners of a rectangle component, eliminating the browser dependencies.</p>
451      * @param v The current rectangle component which is either a VML rounded rectangle 
452      * component for IE or a SVG rectangle component for other browsers.
453      * @param r The of the circle used to round off the corners of the rectangle.
454      * @since 1.0
455      * @see SVG#rectRound(Component, double, double)
456      * @see VML#roundrect(Component, double)
457      * @see #rect()
458      * @see #rectFrom(Component, double, double)
459      * @see #rectSize(Component, double, double)
460      */
461     public static final void rectRound(Component v, double r) {
462         if (Browser.isIE) {
463             VML.roundrect(v, r);
464         } else {
465             SVG.rectRound(v, r, r);
466         }
467     }
468 
469     /**
470      * <p>Creates a rectangle component, eliminating the browser dependencies.</p>
471      * @param x The X coordinate of the base point.
472      * @param y The Y coordinate of the base point.
473      * @param w The X dimension.
474      * @param h The Y dimension.
475      * @return The newly created rectangle component which is either a VML rounded 
476      * rectangle component for IE or a SVG rectangle component for other browsers.
477      * @since 1.0
478      * @see SVG#rect(double, double, double, double)
479      * @see VML#roundrect()
480      * @see #rect()
481      * @see #rect(double, double, double, double, double)
482      */
483     public static final Component rect(double x, double y, double w, double h) {
484         Component v = rect();
485         rectFrom(v, x, y);
486         rectSize(v, w, h);
487         return v;
488     }
489 
490     /**
491      * <p>Creates a rectangle component, eliminating the browser dependencies.</p>
492      * @param x The X coordinate of the base point.
493      * @param y The Y coordinate of the base point.
494      * @param w The X dimension.
495      * @param h The Y dimension.
496      * @param r The of the circle used to round off the corners of the rectangle.
497      * @return The newly created rectangle component which is either a VML rounded 
498      * rectangle component for IE or a SVG rectangle component for other browsers.
499      * @since 1.0
500      * @see SVG#rect(double, double, double, double, double, double)
501      * @see VML#roundrect(double)
502      * @see #rect()
503      * @see #rect(double, double, double, double)
504      */
505     public static final Component rect(double x, double y, double w, double h, double r) {
506         Component v = rect(x, y, w, h);
507         rectRound(v, r);
508         return v;
509     }
510 
511     /**
512      * <p>Creates a circle component, eliminating the browser dependencies.</p>
513      * @return The newly created circle component which is either a VML oval component 
514      * for IE or a SVG circle component for other browsers.
515      * @since 1.0
516      * @see SVG#circle()
517      * @see VML#oval()
518      * @see #circle(double, double, double)
519      */
520     public static final Component circle() {
521         return Browser.isIE ? VML.oval() : SVG.circle();
522     }
523 
524     /**
525      * <p>Creates a circle component, eliminating the browser dependencies.</p>
526      * @param cx The X coordinate of the center of the circle.
527      * @param cy The Y coordinate of the center of the circle.
528      * @param r The radius of the circle.
529      * @return The newly created circle component which is either a VML oval component 
530      * for IE or a SVG circle component for other browsers.
531      * @since 1.0
532      * @see #circle()
533      */
534     public static final Component circle(double cx, double cy, double r) {
535         if (Browser.isIE) {
536             Component v = VML.oval();
537             ObjectLike s = Component.style(v);
538             Styles.left  (s, Js.toString(cx - r));
539             Styles.top   (s, Js.toString(cy - r));
540             Styles.width (s, Js.toString(r * 2));
541             Styles.height(s, Js.toString(r * 2));
542             return v;
543         } else {
544             Component v = SVG.circle();
545             SVG.circleRadius(v, r);
546             return v;
547         }
548     }
549 
550     /**
551      * <p>Creates a circle component, eliminating the browser dependencies.</p>
552      * @param cx The X coordinate of the center of the ellipse.
553      * @param cy The Y coordinate of the center of the ellipse.
554      * @param rx The X-axis radius of the ellipse.
555      * @param ry The Y-axis radius of the ellipse.
556      * @return The newly created ellipse component which is either a VML oval component 
557      * for IE or a SVG ellipse component for other browsers.
558      * @since 1.0
559      * @see #circle()
560      */
561     public static final Component ellipse(double cx, double cy, double rx, double ry) {
562         if (Browser.isIE) {
563             Component v = VML.oval();
564             ObjectLike s = Component.style(v);
565             Styles.left  (s, Js.toString(cx - rx));
566             Styles.top   (s, Js.toString(cy - ry));
567             Styles.width (s, Js.toString(rx * 2));
568             Styles.height(s, Js.toString(ry * 2));
569             return v;
570         } else {
571             Component v = SVG.ellipse();
572             SVG.ellipseRadius(v, rx, ry);
573             return v;
574         }
575     }
576 
577     /**
578      * <p>Creates a line component, eliminating the browser dependencies.</p>
579      * @return The newly created line component which is either a VML line component 
580      * for IE or a SVG line component for other browsers.
581      * @since 1.0
582      * @see #lineFrom(Component, Number, Number)
583      * @see #lineTo(Component, Number, Number)
584      * @see #line(Number, Number, Number, Number)
585      */
586     public static final Component line() {
587         return Browser.isIE ? VML.line() : SVG.line();
588     }
589 
590     /**
591      * <p>Defines the starting point of a specified line component, eliminating the 
592      * browser dependencies.</p>
593      * @param v The current rectangle component which is either a VML line component 
594      * for IE or a SVG line component for other browsers.
595      * @param x The X coordinate of the start point of the line.
596      * @param y The Y coordinate of the start point of the line.
597      * @since 1.0
598      * @see #line()
599      * @see #lineTo(Component, Number, Number)
600      */
601     public static final void lineFrom(Component v, Number x, Number y) {
602         if (Browser.isIE) {
603             VML.lineFrom(v, x.intValue(), y.intValue());
604         } else {
605             SVG.lineFrom(v, x.doubleValue(), y.doubleValue());
606         }
607     }
608 
609     /**
610      * <p>Defines the ending point of a specified line component, eliminating the 
611      * browser dependencies.</p>
612      * @param v The current rectangle component which is either a VML line component 
613      * for IE or a SVG line component for other browsers.
614      * @param x The X coordinate of the end point of the line.
615      * @param y The Y coordinate of the end point of the line.
616      * @since 1.0
617      * @see #line()
618      * @see #lineFrom(Component, Number, Number)
619      */
620     public static final void lineTo(Component v, Number x, Number y) {
621         if (Browser.isIE) {
622             VML.lineTo(v, x.intValue(), y.intValue());
623         } else {
624             SVG.lineTo(v, x.doubleValue(), y.doubleValue());
625         }
626     }
627 
628     /**
629      * <p>Creates a line component, eliminating the browser dependencies.</p>
630      * @param x1 The X coordinate of the start point of the line.
631      * @param y1 The Y coordinate of the start point of the line.
632      * @param x2 The X coordinate of the end point of the line.
633      * @param y2 The Y coordinate of the end point of the line.
634      * @return The newly created line component which is either a VML line component 
635      * for IE or a SVG line component for other browsers.
636      * @since 1.0
637      * @see #line()
638      */
639     public static final Component line(Number x1, Number y1, Number x2, Number y2) {
640         return Browser.isIE ? VML.line(x1.intValue   (), y1.intValue   (), x2.intValue   (), y2.intValue   ()) :
641                                 SVG.line(x1.doubleValue(), y1.doubleValue(), x2.doubleValue(), y2.doubleValue());
642     }
643 
644     /**
645      * <p>Draws a curve specified by a motion on a graphic widget.</p>
646      * @param g The current graphic wrapper.
647      * @param m The motion definition.
648      * @param n The number of steps used to draw the curve. The larger this number, the 
649      * more precise the curve but the more time it takes to draw the curve.
650      * @return The path component of the curve which is either a VML shape component 
651      * for IE or a SVG path component for other browsers.
652      * @since 1.0
653      */
654     public static final Component curve(Graphic g, Motion m, int n) {
655         Component v = g.unwrap();
656         int w = (int)(Component.contentWidth (v));
657         int h = (int)(Component.contentHeight(v) / 2);
658         ArrayLike<String> c = new Vars<String>().add(Graphic.moveTo(0, h)).var();
659         Uniform un = new Uniform();
660         un.init(n);
661         m.init(n);
662         for (int i = 0; i < n; i++) {
663             c.push(Graphic.lineTo((int)(w * un.get(i) * 0.75), (int)(h - h * m.get(i) * 0.75)));
664         }
665         Component path = Graphic.path(c);
666         Graphic.add(g, path);
667         return path;
668     }
669 }