Package org.rssowl.ui.internal.util

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

/*   **********************************************************************  **
**   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:                                                          **
**     RSSOwl Development Team - initial API and implementation             **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.ui.internal.util;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.persist.pref.DefaultPreferences;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.event.FolderAdapter;
import org.rssowl.core.persist.event.FolderEvent;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.actions.NewFolderAction;
import org.rssowl.ui.internal.views.explorer.BookMarkLabelProvider;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
* The <code>FolderChooser</code> allows to select a <code>IFolder</code>. It
* provides an expandable Tree-Viewer to display all folders which is initially
* collapsed.
*
* @author bpasero
*/
public class FolderChooser extends Composite implements DisposeListener {

  /* Delay in ms before updating Selection on Events */
  private static final int SELECTION_DELAY = 20;

  /* Default Height in Items */
  private static final int DEFAULT_ITEM_HEIGHT = 10;

  private Composite fParent;
  private IFolder fSelectedFolder;
  private ResourceManager fResources;
  private Composite fFolderViewerContainer;
  private ToolItem fToggleItem;
  private TreeViewer fFolderViewer;
  private Label fFolderIcon;
  private Label fFolderName;
  private int fViewerHeight;
  private FolderAdapter fFolderListener;
  private ToolBar fAddFolderBar;
  private List<IFolder> fExcludes;
  private final boolean fExpandable;
  private int fItemHeight;
  private ExpandStrategy fExpandStrategy = ExpandStrategy.RESIZE;

  /** The strategy when expanding the Control */
  public enum ExpandStrategy {

    /** Pack the Parent */
    PACK,

    /** Resize the Parent */
    RESIZE;
  }

  /**
   * @param parent
   * @param initial
   * @param style
   * @param expandable
   */
  public FolderChooser(Composite parent, IFolder initial, int style, boolean expandable) {
    this(parent, initial, null, style, expandable);
  }

  /**
   * @param parent
   * @param initial
   * @param excludes
   * @param style
   * @param expandable
   */
  public FolderChooser(Composite parent, IFolder initial, List<IFolder> excludes, int style, boolean expandable) {
    this(parent, initial, excludes, style, expandable, DEFAULT_ITEM_HEIGHT);
  }

  /**
   * @param parent
   * @param initial
   * @param excludes
   * @param style
   * @param expandable
   * @param itemHeight
   */
  public FolderChooser(Composite parent, IFolder initial, List<IFolder> excludes, int style, boolean expandable, int itemHeight) {
    super(parent, style);
    fParent = parent;
    fSelectedFolder = initial;
    fExcludes = excludes;
    fExpandable = expandable;
    fItemHeight = itemHeight;
    fResources = new LocalResourceManager(JFaceResources.getResources(), parent);

    initComponents();
    addDisposeListener(this);
  }

  /**
   * @return Returns the <code>IFolder</code> that has been selected.
   */
  public IFolder getFolder() {
    return fSelectedFolder;
  }

  /**
   * @param expandStrategy the strategy when expanding the Control (either
   * {@link ExpandStrategy#PACK} or {@link ExpandStrategy#RESIZE}.
   */
  public void setExpandStrategy(ExpandStrategy expandStrategy) {
    fExpandStrategy = expandStrategy;
  }

  /*
   * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
   */
  public void widgetDisposed(DisposeEvent e) {
    unregisterListeners();
  }

  private void registerListeners() {
    fFolderListener = new FolderAdapter() {
      @Override
      public void entitiesUpdated(final Set<FolderEvent> events) {
        if (events.isEmpty())
          return;

        /* Refresh and show added Folder */
        JobRunner.runInUIThread(fFolderViewer.getControl(), new Runnable() {
          public void run() {
            fFolderViewer.refresh();
            FolderEvent event = events.iterator().next();
            expand(event.getEntity());
          }
        });
      }

      @Override
      public void entitiesAdded(final Set<FolderEvent> events) {
        if (events.isEmpty())
          return;

        /* Select added Folder */
        JobRunner.runInUIThread(SELECTION_DELAY, fFolderViewer.getControl(), new Runnable() {
          public void run() {
            FolderEvent event = events.iterator().next();
            fFolderViewer.setSelection(new StructuredSelection(event.getEntity()));
          }
        });
      }
    };

    DynamicDAO.addEntityListener(IFolder.class, fFolderListener);
  }

  private void expand(IFolder folder) {
    IFolder parent = folder.getParent();
    if (parent != null)
      expand(parent);

    fFolderViewer.setExpandedState(folder, true);
  }

  private void unregisterListeners() {
    DynamicDAO.removeEntityListener(IFolder.class, fFolderListener);
  }

