diff --git a/eclipse/src/saros/Saros.java b/eclipse/src/saros/Saros.java
index 9d9edc6ab5..b7adbb1e29 100644
--- a/eclipse/src/saros/Saros.java
+++ b/eclipse/src/saros/Saros.java
@@ -3,6 +3,7 @@
import java.io.File;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.ConfigurationSource;
@@ -11,12 +12,16 @@
import org.apache.logging.log4j.status.StatusLogger;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.di.UIEventTopic;
+import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchListener;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
+import org.osgi.service.event.Event;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import saros.annotations.Component;
@@ -130,10 +135,17 @@ public void start(BundleContext context) throws Exception {
isLifecycleStarted = true;
- getWorkbench().addWorkbenchListener(workbenchShutdownListener);
isInitialized = true;
}
+ @Inject
+ @Optional
+ public void applicationStarted(
+ @UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Event event, Saros saros) {
+
+ saros.getWorkbench().addWorkbenchListener(saros.workbenchShutdownListener);
+ }
+
@Override
public void stop(BundleContext context) throws Exception {
diff --git a/eclipse/src/saros/StartupSaros.java b/eclipse/src/saros/StartupSaros.java
index a4a1dad43a..801d6b7eb0 100644
--- a/eclipse/src/saros/StartupSaros.java
+++ b/eclipse/src/saros/StartupSaros.java
@@ -1,88 +1,129 @@
package saros;
+import java.util.List;
+import javax.annotation.PostConstruct;
import org.apache.log4j.Logger;
-import org.eclipse.ui.IStartup;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.intro.IIntroManager;
-import org.eclipse.ui.intro.IIntroPart;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
import saros.account.XMPPAccountStore;
import saros.preferences.Preferences;
import saros.repackaged.picocontainer.annotations.Inject;
import saros.ui.util.SWTUtils;
-import saros.ui.util.ViewUtils;
import saros.ui.util.WizardUtils;
import saros.ui.util.XMPPConnectionSupport;
/**
- * An instance of this class is instantiated when Eclipse starts, after the Saros plugin has been
- * started.
+ * An instance of this class is instantiated when Eclipse starts, after the
+ * Saros plugin has been started.
*
- * {@link #earlyStartup()} is called after the workbench is initialized.
+ *
+ * {@link #earlyStartup()} is called after the workbench is initialized.
*/
-public class StartupSaros implements IStartup {
+public class StartupSaros {
- private static final Logger log = Logger.getLogger(StartupSaros.class);
+ private static final Logger log = Logger.getLogger(StartupSaros.class);
- @Inject private Preferences preferences;
+ @Inject
+ private Preferences preferences;
- @Inject private XMPPAccountStore xmppAccountStore;
-
- public StartupSaros() {
- SarosPluginContext.initComponent(this);
- }
-
- /*
- * Once the workbench is started, the method earlyStartup() will be called
- * from a separate thread
- */
-
- @Override
- public void earlyStartup() {
-
- if (xmppAccountStore.isEmpty()) SWTUtils.runSafeSWTAsync(log, StartupSaros::openSarosView);
-
- Integer testmode = Integer.getInteger("saros.testmode");
-
- if (testmode != null) return;
-
- /*
- * Only show the Configuration Wizard if no accounts are configured. If
- * Saros is already configured, do not show the tutorial because the
- * user is probably already experienced.
- */
+ @Inject
+ private XMPPAccountStore xmppAccountStore;
/*
- * TODO first display a dialog if the user wants to get some help. Afterwards open this wizard
- * and maybe also open a web site with getting started?
+ * Once the workbench is started, the method earlyStartup() will be called
+ * from a separate thread
*/
- if (xmppAccountStore.isEmpty()) {
- SWTUtils.runSafeSWTAsync(log, WizardUtils::openSarosConfigurationWizard);
- return;
+ @PostConstruct
+ public void earlyStartup(IEventBroker eb, EPartService partService,
+ EModelService service, MApplication app) {
+ SarosPluginContext.initComponent(this);
+
+ eb.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE,
+ new EventHandler() {
+
+ @Override
+ public void handleEvent(Event event) {
+
+ // Create the View
+ MPart sarosView = partService
+ .createPart("saros.ui.views.SarosView");
+ MWindow mainWindow = app.getChildren().get(0);
+
+ List parts = service.findElements(mainWindow,
+ "bottomRight", MPartStack.class, null);
+
+ if (parts.size() > 0) {
+ MPartStack partStackSaros = service
+ .createModelElement(MPartStack.class);
+ partStackSaros.getChildren().add(sarosView);
+ MPartSashContainer partSashContainer = service
+ .createModelElement(MPartSashContainer.class);
+ MPartStack partStackBottomRight = parts.get(0);
+ MElementContainer parent = partStackBottomRight
+ .getParent();
+ parent.getChildren().remove(partStackBottomRight);
+ partSashContainer.getChildren()
+ .add(partStackBottomRight);
+ partSashContainer.getChildren().add(partStackSaros);
+ partSashContainer.setHorizontal(true);
+ parent.getChildren().add(partSashContainer);
+ }
+
+ Integer testmode = Integer.getInteger("saros.testmode");
+
+ if (testmode != null)
+ return;
+
+ /*
+ * Only show the Configuration Wizard if no accounts are
+ * configured. If Saros is already configured, do not show
+ * the tutorial because the user is probably already
+ * experienced.
+ */
+
+ /*
+ * TODO first display a dialog if the user wants to get some
+ * help. Afterwards open this wizard and maybe also open a
+ * web site with getting started?
+ */
+
+ if (xmppAccountStore.isEmpty()) {
+ SWTUtils.runSafeSWTAsync(log,
+ WizardUtils::openSarosConfigurationWizard);
+ return;
+ }
+
+ /*
+ * HACK workaround for
+ * http://sourceforge.net/p/dpp/bugs/782/ Perform connecting
+ * after the view is created so that the necessary GUI
+ * elements for the chat have already installed their
+ * listeners.
+ *
+ * FIXME This will not work if the view is not created on
+ * startup !
+ */
+
+ if (preferences.isAutoConnecting()
+ && xmppAccountStore.getDefaultAccount() != null)
+ SWTUtils.runSafeSWTAsync(log,
+ () -> XMPPConnectionSupport.getInstance()
+ .connect(true));
+
+ eb.unsubscribe(this);
+ }
+ });
}
-
- /*
- * HACK workaround for http://sourceforge.net/p/dpp/bugs/782/
- * Perform connecting after the view is created so that the
- * necessary GUI elements for the chat have already installed
- * their listeners.
- *
- * FIXME This will not work if the view is not created on
- * startup !
- */
-
- if (preferences.isAutoConnecting() && xmppAccountStore.getDefaultAccount() != null)
- SWTUtils.runSafeSWTAsync(log, () -> XMPPConnectionSupport.getInstance().connect(true));
- }
-
- private static void openSarosView() {
-
- IIntroManager m = PlatformUI.getWorkbench().getIntroManager();
- IIntroPart i = m.getIntro();
- /*
- * if there is a welcome screen, do not open the SarosView
- * because it would be maximized and hiding the workbench window.
- */
- if (i == null) ViewUtils.openSarosView();
- }
}
diff --git a/eclipse/src/saros/ui/actions/ChangeXMPPAccountAction.java b/eclipse/src/saros/ui/actions/ChangeXMPPAccountAction.java
deleted file mode 100644
index 950961cd94..0000000000
--- a/eclipse/src/saros/ui/actions/ChangeXMPPAccountAction.java
+++ /dev/null
@@ -1,255 +0,0 @@
-package saros.ui.actions;
-
-import java.util.List;
-import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.ActionContributionItem;
-import org.eclipse.jface.action.IMenuCreator;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.handlers.IHandlerService;
-import saros.SarosPluginContext;
-import saros.account.IAccountStoreListener;
-import saros.account.XMPPAccount;
-import saros.account.XMPPAccountStore;
-import saros.communication.connection.ConnectionHandler;
-import saros.communication.connection.IConnectionStateListener;
-import saros.net.ConnectionState;
-import saros.net.xmpp.JID;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.util.SWTUtils;
-import saros.ui.util.WizardUtils;
-import saros.ui.util.XMPPConnectionSupport;
-
-/**
- * In addition to the connect/disconnect action, this allows the user to switch between accounts.
- */
-public class ChangeXMPPAccountAction extends Action implements IMenuCreator, Disposable {
-
- public static final String ACTION_ID = ChangeXMPPAccountAction.class.getName();
-
- private static final Logger log = Logger.getLogger(ChangeXMPPAccountAction.class);
-
- private Menu accountMenu;
-
- @Inject private XMPPAccountStore accountService;
-
- @Inject private ConnectionHandler connectionHandler;
-
- private boolean isConnectionError;
-
- private boolean defaultAccountChanged;
-
- private final IConnectionStateListener connectionStateListener =
- (state, error) -> SWTUtils.runSafeSWTAsync(log, () -> updateStatus(state));
-
- private final IAccountStoreListener accountStoreListener =
- new IAccountStoreListener() {
- @Override
- public void activeAccountChanged(final XMPPAccount activeAccount) {
- defaultAccountChanged = true;
- }
- };
-
- public ChangeXMPPAccountAction() {
- SarosPluginContext.initComponent(this);
-
- setText(Messages.ChangeXMPPAccountAction_connect);
- setId(ACTION_ID);
-
- connectionHandler.addConnectionStateListener(connectionStateListener);
- setMenuCreator(this);
- updateStatus(connectionHandler.getConnectionState());
-
- accountService.addListener(accountStoreListener);
- }
-
- @Override
- public void run() {
-
- if (connectionHandler.isConnected()) {
- XMPPConnectionSupport.getInstance().disconnect();
- return;
- }
-
- final XMPPAccount lastUsedAccount = XMPPConnectionSupport.getInstance().getCurrentXMPPAccount();
-
- final List accounts = accountService.getAllAccounts();
-
- final boolean exists = accounts.indexOf(lastUsedAccount) != -1;
-
- final XMPPAccount defaultAccount = accountService.getDefaultAccount();
-
- final boolean isEmpty = accountService.isEmpty();
-
- if (!exists && (defaultAccount == null || isEmpty)) {
- if (!MessageDialog.openQuestion(
- SWTUtils.getShell(),
- "Default account missing",
- "A default account has not been set yet. Do you want set a default account?")) return;
-
- SWTUtils.runSafeSWTAsync(log, this::openPreferences);
- return;
- }
-
- final XMPPAccount accountToConnect;
-
- if (defaultAccountChanged || !exists) {
- defaultAccountChanged = false;
- accountToConnect = defaultAccount;
- } else {
- accountToConnect = lastUsedAccount;
- }
-
- XMPPConnectionSupport.getInstance().connect(accountToConnect, false, false);
- }
-
- @Override
- public void dispose() {
- connectionHandler.removeConnectionStateListener(connectionStateListener);
- accountService.removeListener(accountStoreListener);
- }
-
- @Override
- public Menu getMenu(Menu parent) {
- return null;
- }
-
- @Override
- public Menu getMenu(Control parent) {
- accountMenu = new Menu(parent);
-
- final List accounts = accountService.getAllAccounts();
-
- final String connectionId = connectionHandler.getConnectionID();
-
- if (connectionHandler.isConnected() && connectionId != null) {
-
- final JID jid = new JID(connectionId);
-
- /*
- * TODO this may filter out too much but this situation is somewhat rare (multiple accounts
- * with same name and domain but different server
- */
-
- accounts.removeIf(
- a ->
- a.getUsername().equalsIgnoreCase(jid.getName())
- && a.getDomain().equalsIgnoreCase(jid.getDomain()));
- }
-
- accounts.forEach(this::addMenuItem);
-
- new MenuItem(accountMenu, SWT.SEPARATOR);
-
- addActionToMenu(
- accountMenu,
- new Action(Messages.ChangeXMPPAccountAction_add_account) {
- @Override
- public void run() {
- WizardUtils.openAddXMPPAccountWizard();
- }
- });
-
- addActionToMenu(
- accountMenu,
- new Action(Messages.ChangeXMPPAccountAction_configure_account) {
- @Override
- public void run() {
- openPreferences();
- }
- });
- return accountMenu;
- }
-
- private void addMenuItem(final XMPPAccount account) {
- // The additional @ is needed because @ has special meaning in
- // Action#setText(), see JavaDoc of Action().
-
- String accountText = account.getUsername() + "@" + account.getDomain() + "@";
- Action action =
- new Action(accountText) {
-
- @Override
- public void run() {
- defaultAccountChanged = false;
- XMPPConnectionSupport.getInstance().connect(account, false, false);
- }
- };
-
- addActionToMenu(accountMenu, action);
- }
-
- private void addActionToMenu(Menu parent, Action action) {
- ActionContributionItem item = new ActionContributionItem(action);
- item.fill(parent, -1);
- }
-
- private void updateStatus(ConnectionState state) {
- try {
- switch (state) {
- case CONNECTED:
- isConnectionError = false;
- setText(Messages.ChangeXMPPAccountAction_disconnect);
- setImageDescriptor(
- ImageManager.getImageDescriptor("/icons/elcl16/xmpp_disconnect_tsk.png"));
- break;
- case CONNECTING:
- isConnectionError = false;
- setText(Messages.ChangeXMPPAccountAction_connecting);
- setDisabledImageDescriptor(
- ImageManager.getImageDescriptor("/icons/elcl16/xmpp_connecting_misc.png"));
- break;
- case ERROR:
- isConnectionError = true;
- setImageDescriptor(
- ImageManager.getImageDescriptor("/icons/elcl16/xmpp_connection_error_misc.png"));
- break;
- case NOT_CONNECTED:
- setText(Messages.ChangeXMPPAccountAction_connect);
-
- if (!isConnectionError)
- setImageDescriptor(
- ImageManager.getImageDescriptor("/icons/elcl16/xmpp_connect_tsk.png"));
-
- break;
- case DISCONNECTING:
- default:
- isConnectionError = false;
- setText(Messages.ChangeXMPPAccountAction_disconnecting);
- setDisabledImageDescriptor(
- ImageManager.getImageDescriptor("/icons/elcl16/xmpp_disconnecting_misc.png"));
- break;
- }
-
- setEnabled(
- state == ConnectionState.CONNECTED
- || state == ConnectionState.NOT_CONNECTED
- || state == ConnectionState.ERROR);
-
- } catch (RuntimeException e) {
- log.error("Internal error in ChangeXMPPAccountAction:", e);
- }
- }
-
- private void openPreferences() {
- IHandlerService service =
- PlatformUI.getWorkbench()
- .getActiveWorkbenchWindow()
- .getActivePage()
- .getActivePart()
- .getSite()
- .getService(IHandlerService.class);
- try {
- service.executeCommand("saros.ui.commands.OpenSarosPreferences", null);
- } catch (Exception e) {
- log.debug("Could execute command", e);
- }
- }
-}
diff --git a/eclipse/src/saros/ui/actions/Disposable.java b/eclipse/src/saros/ui/actions/Disposable.java
deleted file mode 100644
index d3ce20aeb6..0000000000
--- a/eclipse/src/saros/ui/actions/Disposable.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package saros.ui.actions;
-
-import saros.ui.views.SarosView;
-
-public interface Disposable {
-
- /**
- * Gets called when the {@link SarosView} is about to being disposed. Actions implementing this
- * interface should release all resources and remove all installed listeners that were allocated
- * and installed during the lifetime of the action.
- */
- public void dispose();
-}
diff --git a/eclipse/src/saros/ui/actions/JumpToUserWithWriteAccessPositionAction.java b/eclipse/src/saros/ui/actions/JumpToUserWithWriteAccessPositionAction.java
deleted file mode 100644
index 1666906173..0000000000
--- a/eclipse/src/saros/ui/actions/JumpToUserWithWriteAccessPositionAction.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package saros.ui.actions;
-
-import java.util.List;
-import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.PlatformUI;
-import saros.SarosPluginContext;
-import saros.annotations.Component;
-import saros.editor.EditorManager;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.session.ISarosSessionManager;
-import saros.session.User;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-import saros.util.ThreadUtils;
-
-/** Action which triggers the viewport of the local user to be changed to a local user's one. */
-@Component(module = "action")
-public class JumpToUserWithWriteAccessPositionAction extends Action implements Disposable {
-
- public static final String ACTION_ID = JumpToUserWithWriteAccessPositionAction.class.getName();
-
- private static final Logger log = Logger.getLogger(JumpToUserWithWriteAccessPositionAction.class);
-
- protected ISelectionListener selectionListener =
- new ISelectionListener() {
- @Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
- updateEnablement();
- }
- };
-
- @Inject protected ISarosSessionManager sessionManager;
-
- @Inject protected EditorManager editorManager;
-
- public JumpToUserWithWriteAccessPositionAction() {
- super(Messages.JumpToUserWithWriteAccessPositionAction_title);
-
- setId(ACTION_ID);
- setToolTipText(Messages.JumpToUserWithWriteAccessPositionAction_tooltip);
- setImageDescriptor(ImageManager.getImageDescriptor("icons/elcl16/jump.png")); // $NON-NLS-1$
-
- SarosPluginContext.initComponent(this);
-
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
- updateEnablement();
- }
-
- public void updateEnablement() {
- try {
- List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
- setEnabled(
- sessionManager.getSession() != null
- && participants.size() == 1
- && !participants.get(0).equals(sessionManager.getSession().getLocalUser()));
- } catch (NullPointerException e) {
- this.setEnabled(false);
- } catch (Exception e) {
- if (!PlatformUI.getWorkbench().isClosing())
- log.error("Unexpected error while updating enablement", e); // $NON-NLS-1$
- }
- }
-
- /** @review runSafe OK */
- @Override
- public void run() {
- ThreadUtils.runSafeSync(
- log,
- new Runnable() {
- @Override
- public void run() {
- List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
- if (participants.size() == 1) {
- editorManager.jumpToUser(participants.get(0));
- } else {
- log.warn("More than one participant selected."); // $NON-NLS-1$
- }
- }
- });
- }
-
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
- }
-}
diff --git a/eclipse/src/saros/ui/actions/LeaveSessionAction.java b/eclipse/src/saros/ui/actions/LeaveSessionAction.java
deleted file mode 100644
index f9dcb6f65f..0000000000
--- a/eclipse/src/saros/ui/actions/LeaveSessionAction.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package saros.ui.actions;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.ImageData;
-import saros.SarosPluginContext;
-import saros.annotations.Component;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.session.ISarosSession;
-import saros.session.ISarosSessionManager;
-import saros.session.ISessionLifecycleListener;
-import saros.session.SessionEndReason;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.util.CollaborationUtils;
-
-/** Leaves the current Saros session. Is deactivated if there is no running session. */
-@Component(module = "action")
-public class LeaveSessionAction extends Action implements Disposable {
-
- public static final String ACTION_ID = LeaveSessionAction.class.getName();
-
- @Inject private ISarosSessionManager sessionManager;
-
- private final ISessionLifecycleListener sessionLifecycleListener =
- new ISessionLifecycleListener() {
- @Override
- public void sessionStarted(ISarosSession newSarosSession) {
- updateEnablement();
- }
-
- @Override
- public void sessionEnded(ISarosSession oldSarosSession, SessionEndReason reason) {
- updateEnablement();
- }
- };
-
- public LeaveSessionAction() {
- setId(ACTION_ID);
- setToolTipText(Messages.LeaveSessionAction_leave_session_tooltip);
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ELCL_SESSION_LEAVE.getImageData();
- }
- });
-
- SarosPluginContext.initComponent(this);
- sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
- updateEnablement();
- }
-
- @Override
- public void run() {
- CollaborationUtils.leaveSession();
- }
-
- @Override
- public void dispose() {
- sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
- }
-
- private void updateEnablement() {
- ISarosSession session = sessionManager.getSession();
-
- if (session == null) {
- setEnabled(false);
- return;
- }
-
- if (session.isHost()) {
- setToolTipText(Messages.LeaveSessionAction_stop_session_tooltip);
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ELCL_SESSION_TERMINATE.getImageData();
- }
- });
- } else {
- setToolTipText(Messages.LeaveSessionAction_leave_session_tooltip);
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ELCL_SESSION_LEAVE.getImageData();
- }
- });
- }
- setEnabled(true);
- }
-}
diff --git a/eclipse/src/saros/ui/actions/NewContactAction.java b/eclipse/src/saros/ui/actions/NewContactAction.java
deleted file mode 100644
index bdd0b7a66c..0000000000
--- a/eclipse/src/saros/ui/actions/NewContactAction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package saros.ui.actions;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.ImageData;
-import saros.SarosPluginContext;
-import saros.communication.connection.ConnectionHandler;
-import saros.communication.connection.IConnectionStateListener;
-import saros.net.ConnectionState;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.util.WizardUtils;
-
-public class NewContactAction extends Action implements Disposable {
-
- public static final String ACTION_ID = NewContactAction.class.getName();
-
- private final IConnectionStateListener connectionListener =
- (state, error) -> setEnabled(state == ConnectionState.CONNECTED);
-
- @Inject private ConnectionHandler connectionHandler;
-
- public NewContactAction() {
- setId(ACTION_ID);
- setToolTipText(Messages.NewContactAction_tooltip);
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ELCL_CONTACT_ADD.getImageData();
- }
- });
-
- SarosPluginContext.initComponent(this);
-
- connectionHandler.addConnectionStateListener(connectionListener);
- setEnabled(connectionHandler.isConnected());
- }
-
- @Override
- public void dispose() {
- connectionHandler.removeConnectionStateListener(connectionListener);
- }
-
- @Override
- public void run() {
- WizardUtils.openAddContactWizard();
- }
-}
diff --git a/eclipse/src/saros/ui/actions/OpenChatAction.java b/eclipse/src/saros/ui/actions/OpenChatAction.java
deleted file mode 100644
index 5f43b66af6..0000000000
--- a/eclipse/src/saros/ui/actions/OpenChatAction.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package saros.ui.actions;
-
-import java.util.List;
-import java.util.Objects;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
-import saros.SarosPluginContext;
-import saros.communication.chat.single.SingleUserChatService;
-import saros.communication.connection.ConnectionHandler;
-import saros.net.xmpp.JID;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.session.User;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.model.session.UserElement;
-import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-import saros.ui.widgets.chat.ChatRoomsComposite;
-
-public class OpenChatAction extends Action implements Disposable {
-
- public static final String ACTION_ID = OpenChatAction.class.getName();
-
- @Inject private ConnectionHandler connectionHandler;
- @Inject private SingleUserChatService chatService;
-
- private ChatRoomsComposite chatRoomsComposite;
-
- private ISelectionListener selectionListener =
- new ISelectionListener() {
- @Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
- updateEnablement();
- }
- };
-
- public OpenChatAction(ChatRoomsComposite chatRoomsComposite) {
- super(Messages.OpenChatAction_MenuItem);
- SarosPluginContext.initComponent(this);
- this.chatRoomsComposite = chatRoomsComposite;
-
- setId(ACTION_ID);
- setImageDescriptor(ImageManager.getImageDescriptor("icons/view16/chat_misc.png"));
-
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
-
- updateEnablement();
- }
-
- @Override
- public void run() {
- JID localJID = connectionHandler.getLocalJID();
- JID jid = getSelectedJID();
-
- if (Objects.equals(localJID, jid)) return;
-
- chatRoomsComposite.openChat(chatService.createChat(jid), true);
- }
-
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
- }
-
- private void updateEnablement() {
- if (!connectionHandler.isConnected()) {
- setEnabled(false);
- return;
- }
-
- if (getSelectedJID() != null) {
- setEnabled(true);
- }
- }
-
- private JID getSelectedJID() {
- List users =
- SelectionRetrieverFactory.getSelectionRetriever(UserElement.class).getSelection();
- List contacts = SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
-
- if (users.size() + contacts.size() == 1) {
- if (users.size() == 1) {
- User user = users.get(0).getUser();
- if (user == null) {
- return null;
- }
-
- return user.getJID();
- } else {
- return contacts.get(0);
- }
- }
-
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/actions/OpenPreferencesAction.java b/eclipse/src/saros/ui/actions/OpenPreferencesAction.java
deleted file mode 100644
index ee4b7f6d2c..0000000000
--- a/eclipse/src/saros/ui/actions/OpenPreferencesAction.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package saros.ui.actions;
-
-import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.handlers.IHandlerService;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-
-public class OpenPreferencesAction extends Action {
-
- public static final String ACTION_ID = OpenPreferencesAction.class.getName();
-
- private static final Logger log = Logger.getLogger(OpenPreferencesAction.class);
-
- public OpenPreferencesAction() {
- super(Messages.OpenPreferencesAction_title);
-
- setId(ACTION_ID);
- setToolTipText(Messages.OpenPreferencesAction_tooltip);
- setImageDescriptor(ImageManager.getImageDescriptor(ImageManager.ELCL_PREFERENCES_OPEN));
- setEnabled(true);
- }
-
- @Override
- public void run() {
- IHandlerService service =
- PlatformUI.getWorkbench()
- .getActiveWorkbenchWindow()
- .getActivePage()
- .getActivePart()
- .getSite()
- .getService(IHandlerService.class);
- try {
- service.executeCommand(
- "saros.ui.commands.OpenSarosPreferences", //$NON-NLS-1$
- null);
- } catch (Exception e) {
- log.error("Could not execute command", e); // $NON-NLS-1$
- }
- }
-}
diff --git a/eclipse/src/saros/ui/actions/RequestSessionInviteAction.java b/eclipse/src/saros/ui/actions/RequestSessionInviteAction.java
deleted file mode 100644
index 7ce6c2616e..0000000000
--- a/eclipse/src/saros/ui/actions/RequestSessionInviteAction.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package saros.ui.actions;
-
-import java.util.List;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
-import saros.SarosPluginContext;
-import saros.communication.extensions.JoinSessionRequestExtension;
-import saros.net.ITransmitter;
-import saros.net.xmpp.JID;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.session.ISarosSession;
-import saros.session.ISarosSessionManager;
-import saros.ui.Messages;
-import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-
-/**
- * Action for requesting an invitation to a session from a contact.
- *
- * This currently relies on the fact, that only Saros/S has a working JoinSessionRequestHandler.
- * To make this feature generic in the future we need to add another XMPP namespace
- */
-public class RequestSessionInviteAction extends Action implements Disposable {
-
- @Inject private ISarosSessionManager sessionManager;
- @Inject private ITransmitter transmitter;
-
- private ISelectionListener selectionListener =
- new ISelectionListener() {
- @Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
- updateActionState();
- }
- };
-
- public static final String ACTION_ID = RequestSessionInviteAction.class.getName();
-
- public RequestSessionInviteAction() {
- super(Messages.RequestSessionInviteAction_title);
- setId(ACTION_ID);
- SarosPluginContext.initComponent(this);
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
- updateActionState();
- }
-
- @Override
- public void run() {
- ISarosSession session = sessionManager.getSession();
- JID jid = getSelectedJID();
- if (session != null || jid == null) {
- return;
- }
-
- transmitter.sendPacketExtension(
- jid, JoinSessionRequestExtension.PROVIDER.create(new JoinSessionRequestExtension()));
- }
-
- private JID getSelectedJID() {
- List selected = SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
-
- if (selected.size() != 1) return null;
-
- return selected.get(0);
- }
-
- private void updateActionState() {
- ISarosSession session = sessionManager.getSession();
- setEnabled(session == null && getSelectedJID() != null);
- }
-
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
- }
-}
diff --git a/eclipse/src/saros/ui/actions/SendFileAction.java b/eclipse/src/saros/ui/actions/SendFileAction.java
deleted file mode 100644
index beb4c5e54c..0000000000
--- a/eclipse/src/saros/ui/actions/SendFileAction.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package saros.ui.actions;
-
-import java.io.File;
-import java.util.List;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.action.Action;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import saros.net.xmpp.JID;
-import saros.net.xmpp.contact.XMPPContact;
-import saros.session.User;
-import saros.ui.Messages;
-import saros.ui.jobs.OutgoingFileTransferJob;
-import saros.ui.util.SWTUtils;
-import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-
-/** Action for sending a file over XMPP. */
-public class SendFileAction extends Action implements Disposable {
-
- public static final String ACTION_ID = SendFileAction.class.getName();
-
- private ISelectionListener selectionListener = (part, selection) -> updateEnablement();
-
- public SendFileAction() {
- super(Messages.SendFileAction_title);
-
- setImageDescriptor(
- PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
- setId(ACTION_ID);
- setToolTipText(Messages.SendFileAction_tooltip);
-
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
-
- updateEnablement();
- }
-
- @Override
- public void run() {
- JID jid = getSelectedJID();
- if (jid == null) return;
-
- FileDialog fd = new FileDialog(SWTUtils.getShell(), SWT.OPEN);
- fd.setText(Messages.SendFileAction_filedialog_text);
-
- String filename = fd.open();
- if (filename == null) return;
-
- File file = new File(filename);
- if (file.isDirectory()) return;
-
- Job job = new OutgoingFileTransferJob(jid, file);
- job.setUser(true);
- job.schedule();
- }
-
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
- }
-
- private void updateEnablement() {
- setEnabled(getSelectedJID() != null);
- }
-
- private JID getSelectedJID() {
- List sessionUsers =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
-
- List contacts =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
-
- // currently only one transfer per click (maybe improved later)
- if (contacts.size() + sessionUsers.size() != 1) return null;
-
- if (sessionUsers.size() == 1) {
- if (sessionUsers.get(0).isLocal()) return null;
- return sessionUsers.get(0).getJID();
- }
-
- return contacts.get(0).getOnlineJid().orElse(null);
- }
-}
diff --git a/eclipse/src/saros/ui/actions/SkypeAction.java b/eclipse/src/saros/ui/actions/SkypeAction.java
deleted file mode 100644
index 167ddf23c7..0000000000
--- a/eclipse/src/saros/ui/actions/SkypeAction.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package saros.ui.actions;
-
-import java.util.List;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.hyperlink.URLHyperlink;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
-import saros.SarosPluginContext;
-import saros.communication.SkypeManager;
-import saros.net.xmpp.contact.XMPPContact;
-import saros.repackaged.picocontainer.annotations.Inject;
-import saros.ui.ImageManager;
-import saros.ui.Messages;
-import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-
-/** An action for starting a Skype Audio Session to other contacts. */
-public class SkypeAction extends Action implements Disposable {
-
- public static final String ACTION_ID = SkypeAction.class.getName();
-
- private ISelectionListener selectionListener =
- new ISelectionListener() {
- @Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
- updateEnablement();
- }
- };
-
- @Inject private SkypeManager skypeManager;
-
- public SkypeAction() {
- super(Messages.SkypeAction_title);
-
- SarosPluginContext.initComponent(this);
-
- setId(ACTION_ID);
- setToolTipText(Messages.SkypeAction_tooltip);
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ELCL_CONTACT_SKYPE_CALL.getImageData();
- }
- });
-
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
- updateEnablement();
- }
-
- private void updateEnablement() {
-
- setEnabled(false);
-
- final List contacts =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
-
- if (contacts.size() != 1) return;
-
- final String skypeName = skypeManager.getSkypeName(contacts.get(0));
-
- setEnabled(
- SkypeManager.isSkypeAvailable(false)
- && skypeName != null
- && !SkypeManager.isEchoService(skypeName));
- }
-
- @Override
- public void run() {
-
- final List participants =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
-
- if (participants.size() != 1) return;
-
- final String skypeName = skypeManager.getSkypeName(participants.get(0));
-
- if (skypeName == null || SkypeManager.isEchoService(skypeName)) return;
-
- final String uri = SkypeManager.getAudioCallUri(skypeName);
-
- if (uri == null) return;
-
- final URLHyperlink link = new URLHyperlink(new Region(0, 0), uri);
-
- link.open();
- }
-
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
- }
-}
diff --git a/eclipse/src/saros/ui/actions/package-info.java b/eclipse/src/saros/ui/actions/package-info.java
deleted file mode 100644
index d46ef64b81..0000000000
--- a/eclipse/src/saros/ui/actions/package-info.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- *
- *
- * Actions Overview
- *
- * This package contains all possible actions in the saros view which a user can initiate.
- *
- * This package comprises of the following subpackages:
- *
- *
- * - the {@link saros.ui.actions.ChangeColorAction} allows the user to change his personal color
- * which is also shown to all other session users.
- *
- the {@link saros.ui.actions.ChangeXMPPAccountAction} allows the user to switch between
- * several accounts
- *
- the {@link saros.ui.actions.ConsistencyAction} calls {@link
- * saros.concurrent.watchdog.ConsistencyWatchdogClient} and if an inconsistency is found, the
- * Action gives you the possibility to resolve it.
- *
- the {@link saros.ui.actions.DeleteContactAction} allows the user to delete other contacts
- * from his contact list.
- *
- the {@link saros.ui.actions.FollowModeAction} allows the user to follow the first person in
- * the session which has {@link saros.session.User.Permission#WRITE_ACCESS}. Activated through
- * toolbar-button.
- *
- the {@link saros.ui.actions.FollowThisPersonAction} allow to follow a selected session
- * user.
- *
- the {@link saros.ui.actions.ChangeWriteAccessAction} is responsible for grant or revoke
- * {@link saros.session.User.Permission#WRITE_ACCESS} to a non-host session user.
- *
- the {@link saros.ui.actions.JumpToUserWithWriteAccessPositionAction} allows the user to
- * jump to a selected session user current viewpoint
- *
- the {@link saros.ui.actions.LeaveSessionAction} allows the user to leave a session.
- *
- the {@link saros.ui.actions.NewContactAction} allows to add a new contact to the contact
- * list.
- *
- the {@link saros.ui.actions.RenameContactAction} allows to rename a contact in the contact
- * list.
- *
- the {@link saros.ui.actions.SendFileAction} allows a user to send a file to a session user.
- *
- the {@link saros.ui.actions.SkypeAction} calls the {@link saros.communication.SkypeManager}
- * to call a contact for Skype.
- *
- */
-package saros.ui.actions;
diff --git a/eclipse/src/saros/ui/command_handlers/AddContactHandler.java b/eclipse/src/saros/ui/command_handlers/AddContactHandler.java
deleted file mode 100644
index f7b27fed3c..0000000000
--- a/eclipse/src/saros/ui/command_handlers/AddContactHandler.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.WizardUtils;
-
-public class AddContactHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- WizardUtils.openAddContactWizard();
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/AddXMPPAccountHandler.java b/eclipse/src/saros/ui/command_handlers/AddXMPPAccountHandler.java
deleted file mode 100644
index 62f228759b..0000000000
--- a/eclipse/src/saros/ui/command_handlers/AddXMPPAccountHandler.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.WizardUtils;
-
-public class AddXMPPAccountHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- WizardUtils.openAddXMPPAccountWizard();
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/CreateXMPPAccountHandler.java b/eclipse/src/saros/ui/command_handlers/CreateXMPPAccountHandler.java
deleted file mode 100644
index eee81f8206..0000000000
--- a/eclipse/src/saros/ui/command_handlers/CreateXMPPAccountHandler.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.WizardUtils;
-
-public class CreateXMPPAccountHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
-
- WizardUtils.openCreateXMPPAccountWizard(true);
-
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/GettingStartedHandler.java b/eclipse/src/saros/ui/command_handlers/GettingStartedHandler.java
deleted file mode 100644
index 9dc9a9cc1b..0000000000
--- a/eclipse/src/saros/ui/command_handlers/GettingStartedHandler.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.SWTUtils;
-
-public class GettingStartedHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
-
- SWTUtils.openInternalBrowser(
- "https://www.saros-project.org/documentation/getting-started.html", "Welcome to Saros");
-
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/OpenSarosPreferencesHandler.java b/eclipse/src/saros/ui/command_handlers/OpenSarosPreferencesHandler.java
deleted file mode 100644
index 1ff118f79d..0000000000
--- a/eclipse/src/saros/ui/command_handlers/OpenSarosPreferencesHandler.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.preference.PreferenceDialog;
-import org.eclipse.ui.dialogs.PreferencesUtil;
-
-public class OpenSarosPreferencesHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- PreferenceDialog pref =
- PreferencesUtil.createPreferenceDialogOn(null, "saros.preferences", null, null);
- if (pref != null) pref.open();
-
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/SessionAddContactsHandler.java b/eclipse/src/saros/ui/command_handlers/SessionAddContactsHandler.java
deleted file mode 100644
index 0b62b50e27..0000000000
--- a/eclipse/src/saros/ui/command_handlers/SessionAddContactsHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.net.xmpp.JID;
-import saros.session.ISarosSession;
-import saros.ui.util.WizardUtils;
-import saros.ui.wizards.AddResourcesToSessionWizard;
-
-/**
- * Handles the addition of {@link JID}s that must explicitly be selected in the opening {@link
- * AddResourcesToSessionWizard} to the running {@link ISarosSession}.
- */
-public class SessionAddContactsHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- WizardUtils.openAddContactsToSessionWizard();
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/SessionAddResourcesHandler.java b/eclipse/src/saros/ui/command_handlers/SessionAddResourcesHandler.java
deleted file mode 100644
index 81f60f2564..0000000000
--- a/eclipse/src/saros/ui/command_handlers/SessionAddResourcesHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.resources.IResource;
-import saros.session.ISarosSession;
-import saros.ui.util.WizardUtils;
-import saros.ui.wizards.AddResourcesToSessionWizard;
-
-/**
- * Handles the addition of {@link IResource}s that must explicitly be selected in the opening {@link
- * AddResourcesToSessionWizard} to the running {@link ISarosSession}.
- *
- * This class is used to define the behavior of the saros menu entry to add reference points to a
- * running session.
- */
-public class SessionAddResourcesHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- WizardUtils.openAddResourcesToSessionWizard(null);
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/SessionAddSelectedContactsHandler.java b/eclipse/src/saros/ui/command_handlers/SessionAddSelectedContactsHandler.java
deleted file mode 100644
index 3c1335fb0c..0000000000
--- a/eclipse/src/saros/ui/command_handlers/SessionAddSelectedContactsHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package saros.ui.command_handlers;
-
-import java.util.List;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.net.xmpp.JID;
-import saros.session.ISarosSession;
-import saros.ui.util.CollaborationUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-
-/** Handles the addition of selected {@link JID}s to the running {@link ISarosSession}. */
-public class SessionAddSelectedContactsHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
-
- List jids = SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
-
- CollaborationUtils.addContactsToSession(jids);
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/SessionAddSelectedResourcesHandler.java b/eclipse/src/saros/ui/command_handlers/SessionAddSelectedResourcesHandler.java
deleted file mode 100644
index 391f7c3556..0000000000
--- a/eclipse/src/saros/ui/command_handlers/SessionAddSelectedResourcesHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package saros.ui.command_handlers;
-
-import java.util.HashSet;
-import java.util.List;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.resources.IResource;
-import saros.session.ISarosSession;
-import saros.ui.util.WizardUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
-
-/**
- * Handles the addition of selected {@link IResource}s to the running {@link ISarosSession}.
- *
- * An {@link saros.ui.wizards.AddResourcesToSessionWizard} is opened for this purpose with the
- * currently selected resources preselected.
- *
- *
This class is used to define the behavior of the package explorer context menu entry to add
- * reference points to a running session.
- */
-public class SessionAddSelectedResourcesHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
-
- List selectedResources =
- SelectionRetrieverFactory.getSelectionRetriever(IResource.class).getSelection();
-
- WizardUtils.openAddResourcesToSessionWizard(new HashSet<>(selectedResources));
-
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/SessionLeaveHandler.java b/eclipse/src/saros/ui/command_handlers/SessionLeaveHandler.java
deleted file mode 100644
index a0942cee0c..0000000000
--- a/eclipse/src/saros/ui/command_handlers/SessionLeaveHandler.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.CollaborationUtils;
-
-public class SessionLeaveHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- CollaborationUtils.leaveSession();
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/command_handlers/StartSarosConfigurationHandler.java b/eclipse/src/saros/ui/command_handlers/StartSarosConfigurationHandler.java
deleted file mode 100644
index df54518659..0000000000
--- a/eclipse/src/saros/ui/command_handlers/StartSarosConfigurationHandler.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package saros.ui.command_handlers;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import saros.ui.util.WizardUtils;
-
-public class StartSarosConfigurationHandler extends AbstractHandler {
-
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
- WizardUtils.openSarosConfigurationWizard();
- return null;
- }
-}
diff --git a/eclipse/src/saros/ui/handlers/menu/AddContactHandler.java b/eclipse/src/saros/ui/handlers/menu/AddContactHandler.java
new file mode 100644
index 0000000000..baa3d2d12e
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/AddContactHandler.java
@@ -0,0 +1,27 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.ui.util.WizardUtils;
+
+public class AddContactHandler {
+ @Inject private ConnectionHandler connectionHandler;
+
+ public AddContactHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute() {
+ WizardUtils.openAddContactWizard();
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionHandler.isConnected();
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/AddXMPPAccountHandler.java b/eclipse/src/saros/ui/handlers/menu/AddXMPPAccountHandler.java
new file mode 100644
index 0000000000..9c3a4883c3
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/AddXMPPAccountHandler.java
@@ -0,0 +1,13 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.ui.util.WizardUtils;
+
+public class AddXMPPAccountHandler {
+
+ @Execute
+ public Object execute() {
+ WizardUtils.openAddXMPPAccountWizard();
+ return null;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/CreateXMPPAccountHandler.java b/eclipse/src/saros/ui/handlers/menu/CreateXMPPAccountHandler.java
new file mode 100644
index 0000000000..e816b5d629
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/CreateXMPPAccountHandler.java
@@ -0,0 +1,15 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.ui.util.WizardUtils;
+
+public class CreateXMPPAccountHandler {
+
+ @Execute
+ public Object execute() {
+
+ WizardUtils.openCreateXMPPAccountWizard(true);
+
+ return null;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/GettingStartedHandler.java b/eclipse/src/saros/ui/handlers/menu/GettingStartedHandler.java
new file mode 100644
index 0000000000..0a272d55cc
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/GettingStartedHandler.java
@@ -0,0 +1,14 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.ui.util.SWTUtils;
+
+public class GettingStartedHandler {
+
+ @Execute
+ public void execute() {
+
+ SWTUtils.openInternalBrowser(
+ "https://www.saros-project.org/documentation/getting-started.html", "Welcome to Saros");
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/OpenSarosPreferencesHandler.java b/eclipse/src/saros/ui/handlers/menu/OpenSarosPreferencesHandler.java
new file mode 100644
index 0000000000..6bc3576779
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/OpenSarosPreferencesHandler.java
@@ -0,0 +1,16 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+public class OpenSarosPreferencesHandler {
+
+ @Execute
+ public Object execute() {
+ PreferenceDialog pref =
+ PreferencesUtil.createPreferenceDialogOn(null, "saros.preferences", null, null);
+ if (pref != null) pref.open();
+ return null;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/SessionAddContactsHandler.java b/eclipse/src/saros/ui/handlers/menu/SessionAddContactsHandler.java
new file mode 100644
index 0000000000..5e3a98c0a4
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/SessionAddContactsHandler.java
@@ -0,0 +1,36 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.net.xmpp.JID;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.WizardUtils;
+import saros.ui.wizards.AddResourcesToSessionWizard;
+
+/**
+ * Handles the addition of {@link JID}s that must explicitly be selected in the opening {@link
+ * AddResourcesToSessionWizard} to the running {@link ISarosSession}.
+ */
+public class SessionAddContactsHandler {
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public SessionAddContactsHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute() {
+ WizardUtils.openAddContactsToSessionWizard();
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionHandler.isConnected() && sessionManager.getSession() != null;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/SessionAddResourcesHandler.java b/eclipse/src/saros/ui/handlers/menu/SessionAddResourcesHandler.java
new file mode 100644
index 0000000000..3df34b82ab
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/SessionAddResourcesHandler.java
@@ -0,0 +1,40 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.WizardUtils;
+import saros.ui.wizards.AddResourcesToSessionWizard;
+
+/**
+ * Handles the addition of {@link IResource}s that must explicitly be selected in the opening {@link
+ * AddResourcesToSessionWizard} to the running {@link ISarosSession}.
+ *
+ * This class is used to define the behavior of the saros menu entry to add reference points to a
+ * running session.
+ */
+public class SessionAddResourcesHandler {
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public SessionAddResourcesHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute() {
+ WizardUtils.openAddResourcesToSessionWizard(null);
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ final ISarosSession session = sessionManager.getSession();
+ return connectionHandler.isConnected() && session != null && session.hasWriteAccess();
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedContactsHandler.java b/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedContactsHandler.java
new file mode 100644
index 0000000000..1144cd136d
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedContactsHandler.java
@@ -0,0 +1,53 @@
+package saros.ui.handlers.menu;
+
+import java.util.List;
+import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.net.xmpp.JID;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.CollaborationUtils;
+import saros.ui.util.selection.SelectionUtils;
+
+/** Handles the addition of selected {@link JID}s to the running {@link ISarosSession}. */
+public class SessionAddSelectedContactsHandler {
+
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public SessionAddSelectedContactsHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute(@Named(IServiceConstants.ACTIVE_SELECTION) @Optional ISelection selection) {
+
+ List jids = SelectionUtils.getAdaptableObjects(selection, JID.class);
+
+ CollaborationUtils.addContactsToSession(jids);
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute(
+ @Named(IServiceConstants.ACTIVE_SELECTION) @Optional ISelection selection) {
+ final ISarosSession session = sessionManager.getSession();
+ if (!(connectionHandler.isConnected() && session != null && session.hasWriteAccess())) {
+ return false;
+ }
+ List jids = SelectionUtils.getAdaptableObjects(selection, JID.class);
+ for (JID jid : jids) {
+ if (session.getUsers().stream().anyMatch(u -> u.getJID().equals(jid))) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedResourcesHandler.java b/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedResourcesHandler.java
new file mode 100644
index 0000000000..0426b896b6
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/SessionAddSelectedResourcesHandler.java
@@ -0,0 +1,72 @@
+package saros.ui.handlers.menu;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.inject.Named;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.filesystem.IReferencePoint;
+import saros.filesystem.ResourceConverter;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.WizardUtils;
+import saros.ui.util.selection.SelectionUtils;
+
+/**
+ * Handles the addition of selected {@link IResource}s to the running {@link ISarosSession}.
+ *
+ * An {@link saros.ui.wizards.AddResourcesToSessionWizard} is opened for this purpose with the
+ * currently selected resources preselected.
+ *
+ *
This class is used to define the behavior of the package explorer context menu entry to add
+ * reference points to a running session.
+ */
+public class SessionAddSelectedResourcesHandler {
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public SessionAddSelectedResourcesHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute(@Named(IServiceConstants.ACTIVE_SELECTION) @Optional ISelection selection) {
+
+ List selectedResources =
+ SelectionUtils.getAdaptableObjects(selection, IResource.class);
+
+ WizardUtils.openAddResourcesToSessionWizard(new HashSet<>(selectedResources));
+
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute(
+ @Named(IServiceConstants.ACTIVE_SELECTION) @Optional ISelection selection) {
+ List resources = SelectionUtils.getAdaptableObjects(selection, IResource.class);
+ if (!(resources.size() > 0)) {
+ return false;
+ }
+ final ISarosSession session = sessionManager.getSession();
+ if (!(connectionHandler.isConnected() && session != null && session.hasWriteAccess())) {
+ return false;
+ }
+ Set sharedReferencePoints = session.getReferencePoints();
+ for (IResource resource : resources) {
+ saros.filesystem.IResource wrappedResource =
+ ResourceConverter.convertToResource(sharedReferencePoints, resource);
+ if (session.isShared(wrappedResource)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/menu/SessionLeaveHandler.java b/eclipse/src/saros/ui/handlers/menu/SessionLeaveHandler.java
new file mode 100644
index 0000000000..161fead514
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/SessionLeaveHandler.java
@@ -0,0 +1,29 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.CollaborationUtils;
+
+public class SessionLeaveHandler {
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public SessionLeaveHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute() {
+ CollaborationUtils.leaveSession();
+ return null;
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionHandler.isConnected() && sessionManager.getSession() != null;
+ }
+}
diff --git a/eclipse/src/saros/ui/command_handlers/ShareResourcesHandler.java b/eclipse/src/saros/ui/handlers/menu/ShareResourcesHandler.java
similarity index 53%
rename from eclipse/src/saros/ui/command_handlers/ShareResourcesHandler.java
rename to eclipse/src/saros/ui/handlers/menu/ShareResourcesHandler.java
index 3220ba4292..3985d555b5 100644
--- a/eclipse/src/saros/ui/command_handlers/ShareResourcesHandler.java
+++ b/eclipse/src/saros/ui/handlers/menu/ShareResourcesHandler.java
@@ -1,12 +1,19 @@
-package saros.ui.command_handlers;
+package saros.ui.handlers.menu;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
+import javax.inject.Named;
import org.eclipse.core.resources.IResource;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSessionManager;
import saros.ui.menu_contributions.StartSessionWithProjects;
import saros.ui.util.WizardUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
+import saros.ui.util.selection.SelectionUtils;
/**
* @JTourBusStop 1, Invitation Process:
@@ -35,12 +42,24 @@
*
* Notice that this is done via the {@link saros.ui.wizards.StartSessionWizard}.
*/
-public class ShareResourcesHandler extends AbstractHandler {
+public class ShareResourcesHandler {
- @Override
- public Object execute(ExecutionEvent event) throws ExecutionException {
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private ISarosSessionManager sessionManager;
+
+ public ShareResourcesHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @Execute
+ public Object execute(@Named(IServiceConstants.ACTIVE_SELECTION) @Optional ISelection selection) {
WizardUtils.openStartSessionWizard(
- SelectionRetrieverFactory.getSelectionRetriever(IResource.class).getSelection());
+ SelectionUtils.getAdaptableObjects(selection, IResource.class));
return null;
}
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionHandler.isConnected() && sessionManager.getSession() == null;
+ }
}
diff --git a/eclipse/src/saros/ui/handlers/menu/StartSarosConfigurationHandler.java b/eclipse/src/saros/ui/handlers/menu/StartSarosConfigurationHandler.java
new file mode 100644
index 0000000000..9285e12c55
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/menu/StartSarosConfigurationHandler.java
@@ -0,0 +1,13 @@
+package saros.ui.handlers.menu;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.ui.util.WizardUtils;
+
+public class StartSarosConfigurationHandler {
+
+ @Execute
+ public Object execute() {
+ WizardUtils.openSarosConfigurationWizard();
+ return null;
+ }
+}
diff --git a/eclipse/src/saros/ui/command_handlers/package-info.java b/eclipse/src/saros/ui/handlers/menu/package-info.java
similarity index 97%
rename from eclipse/src/saros/ui/command_handlers/package-info.java
rename to eclipse/src/saros/ui/handlers/menu/package-info.java
index 7166e16d61..4579d531c0 100644
--- a/eclipse/src/saros/ui/command_handlers/package-info.java
+++ b/eclipse/src/saros/ui/handlers/menu/package-info.java
@@ -24,4 +24,4 @@
* href="http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/guide/workbench_cmd_handlers.htm">plugin.xml
* - org.eclipse.ui.handlers extension point
*/
-package saros.ui.command_handlers;
+package saros.ui.handlers.menu;
diff --git a/eclipse/src/saros/ui/actions/ChangeColorAction.java b/eclipse/src/saros/ui/handlers/popup/ChangeColorHandler.java
similarity index 55%
rename from eclipse/src/saros/ui/actions/ChangeColorAction.java
rename to eclipse/src/saros/ui/handlers/popup/ChangeColorHandler.java
index 59df904d56..09fa31b415 100644
--- a/eclipse/src/saros/ui/actions/ChangeColorAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/ChangeColorHandler.java
@@ -1,23 +1,28 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.util.List;
-import org.eclipse.jface.action.Action;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
import saros.SarosPluginContext;
import saros.annotations.Component;
import saros.repackaged.picocontainer.annotations.Inject;
import saros.session.ISarosSession;
import saros.session.ISarosSessionManager;
import saros.session.User;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
-import saros.ui.util.selection.SelectionUtils;
import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.ui.wizards.ColorChooserWizard;
@@ -27,49 +32,63 @@
* new color or abort the process
*/
@Component(module = "action")
-public final class ChangeColorAction extends Action implements Disposable {
+public final class ChangeColorHandler {
- public static final String ACTION_ID = ChangeColorAction.class.getName();
+ public static final String ID = ChangeColorHandler.class.getName();
private ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateEnablement();
}
};
@Inject private ISarosSessionManager sessionManager;
- public ChangeColorAction() {
- super(Messages.ChangeColorAction_title);
+ private MDirectMenuItem changeColorMenuItem;
+
+ public ChangeColorHandler() {
SarosPluginContext.initComponent(this);
+ }
- setId(ACTION_ID);
- setToolTipText(Messages.ChangeColorAction_tooltip);
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService, EModelService modelService, MPart sarosView) {
+ selectionService.addSelectionListener(selectionListener);
- setImageDescriptor(
- ImageManager.getImageDescriptor("icons/elcl16/changecolor.png")); // $NON-NLS-1$
+ MPopupMenu popupMenu = null;
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ changeColorMenuItem = (MDirectMenuItem) menuItem;
+ }
updateEnablement();
}
public void updateEnablement() {
+ if (changeColorMenuItem == null) return;
+
List participants =
SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
ISarosSession session = sessionManager.getSession();
- setEnabled(
+ changeColorMenuItem.setEnabled(
session != null
&& participants.size() == 1
&& participants.get(0).equals(session.getLocalUser()));
}
- @Override
- public void run() {
+ @Execute
+ public void execute() {
ColorChooserWizard wizard = new ColorChooserWizard();
@@ -95,8 +114,8 @@ public void run() {
Messages.ChangeColorAction_message_text);
}
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
}
}
diff --git a/eclipse/src/saros/ui/actions/ChangeWriteAccessAction.java b/eclipse/src/saros/ui/handlers/popup/ChangeWriteAccessHandler.java
similarity index 59%
rename from eclipse/src/saros/ui/actions/ChangeWriteAccessAction.java
rename to eclipse/src/saros/ui/handlers/popup/ChangeWriteAccessHandler.java
index 44ee5edf72..170641ae38 100644
--- a/eclipse/src/saros/ui/actions/ChangeWriteAccessAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/ChangeWriteAccessHandler.java
@@ -1,20 +1,26 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.CancellationException;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.action.Action;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
import saros.SarosPluginContext;
import saros.repackaged.picocontainer.annotations.Inject;
import saros.session.ISarosSession;
@@ -24,46 +30,100 @@
import saros.session.SessionEndReason;
import saros.session.User;
import saros.session.User.Permission;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.util.ThreadUtils;
/**
* Change the write access of a session participant (granting write access, restricting to
* read-only).
*/
-public class ChangeWriteAccessAction extends Action implements Disposable {
+public class ChangeWriteAccessHandler {
- private static final Logger log = Logger.getLogger(ChangeWriteAccessAction.class);
+ private static final Logger log = Logger.getLogger(ChangeWriteAccessHandler.class);
public static final class WriteAccess {
- public static final String ACTION_ID =
- ChangeWriteAccessAction.class.getName() + "." + WriteAccess.class.getSimpleName();
-
- public static ChangeWriteAccessAction newInstance() {
- return new ChangeWriteAccessAction(
- ACTION_ID,
- Permission.WRITE_ACCESS,
- Messages.GiveWriteAccessAction_title,
- Messages.GiveWriteAccessAction_tooltip,
- ImageManager.ICON_CONTACT_SAROS_SUPPORT);
+ public static final String ID =
+ ChangeWriteAccessHandler.class.getName() + "." + WriteAccess.class.getSimpleName();
+
+ private ChangeWriteAccessHandler handler;
+
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService, EModelService modelService, MPart sarosView) {
+
+ MPopupMenu popupMenu = null;
+
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ MDirectMenuItem changeWriteAccessItem = (MDirectMenuItem) menuItem;
+ handler =
+ new ChangeWriteAccessHandler(
+ Permission.WRITE_ACCESS, selectionService, changeWriteAccessItem);
+ }
+ }
+
+ @Execute
+ public void execute() {
+ handler.execute();
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ handler.dispose();
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return handler.canExecute();
}
}
public static final class ReadOnly {
- public static final String ACTION_ID =
- ChangeWriteAccessAction.class.getName() + "." + ReadOnly.class.getSimpleName();
-
- public static ChangeWriteAccessAction newInstance() {
- return new ChangeWriteAccessAction(
- ACTION_ID,
- Permission.READONLY_ACCESS,
- Messages.RestrictToReadOnlyAccessAction_title,
- Messages.RestrictToReadOnlyAccessAction_tooltip,
- ImageManager.ICON_USER_SAROS_READONLY);
+ public static final String ID =
+ ChangeWriteAccessHandler.class.getName() + "." + ReadOnly.class.getSimpleName();
+
+ private ChangeWriteAccessHandler handler;
+
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService, EModelService modelService, MPart sarosView) {
+
+ MPopupMenu popupMenu = null;
+
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ MDirectMenuItem changeWriteAccessItem = (MDirectMenuItem) menuItem;
+ handler =
+ new ChangeWriteAccessHandler(
+ Permission.READONLY_ACCESS, selectionService, changeWriteAccessItem);
+ }
+ }
+
+ @Execute
+ public void execute() {
+ handler.execute();
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ handler.dispose();
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return handler.canExecute();
}
}
@@ -95,36 +155,25 @@ public void permissionChanged(User user) {
private ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateEnablement();
}
};
- private ChangeWriteAccessAction(
- final String id,
- final Permission permission,
- final String text,
- final String tooltip,
- final Image icon) {
+ private ESelectionService selectionService;
+ private MDirectMenuItem changeWriteAccessItem;
- super(text);
+ private ChangeWriteAccessHandler(
+ final Permission permission,
+ ESelectionService selectionService,
+ MDirectMenuItem changeWriteAccessItem) {
SarosPluginContext.initComponent(this);
-
- setId(id);
-
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return icon.getImageData();
- }
- });
-
- setToolTipText(tooltip);
-
this.permission = permission;
+ this.selectionService = selectionService;
+ this.changeWriteAccessItem = changeWriteAccessItem;
/*
* if SessionView is not "visible" on session start up this constructor
@@ -138,29 +187,38 @@ public ImageData getImageData() {
}
sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ selectionService.addSelectionListener(selectionListener);
updateEnablement();
}
- private void updateEnablement() {
+ private boolean getEnabledState() {
List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
boolean sessionRunning = (sessionManager.getSession() != null);
boolean selectedOneWithOppositePermission =
(participants.size() == 1 && participants.get(0).getPermission() != permission);
- setEnabled(sessionRunning && selectedOneWithOppositePermission);
+ return sessionRunning && selectedOneWithOppositePermission;
+ }
+
+ private void updateEnablement() {
+ if (changeWriteAccessItem == null) return;
+
+ changeWriteAccessItem.setEnabled(getEnabledState());
+ }
+
+ public boolean canExecute() {
+ return getEnabledState();
}
- @Override
public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ selectionService.removeSelectionListener(selectionListener);
sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
}
- @Override
- public void run() {
+ public void execute() {
ThreadUtils.runSafeSync(
log,
new Runnable() {
@@ -171,7 +229,8 @@ public void run() {
if (session == null) return;
List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
if (participants.size() == 1) {
User selected = participants.get(0);
if (selected.getPermission() != permission) {
diff --git a/eclipse/src/saros/ui/actions/DeleteContactAction.java b/eclipse/src/saros/ui/handlers/popup/DeleteContactHandler.java
similarity index 51%
rename from eclipse/src/saros/ui/actions/DeleteContactAction.java
rename to eclipse/src/saros/ui/handlers/popup/DeleteContactHandler.java
index dc8e90d657..97f1b38d9f 100644
--- a/eclipse/src/saros/ui/actions/DeleteContactAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/DeleteContactHandler.java
@@ -1,14 +1,26 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.text.MessageFormat;
import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.PlatformUI;
+import org.eclipse.jface.viewers.ISelection;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
import saros.SarosPluginContext;
import saros.communication.connection.ConnectionHandler;
import saros.communication.connection.IConnectionStateListener;
@@ -21,14 +33,13 @@
import saros.session.User;
import saros.ui.Messages;
import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.util.ThreadUtils;
-public class DeleteContactAction extends Action implements Disposable {
+public class DeleteContactHandler {
- public static final String ACTION_ID = DeleteContactAction.class.getName();
+ public static final String ID = DeleteContactHandler.class.getName();
- private static final Logger log = Logger.getLogger(DeleteContactAction.class);
+ private static final Logger log = Logger.getLogger(DeleteContactHandler.class);
protected IConnectionStateListener connectionListener = (state, error) -> updateEnablement();
@@ -38,41 +49,82 @@ public class DeleteContactAction extends Action implements Disposable {
@Inject private XMPPContactsService contactsService;
@Inject private ISarosSessionManager sessionManager;
+ private MDirectMenuItem deleteContact;
+ private ESelectionService selectionService;
+
+ private boolean workbenchIsClosing = false;
+
protected final String DELETE_ERROR_IN_SESSION =
Messages.DeleteContactAction_delete_error_in_session;
- public DeleteContactAction() {
- super(Messages.DeleteContactAction_title);
+ public DeleteContactHandler() {
+ SarosPluginContext.initComponent(this);
- setId(ACTION_ID);
- setToolTipText(Messages.DeleteContactAction_tooltip);
+ connectionHandler.addConnectionStateListener(connectionListener);
+ }
- IWorkbench workbench = PlatformUI.getWorkbench();
- setImageDescriptor(
- workbench.getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
+ @PostConstruct
+ public void postConstruct(
+ MPart sarosView,
+ EModelService modelService,
+ ESelectionService selectionService,
+ IEventBroker eb) {
+ this.selectionService = selectionService;
+ MPopupMenu popupMenu = null;
+
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ deleteContact = (MDirectMenuItem) menuItem;
+ }
- SarosPluginContext.initComponent(this);
+ eb.subscribe(
+ UILifeCycle.APP_SHUTDOWN_STARTED,
+ new EventHandler() {
+
+ @Override
+ public void handleEvent(Event event) {
+ workbenchIsClosing = true;
+ }
+ });
+
+ selectionService.addSelectionListener(selectionListener);
- connectionHandler.addConnectionStateListener(connectionListener);
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
updateEnablement();
}
+ @CanExecute
+ public boolean canExecute() {
+ return getEnabledState();
+ }
+
+ private boolean getEnabledState() {
+ List contacts =
+ SelectionUtils.getAdaptableObjects((ISelection) selectionService.getSelection(), JID.class);
+
+ return connectionHandler.isConnected() && contacts.size() == 1;
+ }
+
protected void updateEnablement() {
+ if (deleteContact == null) {
+ return;
+ }
try {
- List contacts =
- SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
- this.setEnabled(connectionHandler.isConnected() && contacts.size() == 1);
+ deleteContact.setEnabled(getEnabledState());
} catch (NullPointerException e) {
- this.setEnabled(false);
+ deleteContact.setEnabled(false);
} catch (Exception e) {
- if (!PlatformUI.getWorkbench().isClosing())
+ if (!workbenchIsClosing)
log.error("Unexpected error while updating enablement", e); // $NON-NLS-1$
}
}
/** @review runSafe OK */
- @Override
+ @Execute
public void run() {
ThreadUtils.runSafeSync(
log,
@@ -87,7 +139,8 @@ public void run() {
public void runDeleteAction() {
XMPPContact contact = null;
List selectedRosterEntries =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), XMPPContact.class);
if (selectedRosterEntries.size() == 1) {
contact = selectedRosterEntries.get(0);
}
@@ -122,9 +175,9 @@ public void runDeleteAction() {
}
}
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
connectionHandler.removeConnectionStateListener(connectionListener);
}
}
diff --git a/eclipse/src/saros/ui/actions/FollowThisPersonAction.java b/eclipse/src/saros/ui/handlers/popup/FollowThisPersonHandler.java
similarity index 59%
rename from eclipse/src/saros/ui/actions/FollowThisPersonAction.java
rename to eclipse/src/saros/ui/handlers/popup/FollowThisPersonHandler.java
index 8b86bcc0af..c5758f8e69 100644
--- a/eclipse/src/saros/ui/actions/FollowThisPersonAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/FollowThisPersonHandler.java
@@ -1,13 +1,19 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
import saros.SarosPluginContext;
import saros.annotations.Component;
import saros.editor.FollowModeManager;
@@ -18,20 +24,18 @@
import saros.session.ISessionLifecycleListener;
import saros.session.SessionEndReason;
import saros.session.User;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.util.ThreadUtils;
/** This follow mode action is used to select the person to follow. */
@Component(module = "action")
-public class FollowThisPersonAction extends Action implements Disposable {
+public class FollowThisPersonHandler {
- public static final String ACTION_ID = FollowThisPersonAction.class.getName();
+ public static final String ID = FollowThisPersonHandler.class.getName();
- private static final Logger log = Logger.getLogger(FollowThisPersonAction.class);
+ private static final Logger log = Logger.getLogger(FollowThisPersonHandler.class);
protected ISessionLifecycleListener sessionLifecycleListener =
new ISessionLifecycleListener() {
@@ -70,8 +74,9 @@ public void startedFollowing(User target) {
protected ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateActionEnablement();
}
};
@@ -80,38 +85,47 @@ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
private FollowModeManager followModeManager;
- public FollowThisPersonAction() {
- super(Messages.FollowThisPersonAction_follow_title);
+ private ESelectionService selectionService;
+ private MDirectMenuItem followThisPersonMenuItem;
+ public FollowThisPersonHandler() {
SarosPluginContext.initComponent(this);
+ }
- setImageDescriptor(
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ICON_USER_SAROS_FOLLOWMODE.getImageData();
- }
- });
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService, MPart sarosView, EModelService modelService) {
+ this.selectionService = selectionService;
+
+ MPopupMenu popupMenu = null;
- setToolTipText(Messages.FollowThisPersonAction_follow_tooltip);
- setId(ACTION_ID);
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ followThisPersonMenuItem = (MDirectMenuItem) menuItem;
+ }
sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ selectionService.addSelectionListener(selectionListener);
updateEnablement();
}
/** @review runSafe OK */
- @Override
- public void run() {
+ @Execute
+ public void execute() {
ThreadUtils.runSafeSync(
log,
new Runnable() {
@Override
public void run() {
List users =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
if (!canBeExecuted(users)) {
log.warn(
@@ -142,22 +156,24 @@ public void run() {
protected void updateEnablement() {
- List users = SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
+ List users =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
if (!canBeExecuted(users)) {
- setEnabled(false);
+ followThisPersonMenuItem.setEnabled(false);
return;
}
if (followModeManager.isFollowing(users.get(0))) {
- setText(Messages.FollowThisPersonAction_stop_follow_title);
- setToolTipText(Messages.FollowThisPersonAction_stop_follow_tooltip);
+ followThisPersonMenuItem.setLabel(Messages.FollowThisPersonAction_stop_follow_title);
+ followThisPersonMenuItem.setTooltip(Messages.FollowThisPersonAction_stop_follow_tooltip);
} else {
- setText(Messages.FollowThisPersonAction_follow_title);
- setToolTipText(Messages.FollowThisPersonAction_follow_tooltip);
+ followThisPersonMenuItem.setLabel(Messages.FollowThisPersonAction_follow_title);
+ followThisPersonMenuItem.setTooltip(Messages.FollowThisPersonAction_follow_tooltip);
}
- setEnabled(true);
+ followThisPersonMenuItem.setEnabled(true);
}
protected boolean canBeExecuted(List users) {
@@ -169,9 +185,9 @@ protected boolean canBeExecuted(List users) {
&& !users.get(0).isLocal();
}
- @Override
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
}
}
diff --git a/eclipse/src/saros/ui/handlers/popup/JumpToUserWithWriteAccessPositionHandler.java b/eclipse/src/saros/ui/handlers/popup/JumpToUserWithWriteAccessPositionHandler.java
new file mode 100644
index 0000000000..7cca7cb760
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/popup/JumpToUserWithWriteAccessPositionHandler.java
@@ -0,0 +1,136 @@
+package saros.ui.handlers.popup;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.apache.log4j.Logger;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.UIEvents.UILifeCycle;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+import saros.SarosPluginContext;
+import saros.annotations.Component;
+import saros.editor.EditorManager;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSessionManager;
+import saros.session.User;
+import saros.ui.util.selection.SelectionUtils;
+import saros.util.ThreadUtils;
+
+/** Action which triggers the viewport of the local user to be changed to a local user's one. */
+@Component(module = "action")
+public class JumpToUserWithWriteAccessPositionHandler {
+
+ public static final String ID = JumpToUserWithWriteAccessPositionHandler.class.getName();
+
+ private static final Logger log =
+ Logger.getLogger(JumpToUserWithWriteAccessPositionHandler.class);
+
+ protected ISelectionListener selectionListener =
+ new ISelectionListener() {
+
+ @Override
+ public void selectionChanged(MPart part, Object selection) {
+ updateEnablement();
+ }
+ };
+
+ @Inject protected ISarosSessionManager sessionManager;
+
+ @Inject protected EditorManager editorManager;
+
+ private ESelectionService selectionService;
+ private MDirectMenuItem jumpToUserWithWriteAccessPositionItem;
+
+ private boolean workbenchIsClosing = false;
+
+ public JumpToUserWithWriteAccessPositionHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService,
+ EModelService modelService,
+ MPart sarosView,
+ IEventBroker eb) {
+ this.selectionService = selectionService;
+
+ MPopupMenu popupMenu = null;
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+
+ eb.subscribe(
+ UILifeCycle.APP_SHUTDOWN_STARTED,
+ new EventHandler() {
+
+ @Override
+ public void handleEvent(Event event) {
+ workbenchIsClosing = true;
+ }
+ });
+
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ jumpToUserWithWriteAccessPositionItem = (MDirectMenuItem) menuItem;
+ }
+
+ selectionService.addSelectionListener(selectionListener);
+ updateEnablement();
+ }
+
+ public void updateEnablement() {
+ try {
+ List participants =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
+ jumpToUserWithWriteAccessPositionItem.setEnabled(
+ sessionManager.getSession() != null
+ && participants.size() == 1
+ && !participants.get(0).equals(sessionManager.getSession().getLocalUser()));
+ } catch (NullPointerException e) {
+ jumpToUserWithWriteAccessPositionItem.setEnabled(false);
+ } catch (Exception e) {
+ if (!workbenchIsClosing)
+ log.error("Unexpected error while updating enablement", e); // $NON-NLS-1$
+ }
+ }
+
+ /** @review runSafe OK */
+ @Execute
+ public void execute() {
+ ThreadUtils.runSafeSync(
+ log,
+ new Runnable() {
+ @Override
+ public void run() {
+ List participants =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
+ if (participants.size() == 1) {
+ editorManager.jumpToUser(participants.get(0));
+ } else {
+ log.warn("More than one participant selected."); // $NON-NLS-1$
+ }
+ }
+ });
+ }
+
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/popup/OpenChatHandler.java b/eclipse/src/saros/ui/handlers/popup/OpenChatHandler.java
new file mode 100644
index 0000000000..25adc427fb
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/popup/OpenChatHandler.java
@@ -0,0 +1,139 @@
+package saros.ui.handlers.popup;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.chat.single.SingleUserChatService;
+import saros.communication.connection.ConnectionHandler;
+import saros.net.xmpp.JID;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.User;
+import saros.ui.model.session.UserElement;
+import saros.ui.util.selection.SelectionUtils;
+import saros.ui.widgets.chat.ChatRoomsComposite;
+
+public class OpenChatHandler {
+
+ public static final String ID = OpenChatHandler.class.getName();
+
+ @Inject private ConnectionHandler connectionHandler;
+ @Inject private SingleUserChatService chatService;
+
+ private ISelectionListener selectionListener =
+ new ISelectionListener() {
+
+ @Override
+ public void selectionChanged(MPart part, Object selection) {
+ updateEnablement();
+ }
+ };
+
+ private MDirectMenuItem openChatMenuItem;
+ private ISelection selection;
+
+ public OpenChatHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService,
+ EModelService modelService,
+ MPart sarosView,
+ @Named(IServiceConstants.ACTIVE_SELECTION) ISelection activeSelection) {
+ this.selection = activeSelection;
+
+ MPopupMenu popupMenu = null;
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ openChatMenuItem = (MDirectMenuItem) menuItem;
+ }
+
+ selectionService.addSelectionListener(selectionListener);
+
+ updateEnablement();
+ }
+
+ @Execute
+ public void execute() {
+ JID localJID = connectionHandler.getLocalJID();
+ JID jid = getSelectedJID();
+
+ if (Objects.equals(localJID, jid)) return;
+
+ Map data = openChatMenuItem.getTransientData();
+ Object object = data.get("chatRoomsComposite");
+
+ if (object instanceof ChatRoomsComposite) {
+ ChatRoomsComposite chatRoomsComposite = (ChatRoomsComposite) object;
+ chatRoomsComposite.openChat(chatService.createChat(jid), true);
+ }
+ }
+
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionHandler.isConnected() && getSelectedJID() != null;
+ }
+
+ private void updateEnablement() {
+ if (openChatMenuItem == null) {
+ return;
+ }
+
+ if (!connectionHandler.isConnected()) {
+ openChatMenuItem.setEnabled(false);
+ return;
+ }
+
+ if (getSelectedJID() != null) {
+ openChatMenuItem.setEnabled(true);
+ }
+ }
+
+ private JID getSelectedJID() {
+ List users = SelectionUtils.getAdaptableObjects(selection, UserElement.class);
+ List contacts = SelectionUtils.getAdaptableObjects(selection, JID.class);
+
+ if (users.size() + contacts.size() == 1) {
+ if (users.size() == 1) {
+ User user = users.get(0).getUser();
+ if (user == null) {
+ return null;
+ }
+
+ return user.getJID();
+ } else {
+ return contacts.get(0);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/eclipse/src/saros/ui/actions/RemoveUserAction.java b/eclipse/src/saros/ui/handlers/popup/RemoveUserHandler.java
similarity index 64%
rename from eclipse/src/saros/ui/actions/RemoveUserAction.java
rename to eclipse/src/saros/ui/handlers/popup/RemoveUserHandler.java
index a62ebdd652..43915ab868 100644
--- a/eclipse/src/saros/ui/actions/RemoveUserAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/RemoveUserHandler.java
@@ -1,43 +1,54 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.action.Action;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
import saros.SarosPluginContext;
import saros.repackaged.picocontainer.annotations.Inject;
import saros.session.ISarosSession;
import saros.session.ISarosSessionManager;
import saros.session.ISessionLifecycleListener;
import saros.session.User;
-import saros.ui.ImageManager;
import saros.ui.util.SWTUtils;
import saros.ui.util.selection.SelectionUtils;
import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.util.CoreUtils;
-public class RemoveUserAction extends Action {
+public class RemoveUserHandler {
- public static final String ACTION_ID = RemoveUserAction.class.getName();
+ public static final String ID = RemoveUserHandler.class.getName();
- private static final Logger log = Logger.getLogger(RemoveUserAction.class);
+ private static final Logger log = Logger.getLogger(RemoveUserHandler.class);
@Inject private ISarosSessionManager sessionManager;
private volatile ISarosSession session;
+ private ESelectionService selectionService;
+ private MDirectMenuItem removeUserItem;
+
private ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateEnablement();
}
};
@@ -72,14 +83,26 @@ public void run() {
}
};
- public RemoveUserAction() {
- super("Remove from Session");
+ public RemoveUserHandler() {
SarosPluginContext.initComponent(this);
+ }
- setId(ACTION_ID);
- setImageDescriptor(ImageManager.getImageDescriptor("icons/elcl16/contact_remove_tsk.png"));
+ @PostConstruct
+ public void postConstruct(
+ ESelectionService selectionService, MPart sarosView, EModelService modelService) {
+ MPopupMenu popupMenu = null;
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ removeUserItem = (MDirectMenuItem) menuItem;
+ }
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ selectionService.addSelectionListener(selectionListener);
sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
session = sessionManager.getSession();
@@ -87,8 +110,8 @@ public RemoveUserAction() {
updateEnablement();
}
- @Override
- public void run() {
+ @Execute
+ public void execute() {
final ISarosSession currentSession = session;
@@ -131,8 +154,9 @@ public void run(IProgressMonitor monitor) throws InterruptedException {
}
}
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
}
@@ -140,9 +164,12 @@ public void dispose() {
private void updateEnablement() {
ISarosSession currentSession = session;
- List users = SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
+ List users =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
- setEnabled(currentSession != null && currentSession.isHost() && canRemoveUsers(users));
+ removeUserItem.setEnabled(
+ currentSession != null && currentSession.isHost() && canRemoveUsers(users));
}
private boolean canRemoveUsers(List users) {
diff --git a/eclipse/src/saros/ui/actions/RenameContactAction.java b/eclipse/src/saros/ui/handlers/popup/RenameContactHandler.java
similarity index 55%
rename from eclipse/src/saros/ui/actions/RenameContactAction.java
rename to eclipse/src/saros/ui/handlers/popup/RenameContactHandler.java
index 7c3ea95a5d..4f38fb5cc7 100644
--- a/eclipse/src/saros/ui/actions/RenameContactAction.java
+++ b/eclipse/src/saros/ui/handlers/popup/RenameContactHandler.java
@@ -1,15 +1,26 @@
-package saros.ui.actions;
+package saros.ui.handlers.popup;
import java.text.MessageFormat;
import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Named;
import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
import saros.SarosPluginContext;
import saros.communication.connection.ConnectionHandler;
import saros.communication.connection.IConnectionStateListener;
@@ -17,26 +28,25 @@
import saros.net.xmpp.contact.XMPPContact;
import saros.net.xmpp.contact.XMPPContactsService;
import saros.repackaged.picocontainer.annotations.Inject;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
import saros.ui.util.selection.SelectionUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.util.ThreadUtils;
/** Renames the nickname of the selected roster entry. */
-public class RenameContactAction extends Action {
+public class RenameContactHandler {
- public static final String ACTION_ID = RenameContactAction.class.getName();
+ public static final String ID = RenameContactHandler.class.getName();
- private static final Logger log = Logger.getLogger(RenameContactAction.class);
+ private static final Logger log = Logger.getLogger(RenameContactHandler.class);
private IConnectionStateListener connectionListener = (state, error) -> updateEnablement();
protected ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateEnablement();
}
};
@@ -44,29 +54,58 @@ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
@Inject private ConnectionHandler connectionHandler;
@Inject private XMPPContactsService contactsService;
- public RenameContactAction() {
- super(Messages.RenameContactAction_title);
-
- setId(ACTION_ID);
- setToolTipText(Messages.RenameContactAction_tooltip);
- setImageDescriptor(ImageManager.ETOOL_EDIT);
+ private MDirectMenuItem renameContactMenuItem;
+ private ESelectionService selectionService;
+ public RenameContactHandler() {
SarosPluginContext.initComponent(this);
+ }
+ @PostConstruct
+ public void postConstruct(
+ EModelService modelService, ESelectionService selectionService, MPart sarosView) {
+ this.selectionService = selectionService;
+
+ MPopupMenu popupMenu = null;
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ // Search for menu item renameContact
+ MUIElement menuItem = modelService.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ renameContactMenuItem = (MDirectMenuItem) menuItem;
+ }
connectionHandler.addConnectionStateListener(connectionListener);
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ selectionService.addSelectionListener(selectionListener);
+
updateEnablement();
}
+ @CanExecute
+ public boolean canExecute() {
+ return getEnabledState();
+ }
+
protected void updateEnablement() {
- List contacts = SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
+ if (renameContactMenuItem == null) {
+ return;
+ }
- setEnabled(connectionHandler.isConnected() && contacts.size() == 1);
+ renameContactMenuItem.setEnabled(getEnabledState());
}
- @Override
- public void run() {
+ private boolean getEnabledState() {
+ List contacts =
+ SelectionUtils.getAdaptableObjects((ISelection) selectionService.getSelection(), JID.class);
+
+ return connectionHandler.isConnected() && contacts.size() == 1;
+ }
+
+ @Execute
+ public void execute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection activeSelection) {
ThreadUtils.runSafeSync(
log,
new Runnable() {
@@ -74,7 +113,8 @@ public void run() {
public void run() {
XMPPContact contact = null;
List selectedRosterEntries =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
+ SelectionUtils.getAdaptableObjects(activeSelection, XMPPContact.class);
+
if (selectedRosterEntries.size() == 1) {
contact = selectedRosterEntries.get(0);
/*
@@ -116,8 +156,9 @@ public void run() {
});
}
- public void dispose() {
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
connectionHandler.removeConnectionStateListener(connectionListener);
}
}
diff --git a/eclipse/src/saros/ui/handlers/popup/RequestSessionInviteHandler.java b/eclipse/src/saros/ui/handlers/popup/RequestSessionInviteHandler.java
new file mode 100644
index 0000000000..07be045fc5
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/popup/RequestSessionInviteHandler.java
@@ -0,0 +1,106 @@
+package saros.ui.handlers.popup;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.extensions.JoinSessionRequestExtension;
+import saros.net.ITransmitter;
+import saros.net.xmpp.JID;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.ui.util.selection.SelectionUtils;
+
+/**
+ * Action for requesting an invitation to a session from a contact.
+ *
+ * This currently relies on the fact, that only Saros/S has a working JoinSessionRequestHandler.
+ * To make this feature generic in the future we need to add another XMPP namespace
+ */
+public class RequestSessionInviteHandler {
+
+ @Inject private ISarosSessionManager sessionManager;
+ @Inject private ITransmitter transmitter;
+
+ private ESelectionService selectionService;
+ private MDirectMenuItem requestSessionInviteMenuItem;
+
+ private ISelectionListener selectionListener =
+ new ISelectionListener() {
+
+ @Override
+ public void selectionChanged(MPart part, Object selection) {
+ updateActionState();
+ }
+ };
+ public static final String ID = RequestSessionInviteHandler.class.getName();
+
+ public RequestSessionInviteHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(
+ EModelService modelService, ESelectionService selectionService, MPart sarosView) {
+ this.selectionService = selectionService;
+
+ MPopupMenu popupMenu = null;
+
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+
+ Object menuElement = modelService.find(ID, popupMenu);
+ if (menuElement instanceof MDirectMenuItem) {
+ requestSessionInviteMenuItem = (MDirectMenuItem) menuElement;
+ }
+
+ selectionService.addSelectionListener(selectionListener);
+ updateActionState();
+ }
+
+ @Execute
+ public void execute() {
+ ISarosSession session = sessionManager.getSession();
+ JID jid = getSelectedJID();
+ if (session != null || jid == null) {
+ return;
+ }
+
+ transmitter.sendPacketExtension(
+ jid, JoinSessionRequestExtension.PROVIDER.create(new JoinSessionRequestExtension()));
+ }
+
+ private JID getSelectedJID() {
+ List selected =
+ SelectionUtils.getAdaptableObjects((ISelection) selectionService.getSelection(), JID.class);
+
+ if (selected.size() != 1) return null;
+
+ return selected.get(0);
+ }
+
+ private void updateActionState() {
+ if (requestSessionInviteMenuItem == null) return;
+
+ ISarosSession session = sessionManager.getSession();
+ requestSessionInviteMenuItem.setEnabled(session == null && getSelectedJID() != null);
+ }
+
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/popup/SendFileHandler.java b/eclipse/src/saros/ui/handlers/popup/SendFileHandler.java
new file mode 100644
index 0000000000..b7ed966a23
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/popup/SendFileHandler.java
@@ -0,0 +1,115 @@
+package saros.ui.handlers.popup;
+
+import java.io.File;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import saros.net.xmpp.JID;
+import saros.net.xmpp.contact.XMPPContact;
+import saros.session.User;
+import saros.ui.Messages;
+import saros.ui.jobs.OutgoingFileTransferJob;
+import saros.ui.util.SWTUtils;
+import saros.ui.util.selection.SelectionUtils;
+
+/** Action for sending a file over XMPP. */
+public class SendFileHandler {
+
+ public static final String ID = SendFileHandler.class.getName();
+
+ private ISelectionListener selectionListener = (part, selection) -> updateEnablement();
+
+ private MDirectMenuItem sendFileMenuItem;
+ private ESelectionService selectionService;
+
+ @PostConstruct
+ public void postConstruct(
+ MPart sarosView, EModelService service, ESelectionService selectionService) {
+ selectionService.addSelectionListener(selectionListener);
+ this.selectionService = selectionService;
+ // TODO: create icon
+
+ MPopupMenu popupMenu = null;
+
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+ MUIElement menuItem = service.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ sendFileMenuItem = (MDirectMenuItem) menuItem;
+ }
+
+ updateEnablement();
+ }
+
+ @Execute
+ public void run() {
+ JID jid = getSelectedJID();
+ if (jid == null) return;
+
+ FileDialog fd = new FileDialog(SWTUtils.getShell(), SWT.OPEN);
+ fd.setText(Messages.SendFileAction_filedialog_text);
+
+ String filename = fd.open();
+ if (filename == null) return;
+
+ File file = new File(filename);
+ if (file.isDirectory()) return;
+
+ Job job = new OutgoingFileTransferJob(jid, file);
+ job.setUser(true);
+ job.schedule();
+ }
+
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
+ }
+
+ private void updateEnablement() {
+ if (sendFileMenuItem == null) return;
+
+ sendFileMenuItem.setEnabled(getSelectedJID() != null);
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return getSelectedJID() != null;
+ }
+
+ private JID getSelectedJID() {
+ List sessionUsers =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), User.class);
+
+ List contacts =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), XMPPContact.class);
+
+ // currently only one transfer per click (maybe improved later)
+ if (contacts.size() + sessionUsers.size() != 1) return null;
+
+ if (sessionUsers.size() == 1) {
+ if (sessionUsers.get(0).isLocal()) return null;
+ return sessionUsers.get(0).getJID();
+ }
+
+ return contacts.get(0).getOnlineJid().orElse(null);
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/popup/SkypeHandler.java b/eclipse/src/saros/ui/handlers/popup/SkypeHandler.java
new file mode 100644
index 0000000000..09dfa357ed
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/popup/SkypeHandler.java
@@ -0,0 +1,123 @@
+package saros.ui.handlers.popup;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.hyperlink.URLHyperlink;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.SkypeManager;
+import saros.net.xmpp.contact.XMPPContact;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.ui.util.selection.SelectionUtils;
+
+/** An action for starting a Skype Audio Session to other contacts. */
+public class SkypeHandler {
+
+ public static final String ID = SkypeHandler.class.getName();
+
+ private ISelectionListener selectionListener =
+ new ISelectionListener() {
+
+ @Override
+ public void selectionChanged(MPart part, Object selection) {
+ updateEnablement();
+ }
+ };
+
+ @Inject private SkypeManager skypeManager;
+
+ private MDirectMenuItem skypeMenuEntry;
+ private ESelectionService selectionService;
+
+ public SkypeHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(
+ EModelService service, MPart sarosView, ESelectionService selectionService) {
+ this.selectionService = selectionService;
+
+ MPopupMenu popupMenu = null;
+ for (MMenu menu : sarosView.getMenus()) {
+ if (menu instanceof MPopupMenu) {
+ popupMenu = (MPopupMenu) menu;
+ }
+ }
+
+ MUIElement menuItem = service.find(ID, popupMenu);
+ if (menuItem instanceof MDirectMenuItem) {
+ skypeMenuEntry = (MDirectMenuItem) menuItem;
+ }
+
+ selectionService.addSelectionListener(selectionListener);
+ updateEnablement();
+ }
+
+ private void updateEnablement() {
+ if (skypeMenuEntry == null) {
+ return;
+ }
+
+ skypeMenuEntry.setEnabled(getEnabledState());
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return getEnabledState();
+ }
+
+ private boolean getEnabledState() {
+ final List contacts =
+ SelectionUtils.getAdaptableObjects(
+ (ISelection) selectionService.getSelection(), XMPPContact.class);
+
+ if (contacts.size() != 1) return false;
+
+ final String skypeName = skypeManager.getSkypeName(contacts.get(0));
+
+ return SkypeManager.isSkypeAvailable(false)
+ && skypeName != null
+ && !SkypeManager.isEchoService(skypeName);
+ }
+
+ @Execute
+ public void run(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection activeSelection) {
+
+ final List participants =
+ SelectionUtils.getAdaptableObjects(activeSelection, XMPPContact.class);
+
+ if (participants.size() != 1) return;
+
+ final String skypeName = skypeManager.getSkypeName(participants.get(0));
+
+ if (skypeName == null || SkypeManager.isEchoService(skypeName)) return;
+
+ final String uri = SkypeManager.getAudioCallUri(skypeName);
+
+ if (uri == null) return;
+
+ final URLHyperlink link = new URLHyperlink(new Region(0, 0), uri);
+
+ link.open();
+ }
+
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
+ selectionService.removeSelectionListener(selectionListener);
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/toolbar/ChangeXMPPAccountHandler.java b/eclipse/src/saros/ui/handlers/toolbar/ChangeXMPPAccountHandler.java
new file mode 100644
index 0000000000..0e66a4055d
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/toolbar/ChangeXMPPAccountHandler.java
@@ -0,0 +1,215 @@
+package saros.ui.handlers.toolbar;
+
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.apache.log4j.Logger;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.dialogs.MessageDialog;
+import saros.SarosPluginContext;
+import saros.account.IAccountStoreListener;
+import saros.account.XMPPAccount;
+import saros.account.XMPPAccountStore;
+import saros.communication.connection.ConnectionHandler;
+import saros.communication.connection.IConnectionStateListener;
+import saros.net.ConnectionState;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.ui.Messages;
+import saros.ui.util.SWTUtils;
+import saros.ui.util.XMPPConnectionSupport;
+
+/**
+ * In addition to the connect/disconnect action, this allows the user to switch between accounts.
+ */
+public class ChangeXMPPAccountHandler {
+
+ static class AddAccountToMenuHandler {
+
+ @Execute
+ public void execute(MDirectMenuItem item) {
+ defaultAccountChanged = false;
+
+ Map objectData = item.getTransientData();
+ Object data = objectData.get("account");
+
+ if (data instanceof XMPPAccount) {
+ XMPPAccount account = (XMPPAccount) data;
+ XMPPConnectionSupport.getInstance().connect(account, false, false);
+ }
+ }
+ }
+
+ public static final String ID = ChangeXMPPAccountHandler.class.getName();
+
+ private static final String PLATFORM_PLUGIN_SAROS_ECLIPSE = "platform:/plugin/saros.eclipse";
+
+ private static final Logger log = Logger.getLogger(ChangeXMPPAccountHandler.class);
+
+ @Inject private XMPPAccountStore accountService;
+
+ @Inject private ConnectionHandler connectionHandler;
+
+ private boolean isConnectionError;
+
+ protected static boolean defaultAccountChanged;
+
+ private final IConnectionStateListener connectionStateListener =
+ (state, error) -> SWTUtils.runSafeSWTAsync(log, () -> updateStatus(state));
+
+ private final IAccountStoreListener accountStoreListener =
+ new IAccountStoreListener() {
+ @Override
+ public void activeAccountChanged(final XMPPAccount activeAccount) {
+ defaultAccountChanged = true;
+ }
+ };
+
+ private boolean isEnabled = false;
+
+ private MToolItem connectToolItem;
+
+ private ECommandService commandService;
+
+ public ChangeXMPPAccountHandler() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(
+ EModelService service, MPart sarosView, ECommandService commandService) {
+ this.commandService = commandService;
+
+ MUIElement toolBarElement = service.find(ID, sarosView.getToolbar());
+ if (toolBarElement instanceof MToolItem) {
+ connectToolItem = (MToolItem) toolBarElement;
+ }
+
+ connectionHandler.addConnectionStateListener(connectionStateListener);
+ updateStatus(connectionHandler.getConnectionState());
+
+ accountService.addListener(accountStoreListener);
+ }
+
+ @Execute
+ public void execute() {
+ if (connectionHandler.isConnected()) {
+ XMPPConnectionSupport.getInstance().disconnect();
+ return;
+ }
+
+ final XMPPAccount lastUsedAccount = XMPPConnectionSupport.getInstance().getCurrentXMPPAccount();
+
+ final List accounts = accountService.getAllAccounts();
+
+ final boolean exists = accounts.indexOf(lastUsedAccount) != -1;
+
+ final XMPPAccount defaultAccount = accountService.getDefaultAccount();
+
+ final boolean isEmpty = accountService.isEmpty();
+
+ if (!exists && (defaultAccount == null || isEmpty)) {
+ if (!MessageDialog.openQuestion(
+ SWTUtils.getShell(),
+ "Default account missing",
+ "A default account has not been set yet. Do you want set a default account?")) return;
+
+ SWTUtils.runSafeSWTAsync(log, this::openPreferences);
+ return;
+ }
+
+ final XMPPAccount accountToConnect;
+
+ if (defaultAccountChanged || !exists) {
+ defaultAccountChanged = false;
+ accountToConnect = defaultAccount;
+ } else {
+ accountToConnect = lastUsedAccount;
+ }
+
+ XMPPConnectionSupport.getInstance().connect(accountToConnect, false, false);
+ }
+
+ @PreDestroy
+ public void dispose() {
+ connectionHandler.removeConnectionStateListener(connectionStateListener);
+ accountService.removeListener(accountStoreListener);
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return isEnabled;
+ }
+
+ private void updateStatus(ConnectionState state) {
+ if (connectToolItem == null) {
+ return;
+ }
+ try {
+ switch (state) {
+ case CONNECTED:
+ isConnectionError = false;
+ connectToolItem.setLabel(Messages.ChangeXMPPAccountAction_disconnect);
+ connectToolItem.setIconURI(
+ PLATFORM_PLUGIN_SAROS_ECLIPSE + "/icons/elcl16/xmpp_disconnect_tsk.png");
+ break;
+ case CONNECTING:
+ isConnectionError = false;
+ connectToolItem.setLabel(Messages.ChangeXMPPAccountAction_connecting);
+ connectToolItem.setIconURI(
+ PLATFORM_PLUGIN_SAROS_ECLIPSE + "/icons/elcl16/xmpp_connecting_misc.png");
+ break;
+ case ERROR:
+ isConnectionError = true;
+ connectToolItem.setIconURI(
+ PLATFORM_PLUGIN_SAROS_ECLIPSE + "/icons/elcl16/xmpp_connection_error_misc.png");
+ break;
+ case NOT_CONNECTED:
+ connectToolItem.setLabel(Messages.ChangeXMPPAccountAction_connect);
+
+ if (!isConnectionError)
+ connectToolItem.setIconURI(
+ PLATFORM_PLUGIN_SAROS_ECLIPSE + "/icons/elcl16/xmpp_connect_tsk.png");
+ break;
+ case DISCONNECTING:
+ default:
+ isConnectionError = false;
+ connectToolItem.setLabel(Messages.ChangeXMPPAccountAction_disconnecting);
+ connectToolItem.setIconURI(
+ PLATFORM_PLUGIN_SAROS_ECLIPSE + "/icons/elcl16/xmpp_disconnecting_misc.png");
+ break;
+ }
+
+ boolean setEnabled =
+ state == ConnectionState.CONNECTED
+ || state == ConnectionState.NOT_CONNECTED
+ || state == ConnectionState.ERROR;
+
+ isEnabled = setEnabled;
+
+ connectToolItem.setEnabled(setEnabled);
+
+ } catch (RuntimeException e) {
+ log.error("Internal error in ChangeXMPPAccountAction:", e);
+ }
+ }
+
+ private void openPreferences() {
+ Command openPreferencesCmd =
+ commandService.getCommand("saros.ui.commands.OpenSarosPreferences");
+ try {
+ openPreferencesCmd.executeWithChecks(new ExecutionEvent());
+ } catch (Exception e) {
+ log.debug("Could execute command", e);
+ }
+ }
+}
diff --git a/eclipse/src/saros/ui/actions/ConsistencyAction.java b/eclipse/src/saros/ui/handlers/toolbar/ConsistencyHandler.java
similarity index 81%
rename from eclipse/src/saros/ui/actions/ConsistencyAction.java
rename to eclipse/src/saros/ui/handlers/toolbar/ConsistencyHandler.java
index ef1ff7220b..625526aa1f 100644
--- a/eclipse/src/saros/ui/actions/ConsistencyAction.java
+++ b/eclipse/src/saros/ui/handlers/toolbar/ConsistencyHandler.java
@@ -1,22 +1,26 @@
-package saros.ui.actions;
+package saros.ui.handlers.toolbar;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.action.Action;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
@@ -33,7 +37,6 @@
import saros.session.ISarosSessionManager;
import saros.session.ISessionLifecycleListener;
import saros.session.SessionEndReason;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
import saros.ui.views.SarosView;
@@ -47,11 +50,11 @@
* will display "bar" if the action is disabled.
*/
@Component(module = "action")
-public class ConsistencyAction extends Action implements Disposable {
+public class ConsistencyHandler {
- public static final String ACTION_ID = ConsistencyAction.class.getName();
+ public static final String ID = ConsistencyHandler.class.getName();
- private static final Logger log = Logger.getLogger(ConsistencyAction.class);
+ private static final Logger log = Logger.getLogger(ConsistencyHandler.class);
private static final int MIN_ALPHA_VALUE = 64;
private static final int MAX_ALPHA_VALUE = 255;
@@ -61,25 +64,11 @@ public class ConsistencyAction extends Action implements Disposable {
private static final int FADE_DOWN = -1;
private static final int FADE_UP = 1;
- private static final ImageDescriptor IN_SYNC =
- ImageManager.getImageDescriptor("icons/etool16/in_sync.png"); // $NON-NLS-1$;
+ private boolean isConsistent = false;
- private static final Image OUT_SYNC =
- ImageManager.getImage("icons/etool16/out_sync.png"); // $NON-NLS-1$;
-
- private static class MemoryImageDescriptor extends ImageDescriptor {
-
- private final ImageData data;
-
- public MemoryImageDescriptor(ImageData data) {
- this.data = data;
- }
-
- @Override
- public ImageData getImageData() {
- return data;
- }
- }
+ private static final String IN_SYNC = "platform:/plugin/saros.eclipse/icons/etool16/in_sync.png";
+ private static final String OUT_SYNC =
+ "platform:/plugin/saros.eclipse/icons/etool16/out_sync.png";
private final ISessionLifecycleListener sessionLifecycleListener =
new ISessionLifecycleListener() {
@@ -111,12 +100,9 @@ public void setValue(Boolean newValue) {
private volatile ISarosSession sarosSession;
- public ConsistencyAction() {
-
- setId(ACTION_ID);
- setImageDescriptor(IN_SYNC);
- setToolTipText(Messages.ConsistencyAction_tooltip_no_inconsistency);
+ private MToolItem consistencyToolItem;
+ public ConsistencyHandler() {
SarosPluginContext.initComponent(this);
sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
@@ -124,6 +110,19 @@ public ConsistencyAction() {
setSession(sessionManager.getSession());
}
+ @PostConstruct
+ public void postConstruct(EModelService service, MPart sarosView) {
+ MUIElement toolItem = service.find(ID, sarosView.getToolbar());
+ if (toolItem instanceof MToolItem) {
+ consistencyToolItem = (MToolItem) toolItem;
+ }
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return isConsistent;
+ }
+
private void setSession(ISarosSession newSession) {
// TODO Why are we removing the listener and adding it again?
@@ -134,13 +133,18 @@ private void setSession(ISarosSession newSession) {
sarosSession = newSession;
- if (sarosSession != null) setDisabledImageDescriptor(IN_SYNC);
- else setDisabledImageDescriptor(null);
+ if (consistencyToolItem == null) return;
+
+ if (sarosSession != null) {
+ consistencyToolItem.setIconURI(IN_SYNC);
+ } else {
+ consistencyToolItem.setIconURI(null);
+ }
if (sarosSession != null) {
inconsistentObservable.addAndNotify(isConsistencyListener);
} else {
- setEnabled(false);
+ consistencyToolItem.setEnabled(false);
/*
* make sure we reset the default "enabled image" otherwise the GUI
@@ -152,14 +156,13 @@ private void setSession(ISarosSession newSession) {
new Runnable() {
@Override
public void run() {
- setImageDescriptor(IN_SYNC);
+ consistencyToolItem.setIconURI(IN_SYNC);
}
});
}
}
private void handleConsistencyChange(Boolean isInconsistent) {
-
final ISarosSession currentSession = sarosSession;
if (currentSession == null) return;
@@ -184,11 +187,13 @@ private void handleConsistencyChange(Boolean isInconsistent) {
"Inconsistency indicator goes: " //$NON-NLS-1$
+ (isInconsistent ? "on" : "off")); // $NON-NLS-1$ //$NON-NLS-2$
- setEnabled(isInconsistent);
+ if (consistencyToolItem != null) {
+ consistencyToolItem.setEnabled(isInconsistent);
- if (!isInconsistent) {
- setToolTipText(Messages.ConsistencyAction_tooltip_no_inconsistency);
- return;
+ if (!isInconsistent) {
+ consistencyToolItem.setTooltip(Messages.ConsistencyAction_tooltip_no_inconsistency);
+ return;
+ }
}
SWTUtils.runSafeSWTSync(
@@ -223,9 +228,11 @@ public void run() {
String files = sb.toString();
// set tooltip
- setToolTipText(
- MessageFormat.format(
- Messages.ConsistencyAction_tooltip_inconsistency_detected, files));
+ if (consistencyToolItem != null) {
+ consistencyToolItem.setTooltip(
+ MessageFormat.format(
+ Messages.ConsistencyAction_tooltip_inconsistency_detected, files));
+ }
// TODO Balloon is too aggressive at the moment, when
// the host is slow in sending changes (for instance
@@ -240,7 +247,7 @@ public void run() {
});
}
- @Override
+ @Execute
public void run() {
final ISarosSession currentSession = sarosSession;
@@ -329,7 +336,7 @@ public void run(IProgressMonitor monitor) throws InterruptedException {
}
}
- @Override
+ @PreDestroy
public void dispose() {
sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
}
@@ -340,7 +347,11 @@ private void startFading(final int startValue, final int direction) {
isFading = false;
- if (display.isDisposed() || !isEnabled()) return;
+ if (consistencyToolItem == null) {
+ return;
+ }
+
+ if (display.isDisposed() || !consistencyToolItem.isEnabled()) return;
isFading = true;
@@ -350,9 +361,8 @@ private void startFading(final int startValue, final int direction) {
@Override
public void run() {
-
- if (!isEnabled()) {
- setImageDescriptor(IN_SYNC);
+ if (!consistencyToolItem.isEnabled()) {
+ consistencyToolItem.setIconURI(IN_SYNC);
isFading = false;
return;
}
@@ -368,32 +378,10 @@ public void run() {
newDirection = FADE_UP;
}
- setImageDescriptor(new MemoryImageDescriptor(modifyAlphaChannel(OUT_SYNC, newValue)));
+ // TODO: create modified icon
startFading(newValue, newDirection);
}
});
}
-
- private static ImageData modifyAlphaChannel(Image image, int alpha) {
-
- if (alpha < 0) alpha = 0;
-
- if (alpha > 255) alpha = 255;
-
- ImageData data = image.getImageData();
-
- for (int x = 0; x < data.width; x++) {
- for (int y = 0; y < data.height; y++) {
- int a = data.getAlpha(x, y);
-
- // value depends on the image, must be determined empirically
- if (a <= MIN_ALPHA_VALUE) continue;
-
- data.setAlpha(x, y, alpha);
- }
- }
-
- return data;
- }
}
diff --git a/eclipse/src/saros/ui/actions/FollowModeAction.java b/eclipse/src/saros/ui/handlers/toolbar/FollowModeHandler.java
similarity index 59%
rename from eclipse/src/saros/ui/actions/FollowModeAction.java
rename to eclipse/src/saros/ui/handlers/toolbar/FollowModeHandler.java
index b1b4460aa1..56bb28ce30 100644
--- a/eclipse/src/saros/ui/actions/FollowModeAction.java
+++ b/eclipse/src/saros/ui/handlers/toolbar/FollowModeHandler.java
@@ -1,23 +1,25 @@
-package saros.ui.actions;
+package saros.ui.handlers.toolbar;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.ActionContributionItem;
-import org.eclipse.jface.action.IMenuCreator;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.di.AboutToShow;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.ISelectionListener;
import saros.SarosPluginContext;
import saros.editor.FollowModeManager;
import saros.editor.IFollowModeListener;
@@ -28,23 +30,35 @@
import saros.session.ISessionListener;
import saros.session.SessionEndReason;
import saros.session.User;
-import saros.ui.ImageManager;
import saros.ui.Messages;
import saros.ui.util.SWTUtils;
-import saros.ui.util.selection.SelectionUtils;
import saros.util.CoreUtils;
/** Action to enter into FollowMode via toolbar. */
-public class FollowModeAction extends Action implements IMenuCreator, Disposable {
+public class FollowModeHandler {
- public static final String ACTION_ID = FollowModeAction.class.getName();
+ public static final String ID = FollowModeHandler.class.getName();
- private static final Logger log = Logger.getLogger(FollowModeAction.class);
+ static class FollowUserHandler {
+
+ @Execute
+ public void execute(MDirectMenuItem item) {
+ Map itemData = item.getTransientData();
+ Object user = itemData.get("user");
+
+ if (user instanceof User || user == null) {
+ followUser((User) user);
+ }
+ }
+ }
+
+ private static final Logger log = Logger.getLogger(FollowModeHandler.class);
private ISelectionListener selectionListener =
new ISelectionListener() {
+
@Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged(MPart part, Object selection) {
updateEnablement();
}
};
@@ -102,7 +116,7 @@ public void sessionStarted(final ISarosSession session) {
public void run() {
currentlyFollowedUser = followModeManager.getFollowedUser();
- FollowModeAction.this.session = session;
+ FollowModeHandler.this.session = session;
currentRemoteSessionUsers.clear();
currentRemoteSessionUsers.addAll(session.getRemoteUsers());
updateEnablement();
@@ -124,7 +138,7 @@ public void sessionEnded(ISarosSession oldSarosSession, SessionEndReason reason)
@Override
public void run() {
- FollowModeAction.this.session = null;
+ FollowModeHandler.this.session = null;
currentRemoteSessionUsers.clear();
updateEnablement();
}
@@ -164,133 +178,91 @@ public void run() {
@Inject private ISarosSessionManager sessionManager;
- private FollowModeManager followModeManager;
+ private static FollowModeManager followModeManager;
private ISarosSession session;
private User currentlyFollowedUser;
- private Menu followUserMenu;
-
private final Set currentRemoteSessionUsers = new LinkedHashSet();
- private final ImageDescriptor followModeEnabledImageDescriptor =
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ICON_USER_SAROS_FOLLOWMODE.getImageData();
- }
- };
+ private final String followModeEnabledImageURI =
+ "platform:/plugin/saros.eclipse/icons/merged16/user_saros_followmode_enabled.png";
- private final ImageDescriptor followModeDisabledImageDescriptor =
- new ImageDescriptor() {
- @Override
- public ImageData getImageData() {
- return ImageManager.ICON_USER_SAROS_FOLLOWMODE_DISABLED.getImageData();
- }
- };
+ private final String followModeDisabledImageURI =
+ "platform:/plugin/saros.eclipse/icons/merged16/user_saros_followmode_disabled.png";
- public FollowModeAction() {
+ public FollowModeHandler() {
SarosPluginContext.initComponent(this);
- setId(ACTION_ID);
- setText(Messages.FollowModeAction_enter_followmode);
- setMenuCreator(this);
-
session = sessionManager.getSession();
sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
+ }
+
+ private MDirectToolItem followModeItem;
- SelectionUtils.getSelectionService().addSelectionListener(selectionListener);
+ @PostConstruct
+ public void postConstruct(
+ EModelService service, MPart sarosView, ESelectionService selectionService) {
+ MUIElement toolbarElement = service.find(ID, sarosView.getToolbar());
+
+ if (toolbarElement instanceof MDirectToolItem) {
+ followModeItem = (MDirectToolItem) toolbarElement;
+ }
+
+ selectionService.addSelectionListener(selectionListener);
if (session != null) currentRemoteSessionUsers.addAll(session.getRemoteUsers());
updateEnablement();
}
- @Override
- public void run() {
+ @Execute
+ public void run(MDirectToolItem toolBarElement) {
if (session == null) return;
- if (!isEnabled()) return;
+ if (!toolBarElement.isEnabled()) return;
followUser(getNextUserToFollow());
}
- @Override
- public void dispose() {
- if (followUserMenu != null) followUserMenu.dispose();
-
+ @PreDestroy
+ public void dispose(ESelectionService selectionService) {
sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
- SelectionUtils.getSelectionService().removeSelectionListener(selectionListener);
+ selectionService.removeSelectionListener(selectionListener);
}
- @Override
- public Menu getMenu(Control parent) {
- if (followUserMenu != null) followUserMenu.dispose();
-
- followUserMenu = null;
-
- if (session == null) return null;
-
- followUserMenu = new Menu(parent);
+ @AboutToShow
+ public void createMenu(List items, EModelService service) {
+ if (session == null) return;
List users = new ArrayList(currentRemoteSessionUsers);
- for (User user : users) addActionToMenu(followUserMenu, createAction(user));
+ for (User user : users) {
+ // The additional @ is needed because @ has special meaning in
+ // Action#setText(), see JavaDoc of Action().
- new MenuItem(followUserMenu, SWT.SEPARATOR);
+ String followUserMessage = getFollowUserMessage(user);
- Action disableFollowModeAction =
- new Action(Messages.FollowModeAction_leave_followmode) {
- @Override
- public void run() {
- followUser(null);
- }
- };
+ if (followUserMessage.contains("@")) followUserMessage += "@";
- disableFollowModeAction.setImageDescriptor(followModeDisabledImageDescriptor);
+ // Create menu item
+ MDirectMenuItem userMenuItem = service.createModelElement(MDirectMenuItem.class);
+ userMenuItem.setLabel(followUserMessage);
+ userMenuItem.setContributionURI(
+ "bundleclass://saros.eclipse/saros.ui.e4.toolbar.FollowModeHandler$FollowUserHandler");
+ userMenuItem.setIconURI(followModeEnabledImageURI);
- addActionToMenu(followUserMenu, disableFollowModeAction);
- return followUserMenu;
- }
-
- @Override
- public Menu getMenu(Menu parent) {
- return null;
+ items.add(userMenuItem);
+ }
}
- private void followUser(User user) {
+ private static void followUser(User user) {
if (followModeManager != null) followModeManager.follow(user);
}
- private Action createAction(final User user) {
- // The additional @ is needed because @ has special meaning in
- // Action#setText(), see JavaDoc of Action().
-
- String followUserMessage = getFollowUserMessage(user);
-
- if (followUserMessage.contains("@")) followUserMessage += "@";
-
- Action action =
- new Action(followUserMessage) {
-
- @Override
- public void run() {
- followUser(user);
- }
- };
-
- action.setImageDescriptor(followModeEnabledImageDescriptor);
- return action;
- }
-
- private void addActionToMenu(Menu parent, Action action) {
- ActionContributionItem item = new ActionContributionItem(action);
- item.fill(parent, -1);
- }
-
/** Returns the next user to follow or null if follow mode should be disabled. */
private User getNextUserToFollow() {
if (currentRemoteSessionUsers.isEmpty()) return null;
@@ -311,22 +283,33 @@ private User getNextUserToFollow() {
return nextUser;
}
+ @CanExecute
+ public boolean canExecute() {
+ return session != null && !currentRemoteSessionUsers.isEmpty();
+ }
+
private void updateEnablement() {
- setEnabled(session != null && !currentRemoteSessionUsers.isEmpty());
- setImageDescriptor(
- currentlyFollowedUser != null
- ? followModeEnabledImageDescriptor
- : followModeDisabledImageDescriptor);
+ if (followModeItem == null) {
+ return;
+ }
+
+ followModeItem.setEnabled(session != null && !currentRemoteSessionUsers.isEmpty());
+
+ if (currentlyFollowedUser != null) {
+ followModeItem.setIconURI(followModeEnabledImageURI);
+ } else {
+ followModeItem.setIconURI(followModeDisabledImageURI);
+ }
- if (isEnabled()) {
+ if (followModeItem.isEnabled()) {
User nextUserToFollow = getNextUserToFollow();
- setToolTipText(
+ followModeItem.setTooltip(
nextUserToFollow == null
? Messages.FollowModeAction_leave_followmode
: getFollowUserMessage(nextUserToFollow));
} else
// display default text
- setToolTipText(null);
+ followModeItem.setTooltip(null);
}
private String getFollowUserMessage(User user) {
diff --git a/eclipse/src/saros/ui/handlers/toolbar/LeaveSessionHandler.java b/eclipse/src/saros/ui/handlers/toolbar/LeaveSessionHandler.java
new file mode 100644
index 0000000000..111138afb1
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/toolbar/LeaveSessionHandler.java
@@ -0,0 +1,103 @@
+package saros.ui.handlers.toolbar;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import saros.SarosPluginContext;
+import saros.annotations.Component;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.session.ISessionLifecycleListener;
+import saros.session.SessionEndReason;
+import saros.ui.Messages;
+import saros.ui.util.CollaborationUtils;
+
+/** Leaves the current Saros session. Is deactivated if there is no running session. */
+@Component(module = "action")
+public class LeaveSessionHandler {
+
+ public static final String ID = LeaveSessionHandler.class.getName();
+
+ private static final String SAROS_ECLIPSE_URI = "platform:/plugin/saros.eclipse/";
+
+ @Inject private ISarosSessionManager sessionManager;
+
+ private MToolItem leaveSessionToolItem;
+
+ private static final String ELCL_SESSION_TERMINATE =
+ SAROS_ECLIPSE_URI + "icons/elcl16/session_terminate_tsk.png";
+ private static final String ELCL_SESSION_LEAVE =
+ SAROS_ECLIPSE_URI + "icons/elcl16/session_leave_tsk.png";
+
+ private final ISessionLifecycleListener sessionLifecycleListener =
+ new ISessionLifecycleListener() {
+ @Override
+ public void sessionStarted(ISarosSession newSarosSession) {
+ updateEnablement();
+ }
+
+ @Override
+ public void sessionEnded(ISarosSession oldSarosSession, SessionEndReason reason) {
+ updateEnablement();
+ }
+ };
+
+ public LeaveSessionHandler() {
+ SarosPluginContext.initComponent(this);
+ sessionManager.addSessionLifecycleListener(sessionLifecycleListener);
+ }
+
+ @PostConstruct
+ public void construct(EModelService service, MPart sarosView) {
+ MUIElement toolBarElement = service.find(ID, sarosView.getToolbar());
+
+ if (toolBarElement instanceof MToolItem) {
+ leaveSessionToolItem = (MToolItem) toolBarElement;
+ }
+ updateEnablement();
+ }
+
+ @Execute
+ public void run() {
+ CollaborationUtils.leaveSession();
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ ISarosSession session = sessionManager.getSession();
+ return session != null;
+ }
+
+ @PreDestroy
+ public void dispose() {
+ sessionManager.removeSessionLifecycleListener(sessionLifecycleListener);
+ }
+
+ private void updateEnablement() {
+ ISarosSession session = sessionManager.getSession();
+
+ if (leaveSessionToolItem == null) {
+ return;
+ }
+
+ if (session == null) {
+ leaveSessionToolItem.setEnabled(false);
+ return;
+ }
+
+ if (session.isHost()) {
+ leaveSessionToolItem.setTooltip(Messages.LeaveSessionAction_stop_session_tooltip);
+ leaveSessionToolItem.setIconURI(ELCL_SESSION_TERMINATE);
+ } else {
+ leaveSessionToolItem.setTooltip(Messages.LeaveSessionAction_leave_session_tooltip);
+ leaveSessionToolItem.setIconURI(ELCL_SESSION_LEAVE);
+ }
+ leaveSessionToolItem.setEnabled(true);
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/toolbar/NewContactHandler.java b/eclipse/src/saros/ui/handlers/toolbar/NewContactHandler.java
new file mode 100644
index 0000000000..c3842cbc48
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/toolbar/NewContactHandler.java
@@ -0,0 +1,45 @@
+package saros.ui.handlers.toolbar;
+
+import javax.annotation.PreDestroy;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import saros.SarosPluginContext;
+import saros.communication.connection.ConnectionHandler;
+import saros.communication.connection.IConnectionStateListener;
+import saros.net.ConnectionState;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.ui.util.WizardUtils;
+
+public class NewContactHandler {
+
+ public static final String ID = NewContactHandler.class.getName();
+
+ private final IConnectionStateListener connectionListener =
+ (state, error) -> connectionState = state == ConnectionState.CONNECTED;
+
+ private boolean connectionState = false;
+
+ @Inject private ConnectionHandler connectionHandler;
+
+ public NewContactHandler() {
+ SarosPluginContext.initComponent(this);
+
+ connectionHandler.addConnectionStateListener(connectionListener);
+ connectionState = connectionHandler.isConnected();
+ }
+
+ @PreDestroy
+ public void dispose() {
+ connectionHandler.removeConnectionStateListener(connectionListener);
+ }
+
+ @CanExecute
+ public boolean canExecute() {
+ return connectionState;
+ }
+
+ @Execute
+ public void run() {
+ WizardUtils.openAddContactWizard();
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/toolbar/OpenPreferencesHandler.java b/eclipse/src/saros/ui/handlers/toolbar/OpenPreferencesHandler.java
new file mode 100644
index 0000000000..550e0f116f
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/toolbar/OpenPreferencesHandler.java
@@ -0,0 +1,25 @@
+package saros.ui.handlers.toolbar;
+
+import org.apache.log4j.Logger;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.di.annotations.Execute;
+
+public class OpenPreferencesHandler {
+
+ public static final String ID = OpenPreferencesHandler.class.getName();
+
+ private static final Logger log = Logger.getLogger(OpenPreferencesHandler.class);
+
+ @Execute
+ public void run(ECommandService commandService) {
+ Command openPreferencesCmd =
+ commandService.getCommand("saros.ui.commands.OpenSarosPreferences");
+ try {
+ openPreferencesCmd.executeWithChecks(new ExecutionEvent());
+ } catch (Exception e) {
+ log.error("Could not execute command", e); // $NON-NLS-1$
+ }
+ }
+}
diff --git a/eclipse/src/saros/ui/handlers/toolbar/XMPPAccountMenu.java b/eclipse/src/saros/ui/handlers/toolbar/XMPPAccountMenu.java
new file mode 100644
index 0000000000..0d339d5809
--- /dev/null
+++ b/eclipse/src/saros/ui/handlers/toolbar/XMPPAccountMenu.java
@@ -0,0 +1,65 @@
+package saros.ui.handlers.toolbar;
+
+import java.util.List;
+import java.util.Map;
+import org.eclipse.e4.ui.di.AboutToShow;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import saros.SarosPluginContext;
+import saros.account.XMPPAccount;
+import saros.account.XMPPAccountStore;
+import saros.communication.connection.ConnectionHandler;
+import saros.net.xmpp.JID;
+import saros.repackaged.picocontainer.annotations.Inject;
+
+public class XMPPAccountMenu {
+
+ @Inject private XMPPAccountStore accountService;
+
+ @Inject private ConnectionHandler connectionHandler;
+
+ public XMPPAccountMenu() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @AboutToShow
+ public void createMenu(List items, EModelService service) {
+ final List accounts = accountService.getAllAccounts();
+
+ final String connectionId = connectionHandler.getConnectionID();
+
+ if (connectionHandler.isConnected() && connectionId != null) {
+
+ final JID jid = new JID(connectionId);
+
+ /*
+ * TODO this may filter out too much but this situation is somewhat rare (multiple accounts
+ * with same name and domain but different server
+ */
+
+ accounts.removeIf(
+ a ->
+ a.getUsername().equalsIgnoreCase(jid.getName())
+ && a.getDomain().equalsIgnoreCase(jid.getDomain()));
+ }
+
+ accounts.forEach(
+ account -> {
+ // The additional @ is needed because @ has special meaning in
+ // Action#setText(), see JavaDoc of Action().
+
+ String accountText = account.getUsername() + "@" + account.getDomain();
+
+ MDirectMenuItem accountElement = service.createModelElement(MDirectMenuItem.class);
+ accountElement.setContributionURI(
+ "bundleclass://saros.eclipse/saros.ui.e4.toolbar.ChangeXMPPAccountHandler$AddAccountToMenuHandler");
+ accountElement.setLabel(accountText);
+
+ Map objectData = accountElement.getTransientData();
+ objectData.put("account", account);
+
+ items.add(accountElement);
+ });
+ }
+}
diff --git a/eclipse/src/saros/ui/util/SWTUtils.java b/eclipse/src/saros/ui/util/SWTUtils.java
index c92eeb658b..96b98ccf7d 100644
--- a/eclipse/src/saros/ui/util/SWTUtils.java
+++ b/eclipse/src/saros/ui/util/SWTUtils.java
@@ -21,6 +21,8 @@ public class SWTUtils {
private static final Logger log = Logger.getLogger(SWTUtils.class);
+ private static Display display;
+
private static class CallableResult {
private T result;
private Exception exception;
@@ -187,7 +189,21 @@ public static void runSafeSWTSync(final Logger log, final Runnable runnable) {
* @return the display of the current workbench
*/
public static Display getDisplay() {
- return PlatformUI.getWorkbench().getDisplay();
+ /**
+ * This is a temporary solution. Migrating the UI from Eclipse3 to Eclipse4 caused an earlier
+ * initialization of Saros and its context. Calling PlatformUI.getWorkbench.getDisplay() can not
+ * be used, since the Workbench wont be created at that point, when this function is first
+ * called. Continuing the migration it would be best to find an other solution by replacing all
+ * calls to this function and keeping track of the display another way or find an equivalent to
+ * PlatformUI.getWorkbench.getDisplay() working in E4.
+ */
+ if (display == null) {
+ display = Display.getCurrent();
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ }
+ return display;
}
/**
@@ -205,18 +221,6 @@ public static Shell getShell() {
if (display.isDisposed()) return null;
- final IWorkbench workbench = PlatformUI.getWorkbench();
-
- final IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
-
- if (activeWorkbenchWindow != null && !activeWorkbenchWindow.getShell().isDisposed())
- return activeWorkbenchWindow.getShell();
-
- final IWorkbenchWindow[] workbenchWindows = workbench.getWorkbenchWindows();
-
- if (workbenchWindows.length > 0 && !workbenchWindows[0].getShell().isDisposed())
- return workbenchWindows[0].getShell();
-
return display.getActiveShell();
}
}
diff --git a/eclipse/src/saros/ui/views/PopupMenu.java b/eclipse/src/saros/ui/views/PopupMenu.java
new file mode 100644
index 0000000000..84e01833aa
--- /dev/null
+++ b/eclipse/src/saros/ui/views/PopupMenu.java
@@ -0,0 +1,347 @@
+package saros.ui.views;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.inject.Named;
+import org.eclipse.e4.ui.di.AboutToShow;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import saros.SarosPluginContext;
+import saros.communication.InfoManager;
+import saros.net.xmpp.JID;
+import saros.net.xmpp.contact.XMPPContact;
+import saros.preferences.PreferenceConstants;
+import saros.repackaged.picocontainer.annotations.Inject;
+import saros.session.ISarosSession;
+import saros.session.ISarosSessionManager;
+import saros.session.User;
+import saros.ui.Messages;
+import saros.ui.handlers.popup.ChangeColorHandler;
+import saros.ui.handlers.popup.ChangeWriteAccessHandler;
+import saros.ui.handlers.popup.DeleteContactHandler;
+import saros.ui.handlers.popup.FollowThisPersonHandler;
+import saros.ui.handlers.popup.JumpToUserWithWriteAccessPositionHandler;
+import saros.ui.handlers.popup.OpenChatHandler;
+import saros.ui.handlers.popup.RemoveUserHandler;
+import saros.ui.handlers.popup.RenameContactHandler;
+import saros.ui.handlers.popup.RequestSessionInviteHandler;
+import saros.ui.handlers.popup.SendFileHandler;
+import saros.ui.handlers.popup.SkypeHandler;
+import saros.ui.util.selection.SelectionUtils;
+
+/**
+ * This class is responsible for creating the context menu for the saros view.
+ * The class is referenced by the fragment defining the popup menu. The
+ * createPopupMenu() method will be called by the eclipse 4 framework each time
+ * the context menu needs to be created.
+ */
+class PopupMenu {
+
+ @Inject
+ protected ISarosSessionManager sarosSessionManager;
+ @Inject
+ private InfoManager infoManager;
+
+ /*
+ * TODO What about having actions as (disposable and recreatable?)
+ * singletons? This map (together with register and get methods) would not
+ * be necessary, actions could be added to the menus at will (through a
+ * method that would remember only the disposable ones, so they can be
+ * disposed when necessary).
+ */
+ private Map registeredMenuElements = new HashMap();
+
+ private static final String ICONS_DIR_PATH = "platform:/plugin/saros.eclipse/icons/";
+
+ private EModelService modelService;
+
+ public PopupMenu() {
+ SarosPluginContext.initComponent(this);
+ }
+
+ @PostConstruct
+ public void postConstruct(EModelService modelService) {
+ this.modelService = modelService;
+
+ /**
+ * There are a few additional things in the Saros view.
+ *
+ *
+ * There is tool bar that holds the icons along the top (also see
+ * fragment.e4xmi).
+ *
+ *
+ * Also, there are context menus which appear when you: - right-click on
+ * a person in your current session - right-click on a contact in the
+ * contact list.
+ */
+ createUIElements();
+ }
+
+ @AboutToShow
+ public void createPopupMenu(List elements,
+ EModelService modelService,
+ @Named(IServiceConstants.ACTIVE_SELECTION) ISelection activeSelection) {
+ addRosterMenuItems(elements, modelService, activeSelection);
+ addSessionMenuItems(elements, modelService, activeSelection);
+ }
+
+ protected void addRosterMenuItems(List elements,
+ EModelService modelService, ISelection activeSelection) {
+
+ /*
+ * Do not display the following actions if participants are selected.
+ */
+ List participants = SelectionUtils
+ .getAdaptableObjects(activeSelection, User.class);
+ if (participants.size() > 0)
+ return;
+
+ /*
+ * Do not display the following actions if no contacts are selected.
+ */
+ List contacts = SelectionUtils
+ .getAdaptableObjects(activeSelection, XMPPContact.class);
+ if (contacts.isEmpty())
+ return;
+
+ XMPPContact contact = contacts.get(0);
+
+ // TODO OLD Behavior: here (and at other places) we check if contact is
+ // online
+ // (currently you can invite a contact without saros support and get a
+ // error message),
+ // but could check already for saros support via
+ // contact.hasSarosSupport(). In this case
+ // we should probably add a Information about missing saros support.
+ if (sarosSessionManager.getSession() == null
+ && contact.getStatus().isOnline()) {
+ MMenu shareResourcesSubMenu = modelService
+ .createModelElement(MMenu.class);
+ shareResourcesSubMenu.setLabel("Share Resource(s)...");
+ shareResourcesSubMenu.setIconURI(
+ "platform:/plugin/saros.eclipse/icons/elcl16/session_tsk.png");
+
+ List menuEntries = shareResourcesSubMenu
+ .getChildren();
+
+ StartSessionWithProjects sswp = new StartSessionWithProjects(
+ modelService, activeSelection);
+ sswp.createMenu(menuEntries);
+
+ elements.add(shareResourcesSubMenu);
+ elements.add(modelService.createModelElement(MMenuSeparator.class));
+ }
+
+ // TODO: Currently only Saros/S is known to have a working
+ // JoinSessionRequestHandler,
+ // remove this once the situation changes / change this to it's own
+ // feature.
+ if (infoManager
+ .getRemoteInfo(contact, PreferenceConstants.SERVER_SUPPORT)
+ .isPresent()) {
+ elements.add(getMenuElement(RequestSessionInviteHandler.ID));
+ elements.add(modelService.createModelElement(MMenuSeparator.class));
+ }
+
+ MMenuElement openChat = getMenuElement(OpenChatHandler.ID);
+ Map data = openChat.getTransientData();
+ data.put("chatRoomsComposite", SarosView.chatRooms);
+
+ // Add menu elements to popup menu
+ elements.add(getMenuElement(SkypeHandler.ID));
+ elements.add(openChat);
+ elements.add(getMenuElement(SendFileHandler.ID));
+ elements.add(getMenuElement(RenameContactHandler.ID));
+ elements.add(getMenuElement(DeleteContactHandler.ID));
+ }
+
+ protected void addSessionMenuItems(List elements,
+ EModelService modelService, ISelection activeSelection) {
+
+ /*
+ * TODO The decision whether to show an entry at all is made here,
+ * whereas the decision whether to enable an entry is encapsulated in
+ * each action. That does not feel right.
+ */
+ /*
+ * Do not display the following actions if no participants are selected.
+ */
+ List participants = SelectionUtils
+ .getAdaptableObjects(activeSelection, User.class);
+ if (participants.size() == 0)
+ return;
+
+ /*
+ * Do not display the following actions if non-participants are
+ * selected.
+ */
+ List contacts = SelectionUtils.getAdaptableObjects(activeSelection,
+ JID.class);
+
+ if (contacts.size() > 0)
+ return;
+
+ boolean isHost = false;
+
+ ISarosSession session = sarosSessionManager.getSession();
+
+ if (session != null)
+ isHost = session.isHost();
+
+ if (participants.size() != 1)
+ return;
+
+ if (participants.get(0).isLocal()) {
+ elements.add(getMenuElement(ChangeColorHandler.ID));
+
+ if (isHost) {
+ elements.add(
+ getMenuElement(ChangeWriteAccessHandler.WriteAccess.ID));
+
+ elements
+ .add(getMenuElement(ChangeWriteAccessHandler.ReadOnly.ID));
+ }
+ } else {
+ if (isHost) {
+ elements.add(
+ getMenuElement(ChangeWriteAccessHandler.WriteAccess.ID));
+
+ elements
+ .add(getMenuElement(ChangeWriteAccessHandler.ReadOnly.ID));
+
+ elements.add(getMenuElement(RemoveUserHandler.ID));
+ elements
+ .add(modelService.createModelElement(MMenuSeparator.class));
+ }
+ elements.add(getMenuElement(FollowThisPersonHandler.ID));
+ elements.add(
+ getMenuElement(JumpToUserWithWriteAccessPositionHandler.ID));
+
+ elements.add(modelService.createModelElement(MMenuSeparator.class));
+
+ elements.add(getMenuElement(OpenChatHandler.ID));
+ elements.add(getMenuElement(SendFileHandler.ID));
+ }
+ }
+
+ private void registerMenuElement(MMenuElement menuItem) {
+ String id = menuItem.getElementId();
+ if (registeredMenuElements.containsKey(id)) {
+ throw new IllegalArgumentException(
+ "tried to register menu element with id " + id
+ + " more than once");
+ }
+ registeredMenuElements.put(id, menuItem);
+ }
+
+ private MMenuElement getMenuElement(String menuElementId) {
+ MMenuElement menuElement = registeredMenuElements.get(menuElementId);
+
+ if (menuElement == null) {
+ throw new IllegalArgumentException("a menu element for id "
+ + menuElementId + " is not registered");
+ }
+ menuElement.setVisible(true);
+ return menuElement;
+ }
+
+ private MMenuElement createMenuItem(String id, String label, String tooltip,
+ String iconPath, String handlerClass) {
+ MDirectMenuItem item = modelService
+ .createModelElement(MDirectMenuItem.class);
+ item.setElementId(id);
+ item.setLabel(label);
+ item.setContributionURI(handlerClass);
+
+ if (tooltip != null)
+ item.setTooltip(tooltip);
+ if (iconPath != null)
+ item.setIconURI(iconPath);
+
+ return item;
+ }
+
+ /**
+ * Creates all needed menu items once and registers them, so they can be
+ * requested when constructing the context menu.
+ *
+ *
+ * In the eclipse 4 framework you can only reference icons with their path
+ * an not by an {@link ImageDescriptor}. So we created all referenced
+ * overlaid images.
+ */
+ private void createUIElements() {
+ // ContextMenus Session
+ registerMenuElement(createMenuItem(
+ ChangeWriteAccessHandler.WriteAccess.ID,
+ Messages.GiveWriteAccessAction_title,
+ Messages.GiveWriteAccessAction_tooltip,
+ ICONS_DIR_PATH + "obj16/contact_saros_obj.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.ChangeWriteAccessHandler$WriteAccess"));
+ registerMenuElement(createMenuItem(ChangeWriteAccessHandler.ReadOnly.ID,
+ Messages.RestrictToReadOnlyAccessAction_title,
+ Messages.RestrictToReadOnlyAccessAction_tooltip,
+ ICONS_DIR_PATH + "merged16/contact_saros_obj_readonly.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.ChangeWriteAccessHandler$ReadOnly"));
+ registerMenuElement(createMenuItem(FollowThisPersonHandler.ID,
+ Messages.FollowThisPersonAction_follow_title,
+ Messages.FollowThisPersonAction_follow_tooltip,
+ ICONS_DIR_PATH + "merged16/contact_saros_obj_followmode.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.FollowThisPersonHandler"));
+ registerMenuElement(createMenuItem(
+ JumpToUserWithWriteAccessPositionHandler.ID,
+ Messages.JumpToUserWithWriteAccessPositionAction_title,
+ Messages.JumpToUserWithWriteAccessPositionAction_tooltip,
+ ICONS_DIR_PATH + "elcl16/jump.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.JumpToUserWithWriteAccessPositionHandler"));
+ // Using file_obj icon from org.eclipse.ui
+ registerMenuElement(createMenuItem(SendFileHandler.ID,
+ Messages.SendFileAction_title, Messages.SendFileAction_tooltip,
+ "platform:/plugin/org.eclipse.ui/icons/full/obj16/file_obj.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.SendFileHandler"));
+ registerMenuElement(createMenuItem(ChangeColorHandler.ID,
+ Messages.ChangeColorAction_title,
+ Messages.ChangeColorAction_tooltip,
+ ICONS_DIR_PATH + "elcl16/changecolor.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.ChangeColorHandler"));
+ registerMenuElement(createMenuItem(RemoveUserHandler.ID,
+ "Remove from Session", null,
+ ICONS_DIR_PATH + "elcl16/contact_remove_tsk.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.RemoveUserHandler"));
+ registerMenuElement(createMenuItem(RequestSessionInviteHandler.ID,
+ Messages.RequestSessionInviteAction_title, null, null,
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.RequestSessionInviteHandler"));
+
+ // ContextMenus Roster/Contact list
+ registerMenuElement(createMenuItem(SkypeHandler.ID,
+ Messages.SkypeAction_title, Messages.SkypeAction_tooltip,
+ ICONS_DIR_PATH + "elcl16/contact_skype_call_tsk.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.SkypeHandler"));
+ registerMenuElement(createMenuItem(RenameContactHandler.ID,
+ Messages.RenameContactAction_title,
+ Messages.RenameContactAction_tooltip,
+ ICONS_DIR_PATH + "etool16/edit.gif",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.RenameContactHandler"));
+ // Using delete icon from org.eclipse.ui
+ registerMenuElement(createMenuItem(DeleteContactHandler.ID,
+ Messages.DeleteContactAction_title,
+ Messages.DeleteContactAction_tooltip,
+ "platform:/plugin/org.eclipse.ui/icons/full/etool16/delete.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.DeleteContactHandler"));
+
+ // ContextMenus Both
+ registerMenuElement(createMenuItem(OpenChatHandler.ID,
+ Messages.OpenChatAction_MenuItem, null,
+ ICONS_DIR_PATH + "view16/chat_misc.png",
+ "bundleclass://saros.eclipse/saros.ui.handlers.popup.OpenChatHandler"));
+ }
+}
diff --git a/eclipse/src/saros/ui/views/SarosView.java b/eclipse/src/saros/ui/views/SarosView.java
index b47d527e9b..7342a9fba5 100644
--- a/eclipse/src/saros/ui/views/SarosView.java
+++ b/eclipse/src/saros/ui/views/SarosView.java
@@ -1,23 +1,23 @@
package saros.ui.views;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Platform;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IMenuListener;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.EMenuService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.e4.ui.workbench.modeling.IPartListener;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
@@ -32,26 +32,17 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
-import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.IPartListener2;
-import org.eclipse.ui.IViewPart;
-import org.eclipse.ui.IWorkbenchActionConstants;
-import org.eclipse.ui.IWorkbenchPartReference;
-import org.eclipse.ui.part.ViewPart;
import saros.SarosPluginContext;
import saros.annotations.Component;
import saros.communication.InfoManager;
import saros.editor.EditorManager;
-import saros.net.xmpp.JID;
import saros.net.xmpp.contact.ContactStatus.Type;
import saros.net.xmpp.contact.IContactsUpdate;
import saros.net.xmpp.contact.XMPPContact;
import saros.net.xmpp.contact.XMPPContactsService;
import saros.preferences.EclipsePreferenceConstants;
-import saros.preferences.PreferenceConstants;
import saros.repackaged.picocontainer.annotations.Inject;
import saros.session.ISarosSession;
import saros.session.ISarosSessionManager;
@@ -59,33 +50,12 @@
import saros.session.SessionEndReason;
import saros.session.User;
import saros.ui.BalloonNotification;
-import saros.ui.ImageManager;
import saros.ui.Messages;
-import saros.ui.actions.ChangeColorAction;
-import saros.ui.actions.ChangeWriteAccessAction;
-import saros.ui.actions.ChangeXMPPAccountAction;
-import saros.ui.actions.ConsistencyAction;
-import saros.ui.actions.DeleteContactAction;
-import saros.ui.actions.Disposable;
-import saros.ui.actions.FollowModeAction;
-import saros.ui.actions.FollowThisPersonAction;
-import saros.ui.actions.JumpToUserWithWriteAccessPositionAction;
-import saros.ui.actions.LeaveSessionAction;
-import saros.ui.actions.NewContactAction;
-import saros.ui.actions.OpenChatAction;
-import saros.ui.actions.OpenPreferencesAction;
-import saros.ui.actions.RemoveUserAction;
-import saros.ui.actions.RenameContactAction;
-import saros.ui.actions.RequestSessionInviteAction;
-import saros.ui.actions.SendFileAction;
-import saros.ui.actions.SkypeAction;
-import saros.ui.menu_contributions.StartSessionWithProjects;
import saros.ui.model.roster.RosterEntryElement;
import saros.ui.sounds.SoundPlayer;
import saros.ui.sounds.Sounds;
import saros.ui.util.LayoutUtils;
import saros.ui.util.SWTUtils;
-import saros.ui.util.selection.retriever.SelectionRetrieverFactory;
import saros.ui.widgets.ConnectionStateComposite;
import saros.ui.widgets.chat.ChatRoomsComposite;
import saros.ui.widgets.viewer.ViewerComposite;
@@ -106,651 +76,424 @@
/** This view displays the contact list, the Saros Session and Saros Chat. */
@Component(module = "ui")
-public class SarosView extends ViewPart {
+public class SarosView {
- private static final Logger log = Logger.getLogger(SarosView.class);
+ private static final Logger log = Logger.getLogger(SarosView.class);
- public static final String ID = "saros.ui.views.SarosView";
+ public static final String ID = "saros.ui.views.SarosView";
- private final IContactsUpdate contactsUpdate =
- new IContactsUpdate() {
+ private final IContactsUpdate contactsUpdate = new IContactsUpdate() {
private final Set wasAlreadyAvailable = new HashSet<>();
@Override
- public void update(Optional contactOptional, UpdateType type) {
- if (type != IContactsUpdate.UpdateType.STATUS || !contactOptional.isPresent()) {
- return;
- }
-
- XMPPContact contact = contactOptional.get();
- Type contactStatus = contact.getStatus().getType();
- boolean wasAvailable = wasAlreadyAvailable.contains(contact);
-
- if (contactStatus == Type.AVAILABLE && !wasAvailable) {
- wasAlreadyAvailable.add(contact);
- if (playAvailableSound) SoundPlayer.playSound(Sounds.USER_ONLINE);
- } else if (contactStatus == Type.OFFLINE && wasAvailable) {
- wasAlreadyAvailable.remove(contact);
- if (playUnavailableSound) SoundPlayer.playSound(Sounds.USER_OFFLINE);
- }
- }
- };
+ public void update(Optional contactOptional,
+ UpdateType type) {
+ if (type != IContactsUpdate.UpdateType.STATUS
+ || !contactOptional.isPresent()) {
+ return;
+ }
- private final IPartListener2 partListener =
- new IPartListener2() {
- @Override
- public void partInputChanged(IWorkbenchPartReference partRef) {
- // do nothing
+ XMPPContact contact = contactOptional.get();
+ Type contactStatus = contact.getStatus().getType();
+ boolean wasAvailable = wasAlreadyAvailable.contains(contact);
+
+ if (contactStatus == Type.AVAILABLE && !wasAvailable) {
+ wasAlreadyAvailable.add(contact);
+ if (playAvailableSound)
+ SoundPlayer.playSound(Sounds.USER_ONLINE);
+ } else if (contactStatus == Type.OFFLINE && wasAvailable) {
+ wasAlreadyAvailable.remove(contact);
+ if (playUnavailableSound)
+ SoundPlayer.playSound(Sounds.USER_OFFLINE);
+ }
}
+ };
- @Override
- public void partVisible(IWorkbenchPartReference partRef) {
- // do nothing
- }
+ private final IPartListener partListener = new IPartListener() {
@Override
- public void partHidden(IWorkbenchPartReference partRef) {
- // do nothing
+ public void partVisible(MPart part) {
+ // TODO Auto-generated method stub
+
}
@Override
- public void partOpened(IWorkbenchPartReference partRef) {
- // do nothing
+ public void partHidden(MPart part) {
+ // TODO Auto-generated method stub
+
}
@Override
- public void partDeactivated(IWorkbenchPartReference partRef) {
- if (sessionDisplay != null && !sessionDisplay.isDisposed()) {
- sessionDisplay
- .getViewer()
- .setSelection(
- new ISelection() {
- @Override
- public boolean isEmpty() {
+ public void partDeactivated(MPart part) {
+ if (sessionDisplay != null && !sessionDisplay.isDisposed()) {
+ sessionDisplay.getViewer().setSelection(new ISelection() {
+ @Override
+ public boolean isEmpty() {
return true;
- }
- });
- }
+ }
+ });
+ }
}
@Override
- public void partClosed(IWorkbenchPartReference partRef) {
- getViewSite().getPage().removePartListener(partListener);
- }
+ public void partBroughtToTop(MPart part) {
+ // TODO Auto-generated method stub
- @Override
- public void partBroughtToTop(IWorkbenchPartReference partRef) {
- // do nothing
}
@Override
- public void partActivated(IWorkbenchPartReference partRef) {
- // do nothing
+ public void partActivated(MPart part) {
+ // TODO Auto-generated method stub
+
}
- };
+ };
- private final IPropertyChangeListener propertyListener =
- new IPropertyChangeListener() {
+ private final IPropertyChangeListener propertyListener = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
- boolean newValue = Boolean.parseBoolean(event.getNewValue().toString());
- switch (event.getProperty()) {
+ boolean newValue = Boolean
+ .parseBoolean(event.getNewValue().toString());
+ switch (event.getProperty()) {
case EclipsePreferenceConstants.ENABLE_BALLOON_NOTIFICATION:
- showBalloonNotifications = newValue;
- break;
+ showBalloonNotifications = newValue;
+ break;
case EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_ONLINE:
- playAvailableSound = newValue;
- break;
+ playAvailableSound = newValue;
+ break;
case EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_OFFLINE:
- playUnavailableSound = newValue;
- break;
- }
+ playUnavailableSound = newValue;
+ break;
+ }
}
- };
+ };
- private final ISessionLifecycleListener sessionLifecycleListener =
- new ISessionLifecycleListener() {
+ private final ISessionLifecycleListener sessionLifecycleListener = new ISessionLifecycleListener() {
@Override
- public void sessionEnded(ISarosSession session, SessionEndReason reason) {
- showStopNotification(session.getHost(), reason);
+ public void sessionEnded(ISarosSession session,
+ SessionEndReason reason) {
+ showStopNotification(session.getHost(), reason);
}
- };
+ };
+
+ protected Composite leftComposite;
- protected Composite leftComposite;
+ protected ViewerComposite> sessionDisplay;
- protected ViewerComposite> sessionDisplay;
+ static ChatRoomsComposite chatRooms;
- protected ChatRoomsComposite chatRooms;
+ @Inject
+ protected IPreferenceStore preferenceStore;
- @Inject protected IPreferenceStore preferenceStore;
+ @Inject
+ protected ISarosSessionManager sarosSessionManager;
- @Inject protected ISarosSessionManager sarosSessionManager;
+ @Inject
+ protected EditorManager editorManager;
- @Inject protected EditorManager editorManager;
+ @Inject
+ private XMPPContactsService contactsService;
- @Inject private XMPPContactsService contactsService;
+ @Inject
+ private InfoManager infoManager;
- @Inject private InfoManager infoManager;
+ private static EPartService ePartService;
- private static volatile boolean showBalloonNotifications;
- private volatile boolean playAvailableSound;
- private volatile boolean playUnavailableSound;
+ private static volatile boolean showBalloonNotifications;
+ private volatile boolean playAvailableSound;
+ private volatile boolean playUnavailableSound;
- private Composite notificationAnchor;
+ private Composite notificationAnchor;
- /**
- * Stores actions by their {@link IAction#getId() ID}, so they can (1) be {@linkplain
- * #getAction(String) retrieved} and (2) {@linkplain Disposable#dispose() disposed} when and if
- * necessary.
- */
- /*
- * TODO What about having actions as (disposable and recreatable?)
- * singletons? This map (together with register and get methods) would not
- * be necessary, actions could be added to the menus at will (through a
- * method that would remember only the disposable ones, so they can be
- * disposed when necessary).
- */
- private Map registeredActions = new HashMap();
+ public SarosView() {
+ SarosPluginContext.initComponent(this);
+ preferenceStore.addPropertyChangeListener(propertyListener);
+ sarosSessionManager
+ .addSessionLifecycleListener(sessionLifecycleListener);
+
+ showBalloonNotifications = preferenceStore
+ .getBoolean(EclipsePreferenceConstants.ENABLE_BALLOON_NOTIFICATION);
+ playAvailableSound = preferenceStore.getBoolean(
+ EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_ONLINE);
+ playUnavailableSound = preferenceStore.getBoolean(
+ EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_OFFLINE);
+ }
+
+ /**
+ * @JTourBusStop 2, The Interface Tour:
+ *
+ *
+ * The createPartControl method constructs the view's
+ * controls.
+ *
+ *
+ * Notice that the SarosView class doesn't contain everything.
+ * Rather it arranges and manages other components which carry
+ * out most of the functionality.
+ *
+ *
+ * You should have noticed that the Saros view is divided into
+ * parts, left and right. The left side is a composite of the
+ * session information and the roster. The right side
+ * alternates between an info/chat window.
+ */
+ @PostConstruct
+ public void createPartControl(Composite parent, EPartService partService,
+ EMenuService menuService, ESelectionService selectionService) {
- public SarosView() {
- super();
- SarosPluginContext.initComponent(this);
- preferenceStore.addPropertyChangeListener(propertyListener);
- sarosSessionManager.addSessionLifecycleListener(sessionLifecycleListener);
+ ePartService = partService;
- showBalloonNotifications =
- preferenceStore.getBoolean(EclipsePreferenceConstants.ENABLE_BALLOON_NOTIFICATION);
- playAvailableSound =
- preferenceStore.getBoolean(EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_ONLINE);
- playUnavailableSound =
- preferenceStore.getBoolean(EclipsePreferenceConstants.SOUND_PLAY_EVENT_CONTACT_OFFLINE);
- }
+ GridData gridData;
- /**
- * @JTourBusStop 2, The Interface Tour:
- *
- *
The createPartControl method constructs the view's controls.
- *
- *
Notice that the SarosView class doesn't contain everything. Rather it arranges and manages
- * other components which carry out most of the functionality.
- *
- *
You should have noticed that the Saros view is divided into parts, left and right. The left
- * side is a composite of the session information and the roster. The right side alternates
- * between an info/chat window.
- */
- @Override
- public void createPartControl(Composite parent) {
+ final GridLayout layout = new GridLayout(1, false);
- GridData gridData;
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
- final GridLayout layout = new GridLayout(1, false);
+ parent.setLayout(layout);
- layout.horizontalSpacing = 0;
- layout.verticalSpacing = 0;
+ final SashForm baseSashForm = new SashForm(parent, SWT.SMOOTH);
- parent.setLayout(layout);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
- final SashForm baseSashForm = new SashForm(parent, SWT.SMOOTH);
+ baseSashForm.setLayoutData(gridData);
+ /*
+ * LEFT COLUMN
+ */
+ leftComposite = new Composite(baseSashForm, SWT.BORDER);
+ leftComposite.setLayout(LayoutUtils.createGridLayout());
+ leftComposite.setBackground(
+ Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
- gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ /** Sash weight remembering */
+ leftComposite.addControlListener(new ControlListener() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ preferenceStore.setValue(
+ EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_LEFT,
+ baseSashForm.getWeights()[0]);
+ preferenceStore.setValue(
+ EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_RIGHT,
+ baseSashForm.getWeights()[1]);
+ }
- baseSashForm.setLayoutData(gridData);
- /*
- * LEFT COLUMN
- */
- leftComposite = new Composite(baseSashForm, SWT.BORDER);
- leftComposite.setLayout(LayoutUtils.createGridLayout());
- leftComposite.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
-
- /** Sash weight remembering */
- leftComposite.addControlListener(
- new ControlListener() {
- @Override
- public void controlResized(ControlEvent e) {
- preferenceStore.setValue(
- EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_LEFT,
- baseSashForm.getWeights()[0]);
- preferenceStore.setValue(
- EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_RIGHT,
- baseSashForm.getWeights()[1]);
- }
-
- @Override
- public void controlMoved(ControlEvent e) {
- // NOP
- }
+ @Override
+ public void controlMoved(ControlEvent e) {
+ // NOP
+ }
});
- ConnectionStateComposite connectionStateComposite =
- new ConnectionStateComposite(leftComposite, SWT.NONE);
- connectionStateComposite.setLayoutData(LayoutUtils.createFillHGrabGridData());
+ ConnectionStateComposite connectionStateComposite = new ConnectionStateComposite(
+ leftComposite, SWT.NONE);
+ connectionStateComposite
+ .setLayoutData(LayoutUtils.createFillHGrabGridData());
- sessionDisplay = new XMPPSessionDisplayComposite(leftComposite, SWT.V_SCROLL);
- sessionDisplay.setLayoutData(LayoutUtils.createFillGridData());
+ sessionDisplay = new XMPPSessionDisplayComposite(leftComposite,
+ SWT.V_SCROLL);
+ sessionDisplay.setLayoutData(LayoutUtils.createFillGridData());
- final Control control = sessionDisplay.getViewer().getControl();
+ final Control control = sessionDisplay.getViewer().getControl();
- control.addMouseListener(
- new MouseAdapter() {
- @Override
- public void mouseDoubleClick(MouseEvent event) {
+ control.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDoubleClick(MouseEvent event) {
- if (!(control instanceof Tree)) return;
+ if (!(control instanceof Tree))
+ return;
- TreeItem treeItem = ((Tree) control).getItem(new Point(event.x, event.y));
+ TreeItem treeItem = ((Tree) control)
+ .getItem(new Point(event.x, event.y));
- if (treeItem == null) return;
+ if (treeItem == null)
+ return;
- RosterEntryElement rosterEntryElement =
- Platform.getAdapterManager()
+ RosterEntryElement rosterEntryElement = Platform
+ .getAdapterManager()
.getAdapter(treeItem.getData(), RosterEntryElement.class);
- if (rosterEntryElement == null) return;
+ if (rosterEntryElement == null)
+ return;
- chatRooms.openChat(rosterEntryElement.getJID(), true);
- }
+ chatRooms.openChat(rosterEntryElement.getJID(), true);
+ }
});
- /*
- * RIGHT COLUMN
- */
- Composite rightComposite = new Composite(baseSashForm, SWT.NONE);
- rightComposite.setLayout(new FillLayout());
+ /*
+ * RIGHT COLUMN
+ */
+ Composite rightComposite = new Composite(baseSashForm, SWT.NONE);
+ rightComposite.setLayout(new FillLayout());
- /*
- * Initialize sash form weights from preferences (remembering the layout
- * of the saros view), if no prefs exist (first start) use a 50/50 space
- * distribution.
- *
- * Can only set the sash weights after adding all direct child elements
- * of the baseSashForm.
- */
- int[] weights =
- new int[] {
- preferenceStore.getInt(EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_LEFT),
- preferenceStore.getInt(EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_RIGHT)
- };
- baseSashForm.setWeights(weights);
+ /*
+ * Initialize sash form weights from preferences (remembering the layout
+ * of the saros view), if no prefs exist (first start) use a 50/50 space
+ * distribution.
+ *
+ * Can only set the sash weights after adding all direct child elements
+ * of the baseSashForm.
+ */
+ int[] weights = new int[] {
+ preferenceStore
+ .getInt(EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_LEFT),
+ preferenceStore.getInt(
+ EclipsePreferenceConstants.SAROSVIEW_SASH_WEIGHT_RIGHT) };
+ baseSashForm.setWeights(weights);
- chatRooms = new ChatRoomsComposite(rightComposite, SWT.NONE);
+ chatRooms = new ChatRoomsComposite(rightComposite, SWT.NONE);
- notificationAnchor = new Composite(parent, SWT.NONE);
+ notificationAnchor = new Composite(parent, SWT.NONE);
- gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false);
- gridData.heightHint = 0;
+ gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false);
+ gridData.heightHint = 0;
- notificationAnchor.setLayoutData(gridData);
- notificationAnchor.setVisible(false);
+ notificationAnchor.setLayoutData(gridData);
+ notificationAnchor.setVisible(false);
- /**
- * @JTourBusStop 3, The Interface Tour:
- *
- *
There are a few additional things in the Saros view.
- *
- *
There is tool bar that holds the icons along the top (also see addToolbarItems() below).
- *
- *
Also, there are context menus which appear when you: - right-click on a person in your
- * current session - right-click on a contact in the contact list.
- */
- createActions();
+ Viewer sessionViewer = sessionDisplay.getViewer();
- /*
- * Toolbar
- */
- IActionBars bars = getViewSite().getActionBars();
- IToolBarManager toolBar = bars.getToolBarManager();
- addToolBarItems(toolBar);
+ menuService.registerContextMenu(sessionViewer.getControl(),
+ "saros.ui.popup.menu");
- /*
- * Context Menu
- */
- MenuManager menuManager = new MenuManager();
- menuManager.setRemoveAllWhenShown(true);
- addMenuStartSeparator(menuManager);
- addRosterMenuItems(menuManager);
- addSessionMenuItems(menuManager);
- addAdditionsSeparator(menuManager);
-
- Viewer sessionViewer = sessionDisplay.getViewer();
- Menu menu = menuManager.createContextMenu(sessionViewer.getControl());
- sessionViewer.getControl().setMenu(menu);
- getSite().registerContextMenu(menuManager, sessionViewer);
- getSite().setSelectionProvider(sessionViewer);
-
- contactsService.addListener(contactsUpdate);
-
- getViewSite().getPage().addPartListener(partListener);
- }
-
- protected void addToolBarItems(IToolBarManager toolBar) {
- toolBar.add(getAction(ChangeXMPPAccountAction.ACTION_ID));
- toolBar.add(getAction(NewContactAction.ACTION_ID));
- toolBar.add(getAction(OpenPreferencesAction.ACTION_ID));
- toolBar.add(new Separator());
- toolBar.add(getAction(FollowModeAction.ACTION_ID));
- toolBar.add(getAction(ConsistencyAction.ACTION_ID));
- toolBar.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
- toolBar.add(getAction(LeaveSessionAction.ACTION_ID));
- }
-
- /** @param menuManager */
- protected void addRosterMenuItems(MenuManager menuManager) {
-
- menuManager.addMenuListener(
- new IMenuListener() {
- @Override
- public void menuAboutToShow(final IMenuManager manager) {
- /*
- * Do not display the following actions if participants are
- * selected.
- */
- List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
- if (participants.size() > 0) return;
-
- /*
- * Do not display the following actions if no contacts are
- * selected.
- */
- List contacts =
- SelectionRetrieverFactory.getSelectionRetriever(XMPPContact.class).getSelection();
- if (contacts.isEmpty()) return;
-
- XMPPContact contact = contacts.get(0);
-
- // TODO OLD Behavior: here (and at other places) we check if contact is online
- // (currently you can invite a contact without saros support and get a error message),
- // but could check already for saros support via contact.hasSarosSupport(). In this case
- // we should probably add a Information about missing saros support.
- if (sarosSessionManager.getSession() == null && contact.getStatus().isOnline()) {
- MenuManager shareResourcesSubMenu =
- new MenuManager(
- "Share Resource(s)...",
- ImageManager.getImageDescriptor(ImageManager.ELCL_SESSION),
- "Share_Resources");
-
- shareResourcesSubMenu.add(new StartSessionWithProjects());
- // TODO it seems it not that trivial to add tooltips to these entries
- manager.add(shareResourcesSubMenu);
- manager.add(new Separator());
- }
+ sessionViewer
+ .addSelectionChangedListener(new ISelectionChangedListener() {
- // TODO: Currently only Saros/S is known to have a working JoinSessionRequestHandler,
- // remove this once the situation changes / change this to it's own feature.
- if (infoManager
- .getRemoteInfo(contact, PreferenceConstants.SERVER_SUPPORT)
- .isPresent()) {
- manager.add(getAction(RequestSessionInviteAction.ACTION_ID));
- manager.add(new Separator());
- }
-
- manager.add(getAction(SkypeAction.ACTION_ID));
- manager.add(getAction(OpenChatAction.ACTION_ID));
- manager.add(getAction(SendFileAction.ACTION_ID));
- manager.add(getAction(RenameContactAction.ACTION_ID));
- manager.add(getAction(DeleteContactAction.ACTION_ID));
- }
- });
- }
-
- /** @param menuManager */
- protected void addSessionMenuItems(MenuManager menuManager) {
-
- /*
- * TODO The decision whether to show an entry at all is made here,
- * whereas the decision whether to enable an entry is encapsulated in
- * each action. That does not feel right.
- */
- menuManager.addMenuListener(
- new IMenuListener() {
-
- @Override
- public void menuAboutToShow(IMenuManager manager) {
- /*
- * Do not display the following actions if no participants are
- * selected.
- */
- List participants =
- SelectionRetrieverFactory.getSelectionRetriever(User.class).getSelection();
- if (participants.size() == 0) return;
-
- /*
- * Do not display the following actions if non-participants are
- * selected.
- */
- List contacts =
- SelectionRetrieverFactory.getSelectionRetriever(JID.class).getSelection();
-
- if (contacts.size() > 0) return;
-
- boolean isHost = false;
-
- ISarosSession session = sarosSessionManager.getSession();
-
- if (session != null) isHost = session.isHost();
-
- if (participants.size() != 1) return;
-
- if (participants.get(0).isLocal()) {
- manager.add(getAction(ChangeColorAction.ACTION_ID));
-
- if (isHost) {
- manager.add(getAction(ChangeWriteAccessAction.WriteAccess.ACTION_ID));
-
- manager.add(getAction(ChangeWriteAccessAction.ReadOnly.ACTION_ID));
- }
- } else {
- if (isHost) {
- manager.add(getAction(ChangeWriteAccessAction.WriteAccess.ACTION_ID));
-
- manager.add(getAction(ChangeWriteAccessAction.ReadOnly.ACTION_ID));
-
- manager.add(getAction(RemoveUserAction.ACTION_ID));
- manager.add(new Separator());
- }
- manager.add(getAction(FollowThisPersonAction.ACTION_ID));
- manager.add(getAction(JumpToUserWithWriteAccessPositionAction.ACTION_ID));
- manager.add(new Separator());
- manager.add(getAction(OpenChatAction.ACTION_ID));
- manager.add(getAction(SendFileAction.ACTION_ID));
- }
- }
- });
- }
-
- /**
- * Adds the {@link IWorkbenchActionConstants#MB_ADDITIONS additions} {@link Separator} to the
- * {@link MenuManager} in order to let others extend the menu.
- *
- * @param menuManager
- */
- protected void addAdditionsSeparator(MenuManager menuManager) {
- menuManager.addMenuListener(
- new IMenuListener() {
- @Override
- public void menuAboutToShow(IMenuManager manager) {
- manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
- }
- });
- }
-
- protected void addMenuStartSeparator(MenuManager menuManager) {
- menuManager.addMenuListener(
- new IMenuListener() {
- @Override
- public void menuAboutToShow(IMenuManager manager) {
- Separator menuStart = new Separator("menustart");
- menuStart.setVisible(false);
- manager.add(menuStart);
- }
- });
- }
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ selectionService.setSelection(event.getSelection());
+ }
+ });
- @Override
- public void dispose() {
- super.dispose();
+ contactsService.addListener(contactsUpdate);
- contactsService.removeListener(contactsUpdate);
-
- for (IAction action : registeredActions.values())
- if (action instanceof Disposable) ((Disposable) action).dispose();
- }
-
- /**
- * Display a notification next to the given control.
- *
- * @param title
- * @param text
- * @param control
- */
- public static void showNotification(
- final String title, final String text, final Control control) {
- if (title == null) throw new NullPointerException("title is null");
+ partService.addPartListener(partListener);
+ }
- if (text == null) throw new NullPointerException("text is null");
+ @PreDestroy
+ public void dispose(EPartService partService) {
+ partService.removePartListener(partListener);
+ contactsService.removeListener(contactsUpdate);
+ }
- if (!showBalloonNotifications) return;
+ /**
+ * Display a notification next to the given control.
+ *
+ * @param title
+ * @param text
+ * @param control
+ */
+ public static void showNotification(final String title, final String text,
+ final Control control) {
+ if (title == null)
+ throw new NullPointerException("title is null");
- SWTUtils.runSafeSWTAsync(
- log,
- new Runnable() {
- @Override
- public void run() {
+ if (text == null)
+ throw new NullPointerException("text is null");
- Control attachToControl = control;
+ if (!showBalloonNotifications)
+ return;
- if (attachToControl != null) {
- BalloonNotification.showNotification(
- attachToControl, SWT.LEFT | SWT.BOTTOM, title, text);
- return;
+ SWTUtils.runSafeSWTAsync(log, new Runnable() {
+ @Override
+ public void run() {
+
+ Control attachToControl = control;
+
+ if (attachToControl != null) {
+ BalloonNotification.showNotification(attachToControl,
+ SWT.LEFT | SWT.BOTTOM, title, text);
+ return;
+ }
+
+ if (ePartService != null) {
+ MPart sarosView = ePartService
+ .findPart("saros.ui.e4.views.SarosView");
+ if (sarosView != null && sarosView.getObject() != null) {
+ attachToControl = ((SarosView) sarosView
+ .getObject()).notificationAnchor;
+ }
+ } else {
+ attachToControl = Display.getCurrent().getFocusControl();
+ }
+ // IViewPart sarosView = SWTUtils.findView(SarosView.ID);
+
+ /*
+ * If no session view is open then show the balloon notification
+ * in the control which has the keyboard focus
+ */
+
+ /*
+ * if (sarosView != null) { attachToControl = ((SarosView)
+ * sarosView).notificationAnchor; } else { attachToControl =
+ * Display.getCurrent().getFocusControl(); }
+ */
+
+ BalloonNotification.showNotification(attachToControl,
+ SWT.LEFT | SWT.BOTTOM, title, text);
}
+ });
+ }
- IViewPart sarosView = SWTUtils.findView(SarosView.ID);
-
- /*
- * If no session view is open then show the balloon notification
- * in the control which has the keyboard focus
- */
+ /**
+ * Displays a notification next to the Saros View. If the view cannot be
+ * found the notification is displayed next to the element that has the
+ * current focus. The visibility time of the notification will vary,
+ * depending on how much words the text contains. This method SHOULD
+ * NOT be called directly from the business logic.
+ *
+ * @param title
+ * the title of the notification
+ * @param text
+ * the text of the notification
+ * @throws NullPointerException
+ * if title or text is null
+ */
+ public static void showNotification(final String title, final String text) {
+ showNotification(title, text, null);
+ }
- if (sarosView != null) {
- attachToControl = ((SarosView) sarosView).notificationAnchor;
- } else {
- attachToControl = Display.getCurrent().getFocusControl();
- }
+ /**
+ * TODO Move to (yet-to-be-created) IDE-independent NotificationHandler
+ * class
+ */
+ public static void showStopNotification(User user,
+ SessionEndReason reason) {
+ String text = null;
+ String title = null;
+
+ switch (reason) {
+ case KICKED:
+ title = Messages.SessionStop_host_removed_you_title;
+ text = CoreUtils
+ .format(Messages.SessionStop_host_removed_you_message, user);
+ break;
+
+ case HOST_LEFT:
+ title = Messages.SessionStop_host_closed_session_title;
+ text = CoreUtils
+ .format(Messages.SessionStop_host_closed_session_message, user);
+ break;
+ case CONNECTION_LOST:
+ // TODO display the error
+ return;
+ case LOCAL_USER_LEFT:
+ return;
+ default:
+ log.warn("no UI notification available for stop reason: " + reason);
+ return;
+ }
- BalloonNotification.showNotification(
- attachToControl, SWT.LEFT | SWT.BOTTOM, title, text);
- }
- });
- }
-
- /**
- * Displays a notification next to the Saros View. If the view cannot be found the notification is
- * displayed next to the element that has the current focus. The visibility time of the
- * notification will vary, depending on how much words the text contains. This method SHOULD
- * NOT be called directly from the business logic.
- *
- * @param title the title of the notification
- * @param text the text of the notification
- * @throws NullPointerException if title or text is null
- */
- public static void showNotification(final String title, final String text) {
- showNotification(title, text, null);
- }
-
- /** TODO Move to (yet-to-be-created) IDE-independent NotificationHandler class */
- public static void showStopNotification(User user, SessionEndReason reason) {
- String text = null;
- String title = null;
-
- switch (reason) {
- case KICKED:
- title = Messages.SessionStop_host_removed_you_title;
- text = CoreUtils.format(Messages.SessionStop_host_removed_you_message, user);
- break;
-
- case HOST_LEFT:
- title = Messages.SessionStop_host_closed_session_title;
- text = CoreUtils.format(Messages.SessionStop_host_closed_session_message, user);
- break;
- case CONNECTION_LOST:
- // TODO display the error
- return;
- case LOCAL_USER_LEFT:
- return;
- default:
- log.warn("no UI notification available for stop reason: " + reason);
- return;
+ showNotification(title, text);
}
- showNotification(title, text);
- }
-
- /**
- * Remove any balloon notifications that might be left, because they have become obsolete for a
- * reason
- */
- public static void clearNotifications() {
- SWTUtils.runSafeSWTAsync(
- log,
- new Runnable() {
- @Override
- public void run() {
- BalloonNotification.removeAllActiveNotifications();
- }
+ /**
+ * Remove any balloon notifications that might be left, because they have
+ * become obsolete for a reason
+ */
+ public static void clearNotifications() {
+ SWTUtils.runSafeSWTAsync(log, new Runnable() {
+ @Override
+ public void run() {
+ BalloonNotification.removeAllActiveNotifications();
+ }
});
- }
-
- @Override
- public void setFocus() {
- // TODO Auto-generated method stub
- }
-
- private void createActions() {
-
- // ContextMenus Session
- registerAction(ChangeWriteAccessAction.WriteAccess.newInstance());
- registerAction(ChangeWriteAccessAction.ReadOnly.newInstance());
- registerAction(new FollowThisPersonAction());
- registerAction(new JumpToUserWithWriteAccessPositionAction());
- registerAction(new SendFileAction());
- registerAction(new ChangeColorAction());
- registerAction(new RemoveUserAction());
- registerAction(new RequestSessionInviteAction());
-
- // ContextMenus Roster/Contact list
- registerAction(new SkypeAction());
- registerAction(new RenameContactAction());
- registerAction(new DeleteContactAction());
-
- // ContextMenus Both
- registerAction(new OpenChatAction(chatRooms));
-
- // Toolbar
- registerAction(new ChangeXMPPAccountAction());
- registerAction(new NewContactAction());
- registerAction(new OpenPreferencesAction());
- registerAction(new FollowModeAction());
- registerAction(new ConsistencyAction());
- registerAction(new LeaveSessionAction());
- }
-
- private IAction getAction(String id) {
- IAction action = registeredActions.get(id);
-
- if (action == null)
- throw new IllegalArgumentException("an action for id " + id + " is not registered");
-
- return action;
- }
-
- private IAction registerAction(IAction action) {
- IAction oldAction = registeredActions.put(action.getId(), action);
-
- if (oldAction != null)
- throw new IllegalArgumentException(
- "tried to register action with id " + action.getId() + " more than once");
-
- return action;
- }
+ }
}
diff --git a/eclipse/src/saros/ui/views/StartSessionWithProjects.java b/eclipse/src/saros/ui/views/StartSessionWithProjects.java
new file mode 100644
index 0000000000..cd964494c0
--- /dev/null
+++ b/eclipse/src/saros/ui/views/StartSessionWithProjects.java
@@ -0,0 +1,141 @@
+package saros.ui.views;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.jface.viewers.ISelection;
+import saros.net.xmpp.JID;
+import saros.ui.Messages;
+import saros.ui.util.CollaborationUtils;
+import saros.ui.util.WizardUtils;
+import saros.ui.util.selection.SelectionUtils;
+import saros.ui.wizards.StartSessionWizard;
+
+/**
+ * Creates a context menu filled with entries, each of which represents a project that currently
+ * exists in the workspace. Each entry will trigger a session negotiation with the given project.
+ *
+ * In addition, if multiple projects are present in the workspace, an additional entry will be
+ * displayed which will open a {@linkplain StartSessionWizard wizard} instead.
+ */
+public class StartSessionWithProjects {
+
+ @Inject
+ public StartSessionWithProjects(
+ EModelService service,
+ @Named(IServiceConstants.ACTIVE_SELECTION) ISelection activeSelection) {
+ this.service = service;
+ selection = activeSelection;
+ }
+
+ static class MultipleProjectMenuItemHandler {
+
+ @Execute
+ public void execute() {
+ WizardUtils.openStartSessionWizard(null);
+ }
+ }
+
+ static class ProjectMenuItemHandler {
+
+ @Execute
+ public void execute(MDirectMenuItem menuItem) {
+ Map objectData = menuItem.getTransientData();
+ IProject project = (IProject) objectData.get("project");
+ List contacts = (List) objectData.get("contacts");
+
+ CollaborationUtils.startSession(Collections.singleton(project), contacts);
+ }
+ }
+
+ private List menuEntries;
+ private EModelService service;
+
+ private ISelection selection;
+
+ public void createMenu(List menuEntries) {
+ this.menuEntries = menuEntries;
+
+ final List contacts = SelectionUtils.getAdaptableObjects(selection, JID.class);
+
+ final IProject[] projects = getSortedWorkspaceProjects();
+
+ if (projects.length == 0) {
+ createNoProjectsMenuItem(0);
+ return;
+ }
+
+ int idx;
+
+ for (idx = 0; idx < projects.length; idx++) createProjectMenuItem(idx, projects[idx], contacts);
+
+ if (idx > 1) {
+ menuEntries.add(idx++, service.createModelElement(MMenuSeparator.class));
+ createMultipleProjectMenuItem(idx);
+ }
+ }
+
+ /** Returns a sorted list of all {@link IProject}s in the {@link IWorkspace}. */
+ private IProject[] getSortedWorkspaceProjects() {
+ final IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+
+ Arrays.sort(
+ workspaceProjects,
+ new Comparator() {
+ @Override
+ public int compare(final IProject a, final IProject b) {
+ return a.getName().compareToIgnoreCase(b.getName());
+ }
+ });
+
+ return workspaceProjects;
+ }
+
+ /** Creates a menu entry which shares projects with the given Contacts. */
+ private void createProjectMenuItem(
+ final int index, final IProject project, final List contacts) {
+
+ MDirectMenuItem projectMenuItem = service.createModelElement(MDirectMenuItem.class);
+ projectMenuItem.setLabel(project.getName());
+ projectMenuItem.setContributionURI(
+ "bundleclass://saros.eclipse/saros.ui.e4.views.StartSessionWithProjects$MultipleProjectMenuItemHandler");
+ // TODO: set icon for menu element, old e3 variant : workbenchLabelProvider.getImage(project)
+
+ Map objectData = projectMenuItem.getTransientData();
+ objectData.put("project", project);
+ objectData.put("contacts", contacts);
+
+ menuEntries.add(index, projectMenuItem);
+ }
+
+ private void createMultipleProjectMenuItem(final int index) {
+ MDirectMenuItem multipleProjectMenuItem = service.createModelElement(MDirectMenuItem.class);
+ multipleProjectMenuItem.setLabel("Specific resource tree(s)...");
+ multipleProjectMenuItem.setContributionURI(
+ "bundleclass://saros.eclipse/saros.ui.e4.views.StartSessionWithProjects$MultipleProjectMenuItemHandler");
+
+ menuEntries.add(index, multipleProjectMenuItem);
+ }
+
+ /** Creates a menu entry which indicates that no Saros enabled contacts are online. */
+ private void createNoProjectsMenuItem(final int index) {
+ MDirectMenuItem noProjectsMenuItem = service.createModelElement(MDirectMenuItem.class);
+ noProjectsMenuItem.setLabel(Messages.SessionWithProjects_no_projects_in_workspace);
+ noProjectsMenuItem.setEnabled(false);
+
+ menuEntries.add(index, noProjectsMenuItem);
+ }
+}
diff --git a/stf/build.gradle.kts b/stf/build.gradle.kts
index efc7af91a5..460c972942 100644
--- a/stf/build.gradle.kts
+++ b/stf/build.gradle.kts
@@ -33,6 +33,9 @@ dependencies {
// This is a workaround for https://github.com/saros-project/saros/issues/1114
implementation("org.eclipse.platform:org.eclipse.ui.ide:3.17.200")
implementation("org.eclipse.platform:org.eclipse.ui.workbench:3.120.0")
+ // This is a workaround for an Issues, same as https://github.com/saros-project/saros/issues/1114
+ implementation("org.eclipse.platform:org.eclipse.e4.ui.services:1.3.700")
+ implementation("javax.inject:javax.inject:1")
compile(project(path = ":saros.eclipse", configuration = "testing"))
releaseDep(fileTree("libs"))