实现 Eclipse Text 控件的"select on focus"行为



>Goal

我正在尝试为 Eclipse Text 控件实现"在焦点上选择"行为:

  • 当控件聚焦时:

    • 单击和拖动行为正常
  • 当控件聚焦时:

    • 单击并拖动以选择文本的行为正常

    • 单击而不选择文本将选择所有文本

    • 使用键盘给予焦点将选择所有文本

问题

  • 仅选择SWT.FocusIn的所有文本不会在通过鼠标单击聚焦时选择文本。

  • SWT.FocusInSWT.MouseDown之前触发,因此无法判断当用户按下鼠标时控件是否已具有焦点。

问题

  1. 为什么 Eclipse 会按这个顺序触发事件?这对我来说没有任何意义。这是对某些受支持的操作系统的限制吗?

  2. 是否有一些解决方法可用于实现此功能?

#eclipse 中的某个人将我链接到很久以前提出的 Eclipse 错误:无法使用焦点侦听器选择所有文本

使用那里的建议之一,我想出了以下解决方案(适用于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);
}

最新更新