Package org.rssowl.ui.internal.views.explorer

Source Code of org.rssowl.ui.internal.views.explorer.BookMarkSearchbar

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2009 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 - adapted to work with BookMark Explorer     **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.ui.internal.views.explorer;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.progress.WorkbenchJob;
import org.rssowl.ui.internal.Application;
import org.rssowl.ui.internal.ContextMenuCreator;
import org.rssowl.ui.internal.Controller;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.views.explorer.BookMarkFilter.SearchTarget;

/**
* A simple control that provides a text widget. The contents of the text widget
* are used to drive a <code>PatternFilter</code> that is part of a TreeViewer.
*
* @author bpasero
*/
class BookMarkSearchbar extends Composite {

  /* Delay before filtering takes place */
  private static final int FILTER_DELAY = 300;

  /* Action Bar */
  private static final String BAR_ACTION_ID = "org.rssowl.ui.internal.views.explorer.BarAction"; //$NON-NLS-1$

  private Composite fFilterComposite;
  private ToolBarManager fFilterToolBar;
  private Object fExpandedElements[];
  private Text fFilterText;
  private String fInitialText = ""; //$NON-NLS-1$
  private BookMarkFilter fPatternFilter;
  private Job fRefreshJob;
  private Object fSelectedElements[];
  private TreeViewer fViewer;
  private IViewSite fViewSite;

  /**
   * Create a new instance of the receiver.
   *
   * @param viewSite A link to the ViewSite this Bar is in.
   * @param parent parent <code>Composite</code>
   * @param viewer The Viewer this Filter is working for.
   * @param patternFilter The PatternFilter to use.
   */
  BookMarkSearchbar(IViewSite viewSite, Composite parent, TreeViewer viewer, BookMarkFilter patternFilter) {
    super(parent, SWT.NONE);

    fViewSite = viewSite;
    fViewer = viewer;
    fPatternFilter = patternFilter;

    createControl(parent);
    createRefreshJob();

    setFont(parent.getFont());
  }

