1 11 package org.eclipse.ui.internal.forms.widgets; 12 13 import org.eclipse.jface.action.IMenuManager; 14 import org.eclipse.jface.action.MenuManager; 15 import org.eclipse.swt.SWT; 16 import org.eclipse.swt.dnd.DragSource; 17 import org.eclipse.swt.dnd.DragSourceEffect; 18 import org.eclipse.swt.dnd.DragSourceEvent; 19 import org.eclipse.swt.dnd.DragSourceListener; 20 import org.eclipse.swt.dnd.DropTarget; 21 import org.eclipse.swt.dnd.DropTargetListener; 22 import org.eclipse.swt.dnd.Transfer; 23 import org.eclipse.swt.events.MouseEvent; 24 import org.eclipse.swt.events.MouseMoveListener; 25 import org.eclipse.swt.events.MouseTrackListener; 26 import org.eclipse.swt.events.PaintEvent; 27 import org.eclipse.swt.events.PaintListener; 28 import org.eclipse.swt.graphics.Color; 29 import org.eclipse.swt.graphics.Font; 30 import org.eclipse.swt.graphics.FontMetrics; 31 import org.eclipse.swt.graphics.GC; 32 import org.eclipse.swt.graphics.Image; 33 import org.eclipse.swt.graphics.Point; 34 import org.eclipse.swt.graphics.Rectangle; 35 import org.eclipse.swt.widgets.Canvas; 36 import org.eclipse.swt.widgets.Composite; 37 import org.eclipse.swt.widgets.Control; 38 import org.eclipse.swt.widgets.Event; 39 import org.eclipse.swt.widgets.Label; 40 import org.eclipse.swt.widgets.Layout; 41 import org.eclipse.swt.widgets.Listener; 42 import org.eclipse.swt.widgets.Menu; 43 import org.eclipse.ui.forms.IFormColors; 44 import org.eclipse.ui.forms.widgets.ILayoutExtension; 45 import org.eclipse.ui.forms.widgets.SizeCache; 46 import org.eclipse.ui.forms.widgets.Twistie; 47 import org.eclipse.ui.internal.forms.IMessageToolTipManager; 48 49 52 public class TitleRegion extends Canvas { 53 public static final int STATE_NORMAL = 0; 54 public static final int STATE_HOVER_LIGHT = 1; 55 public static final int STATE_HOVER_FULL = 2; 56 private int hoverState; 57 private static final int HMARGIN = 1; 58 private static final int VMARGIN = 5; 59 private static final int SPACING = 5; 60 private static final int ARC_WIDTH = 20; 61 private static final int ARC_HEIGHT = 20; 62 private Image image; 63 private BusyIndicator busyLabel; 64 private Label titleLabel; 65 private SizeCache titleCache; 66 private int fontHeight = -1; 67 private int fontBaselineHeight = -1; 68 private MenuHyperlink menuHyperlink; 69 private MenuManager menuManager; 70 private boolean dragSupport; 71 private int dragOperations; 72 private Transfer[] dragTransferTypes; 73 private DragSourceListener dragListener; 74 private DragSource dragSource; 75 private Image dragImage; 76 77 private class HoverListener implements MouseTrackListener, 78 MouseMoveListener { 79 80 public void mouseEnter(MouseEvent e) { 81 setHoverState(STATE_HOVER_FULL); 82 } 83 84 public void mouseExit(MouseEvent e) { 85 setHoverState(STATE_NORMAL); 86 } 87 88 public void mouseHover(MouseEvent e) { 89 } 90 91 public void mouseMove(MouseEvent e) { 92 if (e.button > 0) 93 setHoverState(STATE_NORMAL); 94 else 95 setHoverState(STATE_HOVER_FULL); 96 } 97 } 98 99 private class MenuHyperlink extends Twistie { 100 private boolean firstTime = true; 101 102 public MenuHyperlink(Composite parent, int style) { 103 super(parent, style); 104 setExpanded(true); 105 } 106 107 public void setExpanded(boolean expanded) { 108 if (firstTime) { 109 super.setExpanded(expanded); 110 firstTime = false; 111 } else { 112 Menu menu = menuManager.createContextMenu(menuHyperlink); 113 menu.setVisible(true); 114 } 115 } 116 } 117 118 private class TitleRegionLayout extends Layout implements ILayoutExtension { 119 120 protected Point computeSize(Composite composite, int wHint, int hHint, 121 boolean flushCache) { 122 return layout(composite, false, 0, 0, wHint, hHint, flushCache); 123 } 124 125 protected void layout(Composite composite, boolean flushCache) { 126 Rectangle carea = composite.getClientArea(); 127 layout(composite, true, carea.x, carea.y, carea.width, 128 carea.height, flushCache); 129 } 130 131 private Point layout(Composite composite, boolean move, int x, int y, 132 int width, int height, boolean flushCache) { 133 int iwidth = width == SWT.DEFAULT ? SWT.DEFAULT : width - HMARGIN 134 * 2; 135 Point bsize = null; 136 Point tsize = null; 137 Point msize = null; 138 139 if (busyLabel != null) { 140 bsize = busyLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT); 141 } 142 if (menuManager != null) { 143 menuHyperlink.setVisible(!menuManager.isEmpty() 144 && titleLabel.getVisible()); 145 if (menuHyperlink.getVisible()) 146 msize = menuHyperlink.computeSize(SWT.DEFAULT, SWT.DEFAULT); 147 } 148 if (flushCache) 149 titleCache.flush(); 150 titleCache.setControl(titleLabel); 151 int twidth = iwidth == SWT.DEFAULT ? iwidth : iwidth - SPACING * 2; 152 if (bsize != null && twidth != SWT.DEFAULT) 153 twidth -= bsize.x + SPACING; 154 if (msize != null && twidth != SWT.DEFAULT) 155 twidth -= msize.x + SPACING; 156 if (titleLabel.getVisible()) { 157 tsize = titleCache.computeSize(twidth, SWT.DEFAULT); 158 if (twidth != SWT.DEFAULT) { 159 int maxWidth = titleCache.computeSize(SWT.DEFAULT, 163 SWT.DEFAULT).x; 164 tsize.x = Math.min(tsize.x, maxWidth); 165 } 168 } else 169 tsize = new Point(0, 0); 170 Point size = new Point(width, height); 171 if (!move) { 172 size.x = tsize.x > 0 ? HMARGIN * 2 + SPACING * 2 + tsize.x : 0; 174 size.y = tsize.y; 175 if (bsize != null) { 176 size.x += bsize.x + SPACING; 177 size.y = Math.max(size.y, bsize.y); 178 } 179 if (msize != null) { 180 size.x += msize.x + SPACING; 181 size.y = Math.max(size.y, msize.y); 182 } 183 if (size.y > 0) 184 size.y += VMARGIN * 2; 185 } else { 188 int xloc = x + HMARGIN + SPACING; 190 int yloc = y + VMARGIN; 191 if (bsize != null) { 192 busyLabel.setBounds(xloc, 193 yloc + getFontHeight() - 1 - bsize.y, 195 bsize.x, bsize.y); 196 xloc += bsize.x + SPACING; 197 } 198 if (titleLabel.getVisible()) { 199 int tw = width - HMARGIN * 2 - SPACING * 2; 200 if (bsize != null) 201 tw -= bsize.x + SPACING; 202 if (msize != null) 203 tw -= msize.x + SPACING; 204 titleLabel.setBounds(xloc, 205 yloc, tw, tsize.y); 207 xloc += tw + SPACING; 209 } 210 if (msize != null) { 211 menuHyperlink.setBounds(xloc, yloc 212 + getFontHeight() / 2 - msize.y / 2, 213 msize.x, msize.y); 214 } 215 } 216 return size; 217 } 218 219 public int computeMaximumWidth(Composite parent, boolean changed) { 220 return computeSize(parent, SWT.DEFAULT, SWT.DEFAULT, changed).x; 221 } 222 223 public int computeMinimumWidth(Composite parent, boolean changed) { 224 return computeSize(parent, 0, SWT.DEFAULT, changed).x; 225 } 226 } 227 228 public TitleRegion(Composite parent) { 229 super(parent, SWT.NULL); 230 titleLabel = new Label(this, SWT.WRAP); 231 titleLabel.setVisible(false); 232 titleCache = new SizeCache(); 233 super.setLayout(new TitleRegionLayout()); 234 hookHoverListeners(); 235 addListener(SWT.Dispose, new Listener() { 236 public void handleEvent(Event e) { 237 if (dragImage != null) { 238 dragImage.dispose(); 239 dragImage = null; 240 } 241 } 242 }); 243 } 244 245 private Color getColor(String key) { 246 return (Color) ((FormHeading) getParent()).colors.get(key); 247 } 248 249 private void hookHoverListeners() { 250 HoverListener listener = new HoverListener(); 251 addMouseTrackListener(listener); 252 addMouseMoveListener(listener); 253 titleLabel.addMouseTrackListener(listener); 254 titleLabel.addMouseMoveListener(listener); 255 addPaintListener(new PaintListener() { 256 public void paintControl(PaintEvent e) { 257 onPaint(e); 258 } 259 }); 260 } 261 262 private void onPaint(PaintEvent e) { 263 if (hoverState == STATE_NORMAL) 264 return; 265 GC gc = e.gc; 266 Rectangle carea = getClientArea(); 267 gc.setBackground(getHoverBackground()); 268 int savedAntialias = gc.getAntialias(); 269 FormUtil.setAntialias(gc, SWT.ON); 270 gc.fillRoundRectangle(carea.x + HMARGIN, carea.y + 2, carea.width 271 - HMARGIN * 2, carea.height - 4, ARC_WIDTH, ARC_HEIGHT); 272 FormUtil.setAntialias(gc, savedAntialias); 273 } 274 275 private Color getHoverBackground() { 276 if (hoverState == STATE_NORMAL) 277 return null; 278 Color color = getColor(hoverState == STATE_HOVER_FULL ? IFormColors.H_HOVER_FULL 279 : IFormColors.H_HOVER_LIGHT); 280 if (color == null) 281 color = getDisplay() 282 .getSystemColor( 283 hoverState == STATE_HOVER_FULL ? SWT.COLOR_WIDGET_BACKGROUND 284 : SWT.COLOR_WIDGET_LIGHT_SHADOW); 285 return color; 286 } 287 288 public void setHoverState(int state) { 289 if (dragSource == null || this.hoverState == state) 290 return; 291 this.hoverState = state; 292 Color color = getHoverBackground(); 293 titleLabel.setBackground(color != null ? color 294 : getColor(FormHeading.COLOR_BASE_BG)); 295 if (busyLabel != null) 296 busyLabel.setBackground(color != null ? color 297 : getColor(FormHeading.COLOR_BASE_BG)); 298 if (menuHyperlink != null) 299 menuHyperlink.setBackground(color != null ? color 300 : getColor(FormHeading.COLOR_BASE_BG)); 301 redraw(); 302 } 303 304 307 public final Point computeSize(int wHint, int hHint, boolean changed) { 308 return ((TitleRegionLayout) getLayout()).computeSize(this, wHint, 309 hHint, changed); 310 } 311 312 public final void setLayout(Layout layout) { 313 } 315 316 public Image getImage() { 317 return image; 318 } 319 320 public void setImage(Image image) { 321 this.image = image; 322 } 323 324 public void updateImage(Image newImage, boolean doLayout) { 325 Image theImage = newImage != null ? newImage : this.image; 326 327 if (theImage != null) { 328 ensureBusyLabelExists(); 329 } else if (busyLabel != null) { 330 if (!busyLabel.isBusy()) { 331 busyLabel.dispose(); 332 busyLabel = null; 333 } 334 } 335 if (busyLabel != null) { 336 busyLabel.setImage(theImage); 337 } 338 if (doLayout) 339 layout(); 340 } 341 342 public void updateToolTip(String toolTip) { 343 if (busyLabel != null) 344 busyLabel.setToolTipText(toolTip); 345 } 346 347 public void setBackground(Color bg) { 348 super.setBackground(bg); 349 titleLabel.setBackground(bg); 350 if (busyLabel != null) 351 busyLabel.setBackground(bg); 352 if (menuHyperlink != null) 353 menuHyperlink.setBackground(bg); 354 } 355 356 public void setForeground(Color fg) { 357 super.setForeground(fg); 358 titleLabel.setForeground(fg); 359 if (menuHyperlink != null) 360 menuHyperlink.setForeground(fg); 361 } 362 363 public void setText(String text) { 364 if (text != null) 365 titleLabel.setText(text); 366 titleLabel.setVisible(text != null); 367 layout(); 368 redraw(); 369 } 370 371 public String getText() { 372 return titleLabel.getText(); 373 } 374 375 public void setFont(Font font) { 376 super.setFont(font); 377 titleLabel.setFont(font); 378 fontHeight = -1; 379 fontBaselineHeight = -1; 380 layout(); 381 } 382 383 private void ensureBusyLabelExists() { 384 if (busyLabel == null) { 385 busyLabel = new BusyIndicator(this, SWT.NULL); 386 busyLabel.setBackground(getColor(FormHeading.COLOR_BASE_BG)); 387 HoverListener listener = new HoverListener(); 388 busyLabel.addMouseTrackListener(listener); 389 busyLabel.addMouseMoveListener(listener); 390 if (menuManager != null) 391 busyLabel.setMenu(menuManager.createContextMenu(this)); 392 if (dragSupport) 393 addDragSupport(busyLabel, dragOperations, dragTransferTypes, dragListener); 394 IMessageToolTipManager mng = ((FormHeading) getParent()) 395 .getMessageToolTipManager(); 396 if (mng != null) 397 mng.createToolTip(busyLabel, true); 398 } 399 } 400 401 private void createMenuHyperlink() { 402 menuHyperlink = new MenuHyperlink(this, SWT.NULL); 403 menuHyperlink.setBackground(getColor(FormHeading.COLOR_BASE_BG)); 404 menuHyperlink.setDecorationColor(getForeground()); 405 menuHyperlink.setHoverDecorationColor(getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); 406 HoverListener listener = new HoverListener(); 407 menuHyperlink.addMouseTrackListener(listener); 408 menuHyperlink.addMouseMoveListener(listener); 409 if (dragSupport) 410 addDragSupport(menuHyperlink, dragOperations, dragTransferTypes, dragListener); 411 } 412 413 420 421 public boolean setBusy(boolean busy) { 422 if (busy) 423 ensureBusyLabelExists(); 424 else if (busyLabel == null) 425 return false; 426 if (busy == busyLabel.isBusy()) 427 return false; 428 busyLabel.setBusy(busy); 429 if (busyLabel.getImage() == null) { 430 layout(); 431 return true; 432 } 433 return false; 434 } 435 436 public boolean isBusy() { 437 return busyLabel != null && busyLabel.isBusy(); 438 } 439 440 443 public int getFontHeight() { 444 if (fontHeight == -1) { 445 Font font = getFont(); 446 GC gc = new GC(getDisplay()); 447 gc.setFont(font); 448 FontMetrics fm = gc.getFontMetrics(); 449 fontHeight = fm.getHeight(); 450 gc.dispose(); 451 } 452 return fontHeight; 453 } 454 455 459 public int getFontBaselineHeight() { 460 if (fontBaselineHeight == -1) { 461 Font font = getFont(); 462 GC gc = new GC(getDisplay()); 463 gc.setFont(font); 464 FontMetrics fm = gc.getFontMetrics(); 465 fontBaselineHeight = fm.getHeight() - fm.getDescent(); 466 gc.dispose(); 467 } 468 return fontBaselineHeight; 469 } 470 471 public IMenuManager getMenuManager() { 472 if (menuManager == null) { 473 menuManager = new MenuManager(); 474 Menu menu = menuManager.createContextMenu(this); 475 setMenu(menu); 476 titleLabel.setMenu(menu); 477 if (busyLabel != null) 478 busyLabel.setMenu(menu); 479 createMenuHyperlink(); 480 } 481 return menuManager; 482 } 483 484 public void addDragSupport(int operations, Transfer[] transferTypes, 485 DragSourceListener listener) { 486 dragSupport = true; 487 dragOperations = operations; 488 dragTransferTypes = transferTypes; 489 dragListener = listener; 490 dragSource = addDragSupport(titleLabel, operations, transferTypes, 491 listener); 492 addDragSupport(this, operations, transferTypes, listener); 493 if (busyLabel != null) 494 addDragSupport(busyLabel, operations, transferTypes, listener); 495 if (menuHyperlink != null) 496 addDragSupport(menuHyperlink, operations, transferTypes, listener); 497 } 498 499 private DragSource addDragSupport(Control control, int operations, 500 Transfer[] transferTypes, DragSourceListener listener) { 501 DragSource source = new DragSource(control, operations); 502 source.setTransfer(transferTypes); 503 source.addDragListener(listener); 504 source.setDragSourceEffect(new DragSourceEffect(control) { 505 public void dragStart(DragSourceEvent event) { 506 event.image = createDragEffectImage(); 507 } 508 }); 509 return source; 510 } 511 512 private Image createDragEffectImage() { 513 519 return null; 520 } 521 522 public void addDropSupport(int operations, Transfer[] transferTypes, 523 DropTargetListener listener) { 524 final DropTarget target = new DropTarget(this, operations); 525 target.setTransfer(transferTypes); 526 target.addDropListener(listener); 527 } 528 } | Popular Tags |