1 19 20 package org.netbeans.swing.tabcontrol.plaf; 21 22 import java.awt.Graphics ; 23 import java.awt.Graphics2D ; 24 import java.awt.GraphicsConfiguration ; 25 import java.awt.GraphicsEnvironment ; 26 import java.awt.Image ; 27 import java.awt.Insets ; 28 import java.awt.Point ; 29 import java.awt.Polygon ; 30 import java.awt.Rectangle ; 31 import java.awt.Shape ; 32 import java.awt.event.MouseEvent ; 33 import java.awt.event.MouseListener ; 34 import java.awt.event.MouseMotionListener ; 35 import java.awt.event.MouseWheelEvent ; 36 import java.awt.event.MouseWheelListener ; 37 import java.awt.geom.Area ; 38 import java.awt.image.BufferedImage ; 39 import java.beans.PropertyChangeListener ; 40 import javax.swing.JComponent ; 41 import javax.swing.JLabel ; 42 import javax.swing.SwingUtilities ; 43 import javax.swing.event.ChangeEvent ; 44 import javax.swing.event.ChangeListener ; 45 import javax.swing.event.ListDataEvent ; 46 import org.netbeans.swing.tabcontrol.TabData; 47 import org.netbeans.swing.tabcontrol.TabDisplayer; 48 import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent; 49 50 94 public abstract class BasicTabDisplayerUI extends AbstractTabDisplayerUI { 95 protected TabState tabState = null; 96 private static final boolean swingpainting = Boolean.getBoolean( 97 "nb.tabs.swingpainting"); 99 protected TabCellRenderer defaultRenderer = null; 100 protected int repaintPolicy = 0; 101 102 private Rectangle scratch = new Rectangle (); 104 private Rectangle scratch2 = new Rectangle (); 105 private Rectangle scratch3 = new Rectangle (); 106 107 private Point lastKnownMouseLocation = new Point (); 108 109 int pixelsToAdd = 0; 110 111 public BasicTabDisplayerUI(TabDisplayer displayer) { 112 super(displayer); 113 } 114 115 118 protected void install() { 119 super.install(); 120 tabState = createTabState(); 121 defaultRenderer = createDefaultRenderer(); 122 layoutModel.setPadding (defaultRenderer.getPadding()); 123 pixelsToAdd = defaultRenderer.getPixelsToAddToSelection(); 124 repaintPolicy = createRepaintPolicy(); 125 if (displayer.getSelectionModel().getSelectedIndex() != -1) { 126 tabState.setSelected(displayer.getSelectionModel().getSelectedIndex()); 127 tabState.setActive(displayer.isActive()); 128 } 129 } 130 131 protected void uninstall() { 132 tabState = null; 133 defaultRenderer = null; 134 super.uninstall(); 135 } 136 137 138 TabState getTabState() { 139 return tabState; 140 } 141 142 159 protected TabState createTabState() { 160 return new BasicTabState(); 161 } 162 163 167 protected abstract TabCellRenderer createDefaultRenderer(); 168 169 175 public abstract Insets getTabAreaInsets(); 176 177 181 protected TabCellRenderer getTabCellRenderer(int tab) { 182 return defaultRenderer; 183 } 184 185 192 protected final void getTabsVisibleArea(Rectangle rect) { 193 Insets ins = getTabAreaInsets(); 194 rect.x = ins.left; 195 rect.y = ins.top; 196 rect.width = displayer.getWidth() - ins.right - ins.left; 197 rect.height = displayer.getHeight() - ins.bottom - ins.top; 198 } 199 200 protected MouseListener createMouseListener() { 201 return new BasicDisplayerMouseListener(); 202 } 203 204 protected PropertyChangeListener createPropertyChangeListener() { 205 return new BasicDisplayerPropertyChangeListener(); 206 } 207 208 public Polygon getExactTabIndication(int index) { 209 Rectangle r = getTabRect(index, scratch); 210 return getTabCellRenderer(index).getTabShape(tabState.getState(index), r); 211 } 212 213 public Polygon getInsertTabIndication(int index) { 214 Polygon p; 215 if (index == getLastVisibleTab() + 1) { 216 p = (Polygon ) getExactTabIndication (index-1); 217 Rectangle r = getTabRect(index-1, scratch); 218 p.translate(r.width/2, 0); 219 } else { 220 p = (Polygon ) getExactTabIndication (index); 221 Rectangle r = getTabRect(index, scratch); 222 p.translate(-(r.width/2), 0); 223 } 224 return p; 225 } 226 227 public int tabForCoordinate(Point p) { 228 if (displayer.getModel().size() == 0) { 229 return -1; 230 } 231 getTabsVisibleArea(scratch); 232 if (!scratch.contains(p)) { 233 return -1; 234 } 235 return layoutModel.indexOfPoint(p.x, p.y); 236 } 237 238 public Rectangle getTabRect(int idx, Rectangle rect) { 239 if (rect == null) { 240 rect = new Rectangle (); 241 } 242 if (idx < 0 || idx >= displayer.getModel().size()) { 243 rect.x = rect.y = rect.width = rect.height = 0; 244 return rect; 245 } 246 rect.x = layoutModel.getX(idx); 247 rect.y = layoutModel.getY(idx); 248 rect.width = layoutModel.getW(idx); 249 getTabsVisibleArea(scratch3); 250 int maxPos = scratch.x + scratch3.width; 252 if (rect.x > maxPos) { 253 rect.width = 0; 254 } else if (rect.x + rect.width > maxPos) { 255 rect.width = (maxPos - rect.x); 256 } 257 rect.height = layoutModel.getH(idx); 258 getTabsVisibleArea(scratch2); 259 if (rect.y + rect.height > scratch2.y + scratch2.height) { 260 rect.height = (scratch2.y + scratch2.height) - rect.y; 261 } 262 if (rect.x + rect.width > scratch2.x + scratch2.width) { 263 rect.width = (scratch2.x + scratch2.width) - rect.x; 264 } 265 return rect; 266 } 267 268 public Image createImageOfTab(int index) { 269 TabData td = displayer.getModel().getTab(index); 270 271 JLabel lbl = new JLabel (td.getText()); 272 int width = lbl.getFontMetrics(lbl.getFont()).stringWidth(td.getText()); 273 int height = lbl.getFontMetrics(lbl.getFont()).getHeight(); 274 width = width + td.getIcon().getIconWidth() + 6; 275 height = Math.max(height, td.getIcon().getIconHeight()) + 5; 276 277 GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment() 278 .getDefaultScreenDevice().getDefaultConfiguration(); 279 280 BufferedImage image = config.createCompatibleImage(width, height); 281 Graphics2D g = image.createGraphics(); 282 g.setColor(lbl.getForeground()); 283 g.setFont(lbl.getFont()); 284 td.getIcon().paintIcon(lbl, g, 0, 0); 285 g.drawString(td.getText(), 18, height / 2); 286 287 288 return image; 289 } 290 291 public int dropIndexOfPoint(Point p) { 292 Point p2 = toDropPoint(p); 293 int start = getFirstVisibleTab(); 294 int end = getLastVisibleTab(); 295 int target; 296 for (target = start; target <= end; target ++) { 297 getTabRect (target, scratch); 298 if (scratch.contains(p2)) { 299 if (target == end) { 300 Object orientation = displayer.getClientProperty (TabDisplayer.PROP_ORIENTATION); 301 boolean flip = displayer.getType() == TabDisplayer.TYPE_SLIDING && ( 302 orientation == TabDisplayer.ORIENTATION_EAST || 303 orientation == TabDisplayer.ORIENTATION_WEST); 304 305 if (flip) { 306 if (p2.y > scratch.y + (scratch.height / 2)) { 307 return target+1; 308 } 309 } else { 310 if (p2.x > scratch.x + (scratch.width / 2)) { 311 return target+1; 312 } 313 } 314 } 315 return target; 316 } 317 } 318 return -1; 319 } 320 321 protected boolean isAntialiased() { 322 return ColorUtil.shouldAntialias(); 323 } 324 325 330 public final void paint(Graphics g, JComponent c) { 331 assert c == displayer; 332 333 ColorUtil.setupAntialiasing(g); 334 335 boolean showClose = displayer.isShowCloseButton(); 336 337 paintBackground(g); 338 int start = getFirstVisibleTab(); 339 if (start == -1 || !displayer.isShowing()) { 340 return; 341 } 342 int stop = Math.min(getLastVisibleTab(), displayer.getModel().size() - 1); 344 getTabsVisibleArea(scratch); 345 346 348 if (g.hitClip(scratch.x, scratch.y, scratch.width, scratch.height)) { 349 Shape s = g.getClip(); 350 try { 351 if (s != null) { 354 Area a = new Area (s); 356 a.intersect(new Area (scratch.getBounds2D())); 357 g.setClip(a); 358 } else { 359 g.setClip(scratch.x, scratch.y, scratch.width, 362 scratch.height); 363 } 364 365 366 for (int i = start; i <= stop; i++) { 367 getTabRect(i, scratch); 368 if (g.hitClip(scratch.x, scratch.y, scratch.width + 1, 369 scratch.height + 1)) { 370 371 int state = tabState.getState(i); 372 373 if ((state & TabState.NOT_ONSCREEN) == 0) { 374 TabCellRenderer ren = getTabCellRenderer(i); 375 ren.setShowCloseButton(showClose); 376 377 TabData data = displayer.getModel().getTab(i); 378 379 380 JComponent renderer = ren.getRendererComponent( 381 data, scratch, state); 382 383 renderer.setFont(displayer.getFont()); 384 if (swingpainting) { 386 SwingUtilities.paintComponent(g, renderer, 390 displayer, 391 scratch); 392 } else { 393 try { 394 g.translate(scratch.x, scratch.y); 395 renderer.setBounds(scratch); 396 renderer.paint(g); 397 } finally { 398 g.translate(-scratch.x, -scratch.y); 399 } 400 } 401 } 402 } 403 } 404 } finally { 405 g.setClip(s); 406 } 407 } 408 paintAfterTabs(g); 409 } 410 411 416 protected void paintBackground(Graphics g) { 417 418 } 419 420 424 protected void paintAfterTabs(Graphics g) { 425 } 427 428 434 protected int getFirstVisibleTab() { 435 return displayer.getModel().size() > 0 ? 0 : -1; 436 } 437 438 444 protected int getLastVisibleTab() { 445 return displayer.getModel().size() - 1; 446 } 447 448 protected ChangeListener createSelectionListener() { 449 return new BasicSelectionListener(); 450 } 451 452 protected final Point getLastKnownMouseLocation() { 453 return lastKnownMouseLocation; 454 } 455 456 460 protected void processMouseWheelEvent(MouseWheelEvent e) { 461 } 463 464 protected final void requestAttention (int tab) { 465 tabState.addAlarmTab(tab); 466 } 467 468 protected final void cancelRequestAttention (int tab) { 469 tabState.removeAlarmTab(tab); 470 } 471 472 473 protected void modelChanged() { 474 tabState.clearTransientStates(); 475 int idx = selectionModel.getSelectedIndex(); 479 tabState.setSelected(idx); 480 tabState.pruneAlarmTabs(displayer.getModel().size()); 481 super.modelChanged(); 482 } 483 484 499 protected int createRepaintPolicy () { 500 return TabState.REPAINT_SELECTION_ON_ACTIVATION_CHANGE 501 | TabState.REPAINT_ON_SELECTION_CHANGE 502 | TabState.REPAINT_ON_MOUSE_ENTER_TAB 503 | TabState.REPAINT_ON_MOUSE_ENTER_CLOSE_BUTTON 504 | TabState.REPAINT_ON_MOUSE_PRESSED; 505 } 506 507 510 protected Rectangle getTabRectForRepaint( int tab, Rectangle rect ) { 511 return getTabRect( tab, rect ); 512 } 513 514 protected class BasicTabState extends TabState { 515 516 public int getState(int tab) { 517 if (displayer.getModel().size() == 0) { 518 return TabState.NOT_ONSCREEN; 519 } 520 int result = super.getState(tab); 521 if (tab == 0) { 522 result |= TabState.LEFTMOST; 523 } 524 if (tab == displayer.getModel().size() - 1) { 525 result |= TabState.RIGHTMOST; 526 } 527 return result; 528 } 529 530 protected void repaintAllTabs() { 531 displayer.repaint(); 536 } 537 538 public int getRepaintPolicy(int tab) { 539 return repaintPolicy; 541 } 542 543 protected void repaintTab(int tab) { 544 if (tab == -1 || tab > displayer.getModel().size()) { 545 return; 546 } 547 getTabRectForRepaint(tab, scratch); 548 scratch.y = 0; 549 scratch.height = displayer.getHeight(); 550 displayer.repaint(scratch.x, scratch.y, scratch.width, 551 scratch.height); 552 } 553 } 554 555 protected ModelListener createModelListener() { 556 return new BasicModelListener(); 557 } 558 559 private class BasicDisplayerPropertyChangeListener 560 extends DisplayerPropertyChangeListener { 561 562 protected void activationChanged() { 563 tabState.setActive(displayer.isActive()); 564 } 565 } 566 567 protected class BasicDisplayerMouseListener implements MouseListener , 568 MouseMotionListener , MouseWheelListener { 569 private int updateMouseLocation(MouseEvent e) { 570 lastKnownMouseLocation.x = e.getX(); 571 lastKnownMouseLocation.y = e.getY(); 572 return tabForCoordinate(lastKnownMouseLocation); 573 } 574 575 public void mouseClicked(MouseEvent e) { 576 int idx = updateMouseLocation(e); 577 if (idx == -1) { 578 return; 579 } 580 581 TabCellRenderer tcr = getTabCellRenderer(idx); 582 getTabRect(idx, scratch); 583 int state = tabState.getState(idx); 584 585 potentialCommand (idx, e, state, tcr, scratch); 586 } 587 588 public void mouseDragged(MouseEvent e) { 589 mouseMoved (e); 590 } 591 592 public void mouseEntered(MouseEvent e) { 593 int idx = updateMouseLocation(e); 594 tabState.setMouseInTabsArea(true); 595 tabState.setContainsMouse(idx); 596 } 597 598 public void mouseExited(MouseEvent e) { 599 updateMouseLocation(e); 600 tabState.setMouseInTabsArea(false); 601 tabState.setContainsMouse(-1); 602 tabState.setCloseButtonContainsMouse(-1); 603 } 604 605 public void mouseMoved(MouseEvent e) { 606 int idx = updateMouseLocation(e); 607 tabState.setMouseInTabsArea(true); 608 tabState.setContainsMouse(idx); 609 if (idx != -1) { 610 TabCellRenderer tcr = getTabCellRenderer(idx); 611 getTabRect(idx, scratch); 612 int state = tabState.getState(idx); 613 614 String s = tcr.getCommandAtPoint(e.getPoint(), state, scratch); 615 if (TabDisplayer.COMMAND_CLOSE == s) { 616 tabState.setCloseButtonContainsMouse(idx); 617 } else { 618 tabState.setCloseButtonContainsMouse(-1); 619 } 620 } else { 621 tabState.setContainsMouse(-1); 622 } 623 } 624 625 private int lastPressedTab = -1; 626 private long pressTime = -1; 627 public void mousePressed(MouseEvent e) { 628 int idx = updateMouseLocation(e); 629 tabState.setPressed(idx); 630 631 long time = e.getWhen(); 634 if (time - pressTime > 200) { 635 lastPressedTab = idx; 636 } 637 pressTime = time; 638 lastPressedTab = idx; 639 if (idx != -1) { 640 TabCellRenderer tcr = getTabCellRenderer(idx); 641 getTabRect(idx, scratch); 642 int state = tabState.getState(idx); 643 644 String command = tcr.getCommandAtPoint (e.getPoint(), state, scratch); 647 if (TabDisplayer.COMMAND_CLOSE == command) { 648 tabState.setCloseButtonContainsMouse(idx); 649 tabState.setMousePressedInCloseButton(idx); 650 651 pressTime = -1; 654 lastPressedTab = -1; 655 } 656 657 potentialCommand (idx, e, state, tcr, scratch); 658 } else { 659 tabState.setMousePressedInCloseButton(-1); } 661 } 662 663 private void potentialCommand (int idx, MouseEvent e, int state, TabCellRenderer tcr, Rectangle bounds) { 664 String command = tcr.getCommandAtPoint (e.getPoint(), state, bounds, 665 e.getButton(), e.getID(), e.getModifiersEx()); 666 if (command == null || TabDisplayer.COMMAND_SELECT == command) { 667 if (e.isPopupTrigger()) { 668 displayer.repaint(); 669 performCommand (TabDisplayer.COMMAND_POPUP_REQUEST, idx, e); 670 return; 671 } else if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() >= 2) { 672 performCommand (TabDisplayer.COMMAND_MAXIMIZE, idx, e); 673 return; 674 } 675 } 676 677 if (command != null) { 678 performCommand (command, lastPressedTab == -1 || lastPressedTab > 679 displayer.getModel().size() ? idx : lastPressedTab, e); 680 } 681 } 682 683 private void performCommand (String command, int idx, MouseEvent evt) { 684 evt.consume(); 685 if (TabDisplayer.COMMAND_SELECT == command) { 686 if (idx != displayer.getSelectionModel().getSelectedIndex()) { 687 boolean go = shouldPerformAction (command, idx, evt); 688 if (go) { 689 selectionModel.setSelectedIndex (idx); 690 } 691 } 692 } else { 693 boolean should = shouldPerformAction (command, idx, evt) && displayer.isShowCloseButton(); 694 if (should) { 695 if (TabDisplayer.COMMAND_CLOSE == command) { 696 displayer.getModel().removeTab(idx); 697 } else if (TabDisplayer.COMMAND_CLOSE_ALL == command) { 698 displayer.getModel().removeTabs (0, displayer.getModel().size()); 699 } else if (TabDisplayer.COMMAND_CLOSE_ALL_BUT_THIS == command) { 700 int start; 701 int end; 702 if (idx != displayer.getModel().size()-1) { 703 start = idx+1; 704 end = displayer.getModel().size(); 705 displayer.getModel().removeTabs(start, end); 706 } 707 if (idx != 0) { 708 start = 0; 709 end = idx; 710 displayer.getModel().removeTabs(start, end); 711 } 712 } 713 } 714 } 715 } 716 717 public void mouseReleased(MouseEvent e) { 718 int idx = updateMouseLocation(e); 719 if (idx != -1) { 720 TabCellRenderer tcr = getTabCellRenderer(idx); 721 getTabRect(idx, scratch); 722 int state = tabState.getState(idx); 723 if ((state & TabState.PRESSED) != 0 && ((state & TabState.CLIP_LEFT) != 0) || (state & TabState.CLIP_RIGHT) != 0) { 724 makeTabVisible(idx); 725 } 726 potentialCommand (idx, e, state, tcr, scratch); 727 } 728 tabState.setMouseInTabsArea(idx != -1); 729 tabState.setPressed(-1); 730 tabState.setMousePressedInCloseButton(-1); 731 } 732 733 public final void mouseWheelMoved(MouseWheelEvent e) { 734 updateMouseLocation(e); 735 processMouseWheelEvent(e); 736 } 737 } 738 739 742 protected class BasicSelectionListener implements ChangeListener { 743 public void stateChanged(ChangeEvent e) { 744 assert e.getSource() == selectionModel : "Unknown event source: " 745 + e.getSource(); 746 int idx = selectionModel.getSelectedIndex(); 747 tabState.setSelected(idx >= 0 ? idx : -1); 748 if (idx >= 0) { 749 makeTabVisible (selectionModel.getSelectedIndex()); 750 } 751 } 752 } 753 754 759 protected class BasicModelListener extends AbstractTabDisplayerUI.ModelListener { 760 public void contentsChanged(ListDataEvent e) { 761 super.contentsChanged(e); 762 tabState.contentsChanged(e); 763 } 764 765 public void indicesAdded(ComplexListDataEvent e) { 766 super.indicesAdded(e); 767 tabState.indicesAdded(e); 768 } 769 770 public void indicesChanged(ComplexListDataEvent e) { 771 tabState.indicesChanged(e); 772 } 773 774 public void indicesRemoved(ComplexListDataEvent e) { 775 tabState.indicesRemoved(e); 776 } 777 778 public void intervalAdded(ListDataEvent e) { 779 tabState.intervalAdded(e); 780 } 781 782 public void intervalRemoved(ListDataEvent e) { 783 tabState.intervalRemoved(e); 784 } 785 } 786 } 787 | Popular Tags |