JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / site / j2s / swingjs / plaf / JSButtonUI.java
1 package swingjs.plaf;
2
3 //import jsjava.awt.FontMetrics;
4 import jsjava.awt.event.MouseMotionListener;
5 import jsjavax.swing.AbstractButton;
6 import jsjavax.swing.LookAndFeel;
7 import jsjavax.swing.UIManager;
8 import swingjs.api.DOMNode;
9 import jsjavax.swing.plaf.UIResource;
10 /**
11  * SWingJS implementation of stateful user interface for buttons. 
12  * Modeled after javax.swing.plaf.basic.BasicButtonUI.java (commented out below).
13  * 
14  * @author Bob Hanson
15  *
16  */
17 public class JSButtonUI extends JSComponentUI {
18
19         
20         /**
21          * the radio or check-box or simple button
22          * 
23          */
24         protected DOMNode domBtn;
25
26         @Override
27         public DOMNode getDOMObject() {
28                 if (domNode == null)
29                         domBtn = enableNode = valueNode = domNode = createDOMObject("input", id,
30                                         "type", "button");
31                 setCssFont(DOMNode.setAttr(domNode, "value", ((AbstractButton) c).getText()),
32                                 c.getFont());
33                 return domNode;
34         }
35
36         /**
37          * validate a button press -- with a simple button, this is just TRUE.
38          * This is needed because sometimes the area near the button is pressed
39          * but not the actual button.
40          * @param isRelease TODO
41          * 
42          * @return true if the HTML5 button was actually pressed
43          */
44   boolean verifyButtonClick(boolean isRelease) {
45                 return true;
46         }
47
48
49         // from BasicButtonUI
50         
51         protected void installJSUI() {
52                 installDefaults((AbstractButton) c);
53                 installListeners((AbstractButton) c);
54                 installKeyboardActions((AbstractButton) c);
55         }
56   
57         protected void uninstallJSUI() {
58                 uninstallKeyboardActions((AbstractButton) c);
59                 uninstallListeners((AbstractButton) c);
60                 //uninstallDefaults((AbstractButton) c);
61         }
62         
63         protected void installListeners(AbstractButton b) {
64                 JSButtonListener listener = new JSButtonListener(b);
65                 if (listener != null) {
66                         b.addMouseListener(listener);
67                         b.addMouseMotionListener(listener);
68                         b.addFocusListener(listener);
69       b.addPropertyChangeListener(listener);
70                         b.addChangeListener(listener);
71                 }
72         }
73
74         protected void uninstallListeners(AbstractButton b) {
75                 JSButtonListener listener = getButtonListener(b);
76                 if (listener != null) {
77                         b.removeMouseListener(listener);
78                         b.removeMouseMotionListener(listener);
79                         b.removeFocusListener(listener);
80                         b.removeChangeListener(listener);
81                         b.removePropertyChangeListener(listener);
82                 }
83         }
84
85         protected void installKeyboardActions(AbstractButton b) {
86                 JSButtonListener listener = getButtonListener(b);
87                 if (listener != null) {
88                         listener.installKeyboardActions(b);
89                 }
90         }
91         
92   protected void uninstallKeyboardActions(AbstractButton b) {
93       JSButtonListener listener = getButtonListener(b);
94       if(listener != null) {
95           listener.uninstallKeyboardActions(b);
96       }
97   }
98
99   /**
100    * Returns the ButtonListener for the passed in Button, or null if one
101    * could not be found.
102    */
103   protected JSButtonListener getButtonListener(AbstractButton b) {
104       MouseMotionListener[] listeners = b.getMouseMotionListeners();
105
106       if (listeners != null) {
107           for (int counter = 0; counter < listeners.length; counter++) {
108               if (listeners[counter] instanceof JSButtonListener) {
109                   return (JSButtonListener)listeners[counter];
110               }
111           }
112       }
113       return null;
114   }
115
116   // SwingJS -- this is interesting, as it summarizes everything we will need
117   // to implement, ultimately. SwingUtilities.layoutCompoundLabel
118   // details what we are going to have to do somewhere. 
119   
120 //      private String layout(AbstractButton b, FontMetrics fm, int width, int height) {
121 //              Insets i = b.getInsets();
122 //              viewRect.x = i.left;
123 //              viewRect.y = i.top;
124 //              viewRect.width = width - (i.right + viewRect.x);
125 //              viewRect.height = height - (i.bottom + viewRect.y);
126 //
127 //              textRect.x = textRect.y = textRect.width = textRect.height = 0;
128 //              iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
129 //
130 //              // layout the text and icon
131 //              return SwingUtilities.layoutCompoundLabel(b, fm, b.getText(), b.getIcon(),
132 //                              b.getVerticalAlignment(), b.getHorizontalAlignment(),
133 //                              b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect,
134 //                              iconRect, textRect, b.getText() == null ? 0 : b.getIconTextGap());
135 //              return null;
136 //      }
137
138
139 //  // Visual constants
140 //  // NOTE: This is not used or set any where. Were we allowed to remove
141 //  // fields, this would be removed.
142 //  protected int defaultTextIconGap;
143 //
144   /** Amount to offset text, the value of this comes from
145    defaultTextShiftOffset once setTextShiftOffset has been invoked.
146    */
147   protected int shiftOffset = 0;
148         
149   /** Value that is set in shiftOffset once setTextShiftOffset has been
150    invoked. The value of this comes from the defaults table.
151    */
152   protected int defaultTextShiftOffset;
153 //
154 //protected String propertyPrefix = "Button.";
155 //  
156 //  private static final Object BASIC_BUTTON_UI_KEY = new Object();
157 //
158 //  // ********************************
159 //  //          Create PLAF
160 //  // ********************************
161 //  public static ComponentUI createUI(JComponent c) {
162 //      AppContext appContext = AppContext.getAppContext();
163 //      BasicButtonUI buttonUI = 
164 //              (BasicButtonUI) appContext.get(BASIC_BUTTON_UI_KEY);
165 //      if (buttonUI == null) {
166 //          buttonUI = new BasicButtonUI();
167 //          appContext.put(BASIC_BUTTON_UI_KEY, buttonUI);
168 //      }
169 //      return buttonUI;
170 //  }
171 //
172   protected String getPropertyPrefix() {
173       return "Button.";
174   }
175 //
176 //
177 //  // ********************************
178 //  //          Install PLAF
179 //  // ********************************
180 //  public void installUI(JComponent c) {
181 //      installDefaults((AbstractButton) c);
182 //      installListeners((AbstractButton) c);
183 //      installKeyboardActions((AbstractButton) c);
184 //      BasicHTML.updateRenderer(c, ((AbstractButton) c).getText());
185 //  }
186 //
187   protected void installDefaults(AbstractButton b) {
188       // load shared instance defaults
189       String pp = getPropertyPrefix();
190
191       defaultTextShiftOffset = UIManager.getInt(pp + "textShiftOffset");
192
193 //      // set the following defaults on the button
194 //      if (b.isContentAreaFilled()) {
195 //          LookAndFeel.installProperty(b, "opaque", Boolean.TRUE);
196 //      } else {
197 //          LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
198 //      }
199
200       if(b.getMargin() == null || (b.getMargin() instanceof UIResource)) {
201           b.setMargin(UIManager.getInsets(pp + "margin"));
202       }
203
204       LookAndFeel.installColorsAndFont(b, pp + "background",
205                                        pp + "foreground", pp + "font");
206 //      LookAndFeel.installBorder(b, pp + "border");
207 //
208 //      Object rollover = UIManager.get(pp + "rollover");
209 //      if (rollover != null) {
210 //          LookAndFeel.installProperty(b, "rolloverEnabled", rollover);
211 //      }
212       LookAndFeel.installProperty(b, "iconTextGap", new Integer(4));
213   }
214 //
215 //  protected void installListeners(AbstractButton b) {
216 //      JSButtonListener listener = createButtonListener(b);
217 //      if(listener != null) {
218 //          b.addMouseListener(listener);
219 //          b.addMouseMotionListener(listener);
220 //          b.addFocusListener(listener);
221 //          b.addPropertyChangeListener(listener);
222 //          b.addChangeListener(listener);
223 //      }
224 //  }
225 //
226 //  protected void installKeyboardActions(AbstractButton b){
227 //      JSButtonListener listener = getButtonListener(b);
228 //
229 //      if(listener != null) {
230 //          listener.installKeyboardActions(b);
231 //      }
232 //  }
233 //
234 //
235 //  // ********************************
236 //  //         Uninstall PLAF
237 //  // ********************************
238 //  public void uninstallUI(JComponent c) {
239 //      uninstallKeyboardActions((AbstractButton) c);
240 //      uninstallListeners((AbstractButton) c);
241 //      uninstallDefaults((AbstractButton) c);
242 //      BasicHTML.updateRenderer(c, "");
243 //  }
244 //
245 //  protected void uninstallKeyboardActions(AbstractButton b) {
246 //      JSButtonListener listener = getButtonListener(b);
247 //      if(listener != null) {
248 //          listener.uninstallKeyboardActions(b);
249 //      }
250 //  }
251 //
252 //  protected void uninstallListeners(AbstractButton b) {
253 //      JSButtonListener listener = getButtonListener(b);
254 //      if(listener != null) {
255 //          b.removeMouseListener(listener);
256 //          b.removeMouseMotionListener(listener);
257 //          b.removeFocusListener(listener);
258 //          b.removeChangeListener(listener);
259 //          b.removePropertyChangeListener(listener);
260 //      }
261 //  }
262 //
263 //  protected void uninstallDefaults(AbstractButton b) {
264 //      LookAndFeel.uninstallBorder(b);
265 //  }
266 //
267 //  // ********************************
268 //  //        Create Listeners
269 //  // ********************************
270 //  protected JSButtonListener createButtonListener(AbstractButton b) {
271 //      return new JSButtonListener(b);
272 //  }
273 //
274 //  public int getDefaultTextIconGap(AbstractButton b) {
275 //      return defaultTextIconGap;
276 //  }
277 //
278 //  /* These rectangles/insets are allocated once for all
279 //   * ButtonUI.paint() calls.  Re-using rectangles rather than
280 //   * allocating them in each paint call substantially reduced the time
281 //   * it took paint to run.  Obviously, this method can't be re-entered.
282 //   */
283 //  private static Rectangle viewRect = new Rectangle();
284 //  private static Rectangle textRect = new Rectangle();
285 //  private static Rectangle iconRect = new Rectangle();
286 //
287 //  // ********************************
288 //  //          Paint Methods
289 //  // ********************************
290 //
291 //  public void paint(Graphics g, JComponent c)
292 //  {
293 //      AbstractButton b = (AbstractButton) c;
294 //      ButtonModel model = b.getModel();
295 //
296 //      String text = layout(b, SwingUtilities2.getFontMetrics(b, g),
297 //             b.getWidth(), b.getHeight());
298 //
299 //      clearTextShiftOffset();
300 //
301 //      // perform UI specific press action, e.g. Windows L&F shifts text
302 //      if (model.isArmed() && model.isPressed()) {
303 //          paintButtonPressed(g,b);
304 //      }
305 //
306 //      // Paint the Icon
307 //      if(b.getIcon() != null) {
308 //          paintIcon(g,c,iconRect);
309 //      }
310 //
311 //      if (text != null && !text.equals("")){
312 //          View v = (View) c.getClientProperty(BasicHTML.propertyKey);
313 //          if (v != null) {
314 //              v.paint(g, textRect);
315 //          } else {
316 //              paintText(g, b, textRect, text);
317 //          }
318 //      }
319 //
320 //      if (b.isFocusPainted() && b.hasFocus()) {
321 //          // paint UI specific focus
322 //          paintFocus(g,b,viewRect,textRect,iconRect);
323 //      }
324 //  }
325 //
326 //  protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect){
327 //          AbstractButton b = (AbstractButton) c;
328 //          ButtonModel model = b.getModel();
329 //          Icon icon = b.getIcon();
330 //          Icon tmpIcon = null;
331 //
332 //          if(icon == null) {
333 //             return;
334 //          }
335 //
336 //          Icon selectedIcon = null;
337 //
338 //          /* the fallback icon should be based on the selected state */
339 //          if (model.isSelected()) {
340 //              selectedIcon = (Icon) b.getSelectedIcon();
341 //              if (selectedIcon != null) {
342 //                  icon = selectedIcon;
343 //              }
344 //          }
345 //
346 //          if(!model.isEnabled()) {
347 //              if(model.isSelected()) {
348 //                 tmpIcon = (Icon) b.getDisabledSelectedIcon();
349 //                 if (tmpIcon == null) {
350 //                     tmpIcon = selectedIcon;
351 //                 }
352 //              }
353 //
354 //              if (tmpIcon == null) {
355 //                  tmpIcon = (Icon) b.getDisabledIcon();
356 //              }
357 //          } else if(model.isPressed() && model.isArmed()) {
358 //              tmpIcon = (Icon) b.getPressedIcon();
359 //              if(tmpIcon != null) {
360 //                  // revert back to 0 offset
361 //                  clearTextShiftOffset();
362 //              }
363 //          } else if(b.isRolloverEnabled() && model.isRollover()) {
364 //              if(model.isSelected()) {
365 //                 tmpIcon = (Icon) b.getRolloverSelectedIcon();
366 //                 if (tmpIcon == null) {
367 //                     tmpIcon = selectedIcon;
368 //                 }
369 //              }
370 //
371 //              if (tmpIcon == null) {
372 //                  tmpIcon = (Icon) b.getRolloverIcon();
373 //              }
374 //          }
375 //
376 //          if(tmpIcon != null) {
377 //              icon = tmpIcon;
378 //          }
379 //
380 //          if(model.isPressed() && model.isArmed()) {
381 //              icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(),
382 //                      iconRect.y + getTextShiftOffset());
383 //          } else {
384 //              icon.paintIcon(c, g, iconRect.x, iconRect.y);
385 //          }
386 //
387 //  }
388 //
389 //  /**
390 //   * As of Java 2 platform v 1.4 this method should not be used or overriden.
391 //   * Use the paintText method which takes the AbstractButton argument.
392 //   */
393 //  protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {
394 //      AbstractButton b = (AbstractButton) c;
395 //      ButtonModel model = b.getModel();
396 //      FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
397 //      int mnemonicIndex = b.getDisplayedMnemonicIndex();
398 //
399 //      /* Draw the Text */
400 //      if(model.isEnabled()) {
401 //          /*** paint the text normally */
402 //          g.setColor(b.getForeground());
403 //          SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
404 //                                        textRect.x + getTextShiftOffset(),
405 //                                        textRect.y + fm.getAscent() + getTextShiftOffset());
406 //      }
407 //      else {
408 //          /*** paint the text disabled ***/
409 //          g.setColor(b.getBackground().brighter());
410 //          SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
411 //                                        textRect.x, textRect.y + fm.getAscent());
412 //          g.setColor(b.getBackground().darker());
413 //          SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
414 //                                        textRect.x - 1, textRect.y + fm.getAscent() - 1);
415 //      }
416 //  }
417 //
418 //  /**
419 //   * Method which renders the text of the current button.
420 //   * <p>
421 //   * @param g Graphics context
422 //   * @param b Current button to render
423 //   * @param textRect Bounding rectangle to render the text.
424 //   * @param text String to render
425 //   * @since 1.4
426 //   */
427 //  protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
428 //      paintText(g, (JComponent)b, textRect, text);
429 //  }
430 //
431 //  // Method signature defined here overriden in subclasses.
432 //  // Perhaps this class should be abstract?
433 //  protected void paintFocus(Graphics g, AbstractButton b,
434 //                            Rectangle viewRect, Rectangle textRect, Rectangle iconRect){
435 //  }
436 //
437 //
438 //
439 //  protected void paintButtonPressed(Graphics g, AbstractButton b){
440 //  }
441 //
442 //  protected void clearTextShiftOffset(){
443 //      this.shiftOffset = 0;
444 //  }
445 //
446 //  protected void setTextShiftOffset(){
447 //      this.shiftOffset = defaultTextShiftOffset;
448 //  }
449 //
450 //  protected int getTextShiftOffset() {
451 //      return shiftOffset;
452 //  }
453 //
454 //  // ********************************
455 //  //          Layout Methods
456 //  // ********************************
457 //  public Dimension getMinimumSize(JComponent c) {
458 //      Dimension d = getPreferredSize(c);
459 //      View v = (View) c.getClientProperty(BasicHTML.propertyKey);
460 //      if (v != null) {
461 //          d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
462 //      }
463 //      return d;
464 //  }
465 //
466 //  public Dimension getPreferredSize(JComponent c) {
467 //      AbstractButton b = (AbstractButton)c;
468 //      return BasicGraphicsUtils.getPreferredButtonSize(b, b.getIconTextGap());
469 //  }
470 //
471 //  public Dimension getMaximumSize(JComponent c) {
472 //      Dimension d = getPreferredSize(c);
473 //      View v = (View) c.getClientProperty(BasicHTML.propertyKey);
474 //      if (v != null) {
475 //          d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
476 //      }
477 //      return d;
478 //  }
479 //
480 //  /**
481 //   * Returns the baseline.
482 //   *
483 //   * @throws NullPointerException {@inheritDoc}
484 //   * @throws IllegalArgumentException {@inheritDoc}
485 //   * @see javax.swing.JComponent#getBaseline(int, int)
486 //   * @since 1.6
487 //   */
488 //  public int getBaseline(JComponent c, int width, int height) {
489 //      super.getBaseline(c, width, height);
490 //      AbstractButton b = (AbstractButton)c;
491 //      String text = b.getText();
492 //      if (text == null || "".equals(text)) {
493 //          return -1;
494 //      }
495 //      FontMetrics fm = b.getFontMetrics(b.getFont());
496 //      layout(b, fm, width, height);
497 //      return BasicHTML.getBaseline(b, textRect.y, fm.getAscent(),
498 //                                   textRect.width, textRect.height);
499 //  }
500 //
501 //  /**
502 //   * Returns an enum indicating how the baseline of the component
503 //   * changes as the size changes.
504 //   *
505 //   * @throws NullPointerException {@inheritDoc}
506 //   * @see javax.swing.JComponent#getBaseline(int, int)
507 //   * @since 1.6
508 //   */
509 //  public Component.BaselineResizeBehavior getBaselineResizeBehavior(
510 //          JComponent c) {
511 //      super.getBaselineResizeBehavior(c);
512 //      if (c.getClientProperty(BasicHTML.propertyKey) != null) {
513 //          return Component.BaselineResizeBehavior.OTHER;
514 //      }
515 //      switch(((AbstractButton)c).getVerticalAlignment()) {
516 //      case AbstractButton.TOP:
517 //          return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
518 //      case AbstractButton.BOTTOM:
519 //          return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
520 //      case AbstractButton.CENTER:
521 //          return Component.BaselineResizeBehavior.CENTER_OFFSET;
522 //      }
523 //      return Component.BaselineResizeBehavior.OTHER;
524 //  }
525 //
526 //  private String layout(AbstractButton b, FontMetrics fm,
527 //                        int width, int height) {
528 //      Insets i = b.getInsets();
529 //      viewRect.x = i.left;
530 //      viewRect.y = i.top;
531 //      viewRect.width = width - (i.right + viewRect.x);
532 //      viewRect.height = height - (i.bottom + viewRect.y);
533 //
534 //      textRect.x = textRect.y = textRect.width = textRect.height = 0;
535 //      iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
536 //
537 //      // layout the text and icon
538 //      return SwingUtilities.layoutCompoundLabel(
539 //          b, fm, b.getText(), b.getIcon(),
540 //          b.getVerticalAlignment(), b.getHorizontalAlignment(),
541 //          b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
542 //          viewRect, iconRect, textRect,
543 //          b.getText() == null ? 0 : b.getIconTextGap());
544 //  }
545 //
546 //  /**
547 //   * Returns the ButtonListener for the passed in Button, or null if one
548 //   * could not be found.
549 //   */
550 //  private JSButtonListener getButtonListener(AbstractButton b) {
551 //      MouseMotionListener[] listeners = b.getMouseMotionListeners();
552 //
553 //      if (listeners != null) {
554 //          for (int counter = 0; counter < listeners.length; counter++) {
555 //              if (listeners[counter] instanceof JSButtonListener) {
556 //                  return (JSButtonListener)listeners[counter];
557 //              }
558 //          }
559 //      }
560 //      return null;
561 //  }
562 //
563 //
564
565 }