1 23 24 package org.netbeans.swing.tabcontrol.plaf; 25 26 import org.netbeans.swing.tabcontrol.TabDisplayer; 27 28 import javax.swing.*; 29 import javax.swing.event.ChangeEvent ; 30 import javax.swing.event.ChangeListener ; 31 import javax.swing.plaf.ButtonUI ; 32 import javax.swing.plaf.ComponentUI ; 33 import java.awt.*; 34 import java.awt.event.*; 35 import java.awt.image.BufferedImage ; 36 import java.beans.PropertyChangeEvent ; 37 import java.util.Arrays ; 38 import java.util.Comparator ; 39 import org.netbeans.swing.tabcontrol.TabData; 40 41 53 public final class BasicSlidingTabDisplayerUI extends AbstractTabDisplayerUI { 54 private Rectangle scratch = new Rectangle(); 55 56 57 public BasicSlidingTabDisplayerUI(TabDisplayer displayer) { 58 super (displayer); 59 } 60 61 public static ComponentUI createUI (JComponent c) { 62 return new BasicSlidingTabDisplayerUI((TabDisplayer) c); 63 } 64 65 protected void install() { 66 displayer.setLayout (new OrientedLayoutManager()); 67 syncButtonsWithModel(); 68 } 69 70 protected Font createFont() { 71 Font f = super.createFont(); 73 f = new Font(f.getName(), Font.BOLD, f.getSize() + 1); 75 return f; 76 } 77 78 protected void uninstall() { 79 displayer.removeAll(); 80 } 81 82 public Dimension getPreferredSize(JComponent c) { 83 return displayer.getLayout().preferredLayoutSize(c); 84 } 85 86 public Dimension getMinimumSize(JComponent c) { 87 return displayer.getLayout().minimumLayoutSize(c); 88 } 89 90 private int buttonCount = 0; 91 private boolean syncButtonsWithModel() { 92 assert SwingUtilities.isEventDispatchThread(); 93 94 int count = displayer.getModel().size(); 95 boolean changed = false; 96 buttonCount = displayer.getComponentCount(); 97 98 if (count != buttonCount) { 99 synchronized (displayer.getTreeLock()) { 100 while (count < buttonCount) { 101 if (buttonCount-- > 0) { 102 displayer.remove (buttonCount- 1); 103 changed = true; 104 } 105 } 106 while (count > buttonCount) { 107 IndexButton ib = new IndexButton (buttonCount++); 108 ib.setFont (displayer.getFont()); 109 displayer.add (ib); 110 changed = true; 111 } 112 Component[] c = displayer.getComponents(); 113 for (int i=0; i < c.length; i++) { 114 if (c[i] instanceof IndexButton) { 115 changed |= ((IndexButton) c[i]).checkChanged(); 116 } 117 } 118 } 119 } 120 return changed; 121 } 122 123 126 protected TabLayoutModel createLayoutModel() { 127 DefaultTabLayoutModel result = new DefaultTabLayoutModel(displayer.getModel(), displayer); 128 result.setPadding (new Dimension (15, 2)); 129 return result; 130 } 131 132 protected MouseListener createMouseListener() { 133 return new MouseAdapter() {}; 134 } 135 136 public void requestAttention (int tab) { 137 } 139 140 public void cancelRequestAttention (int tab) { 141 } 143 144 protected ChangeListener createSelectionListener() { 145 return new ChangeListener () { 146 private int lastKnownSelection = -1; 147 public void stateChanged (ChangeEvent ce) { 148 int selection = selectionModel.getSelectedIndex(); 149 if (selection != lastKnownSelection) { 150 if (lastKnownSelection != -1) { 151 IndexButton last = findButtonFor(lastKnownSelection); 152 if (last != null) { 153 last.getModel().setSelected(false); 154 } 155 } 156 if (selection != -1) { 157 IndexButton current = findButtonFor (selection); 158 if (displayer.getComponentCount() == 0) { 159 syncButtonsWithModel(); 160 } 161 if (current != null) { 162 current.getModel().setSelected (true); 163 } 164 } 165 } 166 lastKnownSelection = selection; 167 } 168 }; 169 } 170 171 public Polygon getExactTabIndication(int index) { 172 return new EqualPolygon (findButtonFor(index).getBounds()); 173 } 174 175 public Polygon getInsertTabIndication(int index) { 176 Rectangle r = findButtonFor (index).getBounds(); 177 Polygon result = new EqualPolygon (findButtonFor(index).getBounds()); 178 return result; 179 } 180 181 private IndexButton findButtonFor (int index) { 182 Component[] c = displayer.getComponents(); 183 for (int i=0; i < c.length; i++) { 184 if (c[i] instanceof IndexButton && ((IndexButton) c[i]).getIndex() == index) { 185 return (IndexButton) c[i]; 186 } 187 } 188 return null; 189 } 190 191 public Rectangle getTabRect(int index, Rectangle destination) { 192 if (destination == null) { 193 destination = new Rectangle(); 194 } 195 IndexButton ib = findButtonFor(index); 196 if (ib != null) { 197 destination.setBounds (ib.getBounds()); 198 } else { 199 destination.setBounds (-20, -20, 0, 0); 200 } 201 return destination; 202 } 203 204 public int tabForCoordinate(Point p) { 205 Component[] c = displayer.getComponents(); 206 for (int i=0; i < c.length; i++) { 207 if (c[i] instanceof IndexButton) { 208 if (c[i].contains(p)) { 209 return ((IndexButton) c[i]).getIndex(); 210 } 211 } 212 } 213 return -1; 214 } 215 216 protected final class SlidingPropertyChangeListener extends AbstractTabDisplayerUI.DisplayerPropertyChangeListener { 217 public void propertyChange(PropertyChangeEvent e) { 218 super.propertyChange(e); 219 if (TabDisplayer.PROP_ORIENTATION.equals(e.getPropertyName())) { 220 displayer.revalidate(); 221 } 222 } 223 } 224 225 private Object getDisplayerOrientation() { 226 return displayer.getClientProperty (TabDisplayer.PROP_ORIENTATION); 227 } 228 229 230 public Image createImageOfTab(int index) { 231 TabData td = displayer.getModel().getTab(index); 232 233 JLabel lbl = new JLabel(td.getText()); 234 int width = lbl.getFontMetrics(lbl.getFont()).stringWidth(td.getText()); 235 int height = lbl.getFontMetrics(lbl.getFont()).getHeight(); 236 width = width + td.getIcon().getIconWidth() + 6; 237 height = Math.max(height, td.getIcon().getIconHeight()) + 5; 238 239 GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment() 240 .getDefaultScreenDevice().getDefaultConfiguration(); 241 242 BufferedImage image = config.createCompatibleImage(width, height); 243 Graphics2D g = image.createGraphics(); 244 g.setColor(lbl.getForeground()); 245 g.setFont(lbl.getFont()); 246 td.getIcon().paintIcon(lbl, g, 0, 0); 247 g.drawString(td.getText(), 18, height / 2); 248 249 return image; 250 251 } 252 253 259 public final class IndexButton extends JToggleButton implements ActionListener { 260 private int index; 261 private String lastKnownText = null; 262 private Icon lastKnownIcon = null; 263 264 265 public static final String UI_KEY = "IndexButtonUI"; 267 272 public IndexButton (int index) { 273 this.index = index; 274 addActionListener(this); 275 setFont (displayer.getFont()); 276 setFocusable(false); 277 } 278 279 public void addNotify() { 280 super.addNotify(); 281 ToolTipManager.sharedInstance().registerComponent(this); 282 } 283 284 public void removeNotify() { 285 super.removeNotify(); 286 ToolTipManager.sharedInstance().unregisterComponent(this); 287 } 288 289 290 public boolean isActive() { 291 return displayer.isActive(); 292 } 293 294 public void updateUI () { 295 SlidingTabDisplayerButtonUI ui = null; 296 try { 297 ui = (SlidingTabDisplayerButtonUI) UIManager.getUI(this); 298 setUI (ui); 299 return; 300 } catch (Error e) { 301 System.err.println ("Error getting sliding button UI: " + e.getMessage()); 302 } catch (Exception ex) { 303 System.err.println ("Exception getting button UI: " + ex.getMessage()); 304 } 305 setUI ((ButtonUI ) SlidingTabDisplayerButtonUI.createUI(this)); 306 } 307 308 public String getUIClassID() { 309 return UI_KEY; 310 } 311 312 314 public Object getOrientation() { 315 return getDisplayerOrientation(); 316 } 317 318 public String getText() { 319 if (index == -1) { 320 return ""; 323 } 324 if (index < displayer.getModel().size()) { 325 lastKnownText = displayer.getModel().getTab(index).getText(); 326 } else { 327 return "This tab doesn't exist."; } 329 return lastKnownText; 330 } 331 332 public String getToolTipText() { 333 return displayer.getModel().getTab(index).getTooltip(); 334 } 335 336 337 public final void actionPerformed(ActionEvent e) { 338 if (!isSelected()) { 339 selectionModel.setSelectedIndex (-1); 340 } else { 341 selectionModel.setSelectedIndex (index); 342 } 343 } 344 345 346 public int getIndex() { 347 return index; 348 } 349 350 public Icon getIcon() { 351 if (index == -1) { 352 return null; 355 } 356 if (index < displayer.getModel().size()) { 357 lastKnownIcon = displayer.getModel().getTab(index).getIcon(); 358 } 359 return lastKnownIcon; 360 } 361 362 370 final boolean checkChanged() { 371 boolean result = false; 372 Icon ic = lastKnownIcon; 373 Icon nue = getIcon(); 374 if (nue != ic) { 375 firePropertyChange ("icon", lastKnownIcon, nue); result = true; 377 } 378 String txt = lastKnownText; 379 String nu = getText(); 380 if (nu != txt) { firePropertyChange ("text", lastKnownText, getText()); result = true; 383 } 384 if (result) { 385 firePropertyChange ("preferredSize", null, null); } 387 return result; 388 } 389 } 390 391 protected void modelChanged() { 392 if (syncButtonsWithModel()) { 393 displayer.validate(); 394 } 395 } 396 397 public Icon getButtonIcon(int buttonId, int buttonState) { 398 return null; 399 } 400 401 private static final Comparator <Component> BUTTON_COMPARATOR = new IndexButtonComparator(); 402 private static class IndexButtonComparator implements Comparator <Component> { 403 public int compare(Component o1, Component o2) { 404 if (o2 instanceof IndexButton && o1 instanceof IndexButton) { 405 return ((IndexButton) o1).getIndex() - ((IndexButton) o2).getIndex(); 406 } 407 return 0; 408 } 409 } 410 411 private final class OrientedLayoutManager implements LayoutManager { 412 public void addLayoutComponent(String name, Component comp) { 413 } 415 416 public void layoutContainer(Container parent) { 417 synchronized (parent.getTreeLock()) { 418 syncButtonsWithModel(); 419 Component[] c = parent.getComponents(); 420 Arrays.sort (c, BUTTON_COMPARATOR); 421 for (int i=0; i < c.length; i++) { 422 if (c[i] instanceof IndexButton) { 423 boundsFor ((IndexButton) c[i], scratch); 424 c[i].setBounds (scratch); 425 } 426 } 427 } 428 } 429 430 private void boundsFor (IndexButton b, Rectangle r) { 431 Object orientation = getDisplayerOrientation(); 432 boolean flip = orientation == TabDisplayer.ORIENTATION_EAST || 433 orientation == TabDisplayer.ORIENTATION_WEST; 434 int index = b.getIndex(); 435 436 if (index >= displayer.getModel().size() || index < 0) { 437 r.setBounds (-20, -20, 0, 0); 438 return; 439 } 440 441 r.x = layoutModel.getX(index); 442 r.y = layoutModel.getY(index); 443 r.width = layoutModel.getW(index); 444 r.height = layoutModel.getH(index); 445 if (flip) { 446 int tmp = r.x; 447 r.x = r.y; 448 r.y = tmp; 449 450 tmp = r.width; 451 r.width = r.height; 452 r.height = tmp; 453 } 454 } 455 456 public Dimension minimumLayoutSize(Container parent) { 457 return preferredLayoutSize(parent); 458 } 459 460 public Dimension preferredLayoutSize(Container parent) { 461 Object orientation = getDisplayerOrientation(); 462 boolean flip = orientation == TabDisplayer.ORIENTATION_EAST || 463 orientation == TabDisplayer.ORIENTATION_WEST; 464 465 int max = displayer.getModel().size(); 466 Dimension result = new Dimension(); 467 for (int i=0; i < max; i++) { 468 result.height = Math.max (result.height, layoutModel.getH(i)); 469 result.width += layoutModel.getW(i); 470 } 471 if (flip) { 472 int tmp = result.height; 473 result.height = result.width; 474 result.width = tmp; 475 } 476 return result; 477 } 478 479 public void removeLayoutComponent(Component comp) { 480 } 482 } 483 } 484 | Popular Tags |