39c525307475b304b7711ac5d827224fc5204052
[jalviewjs.git] / site / j2s / swingjs / plaf / JSComponentUI.java
1 package swingjs.plaf;\r
2 \r
3 import jsjava.awt.AWTEvent;\r
4 import jsjava.awt.Color;\r
5 import jsjava.awt.Component;\r
6 import jsjava.awt.Dimension;\r
7 import jsjava.awt.Font;\r
8 import jsjava.awt.FontMetrics;\r
9 import jsjava.awt.Graphics;\r
10 import jsjava.awt.GraphicsConfiguration;\r
11 import jsjava.awt.Image;\r
12 import jsjava.awt.Insets;\r
13 import jsjava.awt.Point;\r
14 import jsjava.awt.Rectangle;\r
15 import jsjava.awt.Toolkit;\r
16 import jsjava.awt.event.FocusEvent;\r
17 import jsjava.awt.event.PaintEvent;\r
18 import jsjava.awt.image.ColorModel;\r
19 import jsjava.awt.image.ImageObserver;\r
20 import jsjava.awt.image.ImageProducer;\r
21 import jsjava.awt.image.VolatileImage;\r
22 import jsjava.awt.peer.ContainerPeer;\r
23 import jsjava.awt.peer.LightweightPeer;\r
24 import jsjavax.swing.AbstractButton;\r
25 import jsjavax.swing.JComponent;\r
26 import jsjavax.swing.JRootPane;\r
27 import jsjavax.swing.plaf.ComponentUI;\r
28 import jssun.awt.CausedFocusEvent.Cause;\r
29 import swingjs.JSToolkit;\r
30 import swingjs.api.DOMNode;\r
31 import swingjs.api.JQueryObject;\r
32 \r
33 /**\r
34  * The JSComponentUI subclasses are where all the detailed HTML5 implementation is \r
35  * carried out. These subclasses mirror the subclasses found in the actual javax.swing.plaf\r
36  * but have an important difference in that that effectively act as both the UI (a single\r
37  * implementation for a given AppContext in Swing) and a peer (one implementation per component).\r
38  * \r
39  * So here we store both the constants for the HTML5 "LookAndFeel", but also\r
40  * HTML5 objects that really are on the page. \r
41  * \r
42  * Essentially, at least for now, we are not implementing the HTML5LookAndFeel as such. We'll see how that goes. \r
43  * \r
44  *  \r
45  *   \r
46  * @author Bob Hanson\r
47  *\r
48  */\r
49 public abstract class JSComponentUI extends ComponentUI implements JSEventHandler {\r
50 \r
51         /**\r
52          * provides a unique id for any component; set on instantiation\r
53          */\r
54         protected static int incr;  \r
55 \r
56         \r
57         /**\r
58          * a unique id\r
59          */\r
60         protected String id;\r
61         \r
62         /**\r
63          * the associated JComponent; for which this is c.ui\r
64          * \r
65          */\r
66         protected JComponent c;\r
67 \r
68 \r
69         /**\r
70          * the outermost div holding a component -- left, top, and for a container width and height\r
71          */\r
72         protected DOMNode outerNode; \r
73 \r
74         /**\r
75          * the main object for the component, possibly containing others, such as radio button with its label\r
76          */\r
77         protected DOMNode domNode;\r
78         \r
79         /**\r
80          * a component or subcomponent that can be enabled/disabled \r
81          */\r
82         protected DOMNode enableNode; \r
83         \r
84         /**\r
85          * the part of a component that can hold text\r
86          */\r
87         protected DOMNode textNode;\r
88         \r
89         /**\r
90          * the subcomponent with the value field\r
91          */\r
92         protected DOMNode valueNode;\r
93 \r
94         /**\r
95          * a component that is being scrolled by a JScrollPane\r
96          */\r
97         protected DOMNode scrollNode;\r
98 \r
99 \r
100         /**\r
101          * a component that is focusable\r
102          */\r
103         protected DOMNode focusNode;\r
104 \r
105 \r
106         /**\r
107          * DOM components pre-defined (JScrollPane)\r
108          * \r
109          */\r
110         protected Component[] components;\r
111 \r
112         /**\r
113          * a numerical reference for an ID\r
114          */\r
115         protected int num;\r
116         \r
117         /**\r
118          * not implemented/needed currently. Java handles this nicely \r
119          * \r
120          */\r
121         protected boolean isTainted = true;\r
122         \r
123         /**\r
124          * left and top coordinates\r
125          */\r
126         protected int x, y;\r
127         \r
128         /**\r
129          * preferred dimension set by user\r
130          * \r
131          */\r
132         protected Dimension preferredSize;\r
133         \r
134         \r
135         /**\r
136          * panels \r
137          * \r
138          */\r
139         protected boolean isContainer;\r
140         \r
141         /**\r
142          * linked nodes of this class\r
143          * \r
144          */\r
145         protected JSComponentUI parent;\r
146 \r
147 \r
148         String currentText;\r
149 \r
150 \r
151         /**\r
152          * the scroller for a text area\r
153          */\r
154         protected JSScrollPaneUI scrollerNode;\r
155 \r
156 \r
157         /**\r
158          * uiClassID for this component\r
159          */\r
160         protected String classID;\r
161         \r
162 \r
163         private DOMNode document, body;\r
164 \r
165 \r
166         protected boolean needPreferred;\r
167 \r
168 \r
169         \r
170         public JSComponentUI() {\r
171                 setDoc();\r
172         }\r
173 \r
174         protected void setDoc() {\r
175                 /**\r
176                  * @j2sNative\r
177                  * \r
178                  * this.document = document;\r
179                  * this.body = document.body;\r
180                  */\r
181                 {}\r
182         }\r
183 \r
184         protected abstract void installJSUI();\r
185         protected abstract void uninstallJSUI();\r
186         \r
187         public void installUI(JComponent c) {\r
188                 // already done installJSUI();\r
189         }\r
190 \r
191         public void uninstallUI(JComponent c) {\r
192                 uninstallJSUI();\r
193         }\r
194 \r
195         protected JQueryObject $(DOMNode node) {\r
196                 return JSToolkit.getJQuery().$(node);\r
197         }\r
198         \r
199         /**\r
200          * mark this component as in need of update; \r
201          * maybe not necessary, though. It comes after the value  callback \r
202          */\r
203   public void setTainted() {\r
204         isTainted = true;\r
205   }\r
206   \r
207   public abstract DOMNode getDOMObject();\r
208 \r
209         public JSComponentUI set(JComponent target) {\r
210                 c = target;\r
211                 newID();\r
212                 if (needPreferred)\r
213                         getPreferredSize(c);\r
214                 installJSUI(); // need to do this immediately, not later\r
215                 return this;\r
216         }\r
217 \r
218         protected void newID() {\r
219                 classID = c.getUIClassID();\r
220                 if (id == null) {\r
221                         num = ++incr;\r
222                         id = c.getHTMLName(classID) + "_" + num;\r
223                 }\r
224         }\r
225 \r
226         protected DOMNode setCssFont(DOMNode obj, Font font) {\r
227                 if (font != null) {\r
228                         int istyle = font.getStyle();\r
229                         String name = font.getFamily();\r
230                         if (name == "Dialog")\r
231                                 name = "Arial";\r
232                         DOMNode.setStyles(obj, "font-family", name, "font-size",\r
233                                         font.getSize() + "px", "font-style",\r
234                                         ((istyle & Font.ITALIC) == 0 ? "normal" : "italic"), "font-weight",\r
235                                         ((istyle & Font.BOLD) == 0 ? "normal" : "bold"));\r
236                 }\r
237                 if (c.isBackgroundSet())\r
238                         setBackground(c.getBackground());\r
239     setForeground(c.getForeground());\r
240                 return obj;\r
241         }\r
242 \r
243         protected DOMNode createDOMObject(String key, String id, String... attr) {\r
244                 DOMNode obj = DOMNode.createElement(key, id);\r
245                 for (int i = 0; i < attr.length;)\r
246                         DOMNode.setAttr(obj, attr[i++], attr[i++]);\r
247                 if (!c.isEnabled())\r
248                         setEnabled(false);\r
249                 return obj;\r
250         }\r
251 \r
252         /**\r
253          * JSmolCore.js will look for  data-UI attribute  and, if found, reroute directly here \r
254          * @param node \r
255          */\r
256         protected void bindMouse(DOMNode node) {\r
257                 DOMNode.setAttr(node, "data-UI", this);         \r
258         }\r
259         \r
260         /**\r
261          * called by JmolCore.js\r
262          * @return true if handled\r
263          */\r
264         public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) {\r
265                 //System.out.println(id + " handling event " + eventType + jQueryEvent);\r
266                 return false;\r
267         }\r
268 \r
269         protected DOMNode wrap(String type, String id, DOMNode... elements) {\r
270                 return append(createDOMObject(type, id + type), elements);\r
271         }\r
272 \r
273         protected DOMNode append(DOMNode obj, DOMNode[] elements) {\r
274                 for (int i = 0; i < elements.length; i++) {\r
275                         obj.appendChild(elements[i]);\r
276                 }\r
277                 return obj;\r
278         }\r
279 \r
280         protected void debugDump(DOMNode d) {\r
281                 System.out.println(DOMNode.getAttr(d, "outerHTML"));\r
282         }\r
283         \r
284         protected static void vCenter(DOMNode obj, int offset) {\r
285                 DOMNode.setStyles(obj, \r
286                                 "top", "50%", \r
287                                 "transform","translateY(" + offset + "%)");\r
288         }\r
289         \r
290         /**\r
291          * overloaded to allow panel and radiobutton to handle slightly differently \r
292          * \r
293          * @param obj\r
294          * @param addCSS\r
295          * @return\r
296          */\r
297         protected Dimension setHTMLSize(DOMNode obj, boolean addCSS) {\r
298                 return setHTMLSize1(obj, addCSS, true);\r
299         }\r
300 \r
301         /**\r
302          * also called by JSRadioButtonUI so that it can calculate\r
303          * subset dimensions\r
304          *  \r
305          * @param node\r
306          * @param addCSS\r
307          * @param usePreferred\r
308          * @return\r
309          */\r
310         @SuppressWarnings("unused")\r
311         protected Dimension setHTMLSize1(DOMNode node, boolean addCSS, boolean usePreferred) {\r
312                 if (node == null)\r
313                         return null;\r
314                 int h, w;\r
315                 String w0 = null, h0 = null;\r
316                 DOMNode parentNode = null;\r
317 \r
318                 if (scrollerNode != null) {\r
319                         w = scrollerNode.c.getWidth();\r
320                         h = scrollerNode.c.getHeight();\r
321                 } else if (usePreferred && preferredSize != null) {\r
322                         // user has set preferred size\r
323                         w = preferredSize.width;\r
324                         h = preferredSize.height;\r
325                 } else {\r
326       // determine the natural size of this object\r
327                         // save the parent node -- we will need to reset that.\r
328                         parentNode = DOMNode.remove(node);\r
329 \r
330                         // remove position, width, and height, because those are what we are\r
331                         // setting here\r
332                         /**\r
333                          * @j2sNative\r
334                          * \r
335                          * w0 = node.style.width;\r
336                          * h0 = node.style.height;\r
337                          */\r
338                         {}\r
339                         DOMNode.setStyles(node, "position", null, "width", null, "height", null);\r
340                         DOMNode div;\r
341                         if (DOMNode.getAttr(node, "tagName") == "DIV")\r
342                                 div = node;\r
343                         else\r
344                                 div = wrap("div", id + "_temp", node);\r
345                         DOMNode.setStyles(div, "position", "absolute");\r
346 \r
347                         // process of discovering width and height is facilitated using jQuery\r
348                         // and appending to document.body.\r
349 \r
350                         body.appendChild(div);\r
351                         \r
352                         //System.out.println(DOMNode.getAttr(node, "outerHTML"));\r
353                         w = (int) Math.ceil($(div).width() + 0.5);\r
354                         h = (int) Math.ceil($(div).height() + 0.5);\r
355                         body.removeChild(div);\r
356                 }\r
357 \r
358                 Dimension size = getCSSDimension(w, h);\r
359                 if (addCSS) {\r
360                         DOMNode.setStyles(node, "position", "absolute");\r
361                         DOMNode.setSize(node, size.width, size.height);\r
362                 } else {\r
363                         DOMNode.setStyles(node, "position", null);\r
364                         // check to reset width/height after getPreferredSize\r
365                         if (w0 != null)\r
366                                 DOMNode.setStyles(node, "width", w0, "height", h0);\r
367                 }\r
368                 if (parentNode != null)\r
369                         parentNode.appendChild(node);\r
370                 //System.out.println("JSComponentUI " + id + " resized to " + w + "x" + h + " parent=" + DOMNode.getAttr(parentNode,"id"));     \r
371                 return size;\r
372         }\r
373 \r
374         /**\r
375          * can be overloaded to allow some special adjustments\r
376          * \r
377          * @param w\r
378          * @param h\r
379          * @return\r
380          */\r
381         protected Dimension getCSSDimension(int w, int h) {\r
382                 return new Dimension(w, h);\r
383         }\r
384 \r
385         /**\r
386          * creates the DOM node and inserts it into the tree at the correct place,\r
387          * iterating through all children if this is a container\r
388          * \r
389          * @return\r
390          * \r
391          */\r
392         protected DOMNode setHTMLElement() {\r
393                 if (!isTainted)\r
394                         return outerNode;\r
395 \r
396                 // check for root pane -- not included in DOM\r
397                 JRootPane root = (isContainer ? c.getRootPane() : null);\r
398                 if (c == root) {\r
399                         isTainted = false;\r
400                         return outerNode;\r
401                 }\r
402 \r
403                 domNode = getDOMObject();\r
404 \r
405                 // divObj will need recreating if a propertyChange event has occurred\r
406                 // check for content pane -- needs to be added to the HTML5 content layer\r
407                 // div\r
408 \r
409                 // needs some work for changes after applet creation\r
410 \r
411                 if (outerNode == null) {\r
412                         outerNode = wrap("div", id, domNode);\r
413                         if (root != null && root.getContentPane() == c)\r
414                                 swingjs.JSToolkit.getHTML5Applet(c)._getContentLayer()\r
415                                                 .appendChild(outerNode);\r
416                 }\r
417 \r
418                 // set position\r
419 \r
420                 DOMNode.setStyles(outerNode, "position", "absolute", "left", (x = c.getX())\r
421                                 + "px", "top", (y = c.getY()) + "px");\r
422 \r
423                 if (isContainer) {\r
424 \r
425                         // set width from component\r
426 \r
427                         System.out.println("JSComponentUI container " + id + " " + c.getBounds());\r
428                         DOMNode.setSize(outerNode, c.getWidth(), c.getHeight());\r
429 \r
430                         // add all children\r
431                         Component[] children = (components == null ? c.getComponents()\r
432                                         : components);\r
433                         for (int i = children.length; --i >= 0;) {\r
434                                 JSComponentUI ui = JSToolkit.getUI(children[i], false);\r
435                                 if (ui == null) {\r
436                                         // Box.Filler has no ui.\r
437                                         continue;\r
438                                 }\r
439                                 if (ui.outerNode == null)\r
440                                         ui.setHTMLElement();\r
441                                 if (ui.outerNode == null) {\r
442                                         System.out.println("JSCUI could not add " + ui.c.getName() + " to "\r
443                                                         + c.getName());\r
444                                 } else {\r
445                                         outerNode.appendChild(ui.outerNode);\r
446                                 }\r
447                                 ui.parent = this;\r
448                         }\r
449                 }\r
450 \r
451                 // mark as not tainted\r
452                 // debugDump(divObj);\r
453                 isTainted = false;\r
454                 return outerNode;\r
455         }\r
456 \r
457         /**\r
458          * c ignored because JSComponentUI is one per component\r
459          */\r
460         public Dimension getPreferredSize(JComponent c) {\r
461                 //System.out.println("getPreferredSize for " + id + " " + c.getName());\r
462                 Dimension d = setHTMLSize(getDOMObject(), false);\r
463                 //System.out.println("JSComponentUI " + id + " getting preferred size as " + d);\r
464         return d;\r
465   }\r
466 \r
467         public void paint(Graphics g, JComponent c) {\r
468     // Note that for now, button graphics \r
469                 // are BEHIND the button. We will need to paint onto the\r
470                 // glass pane for this to work, and then also manage\r
471                 // mouse clicks and key clicks with that in mind. \r
472                 if (c.isOpaque()) {\r
473                         g.setColor(c.getBackground());\r
474                         g.fillRect(0, 0, c.getWidth(), c.getHeight());\r
475                 }\r
476         }\r
477 \r
478         public void update(Graphics g, JComponent c) {\r
479                 // called from JComponent.paintComponent\r
480                 boolean testing = false;//true;\r
481                 if (testing) {\r
482                         g.setColor(Color.red);\r
483                         g.drawRect(0, 0, c.getWidth(), c.getHeight());\r
484                         System.out.println("drawing " + c.getWidth() + " " + c.getHeight());\r
485                 }\r
486                 setHTMLElement();\r
487                 paint(g, c);\r
488         }\r
489 \r
490         public Dimension getMinimumSize(JComponent c) {\r
491                 return getPreferredSize(c);\r
492         }\r
493 \r
494         public Dimension getMaximumSize(JComponent c) {\r
495                 return null;// getPreferredSize(c);\r
496         }\r
497 \r
498   /**\r
499    * Returns <code>true</code> if the specified <i>x,y</i> location is\r
500    * contained within the look and feel's defined shape of the specified\r
501    * component. <code>x</code> and <code>y</code> are defined to be relative\r
502    * to the coordinate system of the specified component.  Although\r
503    * a component's <code>bounds</code> is constrained to a rectangle,\r
504    * this method provides the means for defining a non-rectangular\r
505    * shape within those bounds for the purpose of hit detection.\r
506    *\r
507    * @param c the component where the <i>x,y</i> location is being queried;\r
508    *          this argument is often ignored,\r
509    *          but might be used if the UI object is stateless\r
510    *          and shared by multiple components\r
511    * @param x the <i>x</i> coordinate of the point\r
512    * @param y the <i>y</i> coordinate of the point\r
513    *\r
514    * @see jsjavax.swing.JComponent#contains\r
515    * @see jsjava.awt.Component#contains\r
516    */\r
517   public boolean contains(JComponent c, int x, int y) {\r
518       return c.inside(x, y);\r
519   }\r
520 \r
521   /**\r
522    * Returns an instance of the UI delegate for the specified component.\r
523    * Each subclass must provide its own static <code>createUI</code>\r
524    * method that returns an instance of that UI delegate subclass.\r
525    * If the UI delegate subclass is stateless, it may return an instance\r
526    * that is shared by multiple components.  If the UI delegate is\r
527    * stateful, then it should return a new instance per component.\r
528    * The default implementation of this method throws an error, as it\r
529    * should never be invoked.\r
530    */\r
531   public static ComponentUI createUI(JComponent c) {\r
532         // SwingJS  so, actually, we don't do this. This class is NOT stateless.\r
533         // Instead, what we do is to create a unique instance \r
534         // right in UIManager. The sequence is:\r
535         // JRadioButton.updateUI() \r
536         // --> jsjavax.swing.UIManager.getUI(this)\r
537         // --> jsjavax.swing.UIManager.getDefaults().getUI(target) \r
538         // --> JSToolkit.getComponentUI(target)\r
539         // --> creates an instance of JRadioButtonUI and returns\r
540         // that instance as JRadioButton.ui, which is NOT static.\r
541         // \r
542 //      throw new Error("ComponentUI.createUI not implemented.");\r
543         return null;\r
544   }\r
545 \r
546   /**\r
547    * Returns the baseline.  The baseline is measured from the top of\r
548    * the component.  This method is primarily meant for\r
549    * <code>LayoutManager</code>s to align components along their\r
550    * baseline.  A return value less than 0 indicates this component\r
551    * does not have a reasonable baseline and that\r
552    * <code>LayoutManager</code>s should not align this component on\r
553    * its baseline.\r
554    * <p>\r
555    * This method returns -1.  Subclasses that have a meaningful baseline\r
556    * should override appropriately.\r
557    *\r
558    * @param c <code>JComponent</code> baseline is being requested for\r
559    * @param width the width to get the baseline for\r
560    * @param height the height to get the baseline for\r
561    * @throws NullPointerException if <code>c</code> is <code>null</code>\r
562    * @throws IllegalArgumentException if width or height is &lt; 0\r
563    * @return baseline or a value &lt; 0 indicating there is no reasonable\r
564    *                  baseline\r
565    * @see jsjavax.swing.JComponent#getBaseline(int,int)\r
566    * @since 1.6\r
567    */\r
568   public int getBaseline(JComponent c, int width, int height) {\r
569       if (c == null) {\r
570           throw new NullPointerException("Component must be non-null");\r
571       }\r
572       if (width < 0 || height < 0) {\r
573           throw new IllegalArgumentException(\r
574                   "Width and height must be >= 0");\r
575       }\r
576       return -1;\r
577   }\r
578 \r
579   /**\r
580    * Returns an enum indicating how the baseline of he component\r
581    * changes as the size changes.  This method is primarily meant for\r
582    * layout managers and GUI builders.\r
583    * <p>\r
584    * This method returns <code>BaselineResizeBehavior.OTHER</code>.\r
585    * Subclasses that support a baseline should override appropriately.\r
586    *\r
587    * @param c <code>JComponent</code> to return baseline resize behavior for\r
588    * @return an enum indicating how the baseline changes as the component\r
589    *         size changes\r
590    * @throws NullPointerException if <code>c</code> is <code>null</code>\r
591    * @see jsjavax.swing.JComponent#getBaseline(int, int)\r
592    * @since 1.6\r
593    */\r
594   public Component.BaselineResizeBehavior getBaselineResizeBehavior(\r
595           JComponent c) {\r
596       if (c == null) {\r
597           throw new NullPointerException("Component must be non-null");\r
598       }\r
599       return Component.BaselineResizeBehavior.OTHER;\r
600   }\r
601 \r
602   /**\r
603    * overridden in JSPasswordFieldUI\r
604    * @return texat\r
605    */\r
606   public String getJSTextValue() {\r
607         return (String) DOMNode.getAttr(domNode, valueNode == null ? "innerHTML" : "value");\r
608   }\r
609   \r
610         public void notifyPropertyChanged(String prop) {\r
611                 DOMNode obj = null;\r
612                 String val = null;\r
613                 if (prop == "text") {\r
614                         val = ((AbstractButton) c).getText();\r
615                         if (val.equals(currentText)) // we set it here, then fired the property change\r
616                                 return;\r
617                         currentText = val;\r
618                         if (textNode != null) {\r
619                                 prop = "innerHTML";\r
620                                 obj = textNode;\r
621                         } else if (valueNode != null) {\r
622                                 prop = "value";\r
623                                 obj = valueNode;\r
624                         }\r
625                 } else if (prop == "preferredSize") {\r
626                         preferredSize = c.getPreferredSize(); // may be null\r
627                         getPreferredSize();\r
628                         return;\r
629                 }\r
630                 if (obj == null) {\r
631                         System.out.println("JSComponentUI: unrecognized prop: " + prop);\r
632                 } else {\r
633                         System.out.println("JSComponentUI: setting " + id + " " + prop);// + " " + val);\r
634                         setProp(obj, prop, val);\r
635                 }\r
636         }\r
637 \r
638         protected DOMNode setProp(DOMNode obj, String prop, String val) {\r
639                 return DOMNode.setAttr(obj, prop, val);\r
640         }\r
641 \r
642         @Override\r
643         public boolean isObscured() {\r
644                 JSToolkit.notImplemented("");\r
645                 return false;\r
646         }\r
647 \r
648         @Override\r
649         public boolean canDetermineObscurity() {\r
650                 JSToolkit.notImplemented("");\r
651                 return false;\r
652         }\r
653 \r
654         @Override\r
655         public void setVisible(boolean b) {\r
656                 DOMNode.setStyles(outerNode, "display", b ? "block" : "none");\r
657         }\r
658 \r
659         @Override\r
660         public void setEnabled(boolean b) {     \r
661                 if (enableNode != null)\r
662                   DOMNode.setAttr(enableNode, "disabled", (b ? null : "TRUE"));\r
663         }\r
664 \r
665         @Override\r
666         public void paint(Graphics g) {\r
667                 // nothing to do here\r
668         }\r
669 \r
670         @Override\r
671         public void repaint(long tm, int x, int y, int width, int height) {\r
672                 // nothing to do here\r
673         }\r
674 \r
675         @Override\r
676         public void print(Graphics g) {\r
677                 JSToolkit.notImplemented("");           \r
678         }\r
679 \r
680         @Override\r
681         public void setBounds(int x, int y, int width, int height, int op) {\r
682                 switch (op) {\r
683                 case SET_SIZE:\r
684                 case SET_BOUNDS:\r
685                 case SET_CLIENT_SIZE:\r
686                         if (scrollerNode != null) {\r
687                                 width = Math.min(width, scrollerNode.c.getWidth());\r
688                                 height = Math.min(height, scrollerNode.c.getHeight());                  \r
689                         }\r
690                         System.out.println(id + " setBounds " + x + " " + y + " " + width + " " + height + " op=" + op);\r
691                         if (domNode != null)\r
692                                 DOMNode.setSize(domNode, width, height);\r
693                         break;\r
694                 }\r
695         }\r
696 \r
697         @Override\r
698         public void handleEvent(AWTEvent e) {\r
699                 JSToolkit.notImplemented("");\r
700                 \r
701         }\r
702 \r
703         @Override\r
704         public void coalescePaintEvent(PaintEvent e) {\r
705                 JSToolkit.notImplemented("");\r
706                 \r
707         }\r
708 \r
709         /**\r
710          * Coordinates relative to the document\r
711          * \r
712          */\r
713         @Override\r
714         public Point getLocationOnScreen() {\r
715                 Insets offset = (Insets) $(outerNode).offset();\r
716                 return new Point(offset.left, offset.top);\r
717         }\r
718 \r
719         @Override\r
720         public Dimension getPreferredSize() {\r
721                 return getPreferredSize(c);\r
722         }\r
723 \r
724         @Override\r
725         public Dimension getMinimumSize() {\r
726                 JSToolkit.notImplemented("");\r
727                 return getPreferredSize(c);\r
728         }\r
729 \r
730         @Override\r
731         public ColorModel getColorModel() {\r
732                 return Toolkit.getDefaultToolkit().getColorModel();\r
733         }\r
734 \r
735         @Override\r
736         public Toolkit getToolkit() {\r
737                 return Toolkit.getDefaultToolkit();\r
738         }\r
739 \r
740         @Override\r
741         public Graphics getGraphics() {\r
742                 // n/a  -- called from java.awt.Component when NOT a LightweightPeer.\r
743                 return null;\r
744         }\r
745 \r
746         @Override\r
747         public FontMetrics getFontMetrics(Font font) {\r
748                 return c.getFontMetrics(font);\r
749         }\r
750 \r
751         @Override\r
752         public void dispose() {\r
753                 JSToolkit.notImplemented("");\r
754         }\r
755 \r
756         @Override\r
757         public void setForeground(Color color) {\r
758                 if (domNode != null)\r
759                         DOMNode.setStyles(domNode, "color", JSToolkit.getCSSColor(color == null ? Color.black : color));\r
760         }\r
761 \r
762         @Override\r
763         public void setBackground(Color color) {\r
764                 if (domNode != null)\r
765                         DOMNode.setStyles(domNode, "background-color", JSToolkit.getCSSColor(color == null ? Color.white : color));\r
766         }\r
767 \r
768         @Override\r
769         public void setFont(Font f) {\r
770                 if (domNode != null)\r
771                         setCssFont(domNode, f);\r
772         }\r
773 \r
774         @Override\r
775         public void updateCursorImmediately() {\r
776                 JSToolkit.notImplemented("");           \r
777         }\r
778 \r
779         @Override\r
780         public boolean requestFocus(Component lightweightChild, boolean temporary,\r
781                         boolean focusedWindowChangeAllowed, long time, Cause cause) {\r
782                 if (focusNode == null)\r
783                         return false;\r
784                 $(focusNode).focus();\r
785                 if (textNode != null)\r
786                         $(textNode).select();\r
787                 return true;\r
788         }\r
789 \r
790         @Override\r
791         public boolean isFocusable() {\r
792                 return (focusNode != null);\r
793         }\r
794 \r
795         @Override\r
796         public Image createImage(ImageProducer producer) {\r
797                 JSToolkit.notImplemented("");\r
798                 return null;\r
799         }\r
800 \r
801         @Override\r
802         public Image createImage(int width, int height) {\r
803                 JSToolkit.notImplemented("");\r
804                 return null;\r
805         }\r
806 \r
807         @Override\r
808         public VolatileImage createVolatileImage(int width, int height) {\r
809                 JSToolkit.notImplemented("");\r
810                 return null;\r
811         }\r
812 \r
813         @Override\r
814         public boolean prepareImage(Image img, int w, int h, ImageObserver o) {\r
815                 JSToolkit.notImplemented("");\r
816                 return false;\r
817         }\r
818 \r
819         @Override\r
820         public int checkImage(Image img, int w, int h, ImageObserver o) {\r
821                 JSToolkit.notImplemented("");\r
822                 return 0;\r
823         }\r
824 \r
825         @Override\r
826         public GraphicsConfiguration getGraphicsConfiguration() {\r
827                 JSToolkit.notImplemented("");\r
828                 return null;\r
829         }\r
830 \r
831         @Override\r
832         public boolean handlesWheelScrolling() {\r
833                 JSToolkit.notImplemented("");\r
834                 return false;\r
835         }\r
836 \r
837         @Override\r
838         public Image getBackBuffer() {\r
839                 JSToolkit.notImplemented("");\r
840                 return null;\r
841         }\r
842 \r
843         @Override\r
844         public void destroyBuffers() {\r
845                 JSToolkit.notImplemented("");\r
846                 \r
847         }\r
848 \r
849         @Override\r
850         public void reparent(ContainerPeer newContainer) {\r
851                 JSToolkit.notImplemented("");\r
852                 \r
853         }\r
854 \r
855         @Override\r
856         public boolean isReparentSupported() {\r
857                 JSToolkit.notImplemented("");\r
858                 return false;\r
859         }\r
860 \r
861         @Override\r
862         public void layout() {\r
863                 JSToolkit.notImplemented("");\r
864                 \r
865         }\r
866 \r
867         @Override\r
868         public Rectangle getBounds() {\r
869                 JSToolkit.notImplemented("");\r
870                 return null;\r
871         }\r
872 \r
873         public boolean hasFocus() {\r
874                 return focusNode != null && focusNode == DOMNode.getAttr(document, "activeElement");\r
875         }\r
876 \r
877         public void notifyFocus(boolean focusGained) {\r
878                 Toolkit.getEventQueue().postEvent(new FocusEvent(c, focusGained ? FocusEvent.FOCUS_GAINED : FocusEvent.FOCUS_LOST));\r
879         }\r
880 }\r