blob: 5ed795d0c129424d0e4ea42b196cecfdc9785d67 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014-2015 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.ui.handler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventObject;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
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.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.tcf.te.core.interfaces.IConnectable;
import org.eclipse.tcf.te.runtime.concurrent.util.ExecutorsUtil;
import org.eclipse.tcf.te.runtime.events.ChangeEvent;
import org.eclipse.tcf.te.runtime.events.EventManager;
import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener;
import org.eclipse.tcf.te.runtime.services.ServiceManager;
import org.eclipse.tcf.te.tcf.locator.interfaces.IPeerModelListener;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode;
import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProperties;
import org.eclipse.tcf.te.tcf.locator.interfaces.services.IDefaultContextService;
import org.eclipse.tcf.te.tcf.locator.model.ModelManager;
import org.eclipse.tcf.te.tcf.locator.utils.CommonUtils;
import org.eclipse.tcf.te.tcf.ui.activator.UIPlugin;
import org.eclipse.tcf.te.tcf.ui.internal.ImageConsts;
import org.eclipse.tcf.te.tcf.ui.internal.preferences.IPreferenceKeys;
import org.eclipse.tcf.te.tcf.ui.nls.Messages;
import org.eclipse.tcf.te.ui.swt.SWTControlUtil;
import org.eclipse.tcf.te.ui.views.ViewsUtil;
import org.eclipse.tcf.te.ui.views.handler.OpenEditorHandler;
import org.eclipse.tcf.te.ui.views.navigator.DelegatingLabelProvider;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.menus.IWorkbenchContribution;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import org.eclipse.ui.services.IServiceLocator;
/**
* Configurations control implementation.
*/
public class DefaultContextSelectorToolbarContribution extends WorkbenchWindowControlContribution
implements IWorkbenchContribution, IEventListener, IPeerModelListener, IPropertyChangeListener {
private static final String WARNING_BACKGROUND_FG_COLOR_NAME = "org.eclipse.ui.themes.matchColors.toolbarWarningBackground"; //$NON-NLS-1$
private Composite panel = null;
private Composite labelPanel = null;
private Label image = null;
private Label text = null;
private Button button = null;
IServiceLocator serviceLocator = null;
private MenuManager menuMgr = null;
private Menu menu = null;
private boolean clickRunning = false;
private final RGB lightYellowRgb = new RGB(255, 250, 150); // Warning background color
/* default */ Color lightYellowColor = null;
private enum PanelStyle {DEFAULT,WARNING} // Color styles
/* default */ Color warningBackgroundColor = null;
/**
* Constructor.
*/
public DefaultContextSelectorToolbarContribution() {
this("org.eclipse.tcf.te.tcf.ui.DefaultContextSelectorToolbarContribution"); //$NON-NLS-1$
PlatformUI.getPreferenceStore().addPropertyChangeListener(this);
JFaceResources.getColorRegistry().addListener(this);
}
/**
* Constructor.
*
* @param id
*/
public DefaultContextSelectorToolbarContribution(String id) {
super(id);
PlatformUI.getPreferenceStore().addPropertyChangeListener(this);
JFaceResources.getColorRegistry().addListener(this);
}
/* (non-Javadoc)
* @see org.eclipse.ui.menus.IWorkbenchContribution#initialize(org.eclipse.ui.services.IServiceLocator)
*/
@Override
public void initialize(IServiceLocator serviceLocator) {
this.serviceLocator = serviceLocator;
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.ControlContribution#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createControl(final Composite parent) {
panel = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 1; layout.marginWidth = 1;
panel.setLayout(layout);
// Create the warning background color
lightYellowColor = new Color(PlatformUI.getWorkbench().getDisplay(), lightYellowRgb);
// Add a dispose listener to the panel to also dispose the color resource
panel.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
lightYellowColor.dispose();
lightYellowColor = null;
}
});
initThemeColors();
labelPanel = new Composite(panel, SWT.BORDER);
labelPanel.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_WHITE));
GridData layoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
labelPanel.setLayoutData(layoutData);
layout = new GridLayout(3, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.horizontalSpacing = 0;
labelPanel.setLayout(layout);
image = new Label(labelPanel, SWT.NONE);
layoutData = new GridData(SWT.LEAD, SWT.CENTER, false, true);
layoutData.horizontalIndent = 1;
layoutData.minimumWidth=20;
layoutData.widthHint=20;
image.setLayoutData(layoutData);
image.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseUp(MouseEvent e) {
onButtonClick();
}
});
text = new Label(labelPanel, SWT.NONE);
layoutData = new GridData(SWT.FILL, SWT.CENTER, true, true);
layoutData.minimumWidth = SWTControlUtil.convertWidthInCharsToPixels(text, 25);
text.setLayoutData(layoutData);
text.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseUp(MouseEvent e) {
IPeerNode peerNode = ServiceManager.getInstance().getService(IDefaultContextService.class).getDefaultContext(null);
if (peerNode != null && (e.stateMask & SWT.MODIFIER_MASK) != 0 && (e.stateMask & SWT.CTRL) == SWT.CTRL && (e.stateMask & SWT.SHIFT) == SWT.SHIFT) {
OpenEditorHandler.openEditorOnSelection(getWorkbenchWindow(), new StructuredSelection(peerNode));
return;
}
onButtonClick();
}
});
button = new Button(labelPanel, SWT.ARROW | SWT.DOWN | SWT.FLAT | SWT.NO_FOCUS);
layoutData = new GridData(SWT.TRAIL, SWT.CENTER, false, true);
layoutData.minimumWidth=20;
layoutData.widthHint = 20;
button.setLayoutData(layoutData);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onButtonClick();
}
});
EventManager.getInstance().addEventListener(this, ChangeEvent.class);
ModelManager.getPeerModel().addListener(this);
update();
return panel;
}
private void initThemeColors() {
// Get colors from Theme preferences
warningBackgroundColor = JFaceResources.getColorRegistry().get(WARNING_BACKGROUND_FG_COLOR_NAME);
if (warningBackgroundColor == null) {
JFaceResources.getColorRegistry().put(WARNING_BACKGROUND_FG_COLOR_NAME, lightYellowRgb);
warningBackgroundColor = JFaceResources.getColorRegistry().get(WARNING_BACKGROUND_FG_COLOR_NAME);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.ContributionItem#dispose()
*/
@Override
public void dispose() {
super.dispose();
EventManager.getInstance().removeEventListener(this);
ModelManager.getPeerModel().removeListener(this);
image.dispose();
text.dispose();
if (menuMgr != null) menuMgr.dispose();
image = null;
text = null;
}
private IPeerNode[] getPeerNodesSorted() {
IPeerNode[] peerNodes = ModelManager.getPeerModel().getPeerNodes();
List<IPeerNode> visiblePeerNodes = new ArrayList<IPeerNode>();
for (IPeerNode peerNode : peerNodes) {
if (peerNode.isVisible()) {
visiblePeerNodes.add(peerNode);
}
}
Collections.sort(visiblePeerNodes, new Comparator<IPeerNode>() {
@Override
public int compare(IPeerNode o1, IPeerNode o2) {
String type1 = o1.getPeerType();
type1 = type1 != null ? type1 : ""; //$NON-NLS-1$
String type2 = o2.getPeerType();
type2 = type2 != null ? type2 : ""; //$NON-NLS-1$
int typeCompare = type1.compareTo(type2);
return typeCompare != 0 ? typeCompare : o1.getName().toUpperCase().compareTo(o2.getName().toUpperCase());
}
});
return visiblePeerNodes.toArray(new IPeerNode[visiblePeerNodes.size()]);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.ContributionItem#update()
*/
@Override
public void update() {
if (menuMgr != null) menuMgr.markDirty();
if (image != null && text != null) {
IPeerNode peerNode = ServiceManager.getInstance().getService(IDefaultContextService.class).getDefaultContext(null);
if (peerNode == null) {
IPeerNode[] peerNodes = getPeerNodesSorted();
if (peerNodes != null && peerNodes.length > 0) {
peerNode = peerNodes[0];
ServiceManager.getInstance().getService(IDefaultContextService.class).setDefaultContext(peerNode);
return;
}
}
changePanelStyle(PanelStyle.DEFAULT);
if (peerNode != null) {
DelegatingLabelProvider labelProvider = new DelegatingLabelProvider();
image.setImage(labelProvider.decorateImage(labelProvider.getImage(peerNode), peerNode));
String fullName = labelProvider.getText(peerNode);
String name = fullName;
if (name.length() > 22 && name.length() >= 25) {
name = name.substring(0, 22) + "..."; //$NON-NLS-1$
}
text.setText(name);
String tooltipMessage = Messages.DefaultContextSelectorToolbarContribution_tooltip_button;
String tooltip = !fullName.equals(name) ? fullName : tooltipMessage;
if (!peerNode.isValid()) {
String error = CommonUtils.getPeerError(peerNode);
tooltip = !fullName.equals(name) ? fullName+"\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$
if (error != null) {
tooltip += error;
}
else {
tooltip += Messages.PeerLabelProviderDelegate_description_invalid;
}
}
else if (peerNode.getConnectState() == IConnectable.STATE_CONNECTED) {
Map<String,String> warnings = CommonUtils.getPeerWarnings(peerNode);
if (warnings != null && !warnings.isEmpty()) {
changePanelStyle(PanelStyle.WARNING);
tooltip = !fullName.equals(name) ? fullName : ""; //$NON-NLS-1$
for (String warning : warnings.values()) {
if (tooltip.trim().length() > 0) {
tooltip += "\n"; //$NON-NLS-1$
}
tooltip += warning;
}
}
}
else if (peerNode.getConnectState() == IConnectable.STATE_CONNECTION_LOST ||
peerNode.getConnectState() == IConnectable.STATE_CONNECTION_RECOVERING ||
peerNode.getConnectState() == IConnectable.STATE_UNKNOWN) {
changePanelStyle(PanelStyle.WARNING);
}
image.setToolTipText(tooltip);
text.setToolTipText(tooltip);
button.setToolTipText(tooltipMessage);
}
else {
image.setImage(UIPlugin.getImage(ImageConsts.NEW_CONFIG));
text.setText(Messages.DefaultContextSelectorToolbarContribution_label_new);
image.setToolTipText(Messages.DefaultContextSelectorToolbarContribution_tooltip_new);
text.setToolTipText(Messages.DefaultContextSelectorToolbarContribution_tooltip_new);
button.setToolTipText(Messages.DefaultContextSelectorToolbarContribution_tooltip_new);
}
}
}
/**
* Switches between themes.
* - Default: when there aren't issues with the connection.
* - Warning: when there is some kind of warning. The background turns yellow.
* @param pStyle
*/
private void changePanelStyle(PanelStyle pStyle) {
if (text != null && labelPanel != null) {
if (pStyle.equals(PanelStyle.DEFAULT)) {
labelPanel.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_WHITE));
text.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_BLACK));
} else if (pStyle.equals(PanelStyle.WARNING)) {
labelPanel.setBackground(warningBackgroundColor);
text.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_BLACK));
}
}
}
protected void onButtonClick() {
if (!clickRunning) {
clickRunning = true;
IPeerNode peerNode = ServiceManager.getInstance().getService(IDefaultContextService.class).getDefaultContext(null);
if (peerNode == null) {
openNewWizard();
}
else {
createContextMenu(panel);
if (menu != null) {
Point point = panel.toDisplay(panel.getLocation());
menu.setLocation(point.x, point.y + panel.getBounds().height);
menu.setVisible(true);
}
}
clickRunning = false;
}
}
protected void openNewWizard() {
try {
new NewToolbarWizardHandler().execute(new ExecutionEvent());
}
catch (Exception e) {
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.ContributionItem#isDynamic()
*/
@Override
public boolean isDynamic() {
return true;
}
protected void createContextMenu(Composite panel) {
if (menu == null || menuMgr == null || menuMgr.isDirty()) {
try {
if (menuMgr != null) menuMgr.dispose();
menuMgr = new MenuManager();
menuMgr.add(new GroupMarker("group.configurations")); //$NON-NLS-1$
IPeerNode defaultContext = ServiceManager.getInstance().getService(IDefaultContextService.class).getDefaultContext(null);
if (defaultContext != null && defaultContext.isVisible()) {
menuMgr.add(getAction(defaultContext));
}
for (final IPeerNode peerNode : getPeerNodesSorted()) {
if (peerNode == defaultContext || !peerNode.isVisible()) {
continue;
}
menuMgr.add(getAction(peerNode));
}
menuMgr.add(new Separator("group.open")); //$NON-NLS-1$
menuMgr.add(new GroupMarker("group.delete")); //$NON-NLS-1$
menuMgr.add(new GroupMarker("group.new")); //$NON-NLS-1$
menuMgr.add(new Separator("group.additions")); //$NON-NLS-1$
final IMenuService service = (IMenuService)serviceLocator.getService(IMenuService.class);
service.populateContributionManager(menuMgr, "menu:" + getId()); //$NON-NLS-1$
if (menu != null && !menu.isDisposed()) {
menu.setVisible(false);
menu.dispose();
}
menu = menuMgr.createContextMenu(panel);
}
catch (Exception e) {
menuMgr = null;
menu = null;
}
}
}
protected IAction getAction(final IPeerNode peerNode) {
IAction action = new Action() {
private IPeerNode node = peerNode;
@Override
public void run() {
ServiceManager.getInstance().getService(IDefaultContextService.class).setDefaultContext(node);
}
};
DelegatingLabelProvider labelProvider = new DelegatingLabelProvider();
action.setText(labelProvider.getText(peerNode));
Image image = labelProvider.decorateImage(labelProvider.getImage(peerNode), peerNode);
action.setImageDescriptor(ImageDescriptor.createFromImage(image));
return action;
}
/**
* Get the label provider for a peer model node.
*
* @param peerNode The peer model node.
* @return The label provider or <code>null</code>.
*/
protected ILabelProvider getLabelProvider(IPeerNode peerNode) {
ILabelProvider labelProvider = (ILabelProvider)peerNode.getAdapter(ILabelProvider.class);
if (labelProvider == null) {
labelProvider = (ILabelProvider)Platform.getAdapterManager().loadAdapter(peerNode, ILabelProvider.class.getName());
}
return labelProvider;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.runtime.interfaces.events.IEventListener#eventFired(java.util.EventObject)
*/
@Override
public void eventFired(EventObject event) {
if (event instanceof ChangeEvent) {
ChangeEvent changeEvent = (ChangeEvent)event;
IPeerNode peerNode = ServiceManager.getInstance().getService(IDefaultContextService.class).getDefaultContext(null);
boolean openEditorOnChange = UIPlugin.getScopedPreferences().getBoolean(IPreferenceKeys.PREF_OPEN_EDITOR_ON_DEFAULT_CONTEXT_CHANGE);
if (peerNode != null && changeEvent.getSource() instanceof IDefaultContextService) {
ICommandService service = (ICommandService)PlatformUI.getWorkbench().getService(ICommandService.class);
service.refreshElements("org.eclipse.tcf.te.ui.toolbar.command.connect", null); //$NON-NLS-1$
service.refreshElements("org.eclipse.tcf.te.ui.toolbar.command.disconnect", null); //$NON-NLS-1$
if (openEditorOnChange) {
ViewsUtil.openEditor(new StructuredSelection(peerNode));
}
}
if (changeEvent.getSource() instanceof IDefaultContextService ||
(changeEvent.getSource() == peerNode &&
(IPeerNodeProperties.PROPERTY_CONNECT_STATE.equals(changeEvent.getEventId()) ||
IPeerNodeProperties.PROPERTY_IS_VALID.equals(changeEvent.getEventId()) ||
IPeerNodeProperties.PROPERTY_WARNINGS.equals(changeEvent.getEventId()) ||
"properties".equals(changeEvent.getEventId())))) { //$NON-NLS-1$
if (menuMgr != null) menuMgr.markDirty();
ExecutorsUtil.executeInUI(new Runnable() {
@Override
public void run() {
update();
}
});
}
}
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.locator.interfaces.IPeerModelListener#modelChanged(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel, org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode, boolean)
*/
@Override
public void modelChanged(IPeerModel model, IPeerNode peerNode, boolean added) {
if (menuMgr != null) menuMgr.markDirty();
ExecutorsUtil.executeInUI(new Runnable() {
@Override
public void run() {
update();
}
});
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.locator.interfaces.IPeerModelListener#modelDisposed(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel)
*/
@Override
public void modelDisposed(IPeerModel model) {
}
@Override
public void propertyChange(PropertyChangeEvent event) {
String property= event.getProperty();
if (property.equals(WARNING_BACKGROUND_FG_COLOR_NAME)) {
initThemeColors();
update();
}
}
}