Package org.rssowl.ui.internal.util

Source Code of org.rssowl.ui.internal.util.ViewerOpenStrategy

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2006 RSSOwl Development Team                                  **
**   http://www.rssowl.org/                                                 **
**                                                                          **
**   All rights reserved                                                    **
**                                                                          **
**   This program and the accompanying materials are made available under   **
**   the terms of the Eclipse Public License v1.0 which accompanies this    **
**   distribution, and is available at:                                     **
**   http://www.rssowl.org/legal/epl-v10.html                               **
**                                                                          **
**   A copy is found in the file epl-v10.html and important notices to the  **
**   license from the team is found in the textfile LICENSE.txt distributed **
**   in this package.                                                       **
**                                                                          **
**   This copyright notice MUST APPEAR in all copies of the file!           **
**                                                                          **
**   Contributors:                                                          **
**     IBM Corporation - initial API and implementation                     **
**     RSSOwl Development Team - additional API and implementation          **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.ui.internal.util;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.util.IOpenEventListener;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;

/**
* The <code>ViewerOpenStrategy</code> is a subset of the JFace
* <code>OpenStrategy</code> with some additional API.
* <p>
* TODO Remove me once Bug "[OpenModes] OpenStrategy not working properly for
* the Expand-Event" is fixed (164372).
* </p>
*
* @author bpasero
*/
public class ViewerOpenStrategy implements Listener {

  /* Default behavior. Double click to open the item. */
  private static final int DOUBLE_CLICK = 0;

  /* Single click will open the item. */
  private static final int SINGLE_CLICK = 1;

  /* Hover will select the item. */
  private static final int SELECT_ON_HOVER = 1 << 1;

  /* Open item when using arrow keys */
  private static final int ARROW_KEYS_OPEN = 1 << 2;

  /* Time used in FILE_EXPLORER and ACTIVE_DESKTOP */
  private static final int TIME = 500;

  /* Listeners */
  private ListenerList fOpenEventListeners = new ListenerList();

  /* Event Fields */
  private boolean fTimerStarted;
  private Event fMouseUpEvent;
  private Event fMouseMoveEvent;
  private SelectionEvent fSelectionPendent;
  private boolean fEnterKeyDown;
  private SelectionEvent fDefaultSelectionPendent;
  private boolean fArrowKeyDown;
  private final int[] fCount = new int[1];
  private long fStartTime = System.currentTimeMillis();
  private boolean fCollapseOccurred;
  private boolean fExpandOccurred;
  private Display fDisplay;

  /**
   * @param control the control the strategy is applied to
   */
  public ViewerOpenStrategy(Control control) {
    fDisplay = control.getDisplay();
    addListener(control);
  }

  /**
   * Adds an IOpenEventListener to the collection of openEventListeners
   *
   * @param listener the listener to add
   */
  public void addOpenListener(IOpenEventListener listener) {
    fOpenEventListeners.add(listener);
  }

  /**
   * Removes an IOpenEventListener to the collection of openEventListeners
   *
   * @param listener the listener to remove
   */
  public void removeOpenListener(IOpenEventListener listener) {
    fOpenEventListeners.remove(listener);
  }

  /**
   * Sets the expandOccurred flag back to false.
   */
  public void clearExpandFlag() {
    fExpandOccurred = false;
  }

  /*
   * Adds all needed listener to the control in order to implement
   * single-click/double-click strategies.
   */
  private void addListener(Control c) {
    c.addListener(SWT.MouseEnter, this);
    c.addListener(SWT.MouseExit, this);
    c.addListener(SWT.MouseMove, this);
    c.addListener(SWT.MouseDown, this);
    c.addListener(SWT.MouseUp, this);
    c.addListener(SWT.KeyDown, this);
    c.addListener(SWT.Selection, this);
    c.addListener(SWT.DefaultSelection, this);
    c.addListener(SWT.Collapse, this);
    c.addListener(SWT.Expand, this);
  }

  /*
   * Fire the open event to all openEventListeners
   */
  private void fireOpenEvent(SelectionEvent e) {
    if (e.item != null && e.item.isDisposed())
      return;

    Object listeners[] = fOpenEventListeners.getListeners();
    for (int i = 0; i < listeners.length; i++)
      ((IOpenEventListener) listeners[i]).handleOpen(e);
  }

