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