Tooltipに関するエトセトラ

ToolTipに設定した文字列って自動改行されずに困っていました。長い文字列を入れるとてろてろ〜んと画面をぶち抜いてどこへやら…。となるでしょう。でもデフォルトの実装に期待しちゃいけないのがEclipseWayだということに最近気づいてきました。
デフォルトで提供されるToolTipクラスはorg.eclipse.jface.window.DefaultToolTipクラスです。ToolTip#createToolTipContentArea(Event,Composite)というメソッドで内部のWidgetが作成されます。引数のCompositeはデフォルトではSWT.Toolがスタイルに指定されたShellが渡ってきます。このShellのLayoutはFillLayoutが指定されています。僕はFillLayoutが指定されている場合、内部Widgetのサイズを指定する術を知りません。*1なので大抵の場合はGridLayoutをLayoutに指定したCompositeでラップします。ラップしたCompositeを使ってWidgetにGridDataを指定してサイズのhintを与えるようにしてます。
デフォルト実装ではToolTipを表示するWidgetとしてorg.eclipse.swt.CLabelクラスを使用しています。CLabelクラスはLabelのカスタムクラスと思いきや、中を見てみるとCanvasクラスを継承したクラスで、Widgetと言うよりは特殊な警告などを表示するようの画面描画用のWidgetです。CLabelにGridDataを使ってhintを与えても画面描画用のWidgetなので途中で三点リーダ(…)が表示されるだけでうまく改行してくれません。
そんな感じなので、createToolTipContentArea(Event,Composite)をこんな風に実装しました。

  @Override
  protected Composite createToolTipContentArea(Event event, Composite parent) {
    Image image = getImage(event);
    Image bgImage = getBackgroundImage(event);
    String text = getText(event);
    Color fgColor = getForegroundColor(event);
    Color bgColor = getBackgroundColor(event);
    Font font = getFont(event);

    Composite comp = new Composite(parent,SWT.NONE);
    GridLayoutFactory.fillDefaults().applyTo(comp);
    
    Label label = new Label(comp,SWT.WRAP);
    text = text != null ? text.trim() : null;
    label.setText(text);
    
    if(fgColor != null){
      label.setForeground(fgColor);
    }
    
    if(bgColor != null){
      label.setBackground(bgColor);
    }
    
    if(image != null){
      label.setImage(image);
    }
    
    if(bgImage != null){
      label.setBackgroundImage(bgImage);
    }

    int width = 400;
    int height = 80;
    if(font != null){
      label.setFont(font);
      GC gc = new GC(Display.getDefault());
      gc.setFont(font);
      height = gc.getFontMetrics().getHeight() * 8;
      gc.dispose();
    }
    GridDataFactory.fillDefaults().hint(width,height).applyTo(label);
    return comp;

FontMetricsを使って、8行分表示させてます。幅の文字数を指定していないのは、等幅フォントを使っているとは限らないためです。

今日もニッチなネタでせめてみました。

*1:より良い方法が分かり次第またBlogを書きます