  /*
   * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
   */
  public void handleEvent(final Event e) {

    /* Default Selection */
    if (e.type == SWT.DefaultSelection) {
      SelectionEvent event = new SelectionEvent(e);
      if (OpenStrategy.getOpenMethod() == DOUBLE_CLICK) {
        fireOpenEvent(event);
      } else {
        if (fEnterKeyDown) {
          fireOpenEvent(event);
          fEnterKeyDown = false;
          fDefaultSelectionPendent = null;
        } else {
          fDefaultSelectionPendent = event;
        }
      }
      return;
    }

    switch (e.type) {

      /* Mouse Enter / Exit */
      case SWT.MouseEnter:
      case SWT.MouseExit:
        fMouseUpEvent = null;
        fMouseMoveEvent = null;
        fSelectionPendent = null;
        break;

      /* Mouse Move */
      case SWT.MouseMove:
        if ((OpenStrategy.getOpenMethod() & SELECT_ON_HOVER) == 0)
          return;

        if (e.stateMask != 0)
          return;

        if (e.widget.getDisplay().getFocusControl() != e.widget)
          return;

        fMouseMoveEvent = e;
        final Runnable runnable[] = new Runnable[1];
        runnable[0] = new Runnable() {
          public void run() {
            long time = System.currentTimeMillis();
            int diff = (int) (time - fStartTime);
            if (diff <= TIME) {
              fDisplay.timerExec(diff * 2 / 3, runnable[0]);
            } else {
              fTimerStarted = false;
              setSelection(fMouseMoveEvent);
            }
          }
        };

        fStartTime = System.currentTimeMillis();
        if (!fTimerStarted) {
          fTimerStarted = true;
          fDisplay.timerExec(TIME * 2 / 3, runnable[0]);
        }
        break;

      /* Mouse Down */
      case SWT.MouseDown:
        fMouseUpEvent = null;
        fArrowKeyDown = false;
        break;

      /* TreeItem Expand */
      case SWT.Expand:
        fExpandOccurred = true;
        break;

      /* TreeItem Collapse */
      case SWT.Collapse:
        fCollapseOccurred = true;
        break;

      /* Mouse Up */
      case SWT.MouseUp:
        fMouseMoveEvent = null;
        if ((e.button != 1) || ((e.stateMask & ~SWT.BUTTON1) != 0))
          return;

        if (fSelectionPendent != null && !(fCollapseOccurred || fExpandOccurred)) {
          mouseSelectItem(fSelectionPendent);
        } else {
          fMouseUpEvent = e;
          fCollapseOccurred = false;
          fExpandOccurred = false;
        }
        break;

      /* Key Down */
      case SWT.KeyDown:
        fMouseMoveEvent = null;
        fMouseUpEvent = null;
        fArrowKeyDown = ((e.keyCode == SWT.ARROW_UP) || (e.keyCode == SWT.ARROW_DOWN)) && e.stateMask == 0;
        if (e.character == SWT.CR) {
          if (fDefaultSelectionPendent != null) {
            fireOpenEvent(new SelectionEvent(e));
            fEnterKeyDown = false;
            fDefaultSelectionPendent = null;
          } else {
            fEnterKeyDown = true;
          }
        }
        break;

      /* Selection */
      case SWT.Selection:
        SelectionEvent event = new SelectionEvent(e);
        fMouseMoveEvent = null;
        if (fMouseUpEvent != null)
          mouseSelectItem(event);
        else
          fSelectionPendent = event;

        fCount[0]++;
        final int id = fCount[0];

        if (fArrowKeyDown) {
          if (id == fCount[0]) {
            if ((OpenStrategy.getOpenMethod() & ARROW_KEYS_OPEN) != 0)
              fireOpenEvent(new SelectionEvent(e));
          }
        }
        break;
    }
  }

  void mouseSelectItem(SelectionEvent e) {
    if ((OpenStrategy.getOpenMethod() & SINGLE_CLICK) != 0)
      fireOpenEvent(e);

    fMouseUpEvent = null;
    fSelectionPendent = null;
  }

  void setSelection(Event e) {
    if (e == null)
      return;

    Widget w = e.widget;
    if (w.isDisposed())
      return;

    SelectionEvent selEvent = new SelectionEvent(e);

    /*
     * ISSUE: May have to create a interface with method: setSelection(Point p)
     * so that user's custom widgets can use this class. If we keep this option.
     */
    if (w instanceof Tree) {
      Tree tree = (Tree) w;
      TreeItem item = tree.getItem(new Point(e.x, e.y));
      if (item != null)
        tree.setSelection(new TreeItem[] { item });

      selEvent.item = item;
    } else if (w instanceof Table) {
      Table table = (Table) w;
      TableItem item = table.getItem(new Point(e.x, e.y));
      if (item != null)
        table.setSelection(new TableItem[] { item });

      selEvent.item = item;
    } else
      return;

    if (selEvent.item == null)
      return;
  }
}
TOP

Related Classes of org.rssowl.ui.internal.util.ViewerOpenStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.