1 29 30 package nextapp.echo2.app; 31 32 import java.beans.PropertyChangeListener ; 33 import java.beans.PropertyChangeSupport ; 34 import java.io.Serializable ; 35 import java.util.ArrayList ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.Locale ; 39 40 import nextapp.echo2.app.event.EventListenerList; 41 42 108 public abstract class Component 109 implements RenderIdSupport, Serializable { 110 111 114 private static final int CHILD_LIST_CAPACITY = 3; 115 116 120 private static final Component[] EMPTY_COMPONENT_ARRAY = new Component[0]; 121 122 125 private static final int FLAG_ENABLED = 0x1; 126 127 130 private static final int FLAG_VISIBLE = 0x2; 131 132 136 private static final int FLAG_FOCUS_TRAVERSAL_PARTICIPANT= 0x4; 137 138 142 private static final int FLAG_REGISTERING = 0x8; 143 144 private static final int FLAG_INIT_IN_PROGRESS = 0x10; 145 146 private static final int FLAG_DISPOSE_IN_PROGRESS = 0x20; 147 148 private static final int FLAG_INITIALIZED = 0x40; 149 150 153 private static final int FLAGS_FOCUS_TRAVERSAL_INDEX = 0x7fff0000; 154 155 public static final String CHILDREN_CHANGED_PROPERTY = "children"; 156 public static final String ENABLED_CHANGED_PROPERTY = "enabled"; 157 public static final String FOCUS_TRAVERSAL_INDEX_CHANGED_PROPERTY = "focusTraversalIndex"; 158 public static final String FOCUS_TRAVERSAL_PARTICIPANT_CHANGED_PROPERTY = "focusTraversalParticipant"; 159 public static final String LAYOUT_DIRECTION_CHANGED_PROPERTY = "layoutDirection"; 160 public static final String LOCALE_CHANGED_PROPERTY = "locale"; 161 162 public static final String PROPERTY_BACKGROUND = "background"; 163 public static final String PROPERTY_FONT = "font"; 164 public static final String PROPERTY_FOREGROUND = "foreground"; 165 public static final String PROPERTY_LAYOUT_DATA = "layoutData"; 166 public static final String STYLE_CHANGED_PROPERTY = "style"; 167 public static final String STYLE_NAME_CHANGED_PROPERTY = "styleName"; 168 public static final String VISIBLE_CHANGED_PROPERTY = "visible"; 169 170 private static final boolean isLetter(char ch) { 172 return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); 173 } 174 175 private static final boolean isLetterOrDigit(char ch) { 177 return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'); 178 } 179 180 181 private ApplicationInstance applicationInstance; 182 183 187 private List children; 188 189 196 private int flags; 197 198 202 private String id; 203 204 210 private LayoutDirection layoutDirection; 211 212 213 private EventListenerList listenerList; 214 215 221 private Locale locale; 222 223 224 private MutableStyle localStyle; 225 226 227 private Component parent; 228 229 233 private PropertyChangeSupport propertyChangeSupport; 234 235 239 private String renderId; 240 241 242 private Style sharedStyle; 243 244 245 private String styleName; 246 247 250 public Component() { 251 super(); 252 flags = FLAG_ENABLED | FLAG_VISIBLE | FLAG_FOCUS_TRAVERSAL_PARTICIPANT; 253 localStyle = new MutableStyle(); 254 } 255 256 263 public void add(Component c) { 264 add(c, -1); 265 } 266 267 282 public void add(Component c, int n) 283 throws IllegalChildException { 284 285 if (!isValidChild(c)) { 287 throw new IllegalChildException(this, c); 288 } 289 290 if (!c.isValidParent(this)) { 292 throw new IllegalChildException(this, c); 293 } 294 295 if (c.parent != null) { 297 c.parent.remove(c); 298 } 299 300 if (children == null) { 302 children = new ArrayList (CHILD_LIST_CAPACITY); 303 } 304 305 c.parent = this; 307 if (n == -1) { 308 children.add(c); 309 } else { 310 children.add(n, c); 311 } 312 313 if (applicationInstance != null) { 315 c.register(applicationInstance); 316 } 317 318 firePropertyChange(CHILDREN_CHANGED_PROPERTY, null, c); 320 321 c.doInit(); 323 } 324 325 330 public void addPropertyChangeListener(PropertyChangeListener l) { 331 if (propertyChangeSupport == null) { 332 propertyChangeSupport = new PropertyChangeSupport (this); 333 } 334 propertyChangeSupport.addPropertyChangeListener(l); 335 } 336 337 348 void assignRenderId(String renderId) { 349 this.renderId = renderId; 350 } 351 352 359 public void dispose() { } 360 361 365 void doDispose() { 366 if (applicationInstance == null) { 367 return; 368 } 369 if ((flags & (FLAG_INIT_IN_PROGRESS | FLAG_DISPOSE_IN_PROGRESS)) != 0) { 370 throw new IllegalStateException ( 371 "Attempt to dispose component when initialize or dispose operation already in progress."); 372 } 373 flags |= FLAG_DISPOSE_IN_PROGRESS; 374 try { 375 if (children != null) { 376 Iterator it = children.iterator(); 377 while (it.hasNext()) { 378 ((Component) it.next()).doDispose(); 379 } 380 } 381 if ((flags & FLAG_INITIALIZED) == 0) { 382 return; 384 } 385 dispose(); 386 flags &= ~FLAG_INITIALIZED; 387 } finally { 388 flags &= ~FLAG_DISPOSE_IN_PROGRESS; 389 } 390 } 391 392 396 void doInit() { 397 if (applicationInstance == null) { 398 return; 399 } 400 if ((flags & FLAG_INITIALIZED) != 0) { 401 return; 403 } 404 405 if ((flags & (FLAG_INIT_IN_PROGRESS | FLAG_DISPOSE_IN_PROGRESS)) != 0) { 406 throw new IllegalStateException ( 407 "Attempt to initialize component when initialize or dispose operation already in progress."); 408 } 409 flags |= FLAG_INIT_IN_PROGRESS; 410 try { 411 init(); 412 flags |= FLAG_INITIALIZED; 413 if (children != null) { 414 Iterator it = children.iterator(); 415 while (it.hasNext()) { 416 ((Component) it.next()).doInit(); 417 } 418 } 419 } finally { 420 flags &= ~FLAG_INIT_IN_PROGRESS; 421 } 422 } 423 424 432 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { 433 if (propertyChangeSupport != null) { 435 propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); 436 } 437 438 if (applicationInstance != null) { 444 applicationInstance.notifyComponentPropertyChange(this, propertyName, oldValue, newValue); 445 } 446 } 447 448 455 public ApplicationInstance getApplicationInstance() { 456 return applicationInstance; 457 } 458 459 467 public Color getBackground() { 468 return (Color) localStyle.getProperty(PROPERTY_BACKGROUND); 469 } 470 471 478 public final Component getComponent(int n) { 479 if (children == null) { 480 throw new IndexOutOfBoundsException (); 481 } 482 483 return (Component) children.get(n); 484 } 485 486 497 public final Component getComponent(String id) { 498 if (id.equals(this.id)) { 499 return this; 500 } 501 if (children == null) { 502 return null; 503 } 504 Iterator it = children.iterator(); 505 while (it.hasNext()) { 506 Component testComponent = (Component) it.next(); 507 Component targetComponent = testComponent.getComponent(id); 508 if (targetComponent != null) { 509 return targetComponent; 510 } 511 } 512 return null; 513 } 514 515 520 public final int getComponentCount() { 521 if (children == null) { 522 return 0; 523 } else { 524 return children.size(); 525 } 526 } 527 528 533 public final Component[] getComponents() { 534 if (children == null) { 535 return EMPTY_COMPONENT_ARRAY; 536 } else { 537 return (Component[]) children.toArray(new Component[children.size()]); 538 } 539 } 540 541 548 protected EventListenerList getEventListenerList() { 549 if (listenerList == null) { 550 listenerList = new EventListenerList(); 551 } 552 return listenerList; 553 } 554 555 564 public final int getFocusTraversalIndex() { 565 return (flags & FLAGS_FOCUS_TRAVERSAL_INDEX) >> 16; 566 } 567 568 576 public Font getFont() { 577 return (Font) localStyle.getProperty(PROPERTY_FONT); 578 } 579 580 588 public Color getForeground() { 589 return (Color) localStyle.getProperty(PROPERTY_FOREGROUND); 590 } 591 592 599 public String getId() { 600 return id; 601 } 602 603 617 public final Object getIndexedProperty(String propertyName, int propertyIndex) { 618 return localStyle.getIndexedProperty(propertyName, propertyIndex); 619 } 620 621 628 public LayoutData getLayoutData() { 629 return (LayoutData) localStyle.getProperty(PROPERTY_LAYOUT_DATA); 630 } 631 632 641 public LayoutDirection getLayoutDirection() { 642 return layoutDirection; 643 } 644 645 654 public Locale getLocale() { 655 return locale; 656 } 657 658 663 public final Component getParent() { 664 return parent; 665 } 666 667 680 public final Object getProperty(String propertyName) { 681 return localStyle.getProperty(propertyName); 682 } 683 684 695 public String getRenderId() { 696 return renderId; 697 } 698 699 719 public final Object getRenderIndexedProperty(String propertyName, int propertyIndex) { 720 return getRenderIndexedProperty(propertyName, propertyIndex, null); 721 } 722 723 740 public final Object getRenderIndexedProperty(String propertyName, int propertyIndex, Object defaultValue) { 741 if (localStyle.isIndexedPropertySet(propertyName, propertyIndex)) { 742 return localStyle.getIndexedProperty(propertyName, propertyIndex); 744 } else if (sharedStyle != null && sharedStyle.isIndexedPropertySet(propertyName, propertyIndex)) { 745 return sharedStyle.getIndexedProperty(propertyName, propertyIndex); 747 } else { 748 if (applicationInstance != null) { 749 Style applicationStyle = applicationInstance.getStyle(getClass(), styleName); 750 if (applicationStyle != null && applicationStyle.isIndexedPropertySet(propertyName, propertyIndex)) { 751 return applicationStyle.getIndexedProperty(propertyName, propertyIndex); 753 } 754 } 755 return defaultValue; 756 } 757 } 758 759 765 public final LayoutDirection getRenderLayoutDirection() { 766 if (layoutDirection == null) { 767 if (locale == null) { 768 if (parent == null) { 769 if (applicationInstance == null) { 770 return null; 771 } else { 772 return applicationInstance.getLayoutDirection(); 773 } 774 } else { 775 return parent.getRenderLayoutDirection(); 776 } 777 } else { 778 return LayoutDirection.forLocale(locale); 779 } 780 } else { 781 return layoutDirection; 782 } 783 } 784 785 797 public final Locale getRenderLocale() { 798 if (locale == null) { 799 if (parent == null) { 800 if (applicationInstance == null) { 801 return null; 802 } else { 803 return applicationInstance.getLocale(); 804 } 805 } else { 806 return parent.getRenderLocale(); 807 } 808 } else { 809 return locale; 810 } 811 } 812 813 833 public final Object getRenderProperty(String propertyName) { 834 return getRenderProperty(propertyName, null); 835 } 836 837 854 public final Object getRenderProperty(String propertyName, Object defaultValue) { 855 Object propertyValue = localStyle.getProperty(propertyName); 856 if (propertyValue != null) { 857 return propertyValue; 858 } 859 if (sharedStyle != null) { 860 propertyValue = sharedStyle.getProperty(propertyName); 861 if (propertyValue != null) { 862 return propertyValue; 863 } 864 } 865 if (applicationInstance != null) { 866 Style applicationStyle = applicationInstance.getStyle(getClass(), styleName); 867 if (applicationStyle != null) { 868 propertyValue = applicationStyle.getProperty(propertyName); 870 if (propertyValue != null) { 871 return propertyValue; 872 } 873 } 874 } 875 return defaultValue; 876 } 877 878 889 public final Style getStyle() { 890 return sharedStyle; 891 } 892 893 903 public final String getStyleName() { 904 return styleName; 905 } 906 907 915 public final Component getVisibleComponent(int n) { 916 if (children == null) { 917 throw new IndexOutOfBoundsException (Integer.toString(n)); 918 } 919 int visibleComponentCount = 0; 920 Component component = null; 921 Iterator it = children.iterator(); 922 while (visibleComponentCount <= n) { 923 if (!it.hasNext()) { 924 throw new IndexOutOfBoundsException (Integer.toString(n)); 925 } 926 component = (Component) it.next(); 927 if (component.isVisible()) { 928 ++visibleComponentCount; 929 } 930 } 931 return component; 932 } 933 934 941 public final int getVisibleComponentCount() { 942 if (children == null) { 943 return 0; 944 } else { 945 int visibleComponentCount = 0; 946 Iterator it = children.iterator(); 947 while (it.hasNext()) { 948 Component component = (Component) it.next(); 949 if (component.isVisible()) { 950 ++visibleComponentCount; 951 } 952 } 953 return visibleComponentCount; 954 } 955 } 956 957 964 public final Component[] getVisibleComponents() { 965 if (children == null) { 966 return EMPTY_COMPONENT_ARRAY; 967 } else { 968 Iterator it = children.iterator(); 969 List visibleChildList = new ArrayList (); 970 while (it.hasNext()) { 971 Component component = (Component) it.next(); 972 if (component.isVisible()) { 973 visibleChildList.add(component); 974 } 975 } 976 return (Component[]) visibleChildList.toArray(new Component[visibleChildList.size()]); 977 } 978 } 979 980 990 protected boolean hasEventListenerList() { 991 return listenerList != null; 992 } 993 994 1003 public final int indexOf(Component c) { 1004 return children == null ? -1 : children.indexOf(c); 1005 } 1006 1007 1014 public void init() { } 1015 1016 1024 public final boolean isAncestorOf(Component c) { 1025 while (c != null && c != this) { 1026 c = c.parent; 1027 } 1028 return c == this; 1029 } 1030 1031 1040 public final boolean isEnabled() { 1041 return (flags & FLAG_ENABLED) != 0; 1042 } 1043 1044 1051 public boolean isFocusTraversalParticipant() { 1052 return (flags & FLAG_FOCUS_TRAVERSAL_PARTICIPANT) != 0; 1053 } 1054 1055 1062 public final boolean isRegistered() { 1063 return applicationInstance != null; 1064 } 1065 1066 1075 public final boolean isRenderEnabled() { 1076 Component component = this; 1077 while (component != null) { 1078 if ((component.flags & FLAG_ENABLED) == 0) { 1079 return false; 1080 } 1081 component = component.parent; 1082 } 1083 return true; 1084 } 1085 1086 1092 public final boolean isRenderVisible() { 1093 Component component = this; 1094 while (component != null) { 1095 if ((component.flags & FLAG_VISIBLE) == 0) { 1096 return false; 1097 } 1098 component = component.parent; 1099 } 1100 return true; 1101 } 1102 1103 1111 public boolean isValidChild(Component child) { 1112 return true; 1113 } 1114 1115 1124 public boolean isValidParent(Component parent) { 1125 return true; 1126 } 1127 1128 1138 public final boolean isVisible() { 1139 return (FLAG_VISIBLE & flags) != 0; 1140 } 1141 1142 1152 public void processInput(String inputName, Object inputValue) { } 1153 1154 1172 void register(ApplicationInstance newValue) { 1173 if ((flags & FLAG_REGISTERING) != 0) { 1175 throw new IllegalStateException ( 1176 "Illegal attempt to register/unregister Component from within invocation of registration change " + 1177 "life-cycle method."); 1178 } 1179 try { 1180 flags |= FLAG_REGISTERING; 1182 1183 if (applicationInstance == newValue) { 1184 return; 1186 } 1187 1188 if (applicationInstance != null && newValue != null) { 1189 throw new IllegalStateException ( 1190 "Illegal attempt to re-register Component to alternate ApplicationInstance."); 1191 } 1192 1193 if (newValue == null) { if (children != null) { 1195 Iterator it = children.iterator(); 1196 while (it.hasNext()) { 1197 ((Component) it.next()).register(null); } 1199 } 1200 1201 applicationInstance.unregisterComponent(this); 1202 } 1203 1204 applicationInstance = newValue; 1205 1206 if (newValue != null) { applicationInstance.registerComponent(this); 1208 1209 if (children != null) { 1210 Iterator it = children.iterator(); 1211 while (it.hasNext()) { 1212 ((Component) it.next()).register(newValue); } 1214 } 1215 } 1216 } finally { 1217 flags &= ~FLAG_REGISTERING; 1219 } 1220 } 1221 1222 1234 public void remove(Component c) { 1235 1236 if (children == null || !children.contains(c)) { 1237 return; 1239 } 1240 1241 c.doDispose(); 1242 1243 if (applicationInstance != null) { 1245 c.register(null); 1246 } 1247 1248 children.remove(c); 1250 c.parent = null; 1251 1252 firePropertyChange(CHILDREN_CHANGED_PROPERTY, c, null); 1254 } 1255 1256 1262 public void remove(int n) { 1263 if (children == null) { 1264 throw new IndexOutOfBoundsException (); 1265 } 1266 remove(getComponent(n)); 1267 } 1268 1269 1272 public void removeAll() { 1273 if (children != null) { 1274 while (children.size() > 0) { 1275 Component c = (Component) children.get(children.size() - 1); 1276 remove(c); 1277 } 1278 children = null; 1279 } 1280 } 1281 1282 1287 public void removePropertyChangeListener(PropertyChangeListener l) { 1288 if (propertyChangeSupport != null) { 1289 propertyChangeSupport.removePropertyChangeListener(l); 1290 } 1291 } 1292 1293 1298 public void setBackground(Color newValue) { 1299 setProperty(PROPERTY_BACKGROUND, newValue); 1300 } 1301 1302 1308 public void setEnabled(boolean newValue) { 1309 boolean oldValue = (flags & FLAG_ENABLED) != 0; 1310 if (oldValue != newValue) { 1311 flags ^= FLAG_ENABLED; firePropertyChange(ENABLED_CHANGED_PROPERTY, new Boolean (oldValue), new Boolean (newValue)); 1313 } 1314 } 1315 1316 1322 public void setFocusTraversalIndex(int newValue) { 1323 int oldValue = getFocusTraversalIndex(); 1324 newValue &= 0x7fff; 1325 flags = flags & ((~FLAGS_FOCUS_TRAVERSAL_INDEX)) | (newValue << 16); 1326 firePropertyChange(FOCUS_TRAVERSAL_INDEX_CHANGED_PROPERTY, new Integer (oldValue), new Integer (newValue)); 1327 } 1328 1329 1336 public void setFocusTraversalParticipant(boolean newValue) { 1337 boolean oldValue = isFocusTraversalParticipant(); 1338 if (oldValue != newValue) { 1339 flags ^= FLAG_FOCUS_TRAVERSAL_PARTICIPANT; firePropertyChange(FOCUS_TRAVERSAL_PARTICIPANT_CHANGED_PROPERTY, new Boolean (oldValue), new Boolean (newValue)); 1341 } 1342 } 1343 1344 1349 public void setFont(Font newValue) { 1350 setProperty(PROPERTY_FONT, newValue); 1351 } 1352 1353 1358 public void setForeground(Color newValue) { 1359 setProperty(PROPERTY_FOREGROUND, newValue); 1360 } 1361 1362 1367 public void setId(String id) { 1368 this.id = id; 1369 } 1370 1371 1381 public void setIndexedProperty(String propertyName, int propertyIndex, Object newValue) { 1382 localStyle.setIndexedProperty(propertyName, propertyIndex, newValue); 1383 firePropertyChange(propertyName, null, null); 1384 } 1385 1386 1395 public void setLayoutData(LayoutData newValue) { 1396 setProperty(PROPERTY_LAYOUT_DATA, newValue); 1397 } 1398 1399 1405 public void setLayoutDirection(LayoutDirection newValue) { 1406 LayoutDirection oldValue = layoutDirection; 1407 layoutDirection = newValue; 1408 firePropertyChange(LAYOUT_DIRECTION_CHANGED_PROPERTY, oldValue, newValue); 1409 } 1410 1411 1417 public void setLocale(Locale newValue) { 1418 Locale oldValue = locale; 1419 locale = newValue; 1420 firePropertyChange(LOCALE_CHANGED_PROPERTY, oldValue, newValue); 1421 } 1422 1423 1431 public void setProperty(String propertyName, Object newValue) { 1432 Object oldValue = localStyle.getProperty(propertyName); 1433 localStyle.setProperty(propertyName, newValue); 1434 firePropertyChange(propertyName, oldValue, newValue); 1435 } 1436 1437 1448 public void setRenderId(String renderId) { 1449 if (this.renderId != null && renderId != null && this.applicationInstance != null) { 1450 throw new IllegalStateException ("Cannot set renderId while component is registered."); 1451 } 1452 if (renderId != null) { 1453 int length = renderId.length(); 1454 if (!isLetter(renderId.charAt(0))) { 1455 throw new IllegalArgumentException ("Invalid identifier:" + renderId); 1456 } 1457 for (int i = 1; i < length; ++i) { 1458 if (!isLetterOrDigit(renderId.charAt(i))) { 1459 throw new IllegalArgumentException ("Invalid identifier:" + renderId); 1460 } 1461 } 1462 1463 } 1464 assignRenderId(renderId); 1465 } 1466 1467 1475 public void setStyle(Style newValue) { 1476 Style oldValue = sharedStyle; 1477 sharedStyle = newValue; 1478 firePropertyChange(STYLE_CHANGED_PROPERTY, oldValue, newValue); 1479 } 1480 1481 1490 public void setStyleName(String newValue) { 1491 String oldValue = styleName; 1492 styleName = newValue; 1493 firePropertyChange(STYLE_NAME_CHANGED_PROPERTY, oldValue, newValue); 1494 } 1495 1496 1502 public void setVisible(boolean newValue) { 1503 boolean oldValue = (flags & FLAG_VISIBLE) != 0; 1504 if (oldValue != newValue) { 1505 flags ^= FLAG_VISIBLE; firePropertyChange(VISIBLE_CHANGED_PROPERTY, new Boolean (oldValue), new Boolean (newValue)); 1507 } 1508 } 1509 1510 1516 public void validate() { } 1517 1518 1537 public boolean verifyInput(String inputName, Object inputValue) { 1538 if (applicationInstance != null && !applicationInstance.verifyModalContext(this)) { 1539 return false; 1540 } 1541 return isVisible() && isEnabled(); 1542 } 1543 1544 1554 public final int visibleIndexOf(Component c) { 1555 if (!c.isVisible()) { 1556 return -1; 1557 } 1558 if (children == null) { 1559 return -1; 1560 } 1561 int visibleIndex = 0; 1562 Iterator it = children.iterator(); 1563 while (it.hasNext()) { 1564 Component component = (Component) it.next(); 1565 if (!component.isVisible()) { 1566 continue; 1567 } 1568 if (component.equals(c)) { 1569 return visibleIndex; 1570 } 1571 ++visibleIndex; 1572 } 1573 return -1; 1574 } 1575} 1576 | Popular Tags |