1 package swingjs.plaf;
\r
3 //import jsjava.awt.FontMetrics;
\r
4 import jsjava.awt.event.MouseMotionListener;
\r
5 import jsjavax.swing.AbstractButton;
\r
6 import jsjavax.swing.LookAndFeel;
\r
7 import jsjavax.swing.UIManager;
\r
8 import swingjs.api.DOMNode;
\r
9 import jsjavax.swing.plaf.UIResource;
\r
11 * SWingJS implementation of stateful user interface for buttons.
\r
12 * Modeled after javax.swing.plaf.basic.BasicButtonUI.java (commented out below).
\r
14 * @author Bob Hanson
\r
17 public class JSMenuItemUI extends JSButtonUI {
\r
21 * the radio or check-box or simple button
\r
24 protected DOMNode domBtn;
\r
27 public DOMNode getDOMObject() {
\r
28 if (domNode == null)
\r
29 domBtn = enableNode = valueNode = domNode = createDOMObject("input", id,
\r
31 setCssFont(DOMNode.setAttr(domNode, "value", ((AbstractButton) c).getText()),
\r
37 * validate a button press -- with a simple button, this is just TRUE.
\r
38 * This is needed because sometimes the area near the button is pressed
\r
39 * but not the actual button.
\r
40 * @param isRelease TODO
\r
42 * @return true if the HTML5 button was actually pressed
\r
44 boolean verifyButtonClick(boolean isRelease) {
\r
49 // from BasicButtonUI
\r
51 protected void installJSUI() {
\r
52 installDefaults((AbstractButton) c);
\r
53 installListeners((AbstractButton) c);
\r
54 installKeyboardActions((AbstractButton) c);
\r
57 protected void uninstallJSUI() {
\r
58 uninstallKeyboardActions((AbstractButton) c);
\r
59 uninstallListeners((AbstractButton) c);
\r
60 //uninstallDefaults((AbstractButton) c);
\r
63 protected void installListeners(AbstractButton b) {
\r
64 JSButtonListener listener = new JSButtonListener(b);
\r
65 if (listener != null) {
\r
66 b.addMouseListener(listener);
\r
67 b.addMouseMotionListener(listener);
\r
68 b.addFocusListener(listener);
\r
69 b.addPropertyChangeListener(listener);
\r
70 b.addChangeListener(listener);
\r
74 protected void uninstallListeners(AbstractButton b) {
\r
75 JSButtonListener listener = getButtonListener(b);
\r
76 if (listener != null) {
\r
77 b.removeMouseListener(listener);
\r
78 b.removeMouseMotionListener(listener);
\r
79 b.removeFocusListener(listener);
\r
80 b.removeChangeListener(listener);
\r
81 b.removePropertyChangeListener(listener);
\r
85 protected void installKeyboardActions(AbstractButton b) {
\r
86 JSButtonListener listener = getButtonListener(b);
\r
87 if (listener != null) {
\r
88 listener.installKeyboardActions(b);
\r
92 protected void uninstallKeyboardActions(AbstractButton b) {
\r
93 JSButtonListener listener = getButtonListener(b);
\r
94 if(listener != null) {
\r
95 listener.uninstallKeyboardActions(b);
\r
99 // SwingJS -- this is interesting, as it summarizes everything we will need
\r
100 // to implement, ultimately. SwingUtilities.layoutCompoundLabel
\r
101 // details what we are going to have to do somewhere.
\r
103 // private String layout(AbstractButton b, FontMetrics fm, int width, int height) {
\r
104 // Insets i = b.getInsets();
\r
105 // viewRect.x = i.left;
\r
106 // viewRect.y = i.top;
\r
107 // viewRect.width = width - (i.right + viewRect.x);
\r
108 // viewRect.height = height - (i.bottom + viewRect.y);
\r
110 // textRect.x = textRect.y = textRect.width = textRect.height = 0;
\r
111 // iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
\r
113 // // layout the text and icon
\r
114 // return SwingUtilities.layoutCompoundLabel(b, fm, b.getText(), b.getIcon(),
\r
115 // b.getVerticalAlignment(), b.getHorizontalAlignment(),
\r
116 // b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect,
\r
117 // iconRect, textRect, b.getText() == null ? 0 : b.getIconTextGap());
\r
122 // // Visual constants
\r
123 // // NOTE: This is not used or set any where. Were we allowed to remove
\r
124 // // fields, this would be removed.
\r
125 // protected int defaultTextIconGap;
\r
127 /** Amount to offset text, the value of this comes from
\r
128 defaultTextShiftOffset once setTextShiftOffset has been invoked.
\r
130 protected int shiftOffset = 0;
\r
132 /** Value that is set in shiftOffset once setTextShiftOffset has been
\r
133 invoked. The value of this comes from the defaults table.
\r
135 protected int defaultTextShiftOffset;
\r
137 //protected String propertyPrefix = "Button.";
\r
139 // private static final Object BASIC_BUTTON_UI_KEY = new Object();
\r
141 // // ********************************
\r
143 // // ********************************
\r
144 // public static ComponentUI createUI(JComponent c) {
\r
145 // AppContext appContext = AppContext.getAppContext();
\r
146 // BasicButtonUI buttonUI =
\r
147 // (BasicButtonUI) appContext.get(BASIC_BUTTON_UI_KEY);
\r
148 // if (buttonUI == null) {
\r
149 // buttonUI = new BasicButtonUI();
\r
150 // appContext.put(BASIC_BUTTON_UI_KEY, buttonUI);
\r
152 // return buttonUI;
\r
155 protected String getPropertyPrefix() {
\r
160 // // ********************************
\r
162 // // ********************************
\r
163 // public void installUI(JComponent c) {
\r
164 // installDefaults((AbstractButton) c);
\r
165 // installListeners((AbstractButton) c);
\r
166 // installKeyboardActions((AbstractButton) c);
\r
167 // BasicHTML.updateRenderer(c, ((AbstractButton) c).getText());
\r
170 protected void installDefaults(AbstractButton b) {
\r
171 // load shared instance defaults
\r
172 String pp = getPropertyPrefix();
\r
174 defaultTextShiftOffset = UIManager.getInt(pp + "textShiftOffset");
\r
176 // // set the following defaults on the button
\r
177 // if (b.isContentAreaFilled()) {
\r
178 // LookAndFeel.installProperty(b, "opaque", Boolean.TRUE);
\r
180 // LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
\r
183 if(b.getMargin() == null || (b.getMargin() instanceof UIResource)) {
\r
184 b.setMargin(UIManager.getInsets(pp + "margin"));
\r
187 LookAndFeel.installColorsAndFont(b, pp + "background",
\r
188 pp + "foreground", pp + "font");
\r
189 // LookAndFeel.installBorder(b, pp + "border");
\r
191 // Object rollover = UIManager.get(pp + "rollover");
\r
192 // if (rollover != null) {
\r
193 // LookAndFeel.installProperty(b, "rolloverEnabled", rollover);
\r
195 LookAndFeel.installProperty(b, "iconTextGap", new Integer(4));
\r
198 // protected void installListeners(AbstractButton b) {
\r
199 // JSButtonListener listener = createButtonListener(b);
\r
200 // if(listener != null) {
\r
201 // b.addMouseListener(listener);
\r
202 // b.addMouseMotionListener(listener);
\r
203 // b.addFocusListener(listener);
\r
204 // b.addPropertyChangeListener(listener);
\r
205 // b.addChangeListener(listener);
\r
209 // protected void installKeyboardActions(AbstractButton b){
\r
210 // JSButtonListener listener = getButtonListener(b);
\r
212 // if(listener != null) {
\r
213 // listener.installKeyboardActions(b);
\r
218 // // ********************************
\r
219 // // Uninstall PLAF
\r
220 // // ********************************
\r
221 // public void uninstallUI(JComponent c) {
\r
222 // uninstallKeyboardActions((AbstractButton) c);
\r
223 // uninstallListeners((AbstractButton) c);
\r
224 // uninstallDefaults((AbstractButton) c);
\r
225 // BasicHTML.updateRenderer(c, "");
\r
228 // protected void uninstallKeyboardActions(AbstractButton b) {
\r
229 // JSButtonListener listener = getButtonListener(b);
\r
230 // if(listener != null) {
\r
231 // listener.uninstallKeyboardActions(b);
\r
235 // protected void uninstallListeners(AbstractButton b) {
\r
236 // JSButtonListener listener = getButtonListener(b);
\r
237 // if(listener != null) {
\r
238 // b.removeMouseListener(listener);
\r
239 // b.removeMouseMotionListener(listener);
\r
240 // b.removeFocusListener(listener);
\r
241 // b.removeChangeListener(listener);
\r
242 // b.removePropertyChangeListener(listener);
\r
246 // protected void uninstallDefaults(AbstractButton b) {
\r
247 // LookAndFeel.uninstallBorder(b);
\r
250 // // ********************************
\r
251 // // Create Listeners
\r
252 // // ********************************
\r
253 // protected JSButtonListener createButtonListener(AbstractButton b) {
\r
254 // return new JSButtonListener(b);
\r
257 // public int getDefaultTextIconGap(AbstractButton b) {
\r
258 // return defaultTextIconGap;
\r
261 // /* These rectangles/insets are allocated once for all
\r
262 // * ButtonUI.paint() calls. Re-using rectangles rather than
\r
263 // * allocating them in each paint call substantially reduced the time
\r
264 // * it took paint to run. Obviously, this method can't be re-entered.
\r
266 // private static Rectangle viewRect = new Rectangle();
\r
267 // private static Rectangle textRect = new Rectangle();
\r
268 // private static Rectangle iconRect = new Rectangle();
\r
270 // // ********************************
\r
271 // // Paint Methods
\r
272 // // ********************************
\r
274 // public void paint(Graphics g, JComponent c)
\r
276 // AbstractButton b = (AbstractButton) c;
\r
277 // ButtonModel model = b.getModel();
\r
279 // String text = layout(b, SwingUtilities2.getFontMetrics(b, g),
\r
280 // b.getWidth(), b.getHeight());
\r
282 // clearTextShiftOffset();
\r
284 // // perform UI specific press action, e.g. Windows L&F shifts text
\r
285 // if (model.isArmed() && model.isPressed()) {
\r
286 // paintButtonPressed(g,b);
\r
289 // // Paint the Icon
\r
290 // if(b.getIcon() != null) {
\r
291 // paintIcon(g,c,iconRect);
\r
294 // if (text != null && !text.equals("")){
\r
295 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
\r
296 // if (v != null) {
\r
297 // v.paint(g, textRect);
\r
299 // paintText(g, b, textRect, text);
\r
303 // if (b.isFocusPainted() && b.hasFocus()) {
\r
304 // // paint UI specific focus
\r
305 // paintFocus(g,b,viewRect,textRect,iconRect);
\r
309 // protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect){
\r
310 // AbstractButton b = (AbstractButton) c;
\r
311 // ButtonModel model = b.getModel();
\r
312 // Icon icon = b.getIcon();
\r
313 // Icon tmpIcon = null;
\r
315 // if(icon == null) {
\r
319 // Icon selectedIcon = null;
\r
321 // /* the fallback icon should be based on the selected state */
\r
322 // if (model.isSelected()) {
\r
323 // selectedIcon = (Icon) b.getSelectedIcon();
\r
324 // if (selectedIcon != null) {
\r
325 // icon = selectedIcon;
\r
329 // if(!model.isEnabled()) {
\r
330 // if(model.isSelected()) {
\r
331 // tmpIcon = (Icon) b.getDisabledSelectedIcon();
\r
332 // if (tmpIcon == null) {
\r
333 // tmpIcon = selectedIcon;
\r
337 // if (tmpIcon == null) {
\r
338 // tmpIcon = (Icon) b.getDisabledIcon();
\r
340 // } else if(model.isPressed() && model.isArmed()) {
\r
341 // tmpIcon = (Icon) b.getPressedIcon();
\r
342 // if(tmpIcon != null) {
\r
343 // // revert back to 0 offset
\r
344 // clearTextShiftOffset();
\r
346 // } else if(b.isRolloverEnabled() && model.isRollover()) {
\r
347 // if(model.isSelected()) {
\r
348 // tmpIcon = (Icon) b.getRolloverSelectedIcon();
\r
349 // if (tmpIcon == null) {
\r
350 // tmpIcon = selectedIcon;
\r
354 // if (tmpIcon == null) {
\r
355 // tmpIcon = (Icon) b.getRolloverIcon();
\r
359 // if(tmpIcon != null) {
\r
363 // if(model.isPressed() && model.isArmed()) {
\r
364 // icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(),
\r
365 // iconRect.y + getTextShiftOffset());
\r
367 // icon.paintIcon(c, g, iconRect.x, iconRect.y);
\r
373 // * As of Java 2 platform v 1.4 this method should not be used or overriden.
\r
374 // * Use the paintText method which takes the AbstractButton argument.
\r
376 // protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {
\r
377 // AbstractButton b = (AbstractButton) c;
\r
378 // ButtonModel model = b.getModel();
\r
379 // FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
\r
380 // int mnemonicIndex = b.getDisplayedMnemonicIndex();
\r
382 // /* Draw the Text */
\r
383 // if(model.isEnabled()) {
\r
384 // /*** paint the text normally */
\r
385 // g.setColor(b.getForeground());
\r
386 // SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
\r
387 // textRect.x + getTextShiftOffset(),
\r
388 // textRect.y + fm.getAscent() + getTextShiftOffset());
\r
391 // /*** paint the text disabled ***/
\r
392 // g.setColor(b.getBackground().brighter());
\r
393 // SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
\r
394 // textRect.x, textRect.y + fm.getAscent());
\r
395 // g.setColor(b.getBackground().darker());
\r
396 // SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
\r
397 // textRect.x - 1, textRect.y + fm.getAscent() - 1);
\r
402 // * Method which renders the text of the current button.
\r
404 // * @param g Graphics context
\r
405 // * @param b Current button to render
\r
406 // * @param textRect Bounding rectangle to render the text.
\r
407 // * @param text String to render
\r
410 // protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
\r
411 // paintText(g, (JComponent)b, textRect, text);
\r
414 // // Method signature defined here overriden in subclasses.
\r
415 // // Perhaps this class should be abstract?
\r
416 // protected void paintFocus(Graphics g, AbstractButton b,
\r
417 // Rectangle viewRect, Rectangle textRect, Rectangle iconRect){
\r
422 // protected void paintButtonPressed(Graphics g, AbstractButton b){
\r
425 // protected void clearTextShiftOffset(){
\r
426 // this.shiftOffset = 0;
\r
429 // protected void setTextShiftOffset(){
\r
430 // this.shiftOffset = defaultTextShiftOffset;
\r
433 // protected int getTextShiftOffset() {
\r
434 // return shiftOffset;
\r
437 // // ********************************
\r
438 // // Layout Methods
\r
439 // // ********************************
\r
440 // public Dimension getMinimumSize(JComponent c) {
\r
441 // Dimension d = getPreferredSize(c);
\r
442 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
\r
443 // if (v != null) {
\r
444 // d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
\r
449 // public Dimension getPreferredSize(JComponent c) {
\r
450 // AbstractButton b = (AbstractButton)c;
\r
451 // return BasicGraphicsUtils.getPreferredButtonSize(b, b.getIconTextGap());
\r
454 // public Dimension getMaximumSize(JComponent c) {
\r
455 // Dimension d = getPreferredSize(c);
\r
456 // View v = (View) c.getClientProperty(BasicHTML.propertyKey);
\r
457 // if (v != null) {
\r
458 // d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
\r
464 // * Returns the baseline.
\r
466 // * @throws NullPointerException {@inheritDoc}
\r
467 // * @throws IllegalArgumentException {@inheritDoc}
\r
468 // * @see javax.swing.JComponent#getBaseline(int, int)
\r
471 // public int getBaseline(JComponent c, int width, int height) {
\r
472 // super.getBaseline(c, width, height);
\r
473 // AbstractButton b = (AbstractButton)c;
\r
474 // String text = b.getText();
\r
475 // if (text == null || "".equals(text)) {
\r
478 // FontMetrics fm = b.getFontMetrics(b.getFont());
\r
479 // layout(b, fm, width, height);
\r
480 // return BasicHTML.getBaseline(b, textRect.y, fm.getAscent(),
\r
481 // textRect.width, textRect.height);
\r
485 // * Returns an enum indicating how the baseline of the component
\r
486 // * changes as the size changes.
\r
488 // * @throws NullPointerException {@inheritDoc}
\r
489 // * @see javax.swing.JComponent#getBaseline(int, int)
\r
492 // public Component.BaselineResizeBehavior getBaselineResizeBehavior(
\r
494 // super.getBaselineResizeBehavior(c);
\r
495 // if (c.getClientProperty(BasicHTML.propertyKey) != null) {
\r
496 // return Component.BaselineResizeBehavior.OTHER;
\r
498 // switch(((AbstractButton)c).getVerticalAlignment()) {
\r
499 // case AbstractButton.TOP:
\r
500 // return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
\r
501 // case AbstractButton.BOTTOM:
\r
502 // return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
\r
503 // case AbstractButton.CENTER:
\r
504 // return Component.BaselineResizeBehavior.CENTER_OFFSET;
\r
506 // return Component.BaselineResizeBehavior.OTHER;
\r
509 // private String layout(AbstractButton b, FontMetrics fm,
\r
510 // int width, int height) {
\r
511 // Insets i = b.getInsets();
\r
512 // viewRect.x = i.left;
\r
513 // viewRect.y = i.top;
\r
514 // viewRect.width = width - (i.right + viewRect.x);
\r
515 // viewRect.height = height - (i.bottom + viewRect.y);
\r
517 // textRect.x = textRect.y = textRect.width = textRect.height = 0;
\r
518 // iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
\r
520 // // layout the text and icon
\r
521 // return SwingUtilities.layoutCompoundLabel(
\r
522 // b, fm, b.getText(), b.getIcon(),
\r
523 // b.getVerticalAlignment(), b.getHorizontalAlignment(),
\r
524 // b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
\r
525 // viewRect, iconRect, textRect,
\r
526 // b.getText() == null ? 0 : b.getIconTextGap());
\r
530 // * Returns the ButtonListener for the passed in Button, or null if one
\r
531 // * could not be found.
\r
533 // private JSButtonListener getButtonListener(AbstractButton b) {
\r
534 // MouseMotionListener[] listeners = b.getMouseMotionListeners();
\r
536 // if (listeners != null) {
\r
537 // for (int counter = 0; counter < listeners.length; counter++) {
\r
538 // if (listeners[counter] instanceof JSButtonListener) {
\r
539 // return (JSButtonListener)listeners[counter];
\r