1 19 20 package org.netbeans.swing.tabcontrol.plaf; 21 22 import java.awt.Component ; 23 import java.awt.Dimension ; 24 import java.awt.Font ; 25 import java.awt.FontMetrics ; 26 import java.awt.Graphics ; 27 import java.awt.Graphics2D ; 28 import java.awt.GraphicsConfiguration ; 29 import java.awt.GraphicsEnvironment ; 30 import java.awt.Image ; 31 import java.awt.KeyboardFocusManager ; 32 import java.awt.Point ; 33 import java.awt.Polygon ; 34 import java.awt.Rectangle ; 35 import javax.swing.AbstractAction ; 36 import javax.swing.Action ; 37 import javax.swing.JPanel ; 38 import javax.swing.event.ListDataEvent ; 39 import org.netbeans.swing.tabcontrol.TabData; 40 import org.netbeans.swing.tabcontrol.TabDataModel; 41 import org.netbeans.swing.tabcontrol.TabDisplayer; 42 import org.netbeans.swing.tabcontrol.TabDisplayerUI; 43 44 import javax.swing.event.ChangeEvent ; 45 import javax.swing.event.ChangeListener ; 46 import java.awt.event.ActionEvent ; 47 import java.awt.event.InputEvent ; 48 import java.awt.event.KeyEvent ; 49 import java.awt.event.MouseAdapter ; 50 import java.awt.event.MouseEvent ; 51 import java.awt.event.MouseMotionListener ; 52 import java.awt.image.BufferedImage ; 53 import java.beans.PropertyChangeEvent ; 54 import java.beans.PropertyChangeListener ; 55 import javax.swing.Icon ; 56 import javax.swing.JComponent ; 57 import javax.swing.JLabel ; 58 import javax.swing.KeyStroke ; 59 import javax.swing.SingleSelectionModel ; 60 import javax.swing.SwingUtilities ; 61 import javax.swing.ToolTipManager ; 62 import javax.swing.UIManager ; 63 import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent; 64 import org.netbeans.swing.tabcontrol.event.ComplexListDataListener; 65 import org.openide.windows.TopComponent; 66 67 79 public abstract class AbstractViewTabDisplayerUI extends TabDisplayerUI { 80 81 private TabDataModel dataModel; 82 83 private ViewTabLayoutModel layoutModel; 84 85 private FontMetrics fm; 86 87 private Font txtFont; 88 89 private Component controlButtons; 90 91 protected Controller controller; 92 93 private TabControlButton btnClose; 94 private TabControlButton btnAutoHidePin; 95 private TabControlButton btnMaximizeRestore; 96 97 98 private final Action pinAction = new PinAction(); 99 private static final String PIN_ACTION = "pinAction"; 100 101 public AbstractViewTabDisplayerUI (TabDisplayer displayer) { 102 super (displayer); 103 displayer.setLayout(null); 104 } 105 106 public void installUI(JComponent c) { 107 super.installUI(c); 108 ToolTipManager.sharedInstance().registerComponent(displayer); 109 controller = createController(); 110 dataModel = displayer.getModel(); 111 layoutModel = new ViewTabLayoutModel(dataModel, displayer); 112 dataModel.addChangeListener (controller); 113 dataModel.addComplexListDataListener(controller); 114 displayer.addPropertyChangeListener (controller); 115 selectionModel.addChangeListener (controller); 116 displayer.addMouseListener(controller); 117 displayer.addMouseMotionListener(controller); 118 installControlButtons(); 119 } 120 121 protected void installControlButtons() { 122 if( null != getControlButtons() ) 123 displayer.add( getControlButtons() ); 124 } 125 126 private static final int ICON_X_PAD = 1; 127 128 133 protected Component getControlButtons() { 134 if( null == controlButtons ) { 135 JPanel buttonsPanel = new JPanel ( null ); 136 buttonsPanel.setOpaque( false ); 137 138 int width = 0; 139 int height = 0; 140 149 if( null != displayer.getWinsysInfo() ) { 151 btnAutoHidePin = TabControlButtonFactory.createSlidePinButton( displayer ); 152 buttonsPanel.add( btnAutoHidePin ); 153 154 Icon icon = btnAutoHidePin.getIcon(); 155 if( 0 != width ) 156 width += ICON_X_PAD; 157 btnAutoHidePin.setBounds( width, 0, icon.getIconWidth(), icon.getIconHeight() ); 158 width += icon.getIconWidth(); 159 } 160 161 btnClose = TabControlButtonFactory.createCloseButton( displayer ); 163 buttonsPanel.add( btnClose ); 164 165 Icon icon = btnClose.getIcon(); 166 if( 0 != width ) 167 width += ICON_X_PAD; 168 btnClose.setBounds( width, 0, icon.getIconWidth(), icon.getIconHeight() ); 169 width += icon.getIconWidth(); 170 height = icon.getIconHeight(); 171 172 Dimension size = new Dimension ( width, height ); 173 buttonsPanel.setMinimumSize( size ); 174 buttonsPanel.setSize( size ); 175 buttonsPanel.setPreferredSize( size ); 176 buttonsPanel.setMaximumSize( size ); 177 178 controlButtons = buttonsPanel; 179 } 180 return controlButtons; 181 } 182 183 public void uninstallUI(JComponent c) { 184 super.uninstallUI(c); 185 ToolTipManager.sharedInstance().unregisterComponent(displayer); 186 displayer.removePropertyChangeListener (controller); 187 dataModel.removeChangeListener(controller); 188 dataModel.removeComplexListDataListener(controller); 189 selectionModel.removeChangeListener(controller); 190 displayer.removeMouseListener(controller); 191 displayer.removeMouseMotionListener(controller); 192 if (controlButtons != null) { 193 displayer.remove(controlButtons); 194 controlButtons = null; 195 } 196 layoutModel = null; 197 selectionModel = null; 198 dataModel = null; 199 controller = null; 200 } 201 202 protected Controller createController() { 203 return new Controller(); 204 } 205 206 public void paint(Graphics g, JComponent c) { 207 208 ColorUtil.setupAntialiasing(g); 209 210 TabData tabData; 211 int x, y, width, height; 212 String text; 213 214 for (int i = 0; i < dataModel.size(); i++) { 215 tabData = dataModel.getTab(i); 217 x = layoutModel.getX(i); 218 y = layoutModel.getY(i); 219 width = layoutModel.getW(i); 220 height = layoutModel.getH(i); 221 text = tabData.getText(); 222 if (g.hitClip(x, y, width, height)) { 224 paintTabBackground(g, i, x, y, width, height); 225 paintTabContent(g, i, text, x, y, width, height); 226 paintTabBorder(g, i, x, y, width, height); 227 } 228 } 229 } 230 231 protected final TabDataModel getDataModel() { 232 return dataModel; 233 } 234 235 public final TabLayoutModel getLayoutModel() { 236 return layoutModel; 237 } 238 239 protected final TabDisplayer getDisplayer() { 240 return displayer; 241 } 242 243 protected final SingleSelectionModel getSelectionModel() { 244 return selectionModel; 245 } 246 247 public Controller getController() { 248 return controller; 249 } 250 251 protected final boolean isSelected(int index) { 252 return selectionModel.getSelectedIndex() == index; 253 } 254 255 protected final boolean isActive() { 256 return displayer.isActive(); 257 } 258 259 protected final boolean isFocused(int index) { 260 return isSelected(index) && isActive(); 261 } 262 263 protected final SingleSelectionModel createSelectionModel() { 264 return new DefaultTabSelectionModel (displayer.getModel()); 265 } 266 267 public int dropIndexOfPoint(Point p) { 268 int result = 0; 269 for (int i=0; i < displayer.getModel().size(); i++) { 270 int x = getLayoutModel().getX(i); 271 int w = getLayoutModel().getW(i); 272 if (p.x >= x && p.x <= x + w) { 273 if (i == displayer.getModel().size() - 1) { 274 if (p.x > x + (w / 2)) { 275 result = displayer.getModel().size(); 276 break; 277 } else { 278 result = i; 279 break; 280 } 281 } else { 282 result = i; 283 break; 284 } 285 } 286 } 287 return result; 288 } 289 290 294 protected Font getTxtFont() { 295 if (txtFont == null) { 296 txtFont = (Font ) UIManager.get("windowTitleFont"); 297 if (txtFont == null) { 298 txtFont = new Font ("Dialog", Font.PLAIN, 11); 299 } else if (txtFont.isBold()) { 300 txtFont = new Font (txtFont.getName(), Font.PLAIN, txtFont.getSize()); 302 } 303 } 304 return txtFont; 305 } 306 307 protected final FontMetrics getTxtFontMetrics() { 308 if (fm == null) { 309 JComponent control = getDisplayer(); 310 fm = control.getFontMetrics(getTxtFont()); 311 } 312 return fm; 313 } 314 315 protected abstract void paintTabContent(Graphics g, int index, String text, 316 int x, int y, int width, 317 int height); 318 319 protected abstract void paintTabBorder(Graphics g, int index, int x, int y, 320 int width, int height); 321 322 protected abstract void paintTabBackground(Graphics g, int index, int x, 323 int y, int width, int height); 324 325 326 327 328 public void unregisterShortcuts(JComponent comp) { 329 comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). 330 remove(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 331 InputEvent.CTRL_DOWN_MASK)); 332 comp.getActionMap().remove(PIN_ACTION); 333 } 334 335 336 public void registerShortcuts(JComponent comp) { 337 comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT). 338 put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 339 InputEvent.CTRL_DOWN_MASK), PIN_ACTION); 340 comp.getActionMap().put(PIN_ACTION, pinAction); 341 } 342 343 public Polygon getExactTabIndication(int index) { 344 JComponent control = getDisplayer(); 348 int height = control.getHeight(); 349 350 TabLayoutModel tlm = getLayoutModel(); 351 352 int tabXStart = tlm.getX(index); 353 354 int tabXEnd = tabXStart + tlm.getW(index); 355 356 int[] xpoints = new int[4]; 357 int[] ypoints = new int[4]; 358 xpoints[0] = tabXStart; 359 ypoints[0] = 0; 360 xpoints[1] = tabXEnd; 361 ypoints[1] = 0; 362 xpoints[2] = tabXEnd; 363 ypoints[2] = height - 1; 364 xpoints[3] = tabXStart; 365 ypoints[3] = height - 1; 366 367 return new EqualPolygon(xpoints, ypoints); 368 } 369 370 public Polygon getInsertTabIndication(int index) { 371 EqualPolygon indication = new EqualPolygon(); 372 JComponent control = getDisplayer(); 373 int height = control.getHeight(); 374 int width = control.getWidth(); 375 TabLayoutModel tlm = getLayoutModel(); 376 377 int tabXStart; 378 int tabXEnd; 379 if (index == 0) { 380 tabXStart = 0; 381 tabXEnd = tlm.getW(0) / 2; 382 } else if (index >= getDataModel().size()) { 383 tabXStart = tlm.getX(index - 1) + tlm.getW(index - 1) / 2; 384 tabXEnd = tabXStart + tlm.getW(index - 1); 385 if (tabXEnd > width) { 386 tabXEnd = width; 387 } 388 } else { 389 tabXStart = tlm.getX(index - 1) + tlm.getW(index - 1) / 2; 390 tabXEnd = tlm.getX(index) + tlm.getW(index) / 2; 391 } 392 393 indication.moveTo(tabXStart, 0); 394 indication.lineTo(tabXEnd, 0); 395 indication.lineTo(tabXEnd, height - 1); 396 indication.lineTo(tabXStart, height - 1); 397 return indication; 398 } 399 400 401 public Image createImageOfTab(int index) { 402 TabData td = displayer.getModel().getTab(index); 403 404 JLabel lbl = new JLabel (td.getText()); 405 int width = lbl.getFontMetrics(lbl.getFont()).stringWidth(td.getText()); 406 int height = lbl.getFontMetrics(lbl.getFont()).getHeight(); 407 width = width + td.getIcon().getIconWidth() + 6; 408 height = Math.max(height, td.getIcon().getIconHeight()) + 5; 409 410 GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment() 411 .getDefaultScreenDevice().getDefaultConfiguration(); 412 413 BufferedImage image = config.createCompatibleImage(width, height); 414 Graphics2D g = image.createGraphics(); 415 g.setColor(lbl.getForeground()); 416 g.setFont(lbl.getFont()); 417 td.getIcon().paintIcon(lbl, g, 0, 0); 418 g.drawString(td.getText(), 18, height / 2); 419 420 421 return image; 422 } 423 424 public Rectangle getTabRect(int index, Rectangle destination) { 425 if (destination == null) { 426 destination = new Rectangle (); 427 } 428 if (index < 0 || index > displayer.getModel().size()) { 429 destination.setBounds (0,0,0,0); 430 return destination; 431 } 432 destination.x = layoutModel.getX(index); 433 destination.width = layoutModel.getW(index); 434 destination.height = layoutModel.getH(index); 435 destination.y = Math.min (0, displayer.getHeight() - destination.height); 436 return destination; 437 } 438 439 public int tabForCoordinate(Point p) { 440 int max = displayer.getModel().size(); 441 if (max == 0 || p.y > displayer.getHeight() || p.y < 0 || p.x < 0 || 442 p.x > displayer.getWidth()) { 443 444 return -1; 445 } 446 447 for (int i=0; i < max; i++) { 448 int left = layoutModel.getX(i); 449 int right = left + layoutModel.getW(i); 450 if (p.x > left && p.x < right) { 451 return i; 452 } 453 } 454 455 return -1; 456 } 457 458 protected int createRepaintPolicy () { 459 return TabState.REPAINT_SELECTION_ON_ACTIVATION_CHANGE 460 | TabState.REPAINT_ON_SELECTION_CHANGE 461 | TabState.REPAINT_ON_MOUSE_ENTER_TAB 462 | TabState.REPAINT_ON_MOUSE_ENTER_CLOSE_BUTTON 463 | TabState.REPAINT_ON_MOUSE_PRESSED; 464 } 465 466 protected final TabState tabState = new ViewTabState(); 467 468 private class ViewTabState extends TabState { 469 public ViewTabState () {} 470 471 public int getRepaintPolicy(int tab) { 472 return createRepaintPolicy(); 473 } 474 475 public void repaintAllTabs() { 476 displayer.repaint(); 477 } 478 479 public void repaintTab (int tab) { 480 if (tab < 0 || tab >= displayer.getModel().size()) { 481 return; 485 } 486 Rectangle r = getTabRect(tab, null); 487 displayer.repaint(r); 488 } 489 } 490 491 494 protected boolean isAttention (int tab) { 495 return (tabState.getState(tab) & TabState.ATTENTION) != 0; 496 } 497 498 499 protected void requestAttention (int tab) { 500 tabState.addAlarmTab(tab); 501 } 502 503 protected void cancelRequestAttention (int tab) { 504 tabState.removeAlarmTab(tab); 505 } 506 507 511 class Controller extends MouseAdapter 512 implements MouseMotionListener , ChangeListener , PropertyChangeListener , ComplexListDataListener { 513 514 517 private boolean selectionChanged; 518 519 protected boolean shouldReact(MouseEvent e) { 520 boolean isLeft = SwingUtilities.isLeftMouseButton(e); 521 return isLeft; 522 } 523 524 public void stateChanged (ChangeEvent ce) { 525 displayer.repaint(); 526 } 527 528 public void propertyChange (PropertyChangeEvent pce) { 529 if (TabDisplayer.PROP_ACTIVE.equals (pce.getPropertyName())) { 530 displayer.repaint(); 531 } 532 } 533 534 538 public boolean inControlButtonsRect( Point p ) { 539 if( null != controlButtons ) { 540 Point p2 = SwingUtilities.convertPoint(displayer, p, controlButtons); 541 return controlButtons.contains(p2); 542 } 543 return false; 544 } 545 546 public void mousePressed(MouseEvent e) { 547 Point p = e.getPoint(); 548 int i = getLayoutModel().indexOfPoint(p.x, p.y); 549 tabState.setPressed(i); 550 SingleSelectionModel sel = getSelectionModel(); 551 selectionChanged = i != sel.getSelectedIndex(); 552 if ((i != -1) || !selectionChanged) { 554 boolean change = shouldPerformAction(TabDisplayer.COMMAND_SELECT, 555 i, e); 556 if (change) { 557 getSelectionModel().setSelectedIndex(i); 558 tabState.setSelected(i); 559 Component tc = getDataModel().getTab(i).getComponent(); 560 if( null != tc && tc instanceof TopComponent 561 && !((TopComponent)tc).isAncestorOf( KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() ) ) { 562 ((TopComponent)tc).requestActive(); 563 } 564 } 565 } 566 if ((i != -1) && e.isPopupTrigger()) { 567 shouldPerformAction(TabDisplayer.COMMAND_POPUP_REQUEST, i, e); 569 } 570 } 571 572 public void mouseClicked (MouseEvent e) { 573 if (e.getClickCount() >= 2 && !e.isPopupTrigger()) { 574 Point p = e.getPoint(); 575 int i = getLayoutModel().indexOfPoint(p.x, p.y); 576 SingleSelectionModel sel = getSelectionModel(); 577 selectionChanged = i != sel.getSelectedIndex(); 578 if ((i != -1) || !selectionChanged) { 580 boolean change = shouldPerformAction(TabDisplayer.COMMAND_SELECT, 581 i, e); 582 if (change) { 583 getSelectionModel().setSelectedIndex(i); 584 } 585 } 586 if (i != -1) { 587 shouldPerformAction(TabDisplayer.COMMAND_MAXIMIZE, i, e); 589 } 590 } 591 } 592 593 public void mouseReleased(MouseEvent e) { 594 tabState.setPressed(-1); 597 Point p = e.getPoint(); 598 int i = getLayoutModel().indexOfPoint(p.x, p.y); 599 if ((i != -1) && e.isPopupTrigger()) { 600 shouldPerformAction(TabDisplayer.COMMAND_POPUP_REQUEST, i, e); 602 } 603 } 604 605 public void indicesAdded(ComplexListDataEvent e) { 606 tabState.indicesAdded(e); 607 } 608 609 615 public void indicesRemoved(ComplexListDataEvent e) { 616 tabState.indicesRemoved(e); 617 } 618 619 627 public void indicesChanged(ComplexListDataEvent e) { 628 tabState.indicesChanged(e); 629 } 630 631 public void intervalAdded (ListDataEvent evt) { 632 tabState.intervalAdded(evt); 633 } 634 635 public void intervalRemoved (ListDataEvent evt) { 636 tabState.intervalRemoved(evt); 637 } 638 639 public void contentsChanged(ListDataEvent evt) { 640 tabState.contentsChanged(evt); 641 } 642 643 public void mouseDragged(MouseEvent e) { 644 } 645 646 public void mouseMoved(MouseEvent e) { 647 } 648 } 650 private class PinAction extends AbstractAction { 651 public void actionPerformed(ActionEvent e) { 652 if( null != btnAutoHidePin ) { 653 btnAutoHidePin.performAction( null ); 654 } 655 } 656 } 657 } 658 | Popular Tags |