1

ゴール

TextEclipseコントロールの「フォーカス選択」動作を実装しようとしています。

  • コントロールがすでにフォーカスされている場合:

    • クリックとドラッグは正常に動作します
  • コントロールがフォーカスされていない場合:

    • クリックおよびドラッグしてテキストを選択すると、通常どおり動作します

    • テキストを選択せず​​にクリックすると、すべてのテキストが選択されます

    • キーボードを使用してフォーカスを与えると、すべてのテキストが選択されます

問題

  • すべてのテキストを選択するだけでSWT.FocusInは、マウス クリックでフォーカスしたときにテキストが選択されません。

  • SWT.FocusInの前 に起動されるSWT.MouseDownため、ユーザーがマウスを押したときにコントロールが既にフォーカスされているかどうかを判断する方法はありません。

質問

  1. Eclipse がその順序でイベントを起動するのはなぜですか? それは私には意味がありません。一部対応OSの制限でしょうか?

  2. この機能を実装するために使用できる回避策はありますか?

4

1 に答える 1

4

#eclipse の誰かが、ずっと前に提起された Eclipse のバグにリンクしてくれました: Can't use focus listener to select all text

そこにある提案の 1 つを使用して、次の解決策を思いつきました (Windows で動作し、他のプラットフォームではテストされていません)。

/**
 * This method adds select-on-focus functionality to a {@link Text} component.
 * 
 * Specific behavior:
 *  - when the Text is already focused -> normal behavior
 *  - when the Text is not focused:
 *    -> focus by keyboard -> select all text
 *    -> focus by mouse click -> select all text unless user manually selects text
 * 
 * @param text
 */
public static void addSelectOnFocusToText(Text text) {
  Listener listener = new Listener() {

    private boolean hasFocus = false;
    private boolean hadFocusOnMousedown = false;

    @Override
    public void handleEvent(Event e) {
      switch(e.type) {
        case SWT.FocusIn: {
          Text t = (Text) e.widget;

          // Covers the case where the user focuses by keyboard.
          t.selectAll();

          // The case where the user focuses by mouse click is special because Eclipse,
          // for some reason, fires SWT.FocusIn before SWT.MouseDown, and on mouse down
          // it cancels the selection. So we set a variable to keep track of whether the
          // control is focused (can't rely on isFocusControl() because sometimes it's wrong),
          // and we make it asynchronous so it will get set AFTER SWT.MouseDown is fired.
          t.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
              hasFocus = true;
            }
          });

          break;
        }
        case SWT.FocusOut: {
          hasFocus = false;
          ((Text) e.widget).clearSelection();

          break;
        }
        case SWT.MouseDown: {
          // Set the variable which is used in SWT.MouseUp.
          hadFocusOnMousedown = hasFocus;

          break;
        }
        case SWT.MouseUp: {
          Text t = (Text) e.widget;
          if(t.getSelectionCount() == 0 && !hadFocusOnMousedown) {
            ((Text) e.widget).selectAll();
          }

          break;
        }
      }
    }

  };

  text.addListener(SWT.FocusIn, listener);
  text.addListener(SWT.FocusOut, listener);
  text.addListener(SWT.MouseDown, listener);
  text.addListener(SWT.MouseUp, listener);
}
于 2012-04-06T20:28:07.440 に答える