1 package com.sshtools.ui.awt; 2 3 import java.awt.Canvas ; 4 import java.awt.Color ; 5 import java.awt.Dimension ; 6 import java.awt.FontMetrics ; 7 import java.awt.Frame ; 8 import java.awt.Graphics ; 9 import java.awt.GridLayout ; 10 import java.awt.Image ; 11 import java.awt.Insets ; 12 import java.awt.Panel ; 13 import java.awt.Point ; 14 import java.awt.SystemColor ; 15 import java.awt.Window ; 16 import java.awt.event.ActionEvent ; 17 import java.awt.event.ComponentEvent ; 18 import java.awt.event.ComponentListener ; 19 import java.awt.event.FocusEvent ; 20 import java.awt.event.FocusListener ; 21 import java.awt.event.ItemEvent ; 22 import java.awt.event.ItemListener ; 23 import java.awt.event.MouseEvent ; 24 import java.awt.event.MouseListener ; 25 import java.awt.event.MouseMotionListener ; 26 import java.awt.image.FilteredImageSource ; 27 import java.beans.PropertyChangeEvent ; 28 import java.beans.PropertyChangeListener ; 29 import java.util.Enumeration ; 30 import java.util.Vector ; 31 32 import com.sshtools.ui.awt.tooltips.ToolTipManager; 33 34 39 public class ActionMenuBar extends Panel implements FocusListener , ComponentListener , PropertyChangeListener { 40 41 Vector menus = new Vector (); 42 Window menuWindow; 43 MenuCanvas menuCanvas; 44 MenuAction currentMenu; 45 Frame parentFrame; 46 Color disabledForeground = SystemColor.textInactiveText; 47 boolean toolTipsEnabled; 48 String icons; 49 String iconType = ActionButton.SMALL_ICONS; 50 int imageTextGap = 4; 51 Separator separator; 52 Color baseBackground = null; 53 Color baseForeground = null; 54 55 public ActionMenuBar() { 56 super(); 57 separator = new Separator(Separator.HORIZONTAL); 58 separator.setPreferredSize(new Dimension (0, 5)); 59 setLayout(new ToolLayout(separator)); 60 setBackground(SystemColor.control); 61 setForeground(SystemColor.controlText); 62 } 64 65 public void setImageTextGap(int imageTextGap) { 66 invalidate(); 67 this.imageTextGap = imageTextGap; 68 validate(); 69 repaint(); 70 } 71 72 public void setIconType(String iconType) { 73 invalidate(); 74 this.iconType = iconType; 75 validate(); 76 repaint(); 77 } 78 79 public void setToolTipsEnabled(boolean toolTipsEnabled) { 80 this.toolTipsEnabled = toolTipsEnabled; 81 if (!toolTipsEnabled) { 82 ToolTipManager.getInstance().hide(); 83 } 84 } 85 86 public void setDisabledForeground(Color disabledForeground) { 87 this.disabledForeground = disabledForeground; 88 repaint(); 89 } 90 91 public void addActionMenu(ActionMenu actionMenu) { 92 final MenuAction menuAction = new MenuAction(actionMenu); 93 ActionButton button = new ActionButton(menuAction) { 94 public boolean isFocusTraversable() { 95 return true; 96 } 97 98 public boolean isFocusable() { 99 return true; 100 } 101 102 }; 103 button.addItemListener(new ItemListener () { 104 105 public void itemStateChanged(ItemEvent e) { 106 if (currentMenu != null) { 107 hideMenuWindow(); 108 showMenuWindow(menuAction); 109 } 110 } 111 112 }); 113 for (Enumeration e = actionMenu.children(); e.hasMoreElements();) { 114 Action action = (Action) e.nextElement(); 115 action.addPropertyChangeListener(this); 116 } 117 menuAction.setButton(button); 118 if(baseForeground != null) { 119 button.setBaseForeground(baseForeground); 120 } 121 if(baseBackground != null) { 122 button.setBaseBackground(baseBackground); 123 } 124 menus.addElement(menuAction); 125 button.addFocusListener(this); 126 add(button); 127 } 128 129 public void remove(int index) { 130 synchronized (getTreeLock()) { 131 super.remove(index); 132 MenuAction menuAction = (MenuAction) menus.elementAt(index); 133 menuAction.button.removeFocusListener(this); 134 menus.removeElementAt(index); 135 } 136 } 137 138 143 protected void finalize() throws Throwable { 144 super.finalize(); 145 if (menuWindow != null) { 146 parentFrame.removeComponentListener(this); 147 } 148 } 149 150 void showMenuWindow(MenuAction menu) { 151 currentMenu = menu; 152 if (menuWindow == null) { 153 parentFrame = UIUtil.getFrameAncestor(this); 154 if (parentFrame == null) { 155 parentFrame = UIUtil.getSharedFrame(); 156 } 157 parentFrame.addComponentListener(this); 158 menuWindow = new Window (parentFrame); 159 menuCanvas = new MenuCanvas(); 160 if(baseBackground != null) { 161 menuCanvas.setBaseBackground(baseBackground); 162 } 163 if(baseForeground != null) { 164 menuCanvas.setBaseForeground(baseForeground); 165 } 166 menuCanvas.itemHeight = currentMenu.button.getSize().height; 167 menuWindow.setLayout(new GridLayout (1, 1)); 168 menuWindow.add(menuCanvas); 169 } 170 int x = currentMenu.button.getLocationOnScreen().x; 171 int y = currentMenu.button.getLocationOnScreen().y; 172 y += currentMenu.button.getSize().height; 173 menuWindow.setLocation(x, y); 174 Dimension d = menuCanvas.getPreferredSize(); 175 menuCanvas.setMenu(currentMenu.menu); 176 menuWindow.setSize(0, 0); 177 menuWindow.pack(); 178 menuWindow.setVisible(true); 179 currentMenu.button.setPressed(true); 180 181 } 182 183 void hideMenuWindow() { 184 if (menuWindow != null) { 185 menuWindow.setVisible(false); 186 if (currentMenu != null) { 187 currentMenu.button.setPressed(false); 188 } 189 currentMenu = null; 190 } 191 } 192 193 196 public int getMenuCount() { 197 return menus.size(); 198 } 199 200 class MenuAction extends AbstractAction { 201 202 private ActionMenu menu; 203 private ActionButton button; 204 205 MenuAction(ActionMenu menu) { 206 super(menu.getDisplayName()); 207 this.menu = menu; 208 } 209 210 215 public void actionPerformed(ActionEvent e) { 216 if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) { 217 showMenuWindow(this); 218 } else { 219 hideMenuWindow(); 220 } 221 } 222 223 void setButton(ActionButton button) { 224 this.button = button; 225 } 226 227 } 228 229 class MenuCanvas extends Canvas implements MouseMotionListener , MouseListener { 230 231 ActionMenu menu; 232 int borderWidth = 1; 233 Insets insets = new Insets (1, 16, 1, 16); 234 Color borderColor = SystemColor.controlShadow; 235 int sel = -1; 236 Color selectionBackground = SystemColor.controlLtHighlight; 237 Color selectionForeground = SystemColor.textText; 238 int itemHeight = 16; 239 String toolTipText; 240 Image backingStore; 241 242 MenuCanvas() { 243 addMouseMotionListener(this); 244 addMouseListener(this); 245 setBackground(SystemColor.control); 246 setForeground(SystemColor.controlText); 247 } 248 249 void setBaseBackground(Color base) { 250 if(base == null) { 251 selectionBackground = SystemColor.controlHighlight; 252 setBackground(SystemColor.control); 253 } 254 else { 255 selectionBackground = base.darker(); 256 setBackground(base); 257 } 258 } 259 260 void setBaseForeground(Color base) { 261 if(base == null) { 262 borderColor = SystemColor.controlShadow; 263 selectionForeground = SystemColor.controlText; 264 setForeground(SystemColor.controlText); 265 } 266 else { 267 borderColor= base.darker(); 268 selectionForeground = base.brighter(); 269 setForeground(base); 270 } 271 } 272 273 public Dimension getPreferredSize() { 274 if (menu == null || getGraphics() == null) { 275 return new Dimension (0, 0); 276 } 277 int w = 0; 278 int h = 0; 279 int iw = 0; 280 FontMetrics fm = getFontMetrics(getFont()); 281 for (Enumeration e = menu.children(); e.hasMoreElements();) { 282 Action action = (Action) e.nextElement(); 283 if(action.getName().equals(ActionMenu.SEPARATOR.getName())) { 284 h += separator.getPreferredSize().height; 285 } 286 else { 287 String imagePath = null; 288 if (iconType.equals(ActionButton.SMALL_ICONS)) { 289 imagePath = (String ) action.getValue(Action.SMALL_IMAGE_PATH); 290 } else if (iconType.equals(ActionButton.LARGE_ICONS)) { 291 imagePath = (String ) action.getValue(Action.IMAGE_PATH); 292 } 293 String n = (String ) action.getValue(Action.SHORT_DESCRIPTION); 294 n = n == null ? action.getName() : n; 295 w = Math.max(w, fm.stringWidth(n)); 296 itemHeight = Math.max(itemHeight, fm.getHeight()); 297 if (imagePath != null) { 298 Image img = UIUtil.loadImage(action.getClass(), imagePath); 299 if (img != null) { 300 UIUtil.waitFor(img, this); 301 iw = Math.max(iw, img.getWidth(this)); 302 itemHeight = Math.max(itemHeight, img.getHeight(this)); 303 } 304 } 305 h += itemHeight; 306 } 307 } 308 if (iw != 0) { 309 w += iw; 310 w += imageTextGap; 311 } 312 if (insets != null) { 313 w += insets.left + insets.right; 314 h += insets.top + insets.bottom; 315 } 316 w += borderWidth * 2; 317 h += borderWidth * 2; 318 return new Dimension (w, h); 319 } 320 321 public void update(Graphics g) { 322 paint(g); 323 } 324 325 public Dimension getMinimumSize() { 326 return getPreferredSize(); 327 } 328 329 public void setMenu(ActionMenu menu) { 330 this.menu = menu; 331 menuCanvas.sel = -1; 332 } 333 334 public void paint(Graphics ig) { 335 Dimension s = getSize(); 336 if (backingStore == null 337 || (backingStore != null && (s.width != backingStore.getWidth(this) || s.height != backingStore 338 .getHeight(this)))) { 339 if (backingStore != null) { 340 backingStore.getGraphics().dispose(); 341 } 342 backingStore = createImage(s.width, s.height); 343 } 344 Graphics g = backingStore.getGraphics(); 345 g.setColor(getBackground()); 346 g.fillRect(0, 0, s.width - 1, s.height - 1); 347 int px = 0; 348 int py = 0; 349 g.setColor(borderColor); 350 for (int i = 0; i < borderWidth; i++) { 351 g.drawRect(px, py, s.width - px - 1, s.height - py - 1); 352 px++; 353 py++; 354 } 355 if (insets != null) { 356 px += insets.left; 357 py += insets.top; 358 } 359 if (menu != null) { 360 Action m = null; 361 FontMetrics fm = getFontMetrics(getFont()); 362 int i = 0; 364 for (Enumeration e = menu.children(); e.hasMoreElements();) { 365 m = (Action) e.nextElement(); 366 if(m.getName().equals(ActionMenu.SEPARATOR.getName())) { 367 int h = separator.getPreferredSize().height; 368 int sw = s.width - ( insets == null ? 0 : ( ( insets.left + insets.right ) / 2 ) ) - ( borderWidth * 2 ); 369 separator.setBounds(0, 0, sw, h); 370 int sx = (s.width - sw ) / 2; 371 g.translate(sx, py); 372 separator.paint(g); 373 g.translate(-sx, -py); 374 py += h; 375 } 376 else { 377 String n = (String ) m.getValue(Action.SHORT_DESCRIPTION); 378 n = n == null ? m.getName() : n; 379 if (m.isEnabled()) { 380 if (i == sel) { 381 g.setColor(selectionBackground); 382 int ty = borderWidth + (insets != null ? insets.top : 0) + (py - borderWidth - insets.top ); 383 g.fillRect(borderWidth, ty, s.width - (borderWidth * 2), itemHeight); 384 if (borderWidth != 0) { 385 g.setColor(borderColor); 386 g.drawLine(borderWidth, ty, (borderWidth * 2) + s.width - 1, ty); 387 g.drawLine(borderWidth, ty + itemHeight - 1, (borderWidth * 2) + s.width - 1, ty + itemHeight - 1); 388 } 389 g.setColor(selectionForeground); 390 } else { 391 g.setColor(getForeground()); 392 } 393 } else { 394 g.setColor(disabledForeground); 395 } 396 String imagePath = null; 397 if (iconType.equals(ActionButton.SMALL_ICONS)) { 398 imagePath = (String ) m.getValue(Action.SMALL_IMAGE_PATH); 399 } else if (iconType.equals(ActionButton.LARGE_ICONS)) { 400 imagePath = (String ) m.getValue(Action.IMAGE_PATH); 401 } 402 int toff = 0; 403 if (imagePath != null) { 404 Image img = UIUtil.loadImage(m.getClass(), imagePath); 405 if(!m.isEnabled()) { 406 img = createImage(new FilteredImageSource (img.getSource(), 407 new GrayFilter())); 408 UIUtil.waitFor(img, this); 409 } 410 411 if (img != null) { 412 g.drawImage(img, px, py + ((itemHeight - img.getHeight(this)) / 2), this); 413 toff = imageTextGap + img.getWidth(this); 414 } 415 } 416 g.drawString(n, px + toff, py + fm.getHeight() - fm.getDescent() + ((itemHeight - fm.getHeight()) / 2)); 417 py += itemHeight; 418 } 419 i++; 420 } 421 } 422 ig.drawImage(backingStore, 0, 0, this); 423 } 424 425 int getIndexForLocation(int x, int ey) { 426 int idx = -1; 427 if (menu != null && getGraphics() != null) { 428 int y = borderWidth; 429 if (insets != null) { 430 y += insets.top; 431 } 432 FontMetrics fm = getFontMetrics(getFont()); 433 Action m = null; 434 for (Enumeration e = menu.children(); e.hasMoreElements();) { 435 idx++; 436 m = (Action) e.nextElement(); 437 if(!m.getName().equals(ActionMenu.SEPARATOR.getName())) { 438 y+= itemHeight; 439 if(y >= ey) { 440 return idx; 441 } 442 } 443 else { 444 y += separator.getPreferredSize().height; 445 } 446 } 447 } 448 return idx; 449 } 450 451 456 public void mouseDragged(MouseEvent e) { 457 459 } 460 461 466 public void mouseMoved(MouseEvent e) { 467 sel = getIndexForLocation(e.getX(), e.getY()); 468 if (sel != -1) { 469 Action action = menu.getChild(sel); 470 if (action.isEnabled()) { 471 String tip = (String ) action.getValue(Action.LONG_DESCRIPTION); 472 if (tip != null) { 473 Point p = getLocationOnScreen(); 474 if (toolTipsEnabled) { 475 ToolTipManager.getInstance().requestToolTip(this, p.x + e.getX() + 4, p.y + e.getY() + 4, tip); 476 } 477 } 478 } else { 479 sel = -1; 480 if (toolTipsEnabled) { 481 ToolTipManager.getInstance().hide(); 482 } 483 } 484 repaint(); 485 } 486 } 487 488 493 public void mouseClicked(MouseEvent e) { 494 if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) { 495 int clicked = getIndexForLocation(e.getX(), e.getY()); 496 if (clicked != -1 && clicked < menu.getChildCount()) { 497 Action action = menu.getChild(clicked); 498 action.actionPerformed(new ActionEvent (this, ActionEvent.ACTION_PERFORMED, action.getName(), e.getModifiers())); 499 } 500 } 501 hideMenuWindow(); 502 503 } 504 505 510 public void mousePressed(MouseEvent e) { 511 513 } 514 515 520 public void mouseReleased(MouseEvent e) { 521 523 } 524 525 530 public void mouseEntered(MouseEvent e) { 531 533 } 534 535 540 public void mouseExited(MouseEvent e) { 541 543 } 544 } 545 546 551 public void focusGained(FocusEvent e) { 552 } 553 554 559 public void focusLost(FocusEvent e) { 560 hideMenuWindow(); 561 } 562 563 566 public void removeAllMenuItems() { 567 for (Enumeration e = menus.elements(); e.hasMoreElements();) { 568 MenuAction act = (MenuAction) e.nextElement(); 569 for (Enumeration e2 = act.menu.children(); e2.hasMoreElements();) { 570 Action a = (Action) e2.nextElement(); 571 a.removePropertyChangeListener(this); 572 } 573 } 574 hideMenuWindow(); 575 menus.removeAllElements(); 576 removeAll(); 577 doLayout(); 578 } 579 580 585 public void componentResized(ComponentEvent e) { 586 hideMenuWindow(); 587 } 588 589 594 public void componentMoved(ComponentEvent e) { 595 hideMenuWindow(); 596 } 597 598 603 public void componentShown(ComponentEvent e) { 604 } 605 606 611 public void componentHidden(ComponentEvent e) { 612 hideMenuWindow(); 613 } 614 615 620 public void propertyChange(PropertyChangeEvent evt) { 621 repaint(); 622 } 623 624 627 public void setBaseBackground(Color baseBackground) { 628 setBackground(baseBackground == null ? SystemColor.control : baseBackground); 629 this.baseBackground = baseBackground; 630 for(Enumeration e = menus.elements(); e.hasMoreElements(); ) { 631 MenuAction m = (MenuAction)e.nextElement(); 632 m.button.setBaseBackground(baseBackground); 633 } 634 if(menuCanvas != null) { 635 menuCanvas.setBaseBackground(baseBackground); 636 } 637 } 638 639 642 public void setBaseForeground(Color baseForeground) { 643 setForeground(baseForeground == null ? SystemColor.controlText : baseForeground); 644 this.baseForeground = baseForeground; 645 for(Enumeration e = menus.elements(); e.hasMoreElements(); ) { 646 MenuAction m = (MenuAction)e.nextElement(); 647 m.button.setBaseForeground(baseForeground); 648 } 649 if(menuCanvas != null) { 650 menuCanvas.setBaseForeground(baseForeground); 651 } 652 } 653 } | Popular Tags |