1 19 package org.openide.explorer.view; 20 21 import java.lang.ref.Reference ; 22 import org.openide.explorer.propertysheet.*; 23 import org.openide.nodes.Node; 24 25 import org.openide.nodes.Node.Property; 26 import org.openide.util.NbBundle; 27 28 import java.awt.Color ; 29 import java.awt.Component ; 30 import java.awt.Container ; 31 import java.awt.Font ; 32 import java.awt.Graphics ; 33 import java.awt.KeyboardFocusManager ; 34 35 import java.beans.*; 36 37 import java.lang.ref.WeakReference ; 38 import java.lang.reflect.InvocationTargetException ; 39 40 import java.text.MessageFormat ; 41 42 import java.util.EventObject ; 43 import java.util.Map ; 44 import java.util.StringTokenizer ; 45 import java.util.WeakHashMap ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 49 import javax.accessibility.AccessibleContext ; 50 import javax.accessibility.AccessibleRole ; 51 52 import javax.swing.*; 53 import javax.swing.event.TableModelEvent ; 54 import javax.swing.event.TableModelListener ; 55 import javax.swing.table.*; 56 57 import org.netbeans.modules.openide.explorer.TTVEnvBridge; 58 59 60 65 class TableSheetCell extends AbstractCellEditor implements TableModelListener , PropertyChangeListener, TableCellEditor, 66 TableCellRenderer { 67 68 private NodeTableModel tableModel; 69 70 71 private Boolean flat; 72 73 77 78 private Node node; 79 80 81 private Property prop; 82 83 87 88 private TableCellRenderer headerRenderer = (new JTableHeader()).getDefaultRenderer(); 89 90 91 private NullPanel nullPanel; 92 93 95 private Map panelCache = new WeakHashMap (); private FocusedPropertyPanel renderer = null; 97 private PropertyPanel editor = null; 98 99 public TableSheetCell(NodeTableModel tableModel) { 100 this.tableModel = tableModel; 101 setFlat(false); 102 } 103 104 108 public void setFlat(boolean f) { 109 Color controlDkShadow = Color.lightGray; 110 111 if (UIManager.getColor("controlDkShadow") != null) { 112 controlDkShadow = UIManager.getColor("controlDkShadow"); } 114 115 Color controlLtHighlight = Color.black; 116 117 if (UIManager.getColor("controlLtHighlight") != null) { 118 controlLtHighlight = UIManager.getColor("controlLtHighlight"); } 120 121 Color buttonFocusColor = Color.blue; 122 123 if (UIManager.getColor("Button.focus") != null) { 124 buttonFocusColor = UIManager.getColor("Button.focus"); } 126 127 flat = f ? Boolean.TRUE : Boolean.FALSE; 128 } 129 130 133 public Object getCellEditorValue() { 134 return null; 135 } 136 137 145 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int r, int c) { 146 prop = (Property) value; 147 node = tableModel.nodeForRow(r); 148 node.addPropertyChangeListener(this); 149 tableModel.addTableModelListener(this); 150 151 PropertyPanel propPanel = getEditor(prop, node); 153 154 propPanel.setBackground(table.getSelectionBackground()); 155 propPanel.setForeground(table.getSelectionForeground()); 156 157 propPanel.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, table.getSelectionBackground())); 160 161 return propPanel; 162 } 163 164 168 public boolean shouldSelectCell(EventObject ev) { 169 return true; 170 } 171 172 176 public boolean isCellEditable(EventObject e) { 177 return true; 178 } 179 180 183 public void propertyChange(PropertyChangeEvent evt) { 184 ((NodeTableModel) tableModel).fireTableDataChanged(); 186 } 187 188 193 public boolean stopCellEditing() { 194 if (prop != null) { 195 detachEditor(); 196 } 197 198 return super.stopCellEditing(); 199 } 200 201 205 public void cancelCellEditing() { 206 if (prop != null) { 207 detachEditor(); 208 } 209 210 super.cancelCellEditing(); 211 } 212 213 216 public void tableChanged(TableModelEvent e) { 217 cancelCellEditing(); 218 } 219 220 222 private void detachEditor() { 223 node.removePropertyChangeListener(this); 224 tableModel.removeTableModelListener(this); 225 node = null; 226 prop = null; 227 } 228 229 private FocusedPropertyPanel getRenderer(Property p, Node n) { 230 TTVEnvBridge bridge = TTVEnvBridge.getInstance(this); 231 bridge.setCurrentBeans(new Node[] { n }); 232 233 if (renderer == null) { 234 renderer = new FocusedPropertyPanel(p, PropertyPanel.PREF_READ_ONLY | PropertyPanel.PREF_TABLEUI); 235 renderer.putClientProperty("beanBridgeIdentifier", this); } 237 238 renderer.setProperty(p); 239 renderer.putClientProperty("flat", Boolean.TRUE); 240 241 return renderer; 242 } 243 244 253 public Component getTableCellRendererComponent( 254 JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column 255 ) { 256 if (row == -1) { 258 Component comp = headerRenderer.getTableCellRendererComponent( 259 table, value, isSelected, hasFocus, row, column 260 ); 261 262 if (comp instanceof JComponent) { 263 String tip = (column > 0) ? tableModel.propertyForColumn(column).getShortDescription() 264 : table.getColumnName(0); 265 ((JComponent) comp).setToolTipText(tip); 266 } 267 268 return comp; 269 } 270 271 Property prop = (Property) value; 272 Node node = tableModel.nodeForRow(row); 273 274 if (prop != null) { 275 FocusedPropertyPanel propPanel = getRenderer(prop, node); 276 propPanel.setFocused(hasFocus); 277 278 String tooltipText = null; 279 280 try { 281 Object tooltipValue = prop.getValue(); 282 283 if (null != tooltipValue) { 284 tooltipText = tooltipValue.toString(); 285 } 286 } catch (IllegalAccessException eaE) { 287 Logger.getLogger(TableSheetCell.class.getName()).log(Level.WARNING, null, eaE); 288 } catch (InvocationTargetException itE) { 289 Logger.getLogger(TableSheetCell.class.getName()).log(Level.WARNING, null, itE); 290 } 291 292 propPanel.setToolTipText(createHtmlTooltip(tooltipText, propPanel.getFont())); 293 propPanel.setOpaque(true); 294 295 if (isSelected) { 296 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 297 298 boolean tableHasFocus = (table == focusOwner) || table.isAncestorOf(focusOwner) || 299 (focusOwner instanceof Container && ((Container ) focusOwner).isAncestorOf(table)); 300 301 if ((table == focusOwner) && table.isEditing()) { 302 tableHasFocus = true; 304 } 305 306 propPanel.setBackground( 307 tableHasFocus ? table.getSelectionBackground() : TreeTable.getUnfocusedSelectedBackground() 308 ); 309 310 propPanel.setForeground( 311 tableHasFocus ? table.getSelectionForeground() : TreeTable.getUnfocusedSelectedForeground() 312 ); 313 } else { 314 propPanel.setBackground(table.getBackground()); 315 propPanel.setForeground(table.getForeground()); 316 } 317 318 return propPanel; 319 } 320 321 if (nullPanel == null) { 322 nullPanel = new NullPanel(node); 323 nullPanel.setOpaque(true); 324 } else { 325 nullPanel.setNode(node); 326 } 327 328 if (isSelected) { 329 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 330 331 boolean tableHasFocus = hasFocus || (table == focusOwner) || table.isAncestorOf(focusOwner) || 332 (focusOwner instanceof Container && ((Container ) focusOwner).isAncestorOf(table)); 333 334 nullPanel.setBackground( 335 tableHasFocus ? table.getSelectionBackground() : TreeTable.getUnfocusedSelectedBackground() 336 ); 337 338 nullPanel.setForeground(table.getSelectionForeground().darker()); 342 } else { 343 nullPanel.setBackground(table.getBackground()); 344 nullPanel.setForeground(table.getForeground()); 345 } 346 347 nullPanel.setFocused(hasFocus); 348 349 return nullPanel; 350 } 351 352 private PropertyPanel getEditor(Property p, Node n) { 353 int prefs = PropertyPanel.PREF_TABLEUI; 354 355 TTVEnvBridge bridge = TTVEnvBridge.getInstance(this); 356 357 bridge.setCurrentBeans(new Node[] { n }); 362 363 if (editor == null) { 364 editor = new PropertyPanel(p, prefs); 365 366 editor.putClientProperty("flat", Boolean.TRUE); editor.putClientProperty("beanBridgeIdentifier", this); 369 editor.setProperty(p); 370 371 return editor; 372 } 373 374 editor.setProperty(p); 375 376 return editor; 379 } 380 381 private static String getString(String key) { 382 return NbBundle.getBundle(TableSheetCell.class).getString(key); 383 } 384 385 389 static String createHtmlTooltip(String value, Font font) { 390 if (value == null) { 391 return "null"; } 393 394 String token = null; 396 397 if (value.indexOf(" ") != -1) { token = " "; } else if (value.indexOf(",") != -1) { token = ","; } else if (value.indexOf(";") != -1) { token = ";"; } else if (value.indexOf("/") != -1) { token = "/"; } else if (value.indexOf(">") != -1) { token = ">"; } else if (value.indexOf("\\") != -1) { token = "\\"; } else { 410 return makeDisplayble(value, font); 412 } 413 414 StringTokenizer tk = new StringTokenizer (value, token, true); 415 416 StringBuffer sb = new StringBuffer (value.length() + 20); 417 sb.append("<html>"); 419 int charCount = 0; 420 int lineCount = 0; 421 422 while (tk.hasMoreTokens()) { 423 String a = tk.nextToken(); 424 a = makeDisplayble(a, font); 425 charCount += a.length(); 426 sb.append(a); 427 428 if (tk.hasMoreTokens()) { 429 charCount++; 430 } 431 432 if (charCount > 80) { 433 sb.append("<br>"); charCount = 0; 435 lineCount++; 436 437 if (lineCount > 10) { 438 sb.append(NbBundle.getMessage(TableSheetCell.class, "MSG_ELLIPSIS")); 443 return sb.toString(); 444 } 445 } 446 } 447 448 sb.append("</html>"); 450 return sb.toString(); 451 } 452 453 459 private static String makeDisplayble(String str, Font f) { 460 if (null == str) { 461 return str; 462 } 463 464 if (null == f) { 465 f = new JLabel().getFont(); 466 } 467 468 StringBuffer buf = new StringBuffer ((int) (str.length() * 1.3)); char[] chars = str.toCharArray(); 470 471 for (int i = 0; i < chars.length; i++) { 472 char c = chars[i]; 473 474 switch (c) { 475 case '\t': 476 buf.append(" " + " " 478 ); break; 480 481 case '\n': 482 break; 483 484 case '\r': 485 break; 486 487 case '\b': 488 buf.append("\\b"); 489 490 break; 492 case '\f': 493 buf.append("\\f"); 494 495 break; 497 default: 498 499 if (!processHtmlEntity(buf, c)) { 500 if ((null == f) || f.canDisplay(c)) { 501 buf.append(c); 502 } else { 503 buf.append("\\u"); 505 String hex = Integer.toHexString(c); 506 507 for (int j = 0; j < (4 - hex.length()); j++) 508 buf.append('0'); 509 510 buf.append(hex); 511 } 512 } 513 } 514 } 515 516 return buf.toString(); 517 } 518 519 private static boolean processHtmlEntity(StringBuffer buf, char c) { 520 switch (c) { 521 case '>': 522 buf.append(">"); 523 524 break; 526 case '<': 527 buf.append("<"); 528 529 break; 531 case '&': 532 buf.append("&"); 533 534 break; 536 default: 537 return false; 538 } 539 540 return true; 541 } 542 543 private static class NullPanel extends JPanel { 544 private Reference <Node> weakNode; 545 private boolean focused = false; 546 547 NullPanel(Node node) { 548 this.weakNode = new WeakReference <Node>(node); 549 } 550 551 void setNode(Node node) { 552 this.weakNode = new WeakReference <Node>(node); 553 } 554 555 public AccessibleContext getAccessibleContext() { 556 if (accessibleContext == null) { 557 accessibleContext = new AccessibleNullPanel(); 558 } 559 560 return accessibleContext; 561 } 562 563 public void setFocused(boolean val) { 564 focused = val; 565 } 566 567 public void paintComponent(Graphics g) { 568 super.paintComponent(g); 569 570 if (focused) { 571 Color bdr = UIManager.getColor("Tree.selectionBorderColor"); 573 if (bdr == null) { 574 if (getForeground().equals(Color.BLACK)) { bdr = getBackground().darker(); 578 } else { 579 bdr = getForeground().darker(); 580 } 581 } 582 583 g.setColor(bdr); 584 g.drawRect(1, 1, getWidth() - 3, getHeight() - 3); 585 g.setColor(bdr); 586 } 587 } 588 589 public void addComponentListener(java.awt.event.ComponentListener l) { 590 } 592 593 public void addHierarchyListener(java.awt.event.HierarchyListener l) { 594 } 596 597 public void repaint() { 598 } 600 601 public void repaint(int x, int y, int width, int height) { 602 } 604 605 public void invalidate() { 606 } 608 609 public void revalidate() { 610 } 612 613 public void validate() { 614 } 616 617 public void firePropertyChange(String s, Object a, Object b) { 618 } 620 621 private class AccessibleNullPanel extends AccessibleJPanel { 622 AccessibleNullPanel() { 623 } 624 625 public String getAccessibleName() { 626 String name = super.getAccessibleName(); 627 628 if (name == null) { 629 name = getString("ACS_NullPanel"); 630 } 631 632 return name; 633 } 634 635 public String getAccessibleDescription() { 636 String description = super.getAccessibleDescription(); 637 638 if (description == null) { 639 Node node = (Node) weakNode.get(); 640 641 if (node != null) { 642 description = MessageFormat.format( 643 getString("ACSD_NullPanel"), new Object [] { node.getDisplayName() } 644 ); 645 } 646 } 647 648 return description; 649 } 650 } 651 } 652 653 654 private static class FocusedPropertyPanel extends PropertyPanel { 655 boolean focused; 657 658 public FocusedPropertyPanel(Property p, int preferences) { 659 super(p, preferences); 660 } 661 662 public void setFocused(boolean focused) { 663 this.focused = focused; 664 } 665 666 public String getToolTipText() { 667 String superTooltip = super.getToolTipText(); 668 String propertyTooltip = getProperty().getShortDescription(); 669 if (propertyTooltip != null) { 670 return propertyTooltip; 671 } else { 672 return superTooltip; 673 } 674 } 675 676 public void addComponentListener(java.awt.event.ComponentListener l) { 677 } 679 680 public void addHierarchyListener(java.awt.event.HierarchyListener l) { 681 } 683 684 public void repaint(long tm, int x, int y, int width, int height) { 685 } 687 688 public void revalidate() { 689 } 691 692 public void firePropertyChange(String s, Object a, Object b) { 693 if ("flat".equals(s)) { 695 super.firePropertyChange(s, a, b); 696 } 697 } 698 699 public boolean isValid() { 700 return true; 701 } 702 703 public boolean isShowing() { 704 return true; 705 } 706 707 public void update(Graphics g) { 708 } 710 711 public void paint(Graphics g) { 712 Color c = getBackground(); 716 Color old = g.getColor(); 717 g.setColor(c); 718 g.fillRect(0, 0, getWidth(), getHeight()); 719 g.setColor(old); 720 721 super.paint(g); 722 723 if (focused) { 724 Color bdr = UIManager.getColor("Tree.selectionBorderColor"); 726 if (bdr == null) { 727 if (getForeground().equals(Color.BLACK)) { bdr = getBackground().darker(); 731 } else { 732 bdr = getForeground().darker(); 733 } 734 } 735 736 g.setColor(bdr); 737 g.drawRect(1, 1, getWidth() - 3, getHeight() - 3); 738 } 739 740 g.setColor(old); 741 } 742 743 public AccessibleContext getAccessibleContext() { 745 if (accessibleContext == null) { 746 accessibleContext = new AccessibleFocusedPropertyPanel(); 747 } 748 749 return accessibleContext; 750 } 751 752 private class AccessibleFocusedPropertyPanel extends AccessibleJComponent { 753 AccessibleFocusedPropertyPanel() { 754 } 755 756 public AccessibleRole getAccessibleRole() { 757 return AccessibleRole.PANEL; 758 } 759 760 public String getAccessibleName() { 761 FeatureDescriptor fd = ((ExPropertyModel) getModel()).getFeatureDescriptor(); 762 PropertyEditor editor = getPropertyEditor(); 763 764 return MessageFormat.format( 765 getString("ACS_PropertyPanelRenderer"), 766 new Object [] { fd.getDisplayName(), (editor == null) ? getString("CTL_No_value") : editor.getAsText() } 767 ); 768 } 769 770 public String getAccessibleDescription() { 771 FeatureDescriptor fd = ((ExPropertyModel) getModel()).getFeatureDescriptor(); 772 Node node = (Node) ((ExPropertyModel) getModel()).getBeans()[0]; 773 Class clazz = getModel().getPropertyType(); 774 775 return MessageFormat.format( 776 getString("ACSD_PropertyPanelRenderer"), 777 new Object [] { 778 fd.getShortDescription(), (clazz == null) ? getString("CTL_No_type") : clazz.getName(), 779 node.getDisplayName() 780 } 781 ); 782 } 783 } 784 } 785 } 786 | Popular Tags |