  private void initComponents() {
    Composite headerContainer = new Composite(this, SWT.None);
    headerContainer.setLayout(LayoutUtils.createGridLayout(3, 0, 0));
    ((GridLayout) headerContainer.getLayout()).marginLeft = 3;
    headerContainer.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    headerContainer.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    if (fExpandable) {
      headerContainer.setCursor(fParent.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
      headerContainer.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseDown(MouseEvent e) {
          onToggle();
          notifyListeners(SWT.Selection, new Event());
        }
      });
    }

    fFolderIcon = new Label(headerContainer, SWT.None);
    fFolderIcon.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));
    fFolderIcon.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    if (fExpandable) {
      fFolderIcon.setCursor(fParent.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
      fFolderIcon.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseDown(MouseEvent e) {
          onToggle();
          notifyListeners(SWT.Selection, new Event());
        }
      });
    }

    fFolderName = new Label(headerContainer, SWT.None);
    fFolderName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    fFolderName.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    if (fExpandable) {
      fFolderName.setCursor(fParent.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
      fFolderName.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseDown(MouseEvent e) {
          onToggle();
          notifyListeners(SWT.Selection, new Event());
        }
      });
    }

    Composite toolbarContainer = new Composite(headerContainer, SWT.NONE);
    toolbarContainer.setLayout(LayoutUtils.createGridLayout(2, 0, 0, 0, 1, false));
    toolbarContainer.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, true));
    toolbarContainer.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    fAddFolderBar = new ToolBar(toolbarContainer, SWT.FLAT);
    OwlUI.makeAccessible(fAddFolderBar, Messages.FolderChooser_NEW_FOLDER);
    fAddFolderBar.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, true));
    fAddFolderBar.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
    fAddFolderBar.setCursor(headerContainer.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
    fAddFolderBar.setVisible(!fExpandable);

    ToolItem addFolderItem = new ToolItem(fAddFolderBar, SWT.PUSH);
    addFolderItem.setImage(OwlUI.getImage(fResources, "icons/etool16/add_crop.gif")); //$NON-NLS-1$
    addFolderItem.setToolTipText(Messages.FolderChooser_NEW_FOLDER);
    addFolderItem.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onNewFolder();
        notifyListeners(SWT.Selection, new Event());
      }
    });

    ToolBar toggleBar = new ToolBar(toolbarContainer, SWT.FLAT);
    OwlUI.makeAccessible(toggleBar, Messages.FolderChooser_SHOW_FOLDERS);
    toggleBar.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, true));
    ((GridData) toggleBar.getLayoutData()).exclude = !fExpandable;
    toggleBar.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
    toggleBar.setCursor(headerContainer.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));

    fToggleItem = new ToolItem(toggleBar, SWT.PUSH);
    fToggleItem.setImage(OwlUI.getImage(fResources, "icons/ovr16/arrow_down.gif")); //$NON-NLS-1$
    fToggleItem.setToolTipText(Messages.FolderChooser_SHOW_FOLDERS);
    fToggleItem.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onToggle();
        notifyListeners(SWT.Selection, new Event());
      }
    });

    fFolderViewerContainer = new Composite(this, SWT.None);
    fFolderViewerContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0, 2, 0, false));
    fFolderViewerContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    fFolderViewerContainer.setBackground(fParent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    Label separator = new Label(fFolderViewerContainer, SWT.SEPARATOR | SWT.HORIZONTAL);
    separator.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

    fFolderViewer = new TreeViewer(fFolderViewerContainer, SWT.None);
    fFolderViewer.setAutoExpandLevel(2);
    fFolderViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    fFolderViewer.getTree().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object());

    fViewerHeight = fFolderViewer.getTree().getItemHeight() * fItemHeight + 12;
    ((GridData) fFolderViewerContainer.getLayoutData()).heightHint = fViewerHeight;
    ((GridData) fFolderViewerContainer.getLayoutData()).exclude = fExpandable;

    /* Sort by Name if set so */
    if (Owl.getPreferenceService().getGlobalScope().getBoolean(DefaultPreferences.BE_SORT_BY_NAME)) {
      fFolderViewer.setComparator(new ViewerComparator() {
        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
          IFolder f1 = (IFolder) e1;
          IFolder f2 = (IFolder) e2;

          return f1.getName().compareTo(f2.getName());
        }
      });
    }

    /* Filter excluded Folders */
    fFolderViewer.addFilter(new ViewerFilter() {
      @Override
      public boolean select(Viewer viewer, Object parentElement, Object element) {
        if (fExcludes == null)
          return true;

        return !fExcludes.contains(element) && !fExcludes.contains(parentElement);
      }
    });

    fFolderViewer.setContentProvider(new ITreeContentProvider() {
      public Object[] getElements(Object inputElement) {
        Collection<IFolder> rootFolders = CoreUtils.loadRootFolders();
        return rootFolders.toArray();
      }

      public Object[] getChildren(Object parentElement) {
        if (parentElement instanceof IFolder) {
          IFolder folder = (IFolder) parentElement;
          return folder.getFolders().toArray();
        }

        return new Object[0];
      }

      public Object getParent(Object element) {
        if (element instanceof IFolder) {
          IFolder folder = (IFolder) element;
          return folder.getParent();
        }

        return null;
      }

      public boolean hasChildren(Object element) {
        if (element instanceof IFolder) {
          IFolder folder = (IFolder) element;
          return !folder.getFolders().isEmpty();
        }

        return false;
      }

      public void dispose() {}

      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
    });

    boolean usedInDialog = (fParent.getShell().getParent() != null);
    fFolderViewer.setLabelProvider(new BookMarkLabelProvider(false, usedInDialog));
    fFolderViewer.setInput(new Object());

    fFolderViewer.addSelectionChangedListener(new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
        if (!selection.isEmpty())
          onFolderSelected((IFolder) selection.getFirstElement());
        notifyListeners(SWT.Selection, new Event());
      }
    });

    fFolderViewer.addDoubleClickListener(new IDoubleClickListener() {
      public void doubleClick(DoubleClickEvent event) {
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
        IFolder folder = (IFolder) selection.getFirstElement();

        /* Expand / Collapse Folder */
        if (!folder.getFolders().isEmpty()) {
          boolean expandedState = !fFolderViewer.getExpandedState(folder);
          fFolderViewer.setExpandedState(folder, expandedState);
        }

        /* Select Folder and toggle */
        else if (fExpandable) {
          onToggle();
        }
      }
    });

    /* Select the input Folder and expand */
    fFolderViewer.setSelection(new StructuredSelection(fSelectedFolder));
    fFolderViewer.setExpandedState(fSelectedFolder, true);

    /* Add Menu: "New Folder" */
    MenuManager menuManager = new MenuManager();
    menuManager.add(new Action(Messages.FolderChooser_NEW_FOLDER) {
      @Override
      public void run() {
        onNewFolder();
      }
    });

    Menu menu = menuManager.createContextMenu(fFolderViewer.getTree());
    fFolderViewer.getTree().setMenu(menu);

    /* Register Model Listeners */
    registerListeners();
  }

  private void onNewFolder() {

    /* Make sure Folder-List is visible */
    if (((GridData) fFolderViewerContainer.getLayoutData()).exclude && fExpandable)
      onToggle();

    /* Create new Folder */
    IStructuredSelection selection = (IStructuredSelection) fFolderViewer.getSelection();
    NewFolderAction action = new NewFolderAction(fFolderViewer.getTree().getShell(), (IFolder) selection.getFirstElement(), null);
    action.run(null);
  }

  private void onFolderSelected(IFolder folder) {
    fSelectedFolder = folder;
    fFolderIcon.setImage(OwlUI.getImage(fResources, folder));
    fFolderName.setText(folder.getName());
  }

  private void onToggle() {
    boolean excluded = ((GridData) fFolderViewerContainer.getLayoutData()).exclude;

    fToggleItem.setImage(OwlUI.getImage(fResources, excluded ? "icons/ovr16/arrow_up.gif" : "icons/ovr16/arrow_down.gif")); //$NON-NLS-1$ //$NON-NLS-2$
    fToggleItem.setToolTipText(excluded ? Messages.FolderChooser_HIDE_FOLDERS : Messages.FolderChooser_SHOW_FOLDERS);

    ((GridData) fFolderViewerContainer.getLayoutData()).exclude = !excluded;
    Shell shell = fFolderViewerContainer.getShell();
    shell.layout();

    fAddFolderBar.setVisible(excluded);

    /* Increase Size of Shell to fit Control */
    if (fExpandStrategy == ExpandStrategy.RESIZE) {
      Point size = shell.getSize();
      shell.setSize(size.x, size.y + (excluded ? fViewerHeight : -fViewerHeight));
    }

    /* Pack Shell and expect enough room to fit the Control */
    else {
      int currentWidth = shell.getSize().x;
      Point desiredSize = shell.computeSize(currentWidth, SWT.DEFAULT);
      if (desiredSize.y > shell.getSize().y)
        shell.setSize(currentWidth, desiredSize.y);
      else
        shell.layout(true, true);
    }

    if (excluded)
      fFolderViewer.getTree().setFocus();
    else
      fFolderViewer.getTree().getShell().setFocus();
  }
}
TOP

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

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.