/*******************************************************************************
* Copyright (c) 2016 ARM Ltd. and others
* 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.eclipse.org/legal/epl-v10.html
*
* Contributors:
* ARM Ltd and ARM Germany GmbH - Initial API and implementation
*******************************************************************************/
package com.arm.cmsis.pack.installer.ui.views;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.help.IWorkbenchHelpSystem;
import org.eclipse.ui.part.ViewPart;
import com.arm.cmsis.pack.CpPlugIn;
import com.arm.cmsis.pack.ICpPackInstaller;
import com.arm.cmsis.pack.common.CmsisConstants;
import com.arm.cmsis.pack.data.ICpItem;
import com.arm.cmsis.pack.data.ICpPack;
import com.arm.cmsis.pack.events.IRteEventListener;
import com.arm.cmsis.pack.events.RteEvent;
import com.arm.cmsis.pack.installer.ui.CpInstallerPlugInUI;
import com.arm.cmsis.pack.installer.ui.Messages;
import com.arm.cmsis.pack.installer.ui.PackInstallerViewController;
import com.arm.cmsis.pack.item.ICmsisItem;
import com.arm.cmsis.pack.ui.CpPlugInUI;
/**
* Base class for all the views in pack manager perspective
*/
public abstract class PackInstallerView extends ViewPart implements IRteEventListener, ISelectionListener {
protected static final int COLBUTTON = 1;
protected static final int COLURL = 1;
protected PackInstallerViewController fViewController;
protected FilteredTree fTree = null;
protected TreeViewer fViewer = null;
protected ViewerFilter[] fViewFilters = null;
PatternFilter fPatternFilter = null;
Action fHelpAction = null;
Action fRemoveSelection = null;
Action fExpandAction = null;
Action fExpandItemAction = null;
Action fCollapseAction = null;
Action fCollapseItemAction = null;
Action fDoubleClickAction = null;
Action fShowPackProperties = null;
static ICpItem getCpItem(Object obj) {
if (obj instanceof ICpItem) {
return (ICpItem)obj;
}
return null;
}
public PackInstallerView() {
fViewController = CpInstallerPlugInUI.getViewController();
}
@Override
public void dispose() {
//viewController.selectionChanged(this, null);
fViewController.removeListener(this);
fViewController = null;
if(getSite() != null && getSite().getPage() != null) {
getSite().getPage().removeSelectionListener(this);
}
super.dispose();
}
public ICpPackInstaller getPackInstaller() {
if(CpPlugIn.getPackManager() == null) {
return null;
}
return CpPlugIn.getPackManager().getPackInstaller();
}
protected abstract String getHelpContextId();
protected abstract void createTreeColumns();
protected abstract void refresh();
protected boolean isExpandable() {
return true;
}
protected boolean hasManagerCommands() {
return false;
}
public boolean isFilterSource() {
return false;
}
public boolean isFilterClient() {
return !isFilterSource();
}
protected ICmsisItem getSelectedItem() {
IStructuredSelection sel = (IStructuredSelection)fViewer.getSelection();
if(sel.size() == 1) {
Object o = sel.getFirstElement();
if(o instanceof ICmsisItem ){
return (ICmsisItem)o;
}
}
return null;
}
protected void hookViewSelection() {
IWorkbenchPartSite site = getSite();
if(site != null) {
if(isFilterClient() || isFilterSource()) {
site.setSelectionProvider(fViewer);
}
if(site.getPage() != null) {
site.getPage().addSelectionListener(this);
}
}
}
@Override
public void setFocus() {
fViewer.getControl().setFocus();
}
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if(part == this && fViewController !=null ) {
fViewController.selectionChanged(part, selection);
}
}
protected void handleFilterChanged() {
if(!isFilterClient()) {
return;
}
if (!fTree.getFilterControl().isDisposed()) {
fTree.getFilterControl().setText(CmsisConstants.EMPTY_STRING);
}
if (!fViewer.getControl().isDisposed()) {
fViewer.setFilters(fViewFilters);
fViewer.setSelection(null);
}
}
@Override
public void createPartControl(Composite parent) {
createViewFilters();
fTree = new FilteredTree(parent,
SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL,
fPatternFilter, true);
fViewer = fTree.getViewer();
Tree tree = fViewer.getTree();
tree.setHeaderVisible(true);
tree.setLinesVisible(true);
createTreeColumns();
refresh();
ColumnViewerToolTipSupport.enableFor(fViewer);
setHelpContext();
hookViewSelection();
makeActions();
hookContextMenu();
contributeToActionBars();
if(fViewFilters != null) {
fViewer.setFilters(fViewFilters);
}
fViewController.addListener(this);
updateOnlineState();
}
protected void createViewFilters() {
fPatternFilter = new PatternFilter() {
@Override
protected boolean isLeafMatch(final Viewer viewer, final Object element) {
TreeViewer treeViewer = (TreeViewer) viewer;
boolean isMatch = false;
ColumnLabelProvider labelProvider = (ColumnLabelProvider) treeViewer.getLabelProvider(0);
String labelText = labelProvider.getText(element);
isMatch |= wordMatches(labelText);
return isMatch;
}
};
fPatternFilter.setIncludeLeadingWildcard(true);
if(isFilterClient()) {
fViewFilters = new ViewerFilter[]{fPatternFilter, fViewController.getFilter()};
}
}
protected void setHelpContext() {
// Create the help context id for the viewer's control
IWorkbench wb = PlatformUI.getWorkbench();
if(wb == null) {
return;
}
IWorkbenchHelpSystem hs = wb.getHelpSystem();
if(hs == null) {
return;
}
hs.setHelp(fViewer.getControl(), getHelpContextId());
}
protected void makeActions() {
fHelpAction = new Action(Messages.Help, IAction.AS_PUSH_BUTTON) {
@Override
public void run() {
fViewer.getControl().notifyListeners(SWT.Help, new Event());
}
};
fHelpAction.setToolTipText(Messages.PackInstallerView_Help);
fHelpAction.setImageDescriptor( CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_HELP));
fShowPackProperties = new Action() {
@Override
public void run() {
fViewController.showPackProperties(fViewer.getSelection()); // the item should be already selected
}
};
fShowPackProperties.setText(Messages.PacksView_ShowPacksOutline);
fShowPackProperties.setToolTipText(Messages.PacksView_ShowPacksOutline);
fShowPackProperties.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_DETAILS));
if(isFilterSource()) {
fRemoveSelection = new Action() {
@Override
public void run() {
// Empty search text and selection
fViewer.setSelection(null);
fTree.getFilterControl().setText(CmsisConstants.EMPTY_STRING);
}
};
fRemoveSelection.setText(Messages.DevicesView_RemoveSelection);
fRemoveSelection.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_REMOVE_ALL));
fRemoveSelection.setToolTipText(Messages.DevicesView_RemoveSelection);
}
if(!isExpandable()) {
return;
}
// expandAction
fExpandAction = new Action() {
@Override
public void run() {
if(fViewer == null) {
return;
}
fViewer.expandAll();
}
};
fExpandAction.setText(Messages.ExpandAll);
fExpandAction.setToolTipText(Messages.ExpandAllNodes);
fExpandAction.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_EXPAND_ALL));
fExpandItemAction = new Action() {
@Override
public void run() {
if(fViewer == null) {
return;
}
ISelection selection = fViewer.getSelection();
if (selection == null) {
return;
}
Object obj = ((IStructuredSelection)selection).getFirstElement();
fViewer.expandToLevel(obj, AbstractTreeViewer.ALL_LEVELS);
}
};
fExpandItemAction.setText(Messages.ExpandSelected);
fExpandItemAction.setToolTipText(Messages.ExpandSelectedNode);
fExpandItemAction.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_EXPAND_ALL));
// collapseAction
fCollapseAction = new Action() {
@Override
public void run() {
if(fViewer == null) {
return;
}
fViewer.collapseAll();
}
};
fCollapseAction.setText(Messages.CollapseAll);
fCollapseAction.setToolTipText(Messages.CollapseAllNodes);
fCollapseAction.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_COLLAPSE_ALL));
fCollapseItemAction = new Action() {
@Override
public void run() {
if(fViewer == null) {
return;
}
ISelection selection = fViewer.getSelection();
if (selection == null) {
return;
}
Object obj = ((IStructuredSelection)selection).getFirstElement();
fViewer.collapseToLevel(obj, AbstractTreeViewer.ALL_LEVELS);
}
};
fCollapseItemAction.setText(Messages.CollapseSelected);
fCollapseItemAction.setToolTipText(Messages.CollapseSelectedNode);
fCollapseItemAction.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_COLLAPSE_ALL));
fHelpAction = new Action(Messages.Help, IAction.AS_PUSH_BUTTON) {
@Override
public void run() {
fViewer.getControl().notifyListeners(SWT.Help, new Event());
}
};
fHelpAction.setToolTipText(Messages.PackInstallerView_Help);
fHelpAction.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_HELP));
fDoubleClickAction = new Action() {
@Override
public void run() {
ISelection selection = fViewer.getSelection();
Object obj = ((IStructuredSelection)selection).getFirstElement();
if (fViewer.getExpandedState(obj)) {
fViewer.collapseToLevel(obj, AbstractTreeViewer.ALL_LEVELS);
} else if (fViewer.isExpandable(obj)) {
fViewer.expandToLevel(obj, 1);
}
}
};
fViewer.addDoubleClickListener(event -> fDoubleClickAction.run());
}
protected void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
protected void fillLocalPullDown(IMenuManager manager) {
if(isExpandable()) {
manager.add(fExpandAction);
manager.add(fCollapseAction);
}
manager.add(fHelpAction);
manager.add(new Separator());
if(isFilterSource()) {
manager.add(fRemoveSelection);
}
if(hasManagerCommands()) {
PackInstallerViewUtils.addManagementCommandsToLocalToolBar(this, manager);
}
}
protected void fillLocalToolBar(IToolBarManager manager) {
if(isExpandable()) {
manager.add(fExpandAction);
manager.add(fCollapseAction);
}
manager.add(fHelpAction);
manager.add(new Separator());
if(isFilterSource()) {
manager.add(fRemoveSelection);
}
if(hasManagerCommands()) {
PackInstallerViewUtils.addManagementCommandsToLocalToolBar(this, manager);
}
}
protected void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(manager -> fillContextMenu(manager));
Menu menu = menuMgr.createContextMenu(fViewer.getControl());
fViewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, fViewer);
}
protected void fillContextMenu(IMenuManager manager) {
if(isExpandable()) {
ICmsisItem item = getSelectedItem();
if (item == null ) {
manager.add(fExpandAction);
manager.add(fCollapseAction);
} else {
if(fViewer.isExpandable(item)) {
boolean isExpanded = fViewer.getExpandedState(item);
if(!isExpanded) {
manager.add(fExpandItemAction);
} else {
manager.add(fCollapseItemAction);
}
}
}
}
ICpPack pack = PackInstallerViewController.getPackFromSelection(fViewer.getSelection());
if(pack != null && (isFilterSource() || isFilterClient())) {
manager.add(new Separator());
manager.add(fShowPackProperties);
}
if(isFilterSource()) {
manager.add(new Separator());
manager.add(fRemoveSelection);
}
}
@Override
public void handle(RteEvent event) {
String topic = event.getTopic();
switch(topic) {
case PackInstallerViewController.INSTALLER_UI_FILTER_CHANGED:
if(isFilterClient()) {
Display.getDefault().asyncExec(() -> handleFilterChanged());
}
return;
case RteEvent.PACK_OLNLINE_STATE_CHANGED:
updateOnlineState(); // already in UI thread
return;
}
Display.getDefault().asyncExec(() -> handleRteEvent(event));
}
protected void updateOnlineState() {
if(getViewSite() == null || getViewSite().getActionBars() == null) {
return;
}
IStatusLineManager mgr = getViewSite().getActionBars().getStatusLineManager();
if(mgr == null) {
return;
}
if (isFilterClient() && fViewer != null && !fViewer.getControl().isDisposed()) {
fViewer.refresh();
}
}
protected void handleRteEvent(RteEvent event) {
switch (event.getTopic()) {
case RteEvent.PACKS_RELOADED:
refresh();
break;
case RteEvent.PACK_INSTALL_JOB_FINISHED:
case RteEvent.PACK_REMOVE_JOB_FINISHED:
case RteEvent.PACK_DELETE_JOB_FINISHED:
fViewer.refresh();
break;
default:
return;
}
}
}