| 1 14 package org.wings; 15 16 17 import org.apache.commons.logging.Log; 18 import org.apache.commons.logging.LogFactory; 19 import org.wings.border.SBorder; 20 import org.wings.event.SComponentEvent; 21 import org.wings.event.SComponentListener; 22 import org.wings.event.SParentFrameEvent; 23 import org.wings.event.SParentFrameListener; 24 import org.wings.event.SRenderEvent; 25 import org.wings.event.SRenderListener; 26 import org.wings.io.Device; 27 import org.wings.plaf.ComponentCG; 28 import org.wings.script.ScriptListener; 29 import org.wings.session.LowLevelEventDispatcher; 30 import org.wings.session.Session; 31 import org.wings.session.SessionManager; 32 import org.wings.style.CSSAttributeSet; 33 import org.wings.style.CSSProperty; 34 import org.wings.style.CSSSelector; 35 import org.wings.style.CSSStyle; 36 import org.wings.style.CSSStyleSheet; 37 import org.wings.style.Style; 38 import org.wings.util.ComponentVisitor; 39 40 import javax.swing.*; 41 import javax.swing.event.EventListenerList ; 42 import java.awt.*; 43 import java.awt.event.ActionEvent ; 44 import java.beans.BeanInfo ; 45 import java.beans.Introspector ; 46 import java.beans.PropertyDescriptor ; 47 import java.io.IOException ; 48 import java.io.Serializable ; 49 import java.lang.reflect.Array ; 50 import java.lang.reflect.Method ; 51 import java.util.ArrayList ; 52 import java.util.Arrays ; 53 import java.util.Collection ; 54 import java.util.Collections ; 55 import java.util.EventListener ; 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 import java.util.Map ; 59 60 66 public abstract class SComponent 67 implements Cloneable , Serializable , Renderable { 68 private static final Object [] EMPTY_OBJECT_ARRAY = new Object [0]; 69 70 private static final Log log = LogFactory.getLog(SComponent.class); 71 72 73 private String name; 74 75 78 private transient Session session; 79 80 84 protected transient ComponentCG cg; 85 86 89 protected int verticalAlignment = SConstants.NO_ALIGN; 90 91 94 protected int horizontalAlignment = SConstants.NO_ALIGN; 95 96 99 protected String style; 100 101 104 protected Map dynamicStyles; 105 106 109 protected boolean visible = true; 110 111 114 protected boolean enabled = true; 115 116 119 protected SContainer parent; 120 121 124 protected SFrame parentFrame; 125 126 129 protected SBorder border; 130 131 134 protected String tooltip; 135 136 139 protected int focusTraversalIndex = -1; 140 141 144 protected SDimension preferredSize; 145 146 152 private boolean fireComponentChangeEvents = false; 153 154 private boolean fireParentFrameChangeEvents = false; 155 156 private EventListenerList listeners; 157 158 private Boolean useNamedEvents; 159 160 private boolean showAsFormComponent = true; 161 162 private SPopupMenu popupMenu; 163 164 private boolean inheritsPopupMenu; 165 166 private InputMap inputMap; 167 168 private ActionMap actionMap; 169 170 private final Map actionEvents = new HashMap (); 171 172 private final CSSSelector thisComponentCssSelector = new CSSSelector(this); 173 174 178 public SComponent() { 179 updateCG(); 180 } 181 182 public SBorder getBorder() { 183 return border; 184 } 185 186 public void setBorder(SBorder border) { 187 reloadIfChange(this.border, border); 188 this.border = border; 189 } 190 191 196 public final SContainer getParent() { 197 return parent; 198 } 199 200 205 public void setParent(SContainer parent) { 206 reloadIfChange(this.parent, parent); 207 this.parent = parent; 208 if (parent != null) 209 setParentFrame(parent.getParentFrame()); 210 else 211 setParentFrame(null); 212 } 213 214 219 protected void setParentFrame(SFrame parentFrame) { 220 if (this.parentFrame == parentFrame) { 221 return; 222 } 223 224 if (this.parentFrame != null) { 225 unregister(); 226 fireParentFrameEvent(new SParentFrameEvent(this, SParentFrameEvent.PARENTFRAME_REMOVED, this.parentFrame)); 227 } 228 229 this.parentFrame = parentFrame; 230 231 if (this.parentFrame != null) { 232 register(); 233 fireParentFrameEvent(new SParentFrameEvent(this, SParentFrameEvent.PARENTFRAME_ADDED, this.parentFrame)); 235 } 236 237 if (this.popupMenu != null) { 238 popupMenu.setParentFrame(parentFrame); 239 } 240 241 reload(); 242 } 243 244 public void setInheritsPopupMenu(boolean inheritsPopupMenu) { 245 reloadIfChange(this.inheritsPopupMenu, inheritsPopupMenu); 246 this.inheritsPopupMenu = inheritsPopupMenu; 247 } 248 249 public boolean getInheritsPopupMenu() { 250 return inheritsPopupMenu; 251 } 252 253 public void setComponentPopupMenu(SPopupMenu popupMenu) { 254 reloadIfChange(this.popupMenu, popupMenu); 255 if (this.popupMenu != null) 256 this.popupMenu.setParentFrame(null); 257 this.popupMenu = popupMenu; 258 if (this.popupMenu != null) 259 this.popupMenu.setParentFrame(getParentFrame()); 260 } 261 262 public SPopupMenu getComponentPopupMenu() { 263 264 return popupMenu; 282 } 283 284 public boolean hasComponentPopupMenu() { 285 return popupMenu != null; 286 } 287 288 public RequestURL getRequestURL() { 289 SFrame p = getParentFrame(); 290 if (p == null) 291 throw new IllegalStateException ("no parent frame"); 292 293 return p.getRequestURL(); 294 } 295 296 305 public void setPreferredSize(SDimension preferredSize) { 306 reloadIfChange(this.preferredSize, preferredSize); 307 this.preferredSize = preferredSize; 308 } 309 310 315 public SDimension getPreferredSize() { 316 return preferredSize; 317 } 318 319 320 330 public final void addComponentListener(SComponentListener l) { 331 addEventListener(SComponentListener.class, l); 332 fireComponentChangeEvents = true; 333 } 334 335 347 public final void removeComponentListener(SComponentListener l) { 348 removeEventListener(SComponentListener.class, l); 349 } 350 351 361 public final void addParentFrameListener(SParentFrameListener l) { 362 addEventListener(SParentFrameListener.class, l); 363 fireParentFrameChangeEvents = true; 364 } 365 366 378 public final void removeParentFrameListener(SParentFrameListener l) { 379 removeEventListener(SParentFrameListener.class, l); 380 } 381 382 388 protected void fireComponentChangeEvent(SComponentEvent aEvent) { 389 Object [] listeners = getListenerList(); 393 for (int i = listeners.length - 2; i >= 0; i -= 2) { 394 if (listeners[i] == SComponentListener.class) { 395 processComponentEvent((SComponentListener) listeners[i + 1], 397 aEvent); 398 } 399 } 400 401 } 402 403 409 private void fireParentFrameEvent(SParentFrameEvent aEvent) { 410 if (fireParentFrameChangeEvents) { 412 Object [] listeners = getListenerList(); 416 for (int i = listeners.length - 2; i >= 0; i -= 2) { 417 if (listeners[i] == SParentFrameListener.class) { 418 processParentFrameEvent((SParentFrameListener) listeners[i + 1], 420 aEvent); 421 } 422 } 423 } 424 425 } 426 427 434 private void processParentFrameEvent(SParentFrameListener listener, SParentFrameEvent event) { 435 int id = event.getID(); 436 switch (id) { 437 case SParentFrameEvent.PARENTFRAME_ADDED: 438 listener.parentFrameAdded(event); 439 break; 440 case SParentFrameEvent.PARENTFRAME_REMOVED: 441 listener.parentFrameRemoved(event); 442 break; 443 } 444 } 445 446 464 protected void processComponentEvent(SComponentListener listener, SComponentEvent e) { 465 int id = e.getID(); 466 switch (id) { 467 case SComponentEvent.COMPONENT_RESIZED: 468 listener.componentResized(e); 469 break; 470 case SComponentEvent.COMPONENT_MOVED: 471 listener.componentMoved(e); 472 break; 473 case SComponentEvent.COMPONENT_SHOWN: 474 listener.componentShown(e); 475 break; 476 case SComponentEvent.COMPONENT_HIDDEN: 477 listener.componentHidden(e); 478 break; 479 } 480 } 481 482 494 public final void addScriptListener(ScriptListener listener) { 495 ScriptListener[] listeners = getScriptListeners(); 496 for (int i = 0; i < listeners.length; i++) { 497 if (listeners[i].equals(listener)) { 498 return; 499 } 500 } 501 addEventListener(ScriptListener.class, listener); 502 } 503 504 505 517 public final void removeScriptListener(ScriptListener listener) { 518 removeEventListener(ScriptListener.class, listener); 519 } 520 521 public ScriptListener[] getScriptListeners() { 522 return (ScriptListener[]) getListeners(ScriptListener.class); 523 } 524 525 public void setName(String name) { 526 if (name != null) { 527 if (!Character.isJavaIdentifierStart(name.charAt(0)) || name.charAt(0) == '_') 528 throw new IllegalArgumentException (name + " is not a valid identifier"); 529 for (int i=1; i < name.length(); i++) 530 if (!Character.isJavaIdentifierPart(name.charAt(i)) || name.charAt(0) == '_') 531 throw new IllegalArgumentException (name + " is not a valid identifier"); 532 } 533 reloadIfChange(this.name, name); 534 this.name = name; 535 } 536 537 public final String getName() { 538 if (name == null) 539 name = getSession().createUniqueId(); 540 return name; 541 } 542 543 548 public final Session getSession() { 549 if (session == null) { 550 session = SessionManager.getSession(); 551 } 552 553 return session; 554 } 555 556 561 public final LowLevelEventDispatcher getDispatcher() { 562 return getSession().getDispatcher(); 563 } 564 565 569 private final void unregister() { 570 if (getDispatcher() != null && this instanceof LowLevelEventListener) { 571 getDispatcher().unregister((LowLevelEventListener) this); 572 } 573 } 574 575 579 private final void register() { 580 if (getDispatcher() != null && this instanceof LowLevelEventListener) { 581 getDispatcher().register((LowLevelEventListener) this); 582 } 583 } 584 585 590 public void setStyle(String value) { 591 reloadIfChange(style, value); 592 this.style = value; 593 } 594 595 598 public String getStyle() { 599 return style; 600 } 601 602 public void addDynamicStyle(Style style) { 603 if (dynamicStyles == null) 604 dynamicStyles = new HashMap (4); 605 dynamicStyles.put(style.getSelector(), style); 606 reload(); 607 } 608 609 public void removeDynamicStyle(String selector) { 610 if (dynamicStyles == null) 611 return; 612 dynamicStyles.remove(selector); 613 reload(); 614 } 615 616 public Style getDynamicStyle(Object selector) { 617 if (dynamicStyles == null) 618 return null; 619 return (Style) dynamicStyles.get(selector); 620 } 621 622 public void setDynamicStyles(Collection dynamicStyles) { 623 if (dynamicStyles == null) 624 return; 625 if (this.dynamicStyles == null) 626 this.dynamicStyles = new HashMap (4); 627 for (Iterator iterator = dynamicStyles.iterator(); iterator.hasNext();) { 628 Style style = (Style) iterator.next(); 629 this.dynamicStyles.put(style.getSelector(), style); 630 } 631 reload(); 632 } 633 634 public Collection getDynamicStyles() { 635 if (dynamicStyles == null || dynamicStyles.size() == 0) 636 return null; 637 return Collections.unmodifiableCollection(dynamicStyles.values()); 638 } 639 640 641 public void setAttribute(String cssPropertyName, String value) { 642 setAttribute(thisComponentCssSelector, new CSSProperty(cssPropertyName), value); 643 } 644 645 public void setAttribute(CSSProperty property, String propertyValue) { 646 setAttribute(thisComponentCssSelector, property, propertyValue); 647 } 648 649 public void setAttribute(CSSSelector selector, CSSProperty property, SIcon icon) { 650 setAttribute(selector, property, icon != null ? "url('"+icon.getURL().toString()+"')" : "none"); 651 } 652 653 public void setAttribute(CSSSelector selector, CSSProperty property, String propertyValue) { 654 CSSStyle style = (CSSStyle) getDynamicStyle(selector); 655 if (style == null) { 656 addDynamicStyle(new CSSStyle(selector, property, propertyValue)); 657 reload(); 658 } else { 659 String old = style.put(property, propertyValue); 660 reloadIfChange(old, propertyValue); 661 } 662 } 663 664 public void setAttributes(CSSAttributeSet attributes) { 665 log.debug("attributes = " + attributes); 666 setAttributes(thisComponentCssSelector, attributes); 667 } 668 669 public void setAttributes(CSSSelector selector, CSSAttributeSet attributes) { 670 CSSStyle style = (CSSStyle) getDynamicStyle(selector); 671 if (style == null) { 672 addDynamicStyle(new CSSStyle(selector, attributes)); 673 reload(); 674 } else { 675 boolean changed = style.putAll(attributes); 676 if (changed) 677 reload(); 678 } 679 } 680 681 686 public Color getBackground() { 687 return dynamicStyles == null || dynamicStyles.get(thisComponentCssSelector) == null ? null : CSSStyleSheet.getBackground((CSSAttributeSet) dynamicStyles.get(thisComponentCssSelector)); 688 } 689 690 695 public void setBackground(Color color) { 696 setAttribute(thisComponentCssSelector, CSSProperty.BACKGROUND_COLOR, CSSStyleSheet.getAttribute(color)); 697 } 698 699 704 public Color getForeground() { 705 return dynamicStyles == null || dynamicStyles.get(thisComponentCssSelector) == null ? null : CSSStyleSheet.getForeground((CSSAttributeSet) dynamicStyles.get(thisComponentCssSelector)); 706 } 707 708 713 public void setForeground(Color color) { 714 setAttribute(thisComponentCssSelector, CSSProperty.COLOR, CSSStyleSheet.getAttribute(color)); 715 } 716 717 722 public void setFont(SFont font) { 723 setAttributes(thisComponentCssSelector, CSSStyleSheet.getAttributes(font)); 724 } 725 726 731 public SFont getFont() { 732 return dynamicStyles == null || dynamicStyles.get(thisComponentCssSelector) == null ? null : CSSStyleSheet.getFont((CSSAttributeSet) dynamicStyles.get(thisComponentCssSelector)); 733 } 734 735 740 public void setVisible(boolean visible) { 741 boolean old = this.visible; 742 this.visible = visible; 743 if (fireComponentChangeEvents && (visible != old)) { 744 fireComponentChangeEvent(new SComponentEvent(this, visible 745 ? SComponentEvent.COMPONENT_SHOWN 746 : SComponentEvent.COMPONENT_HIDDEN)); 747 } 748 } 749 750 755 public boolean isVisible() { 756 return visible; 757 } 758 759 764 public void setEnabled(boolean enabled) { 765 this.enabled = enabled; 766 } 767 768 773 public boolean isEnabled() { 774 return enabled; 775 } 776 777 781 public final void reload() { 782 getSession().getReloadManager().reload(this); 783 } 784 785 793 protected final void reloadIfChange(Object oldVal, Object newVal) { 794 if (!((oldVal == newVal) || (oldVal != null && oldVal.equals(newVal)))) { 795 reload(); 797 } 798 } 799 800 808 protected final void reloadIfChange(int oldVal, int newVal) { 809 if (oldVal != newVal) { 810 reload(); 811 } 812 } 813 814 822 protected final void reloadIfChange(boolean oldVal, boolean newVal) { 823 if (oldVal != newVal) { 824 reload(); 825 } 826 } 827 828 836 protected final void reloadIfChange(byte oldVal, byte newVal) { 837 if (oldVal != newVal) { 838 reload(); 839 } 840 } 841 842 850 protected final void reloadIfChange(short oldVal, short newVal) { 851 if (oldVal != newVal) { 852 reload(); 853 } 854 } 855 856 864 protected final void reloadIfChange(long oldVal, long newVal) { 865 if (oldVal != newVal) { 866 reload(); 867 } 868 } 869 870 878 protected final void reloadIfChange(float oldVal, float newVal) { 879 if (oldVal != newVal) { 880 reload(); 881 } 882 } 883 884 892 protected final void reloadIfChange(double oldVal, double newVal) { 893 if (oldVal != newVal) { 894 reload(); 895 } 896 } 897 898 906 protected final void reloadIfChange(char oldVal, char newVal) { 907 if (oldVal != newVal) { 908 reload(); 909 } 910 } 911 912 920 public void write(Device s) throws IOException { 921 try { 922 if (visible) 923 cg.write(s, this); 924 } catch (IOException se) { 925 log.debug( "Socket exception during code generation for " + getClass().getName() + se); 927 } catch (Throwable t) { 928 log.warn( "Exception during code generation for " + getClass().getName(), t); 929 } 930 } 931 932 936 public String toString() { 937 return paramString(); 938 } 939 940 941 947 public String paramString() { 948 StringBuffer buffer = new StringBuffer  |