Draw2D中如何控制ToolTip的持续时间

软件版本:Eclipse3.2, draw2d_3.2.0.v20060626

在Draw2d中,Figure都支持ToolTip(通过调用setToolTip方法),当鼠标停留在其上面时,显示一个标签,以便提供有用的信息给使用者。这个显示的持续时间为5秒。那么对于ToolTip内容比较长的情况,5秒时间不够用,怎么办?
话说从头。相传SWT与Draw2d连接的桥梁叫做LightweightSystem,而在LightweightSystem中,负责分发SWT事件的,叫做SWTEventDispatcher,这个SWTEventDispatcher呢,使用一个ToolTipHelper的对象来控制ToolTip的显示,而在ToolTipHelper中,那个5秒的持续时间却是写死的。——必须承认,做eclipse插件开发,很多时候都不得不阅读他们的源码并修改——那么,我们的解决办法自然就是:将这个ToolTipHelper的行为替换掉。OK,继承一个:

public class ToolTipHelperX extends ToolTipHelper {
 private Timer timer;
 private IFigure currentTipSource;
 private long duration = 5000;

 /**
  * Constructs a ToolTipHelper to be associated with Control <i>c</i>.
  *
  * @param c the control
  * @since 2.0
  */
 public ToolTipHelperX(Control c) {
  super(c);
 }

 /*
  * Calculates the location where the tooltip will be painted. Returns this as a Point.
  * Tooltip will be painted directly below the cursor if possible, otherwise it will be
  * painted directly above cursor.
  */
 private Point computeWindowLocation(IFigure tip, int eventX, int eventY) {
  org.eclipse.swt.graphics.Rectangle clientArea = control.getDisplay().getClientArea();
  Point preferredLocation = new Point(eventX, eventY + 26);
  
  Dimension tipSize = getLightweightSystem()
   .getRootFigure()
   .getPreferredSize()
   .getExpanded(getShellTrimSize());

  // Adjust location if tip is going to fall outside display
  if (preferredLocation.y + tipSize.height > clientArea.height) 
   preferredLocation.y = eventY - tipSize.height;
  
  if (preferredLocation.x + tipSize.width > clientArea.width)
   preferredLocation.x -= (preferredLocation.x + tipSize.width) - clientArea.width;
  
  return preferredLocation;
 }

 /**
  * Sets the LightWeightSystem's contents to the passed tooltip, and displays the tip. The
  * tip will be displayed only if the tip source is different than the previously viewed
  * tip source. (i.e. The cursor has moved off of the previous tooltip source figure.)
  * <p>
  * The tooltip will be painted directly below the cursor if possible, otherwise it will be
  * painted directly above cursor.
  *
  * @param hoverSource the figure over which the hover event was fired
  * @param tip the tooltip to be displayed
  * @param eventX the x coordinate of the hover event
  * @param eventY the y coordinate of the hover event
  * @since 2.0
  */
 public void displayToolTipNear(IFigure hoverSource, IFigure tip, int eventX, int eventY) {
  if (tip != null && hoverSource != currentTipSource) {
   getLightweightSystem().setContents(tip);
   Point displayPoint = computeWindowLocation(tip, eventX, eventY);
   Dimension shellSize = getLightweightSystem().getRootFigure()
    .getPreferredSize().getExpanded(getShellTrimSize());
   setShellBounds(displayPoint.x, displayPoint.y, shellSize.width, shellSize.height);
   show();
   currentTipSource = hoverSource;
   timer = new Timer(true);
   timer.schedule(new TimerTask() {
    public void run() {
     Display.getDefault().syncExec(new Runnable() {
      public void run() {
       hide();
       timer.cancel();
      }
     });
    }
   }, duration);
  }
 }

 /**
  * Disposes of the tooltip's shell and kills the timer.
  *
  * @see PopUpHelper#dispose()
  */
 public void dispose() {
  if (isShowing()) {
   timer.cancel();
   hide();
  } 
  getShell().dispose();
 }

 /**
  * @see PopUpHelper#hookShellListeners()
  */
 protected void hookShellListeners() {
  // Close the tooltip window if the mouse enters the tooltip
  getShell().addMouseTrackListener(new MouseTrackAdapter() {
   public void mouseEnter(org.eclipse.swt.events.MouseEvent e) {
     hide();
     currentTipSource = null;
     timer.cancel();
   }
  });
 }

 /**
  * Displays the hover source's tooltip if a tooltip of another source is currently being
  * displayed.
  *
  * @param figureUnderMouse the figure over which the cursor was when called
  * @param tip the tooltip to be displayed
  * @param eventX the x coordinate of the cursor
  * @param eventY the y coordinate of the cursor
  * @since 2.0
  */
 public void updateToolTip(IFigure figureUnderMouse, IFigure tip, int eventX, int eventY) {
  /* If the cursor is not on any Figures, it has been moved
     off of the control. Hide the tool tip. */
  if (figureUnderMouse == null) {
   if (isShowing()) {
    hide();
    timer.cancel();
   }
  }
  // Makes tooltip appear without a hover event if a tip is currently being displayed
  if (isShowing() && figureUnderMouse != currentTipSource) {
   hide();
   timer.cancel();
   displayToolTipNear(figureUnderMouse, tip, eventX, eventY);
  } else if (!isShowing() && figureUnderMouse != currentTipSource)  
   currentTipSource = null;   
 }

 public void setDuration(long duration) {
  this.duration = duration;
 }

}

这段代码不短,但它其实可以很短,原因是作者没考虑到会有人想要继承它,以致我们无法直接覆盖displayToolTipNear方法了事,于是我干脆就把ToolTipHelper的代码全拷过来贴上。
然后,再来看SWTEventDispatcher,发现,它的这个toolTipHelper成员无法注入(没有setter),用的时候是直接在getter里new出来的;不过还好,这个getter是protected,也就是说,在设计上考虑了继承的可能性,这样代码就会简单一些了。来来来,再继承一个:

public class SWTEventDispatcherX extends SWTEventDispatcher {
 
 private ToolTipHelperX toolTipHelperX;
 
 private long tooltipDuration;
 
 public SWTEventDispatcherX(long tooltipDuration) {
  super();
  this.tooltipDuration = tooltipDuration;
 }
 
 protected ToolTipHelper getToolTipHelper() {
  if (toolTipHelperX == null) {
   toolTipHelperX = new ToolTipHelperX(control);
   toolTipHelperX.setDuration(tooltipDuration);
  }
  return toolTipHelperX;
 }
}

OK了,还剩下最后一个,传说中的LightweightSystem。这个东西好,他直接提供了SWTEventDispatcher的注入器(就是setter了,说注入器显得唬人一些),就不需要我们再做什么了,小功告成!
譬如说,现在要在一个名叫parent的Composite上放置一个FigureCanvas,做为其它Figure的容器,就可以这样写:

 LightweightSystem lws = new LightweightSystem();
 lws.setEventDispatcher(new SWTEventDispatcherX(1800000L));//半小时
 FigureCanvas canvas = new FigureCanvas(parent, SWT.DOUBLE_BUFFERED, lws);
 canvas.setContents(yourTopMostFigure);
 ...
 
 如此一来,这个FigureCanvas上的Figure的ToolTip都会持续显示半小时。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值