  /* Create Toolbar with "Clear" Button */
  private void createClearText(Composite parent) {
    ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL);
    fFilterToolBar = new ToolBarManager(toolBar);
    fFilterToolBar.getControl().setBackground(parent.getBackground());
    fFilterToolBar.getControl().setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));

    /* Initially Hide */
    ((GridData) toolBar.getLayoutData()).exclude = true;
    toolBar.setVisible(false);

    IAction clearTextAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
      @Override
      public void run() {
        setFilterText(""); //$NON-NLS-1$
      }
    };

    clearTextAction.setToolTipText(Messages.BookMarkSearchbar_CLEAR);
    clearTextAction.setImageDescriptor(OwlUI.getImageDescriptor("icons/etool16/clear.gif")); //$NON-NLS-1$

    fFilterToolBar.add(clearTextAction);
  }

  /* Creates the Container for the Filter Controls */
  private void createControl(Composite parent) {
    GridLayout layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    setLayout(layout);
    setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    /* Container for Filter Controls */
    fFilterComposite = new Composite(this, SWT.NONE);
    GridLayout filterLayout = new GridLayout(Application.IS_MAC ? 2 : 3, false);
    filterLayout.marginHeight = 0;
    filterLayout.marginWidth = 0;
    filterLayout.horizontalSpacing = 3;
    fFilterComposite.setLayout(filterLayout);
    fFilterComposite.setFont(parent.getFont());
    fFilterComposite.setBackground(parent.getBackground());

    /* Create Filter Controls */
    createFilterControls(fFilterComposite);
    fFilterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    fFilterComposite.setBackground(parent.getBackground());

    /* Set height as required */
    if (fFilterToolBar != null) {
      int prefContainerHeight = fFilterComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
      int prefToolbarHeight = fFilterToolBar.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
      if (prefToolbarHeight >= prefContainerHeight)
        ((GridData) fFilterComposite.getLayoutData()).heightHint = prefToolbarHeight;
    }
  }

  /* Create Label, Input Field and ToolBar */
  private Composite createFilterControls(Composite parent) {
    createFilterTarget(parent);
    createFilterText(parent);
    if (!Application.IS_MAC)
      createClearText(parent);

    if (fFilterToolBar != null) {
      fFilterToolBar.update(false);
      fFilterToolBar.getControl().setVisible(false);
    }
    return parent;
  }

  /* ToolBar to control SearchTarget */
  private void createFilterTarget(Composite parent) {
    final ToolBarManager filterTargetManager = new ToolBarManager(SWT.FLAT);

    IAction filterTargetAction = new Action("", IAction.AS_DROP_DOWN_MENU) { //$NON-NLS-1$
      @Override
      public void run() {
        OwlUI.positionDropDownMenu(this, filterTargetManager);
      }

      @Override
      public String getId() {
        return BAR_ACTION_ID;
      }
    };

    filterTargetAction.setMenuCreator(new ContextMenuCreator() {

      @Override
      public Menu createMenu(Control parent) {
        Menu menu = new Menu(parent);

        /* Search on: Name */
        final MenuItem searchName = new MenuItem(menu, SWT.RADIO);
        searchName.setText(Messages.BookMarkSearchbar_NAME);
        searchName.setSelection(BookMarkFilter.SearchTarget.NAME == fPatternFilter.getSearchTarget());
        searchName.addSelectionListener(new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (searchName.getSelection() && fPatternFilter.getSearchTarget() != BookMarkFilter.SearchTarget.NAME)
              doSearch(BookMarkFilter.SearchTarget.NAME);
          }
        });

        /* Search on: Link */
        final MenuItem searchLink = new MenuItem(menu, SWT.RADIO);
        searchLink.setText(Messages.BookMarkSearchbar_LINK);
        searchLink.setSelection(BookMarkFilter.SearchTarget.LINK == fPatternFilter.getSearchTarget());
        searchLink.addSelectionListener(new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (searchLink.getSelection() && fPatternFilter.getSearchTarget() != BookMarkFilter.SearchTarget.LINK)
              doSearch(BookMarkFilter.SearchTarget.LINK);
          }
        });

        return menu;
      }
    });

    filterTargetAction.setImageDescriptor(OwlUI.getImageDescriptor("icons/etool16/find.gif")); //$NON-NLS-1$
    filterTargetManager.add(filterTargetAction);

    filterTargetManager.createControl(parent);
    filterTargetManager.getControl().setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));
  }

  private void doSearch(SearchTarget target) {
    fPatternFilter.setSearchTarget(target);
    fFilterText.setFocus();

    /* Set Message */
    if (fPatternFilter.getSearchTarget() == SearchTarget.NAME)
      fFilterText.setMessage(Messages.BookMarkSearchbar_NAME);
    else
      fFilterText.setMessage(Messages.BookMarkSearchbar_LINK);

    if (fFilterText.getText().length() > 0)
      textChanged();
  }

  /* Input Field for typing into the Filter */
  private void createFilterText(Composite parent) {
    fFilterText = new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.CANCEL);
    fFilterText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));

    /* Set Message */
    if (fPatternFilter.getSearchTarget() == SearchTarget.NAME)
      fFilterText.setMessage(Messages.BookMarkSearchbar_NAME);
    else
      fFilterText.setMessage(Messages.BookMarkSearchbar_LINK);

    /* Register this Input Field to Context Service */
    Controller.getDefault().getContextService().registerInputField(fFilterText);

    /* Override Accessible */
    fFilterText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
      @Override
      public void getName(AccessibleEvent e) {
        String filterTextString = fFilterText.getText();
        if (filterTextString.length() == 0)
          e.result = fInitialText;
        else
          e.result = filterTextString;
      }
    });

    /* Select All on Focus if input matches Initial Text */
    fFilterText.addFocusListener(new FocusAdapter() {
      @Override
      public void focusGained(FocusEvent e) {
        JobRunner.runInUIThread(0, true, fFilterText, new Runnable() {
          public void run() {
            if (fInitialText.equals(fFilterText.getText().trim()))
              fFilterText.selectAll();
          }
        });

        /* Enable some Edit Actions */
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.CUT.getId()).setEnabled(true);
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.COPY.getId()).setEnabled(true);
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.PASTE.getId()).setEnabled(true);
      }

      @Override
      public void focusLost(FocusEvent e) {

        /* Disable some Edit Actions */
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.CUT.getId()).setEnabled(false);
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.COPY.getId()).setEnabled(false);
        fViewSite.getActionBars().getGlobalActionHandler(ActionFactory.PASTE.getId()).setEnabled(false);
      }
    });

    /* Focus Tree on Arrow Up or Down */
    fFilterText.addKeyListener(new KeyAdapter() {
      @Override
      public void keyPressed(KeyEvent e) {

        /* Pressed ESC */
        if (e.character == SWT.ESC) {
          setFilterText(""); //$NON-NLS-1$
          fViewer.getTree().setFocus();
          return;
        }

        /* Pressed Arrow Down or Up */
        boolean hasItems = fViewer.getTree().getItemCount() > 0;
        if (hasItems && (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.ARROW_UP))
          fViewer.getTree().setFocus();
        else if (e.character == SWT.CR)
          return;
      }
    });

    /* Handle the CR Key Pressed */
    fFilterText.addTraverseListener(new TraverseListener() {
      public void keyTraversed(TraverseEvent e) {
        if (e.detail == SWT.TRAVERSE_RETURN) {
          e.doit = false;

          /* Results available */
          if (fViewer.getTree().getItemCount() > 0) {
            boolean hasFocus = fViewer.getTree().setFocus();
            boolean textChanged = !fInitialText.equals(fFilterText.getText().trim());

            /* Select the first matching Item */
            if (hasFocus && textChanged && fFilterText.getText().trim().length() > 0) {
              TreeItem item = getFirstMatchingItem(fViewer.getTree().getItems());
              if (item != null) {
                fViewer.getTree().setSelection(new TreeItem[] { item });
                ISelection sel = fViewer.getSelection();
                fViewer.setSelection(sel, true);
              }
            }
          }
        }
      }
    });

    /* Update Filter on Modified Input */
    fFilterText.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        textChanged();
      }
    });
  }

  /* Create the Job that refreshes the TreeViewer */
  private void createRefreshJob() {
    fRefreshJob = new WorkbenchJob("") {//$NON-NLS-1$
      @Override
      public IStatus runInUIThread(IProgressMonitor monitor) {

        /* Tree Disposed */
        if (fViewer.getControl().isDisposed())
          return Status.CANCEL_STATUS;

        /* Get the Filter Pattern */
        String text = fFilterText != null ? fFilterText.getText() : null;
        if (text == null)
          return Status.OK_STATUS;

        /* Check if the Initial Text was set */
        boolean initial = fInitialText != null && fInitialText.equals(text);
        if (initial)
          fPatternFilter.setPattern(null);
        else
          fPatternFilter.setPattern(text);

        try {
          fViewer.getControl().getParent().setRedraw(false);

          /* Remember Expanded Elements if not yet done */
          if (fExpandedElements == null)
            fExpandedElements = fViewer.getExpandedElements();

          /* Remember Selected Elements if present */
          IStructuredSelection sel = (IStructuredSelection) fViewer.getSelection();
          if (!sel.isEmpty())
            fSelectedElements = sel.toArray();

          /* Refresh Tree */
          BusyIndicator.showWhile(getDisplay(), new Runnable() {
            public void run() {
              fViewer.refresh(false);
            }
          });

          /* Restore Expanded Elements and Selection when Filter is disabled */
          if (text.length() == 0) {

            /* Restore Expansion */
            fViewer.collapseAll();
            for (Object element : fExpandedElements) {
              fViewer.setExpandedState(element, true);
            }

            /* Restore Selection */
            if (fSelectedElements != null)
              fViewer.setSelection(new StructuredSelection(fSelectedElements), true);

            /* Clear Fields */
            fExpandedElements = null;
            fSelectedElements = null;
          }

          /*
           * Expand elements one at a time. After each is expanded, check to see
           * if the filter text has been modified. If it has, then cancel the
           * refresh job so the user doesn't have to endure expansion of all the
           * nodes.
           */
          if (text.length() > 0 && !initial) {
            IStructuredContentProvider provider = (IStructuredContentProvider) fViewer.getContentProvider();
            Object[] elements = provider.getElements(fViewer.getInput());
            for (Object element : elements) {
              if (monitor.isCanceled())
                return Status.CANCEL_STATUS;

              fViewer.expandToLevel(element, AbstractTreeViewer.ALL_LEVELS);
            }

            /* Make Sure to show the First Item */
            TreeItem[] items = fViewer.getTree().getItems();
            if (items.length > 0)
              fViewer.getTree().showItem(items[0]);

            /* Enable Toolbar to allow resetting the Filter */
            setToolBarVisible(true);
          }

          /* Disable Toolbar - No Filter is currently activated */
          else {
            setToolBarVisible(false);
          }
        }

        /* Done updating the tree - set redraw back to true */
        finally {
          fViewer.getControl().getParent().setRedraw(true);
        }

        return Status.OK_STATUS;
      }
    };
    fRefreshJob.setSystem(true);

    /* Cancel the Job once the Tree got disposed */
    fViewer.getControl().addDisposeListener(new DisposeListener() {
      public void widgetDisposed(org.eclipse.swt.events.DisposeEvent e) {
        fRefreshJob.cancel();
      };
    });
  }

  Text getControl() {
    return fFilterText;
  }

  TreeItem getFirstMatchingItem(TreeItem[] items) {
    for (TreeItem element : items) {
      if (fPatternFilter.isLeafMatch(fViewer, element.getData()) && fPatternFilter.isElementSelectable(element.getData()))
        return element;

      return getFirstMatchingItem(element.getItems());
    }
    return null;
  }

  void setFilterText(String string) {
    if (fFilterText != null) {
      fFilterText.setText(string);
      fFilterText.selectAll();
    }
  }

  void textChanged() {
    fRefreshJob.cancel();
    fRefreshJob.schedule(fFilterText.getText().length() != 0 ? FILTER_DELAY : 0);
  }

  void setToolBarVisible(boolean visible) {
    if (fFilterToolBar != null && ((GridData) fFilterToolBar.getControl().getLayoutData()).exclude == visible) {
      ((GridData) fFilterToolBar.getControl().getLayoutData()).exclude = !visible;
      fFilterToolBar.getControl().setVisible(visible);
      fFilterComposite.layout();
    }
  }
}
TOP

Related Classes of org.rssowl.ui.internal.views.explorer.BookMarkSearchbar

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.