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;
11 * SWingJS implementation of stateful user interface for buttons.
12 * Modeled after javax.swing.plaf.basic.BasicButtonUI.java (commented out below).
17 public class JSButtonUI extends JSComponentUI {
21 * the radio or check-box or simple button
24 protected DOMNode domBtn;
27 public DOMNode getDOMObject() {
29 domBtn = enableNode = valueNode = domNode = createDOMObject("input", id,
31 setCssFont(DOMNode.setAttr(domNode, "value", ((AbstractButton) c).getText()),
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
42 * @return true if the HTML5 button was actually pressed
44 boolean verifyButtonClick(boolean isRelease) {
51 protected void installJSUI() {
52 installDefaults((AbstractButton) c);
53 installListeners((AbstractButton) c);
54 installKeyboardActions((AbstractButton) c);
57 protected void uninstallJSUI() {
58 uninstallKeyboardActions((AbstractButton) c);
59 uninstallListeners((AbstractButton) c);
60 //uninstallDefaults((AbstractButton) c);
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);
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);
85 protected void installKeyboardActions(AbstractButton b) {
86 JSButtonListener listener = getButtonListener(b);
87 if (listener != null) {
88 listener.installKeyboardActions(b);
92 protected void uninstallKeyboardActions(AbstractButton b) {
93 JSButtonListener listener = getButtonListener(b);
94 if(listener != null) {
95 listener.uninstallKeyboardActions(b);
100 * Returns the ButtonListener for the passed in Button, or null if one
101 * could not be found.
103 protected JSButtonListener getButtonListener(AbstractButton b) {
104 MouseMotionListener[] listeners = b.getMouseMotionListeners();
106 if (listeners != null) {
107 for (int counter = 0; counter < listeners.length; counter++) {
108 if (listeners[counter] instanceof JSButtonListener) {
109 return (JSButtonListener)listeners[counter];
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.
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);
127 // textRect.x = textRect.y = textRect.width = textRect.height = 0;
128 // iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
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());
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;
144 /** Amount to offset text, the value of this comes from
145 defaultTextShiftOffset once setTextShiftOffset has been invoked.
147 protected int shiftOffset = 0;
149 /** Value that is set in shiftOffset once setTextShiftOffset has been
150 invoked. The value of this comes from the defaults table.
152 protected int defaultTextShiftOffset;
154 //protected String propertyPrefix = "Button.";
156 // private static final Object BASIC_BUTTON_UI_KEY = new Object();
158 // // ********************************
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);
172 protected String getPropertyPrefix() {
177 // // ********************************
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());
187 protected void installDefaults(AbstractButton b) {
188 // load shared instance defaults
189 String pp = getPropertyPrefix();
191 defaultTextShiftOffset = UIManager.getInt(pp + "textShiftOffset");
193 // // set the following defaults on the button
194 // if (b.isContentAreaFilled()) {
195 // LookAndFeel.installProperty(b, "opaque", Boolean.TRUE);
197 // LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
200 if(b.getMargin() == null || (b.getMargin() instanceof UIResource)) {
201 b.setMargin(UIManager.getInsets(pp + "margin"));
204 LookAndFeel.installColorsAndFont(b, pp + "background",
205 pp + "foreground", pp + "font");
206 // LookAndFeel.installBorder(b, pp + "border");
208 // Object rollover = UIManager.get(pp + "rollover");
209 // if (rollover != null) {
210 // LookAndFeel.installProperty(b, "rolloverEnabled", rollover);
212 LookAndFeel.installProperty(b, "iconTextGap", new Integer(4));
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);
226 // protected void installKeyboardActions(AbstractButton b){
227 // JSButtonListener listener = getButtonListener(b);
229 // if(listener != null) {
230 // listener.installKeyboardActions(b);
235 // // ********************************
237 // // ********************************
238 // public void uninstallUI(JComponent c) {
239 // uninstallKeyboardActions((AbstractButton) c);
240 // uninstallListeners((AbstractButton) c);
241 // uninstallDefaults((AbstractButton) c);
242 // BasicHTML.updateRenderer(c, "");
245 // protected void uninstallKeyboardActions(AbstractButton b) {
246 // JSButtonListener listener = getButtonListener(b);
247 // if(listener != null) {
248 // listener.uninstallKeyboardActions(b);
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);
263 // protected void uninstallDefaults(AbstractButton b) {
264 // LookAndFeel.uninstallBorder(b);
267 // // ********************************
268 // // Create Listeners
269 // // ********************************
270 // protected JSButtonListener createButtonListener(AbstractButton b) {
271 // return new JSButtonListener(b);
274 // public int getDefaultTextIconGap(AbstractButton b) {
275 // return defaultTextIconGap;
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.
283 // private static Rectangle viewRect = new Rectangle();
284 // private static Rectangle textRect = new Rectangle();
285 // private static Rectangle iconRect = new Rectangle();
287 // // ********************************
289 // // ********************************
291 // public void paint(Graphics g, JComponent c)
293 // AbstractButton b = (AbstractButton) c;
294 // ButtonModel model = b.getModel();
296 // String text = layout(b, SwingUtilities2.getFontMetrics(b, g),
297 // b.getWidth(), b.getHeight());
299 // clearTextShiftOffset();
301 // // perform UI specific press action, e.g. Windows L&F shifts text
302 // if (model.isArmed() && model.isPressed()) {
303 // paintButtonPressed(g,b);
307 // if(b.getIcon() != null) {
308 // paintIcon(g,c,iconRect);
311 // if (text != null && !text.equals("")){
312 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
314 // v.paint(g, textRect);
316 // paintText(g, b, textRect, text);
320 // if (b.isFocusPainted() && b.hasFocus()) {
321 // // paint UI specific focus
322 // paintFocus(g,b,viewRect,textRect,iconRect);
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;
332 // if(icon == null) {
336 // Icon selectedIcon = null;
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;
346 // if(!model.isEnabled()) {
347 // if(model.isSelected()) {
348 // tmpIcon = (Icon) b.getDisabledSelectedIcon();
349 // if (tmpIcon == null) {
350 // tmpIcon = selectedIcon;
354 // if (tmpIcon == null) {
355 // tmpIcon = (Icon) b.getDisabledIcon();
357 // } else if(model.isPressed() && model.isArmed()) {
358 // tmpIcon = (Icon) b.getPressedIcon();
359 // if(tmpIcon != null) {
360 // // revert back to 0 offset
361 // clearTextShiftOffset();
363 // } else if(b.isRolloverEnabled() && model.isRollover()) {
364 // if(model.isSelected()) {
365 // tmpIcon = (Icon) b.getRolloverSelectedIcon();
366 // if (tmpIcon == null) {
367 // tmpIcon = selectedIcon;
371 // if (tmpIcon == null) {
372 // tmpIcon = (Icon) b.getRolloverIcon();
376 // if(tmpIcon != null) {
380 // if(model.isPressed() && model.isArmed()) {
381 // icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(),
382 // iconRect.y + getTextShiftOffset());
384 // icon.paintIcon(c, g, iconRect.x, iconRect.y);
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.
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();
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());
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);
419 // * Method which renders the text of the current button.
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
427 // protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
428 // paintText(g, (JComponent)b, textRect, text);
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){
439 // protected void paintButtonPressed(Graphics g, AbstractButton b){
442 // protected void clearTextShiftOffset(){
443 // this.shiftOffset = 0;
446 // protected void setTextShiftOffset(){
447 // this.shiftOffset = defaultTextShiftOffset;
450 // protected int getTextShiftOffset() {
451 // return shiftOffset;
454 // // ********************************
456 // // ********************************
457 // public Dimension getMinimumSize(JComponent c) {
458 // Dimension d = getPreferredSize(c);
459 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
461 // d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
466 // public Dimension getPreferredSize(JComponent c) {
467 // AbstractButton b = (AbstractButton)c;
468 // return BasicGraphicsUtils.getPreferredButtonSize(b, b.getIconTextGap());
471 // public Dimension getMaximumSize(JComponent c) {
472 // Dimension d = getPreferredSize(c);
473 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
475 // d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
481 // * Returns the baseline.
483 // * @throws NullPointerException {@inheritDoc}
484 // * @throws IllegalArgumentException {@inheritDoc}
485 // * @see javax.swing.JComponent#getBaseline(int, int)
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)) {
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);
502 // * Returns an enum indicating how the baseline of the component
503 // * changes as the size changes.
505 // * @throws NullPointerException {@inheritDoc}
506 // * @see javax.swing.JComponent#getBaseline(int, int)
509 // public Component.BaselineResizeBehavior getBaselineResizeBehavior(
511 // super.getBaselineResizeBehavior(c);
512 // if (c.getClientProperty(BasicHTML.propertyKey) != null) {
513 // return Component.BaselineResizeBehavior.OTHER;
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;
523 // return Component.BaselineResizeBehavior.OTHER;
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);
534 // textRect.x = textRect.y = textRect.width = textRect.height = 0;
535 // iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
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());
547 // * Returns the ButtonListener for the passed in Button, or null if one
548 // * could not be found.
550 // private JSButtonListener getButtonListener(AbstractButton b) {
551 // MouseMotionListener[] listeners = b.getMouseMotionListeners();
553 // if (listeners != null) {
554 // for (int counter = 0; counter < listeners.length; counter++) {
555 // if (listeners[counter] instanceof JSButtonListener) {
556 // return (JSButtonListener)listeners[counter];