1 19 20 package org.netbeans.modules.form; 21 22 import java.awt.*; 23 import java.awt.event.*; 24 import javax.swing.*; 25 import javax.swing.event.*; 26 import javax.swing.text.JTextComponent ; 27 import java.util.ArrayList ; 28 29 30 39 class InPlaceEditLayer extends JPanel 40 { 41 private boolean layerEditing = true; 42 43 private boolean changeDone = false; 44 45 private String editedText; 46 private String oldText; 47 48 private Component editedComp; 49 private Container superContainer; 50 private JTextComponent editingTextComp; 51 private InPlaceTextField inPlaceField; 52 53 private ComponentListener layerResizeListener; 54 private KeyListener compKeyListener; 55 private FocusListener compFocusListener; 56 private ActionListener compActionListener; 57 58 private ArrayList listeners; 59 60 private Cursor defaultCursor; 61 62 64 InPlaceEditLayer() { 65 setLayout(null); 66 defaultCursor = getCursor(); 67 } 68 69 void setEditedComponent(Component comp, String text) { 70 if (!comp.isShowing() || comp.getParent() == null) 71 throw new IllegalArgumentException (); 72 73 editedComp = comp; 74 editedText = text; 75 if (inPlaceField != null) { 76 remove(inPlaceField); 77 inPlaceField = null; 78 } 79 80 if (comp instanceof JLabel || comp instanceof AbstractButton || comp instanceof JTabbedPane) { 81 layerEditing = true; 82 superContainer = null; 83 createInPlaceField(); 84 } 85 else if (comp instanceof JTextField || comp instanceof JTextArea) { 86 layerEditing = false; 87 superContainer = comp.getParent(); 88 89 Container cont = superContainer; 90 do { 91 if (cont.getParent() instanceof JLayeredPane) { 92 superContainer = cont; 93 break; 94 } 95 else cont = cont.getParent(); 96 } 97 while (cont != null); 98 99 editingTextComp = (JTextComponent )editedComp; 100 oldText = editingTextComp.getText(); 101 editingTextComp.setText(editedText); 102 103 editingTextComp.setFocusable(true); 105 } 106 else throw new IllegalArgumentException (); 107 108 attachListeners(); 109 } 110 111 113 static boolean supportsEditingFor(Class compClass, boolean layerRequired) { 114 return JLabel.class.isAssignableFrom(compClass) 115 || AbstractButton.class.isAssignableFrom(compClass) 116 || JTabbedPane.class.isAssignableFrom(compClass) 117 || (!layerRequired 118 && (JTextField.class.isAssignableFrom(compClass) 119 || JTextArea.class.isAssignableFrom(compClass))); 120 } 121 122 boolean isEditingInitialized() { 123 return editingTextComp != null; 124 } 125 126 boolean isLayerEditing() { 127 return layerEditing; 128 } 129 130 String getEditedText() { 131 return editedText; 132 } 133 134 boolean isTextChanged() { 135 return changeDone; 136 } 137 138 void finishEditing(boolean applyChanges) { 139 if (applyChanges) { 140 String text = editingTextComp.getText(); 141 if (text.equals(editedText)) 142 applyChanges = false; 143 else editedText = text; 144 } 145 else if (!isLayerEditing()) { 146 editingTextComp.setText(oldText); 147 editingTextComp.setFocusable(false); 148 } 149 150 editingTextComp.removeKeyListener(compKeyListener); 151 editingTextComp.removeFocusListener(compFocusListener); 152 if (editingTextComp instanceof JTextField) 153 ((JTextField)editingTextComp).removeActionListener(compActionListener); 154 editingTextComp = null; 155 156 changeDone = applyChanges; 157 fireEditingFinished(); 158 } 159 160 162 private void createInPlaceField() { 163 if (editedComp instanceof JLabel) { 164 JLabel label = (JLabel)editedComp; 165 inPlaceField = new InPlaceTextField(editedText); 166 inPlaceField.setFont(label.getFont()); 167 inPlaceField.setHorizontalAlignment(label.getHorizontalAlignment()); 168 } 174 else if (editedComp instanceof AbstractButton) { 175 AbstractButton button = (AbstractButton)editedComp; 176 inPlaceField = new InPlaceTextField(editedText); 177 inPlaceField.setFont(button.getFont()); 178 inPlaceField.setHorizontalAlignment(button.getHorizontalAlignment()); 179 } 181 else if (editedComp instanceof JTabbedPane) { 182 inPlaceField = new InPlaceTextField(editedText); 183 inPlaceField.setFont(((JTabbedPane)editedComp).getFont()); 184 inPlaceField.setHorizontalAlignment(SwingConstants.CENTER); 185 Insets insets = inPlaceField.getInsets(); 186 inPlaceField.setMargin(new Insets(0, insets.left, 0, insets.right)); 187 } 188 else return; 213 214 editingTextComp = inPlaceField; 215 add(inPlaceField); 216 placeInPlaceField(); 217 } 218 219 private void attachListeners() { 220 if (layerResizeListener != null) 221 removeComponentListener(layerResizeListener); 222 else 223 createListeners(); 224 225 if (isLayerEditing()) 226 addComponentListener(layerResizeListener); 227 228 editingTextComp.addKeyListener(compKeyListener); 229 editingTextComp.addFocusListener(compFocusListener); 230 if (editingTextComp instanceof JTextField) 231 ((JTextField)editingTextComp).addActionListener(compActionListener); 232 } 233 234 private void createListeners() { 235 MouseInputListener layerMouseListener = new MouseInputListener() { 237 public void mouseClicked(MouseEvent e) { 238 processMouse(e); 239 } 240 public void mousePressed(MouseEvent e) { 241 processMouse(e); 242 } 243 public void mouseReleased(MouseEvent e) { 244 processMouse(e); 245 } 246 public void mouseEntered(MouseEvent e) { 247 processMouse(e); 248 } 249 public void mouseExited(MouseEvent e) { 250 processMouse(e); 251 } 252 public void mouseDragged(MouseEvent e) { 253 processMouse(e); 254 } 255 public void mouseMoved(MouseEvent e) { 256 processMouse(e); 257 } 258 }; 259 addMouseListener(layerMouseListener); 260 addMouseMotionListener(layerMouseListener); 261 262 layerResizeListener = new ComponentAdapter() { 264 public void componentResized(ComponentEvent e) { 265 if (InPlaceEditLayer.this.isVisible()) 266 placeInPlaceField(); 267 } 268 }; 269 270 compKeyListener = new KeyAdapter() { 272 public void keyPressed(KeyEvent e) { 273 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) 274 finishEditing(false); 275 else if (e.getModifiers() == InputEvent.CTRL_MASK 276 && (e.getKeyCode() == 10 || e.getKeyCode() == KeyEvent.VK_ENTER)) 277 finishEditing(true); 278 } 279 }; 280 281 compFocusListener = new FocusAdapter() { 283 public void focusLost(FocusEvent event) { 284 finishEditing(true); 285 } 286 }; 287 288 compActionListener = new ActionListener() { 290 public void actionPerformed(ActionEvent evt) { 291 finishEditing(true); 292 } 293 }; 294 } 295 296 private void processMouse(MouseEvent e) { 297 if (!isEditingInitialized()) return; 298 299 if (isLayerEditing()) { 300 if (e.getID() == MouseEvent.MOUSE_PRESSED) 301 finishEditing(true); } 303 else { 304 Point p = SwingUtilities.convertPoint(this, e.getPoint(), superContainer); 305 Component comp = SwingUtilities.getDeepestComponentAt(superContainer, p.x, p.y); 306 if (comp != editedComp) { 307 Container cont = editedComp.getParent(); 308 if (comp != cont || !(cont instanceof JScrollPane)) 309 comp = null; 310 } 311 if (comp != null) { 312 comp.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, comp)); 313 314 if (e.getID() == MouseEvent.MOUSE_MOVED) { 315 Cursor cursor = comp.getCursor(); 316 if (getCursor() != cursor) 317 setCursor(cursor); 318 } 319 } 320 else { 321 if (e.getID() == MouseEvent.MOUSE_PRESSED) 322 finishEditing(true); else if (e.getID() == MouseEvent.MOUSE_MOVED) 324 if (getCursor() != defaultCursor) 325 setCursor(defaultCursor); 326 } 327 } 328 } 329 330 private void placeInPlaceField() { 331 Rectangle bounds = SwingUtilities.convertRectangle(editedComp.getParent(), 334 editedComp.getBounds(), 335 this); 336 Insets editedIns = ((JComponent)editedComp).getInsets(); 337 Insets editingIns = inPlaceField.getInsets(); 338 339 int hA, hTP, vA, vTP; 340 Icon icon; 341 int itGap; 342 String text; 343 344 if (editedComp instanceof JLabel) { 345 JLabel label = (JLabel)editedComp; 346 347 hA = label.getHorizontalAlignment(); 348 hTP = label.getHorizontalTextPosition(); 349 vA = label.getVerticalAlignment(); 350 vTP = label.getVerticalTextPosition(); 351 352 icon = label.getIcon(); 353 itGap = icon != null ? label.getIconTextGap() : 0; 354 text = label.getText(); 355 } 356 else if (editedComp instanceof AbstractButton) { 357 AbstractButton button = (AbstractButton)editedComp; 358 359 hA = button.getHorizontalAlignment(); 360 hTP = button.getHorizontalTextPosition(); 361 vA = button.getVerticalAlignment(); 362 vTP = button.getVerticalTextPosition(); 363 364 icon = button.getIcon(); 365 if (icon != null) { 366 Integer gap = (Integer )UIManager.get("Button.textIconGap"); itGap = gap != null ? gap.intValue() : 4; 368 } 369 else itGap = 0; 370 text = button.getText(); 371 372 if (editedComp instanceof JCheckBox || editedComp instanceof JRadioButton) { 373 if (icon == null) { 374 javax.swing.plaf.ComponentUI cui = UIManager.getUI((JComponent)editedComp); 375 if (cui instanceof javax.swing.plaf.basic.BasicRadioButtonUI ) { 376 icon = ((javax.swing.plaf.basic.BasicRadioButtonUI )cui).getDefaultIcon(); 377 itGap = ((javax.swing.plaf.basic.BasicRadioButtonUI )cui).getDefaultTextIconGap(button); 378 } 379 } 380 if (hA == SwingConstants.LEFT || hA == SwingConstants.LEADING) { 382 editedIns.right += editedIns.left; 383 editedIns.left = 0; 384 } 385 else if (hA == SwingConstants.RIGHT || hA == SwingConstants.TRAILING) { 386 editedIns.left += editedIns.right; 387 editedIns.right = 0; 388 } 389 if (vA == SwingConstants.TOP) { 390 editedIns.bottom += editedIns.top; 391 editedIns.top = 0; 392 } 393 else if (vA == SwingConstants.BOTTOM) { 394 editedIns.top += editedIns.bottom; 395 editedIns.bottom = 0; 396 } 397 } 398 } else if (editedComp instanceof JTabbedPane) { 399 JTabbedPane tabbedPane = (JTabbedPane)editedComp; 400 int index = tabbedPane.getSelectedIndex(); 401 text = tabbedPane.getTitleAt(index); 402 Rectangle relBounds = tabbedPane.getBoundsAt(index); 403 relBounds.x += bounds.x+4; 404 relBounds.y += bounds.y; 405 bounds = relBounds; 406 bounds.width -= 8; 407 icon = tabbedPane.getIconAt(index); 408 itGap = UIManager.getInt("TabbedPane.textIconGap"); vA = hA = vTP = SwingConstants.CENTER; 410 hTP = SwingConstants.TRAILING; 411 editedIns = new Insets(0, 0, 0, 0); 412 } 413 else return; 415 bounds.x += editedIns.left; 416 bounds.y += editedIns.top; 417 bounds.width -= editedIns.left + editedIns.right; 418 bounds.height -= editedIns.top + editedIns.bottom; 419 Rectangle iR = new Rectangle(); Rectangle tR = new Rectangle(); 422 SwingUtilities.layoutCompoundLabel( 423 (JComponent)editedComp, 424 editedComp.getGraphics().getFontMetrics(), 425 text, icon, 426 vA, hA, vTP, hTP, 427 bounds, 428 iR, tR, itGap); 429 430 if (icon != null && hTP != SwingConstants.CENTER) { 431 if (hA == SwingConstants.LEFT || hA == SwingConstants.LEADING) { 432 if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { 433 bounds.width -= tR.x - bounds.x; 434 bounds.x = tR.x; 435 inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); 436 } 437 else if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { 438 bounds.width = tR.width; 439 inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); 440 } 441 } 442 else if (hA == SwingConstants.RIGHT || hA == SwingConstants.TRAILING) { 443 if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { 444 bounds.x = tR.x; 445 bounds.width = tR.width; 446 inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); 447 } 448 if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { 449 bounds.width = tR.x - bounds.x + tR.width; 450 inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); 451 } 452 } 453 else { if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { 455 bounds.width -= tR.x - bounds.x; 456 bounds.x = tR.x; 457 inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); 458 } 459 else if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { 460 bounds.width = tR.x - bounds.x + tR.width; 461 inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); 462 } 463 else if (bounds.width > tR.width) { 464 bounds.x++; 465 bounds.width--; 466 } 467 } 468 } 469 else if (hA == SwingConstants.CENTER && bounds.width > tR.width) { 470 bounds.x++; 471 bounds.width--; 472 } 473 474 bounds.x -= editingIns.left; 475 bounds.width += editingIns.left + editingIns.right + 1; 476 if (bounds.width < 10) 477 bounds.width = 10; 478 479 bounds.y = tR.y - editingIns.top; 480 bounds.height = inPlaceField.getPreferredSize().height; 481 482 512 513 inPlaceField.setBounds(bounds); 515 inPlaceField.baseBounds = bounds; 516 if (!(inPlaceField.getText().equals(editedText))) 517 inPlaceField.adjustSize(); 518 } 519 520 522 public void requestFocus() { 523 if (editingTextComp != null) { 524 editingTextComp.requestFocus(); 529 int n = editingTextComp.getText().length(); 530 editingTextComp.setCaretPosition(n); 531 editingTextComp.moveCaretPosition(0); 532 } 533 else super.requestFocus(); 534 } 535 536 public boolean isOpaque() { 537 return false; 538 } 539 540 542 interface FinishListener extends java.util.EventListener { 543 public void editingFinished(boolean changed); 544 } 545 546 public synchronized void addFinishListener(FinishListener l) { 547 if (listeners == null) 548 listeners = new ArrayList (); 549 listeners.add(l); 550 } 551 552 public synchronized void removeFinishListener(FinishListener l) { 553 if (listeners != null) 554 listeners.remove(l); 555 } 556 557 private void fireEditingFinished() { 558 ArrayList targets; 559 synchronized (this) { 560 if (listeners == null) return; 561 targets = (ArrayList )listeners.clone(); 562 } 563 for (int i=0, n=targets.size(); i < n; i++) 564 ((FinishListener)targets.get(i)).editingFinished(changeDone); 565 } 566 567 569 574 class InPlaceTextField extends JTextField { 575 Rectangle baseBounds; 576 577 public InPlaceTextField() { 578 super(); 579 } 580 581 public InPlaceTextField(String text) { 582 super(text); 583 } 584 585 protected void processKeyEvent(KeyEvent e) { 586 if (e.getKeyCode() == KeyEvent.VK_TAB || e.getKeyChar() == '\t') { 587 e.consume(); 588 } 589 else { 590 super.processKeyEvent(e); 591 if (e.getID() == KeyEvent.KEY_TYPED) 592 adjustSize(); 593 } 594 } 595 596 void adjustSize() { 597 int prefWidth = getPreferredSize().width + 1; 598 if (prefWidth < baseBounds.width) prefWidth = baseBounds.width; 599 Rectangle bounds = getBounds(); 600 601 if (prefWidth != bounds.width) { 602 Rectangle newBounds; 603 if (prefWidth == baseBounds.width) 604 newBounds = baseBounds; 605 else { 606 int layerWidth = InPlaceEditLayer.this.getSize().width; 607 int leftX = baseBounds.x < 0 ? baseBounds.x : 0; 608 int rightX = baseBounds.x + baseBounds.width > layerWidth ? 609 baseBounds.x + baseBounds.width : layerWidth; 610 611 newBounds = new Rectangle(bounds); 612 613 int hA = getHorizontalAlignment(); 614 if (hA == SwingConstants.LEFT 615 || hA == SwingConstants.LEADING) { 616 newBounds.x = rightX - prefWidth; 617 if (newBounds.x < baseBounds.x) { if (newBounds.x < leftX) newBounds.x = leftX; 619 newBounds.width = rightX - newBounds.x; 620 } 621 else { 622 newBounds.x = baseBounds.x; 623 newBounds.width = prefWidth; 624 } 625 } 626 else if (hA == SwingConstants.RIGHT 627 || hA == SwingConstants.TRAILING) { 628 newBounds.x = baseBounds.x + baseBounds.width - prefWidth; 629 if (newBounds.x < leftX) { 630 newBounds.x = leftX; 631 newBounds.width = prefWidth > rightX - leftX ? 632 rightX - leftX : prefWidth; 633 } 634 else newBounds.width = prefWidth; 635 } 636 else { int cX = baseBounds.x + baseBounds.width/2; 638 int dX1 = prefWidth/2; 639 int dX2 = prefWidth - dX1; 640 641 int over1, over2; 642 if (cX - leftX < dX1) over2 = dX1 - (cX - leftX); 643 else over2 = 0; 644 if (rightX - cX < dX2) over1 = dX2 - (rightX - cX); 645 else over1 = 0; 646 647 if (cX - leftX < dX1 + over1) dX1 = cX - leftX; 648 else dX1 += over1; 649 if (rightX - cX < dX2 + over2) dX2 = rightX - cX; 650 else dX2 += over2; 651 652 newBounds.x = cX - dX1; 653 newBounds.width = dX1 + dX2; 654 } 655 } 656 657 if (!(newBounds.equals(bounds))) 658 setBounds(newBounds); 659 } 660 } 661 } 662 } 663 | Popular Tags |