/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2014 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.env.ui;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.Icon;
import ij.IJ;
import ij.ImagePlus;
import org.openmicroscopy.shoola.env.Agent;
import org.openmicroscopy.shoola.env.Container;
import org.openmicroscopy.shoola.env.Environment;
import org.openmicroscopy.shoola.env.LookupNames;
import org.openmicroscopy.shoola.env.config.AgentInfo;
import org.openmicroscopy.shoola.env.config.OMEROInfo;
import org.openmicroscopy.shoola.env.config.Registry;
import org.openmicroscopy.shoola.env.data.AdminService;
import org.openmicroscopy.shoola.env.data.DataServicesFactory;
import org.openmicroscopy.shoola.env.data.events.ExitApplication;
import org.openmicroscopy.shoola.env.data.events.HeartbeatEvent;
import org.openmicroscopy.shoola.env.data.events.LogOff;
import org.openmicroscopy.shoola.env.data.events.ReconnectedEvent;
import org.openmicroscopy.shoola.env.data.events.RemoveGroupEvent;
import org.openmicroscopy.shoola.env.data.events.SaveEventResponse;
import org.openmicroscopy.shoola.env.data.events.ServiceActivationRequest;
import org.openmicroscopy.shoola.env.data.events.ServiceActivationResponse;
import org.openmicroscopy.shoola.env.data.events.SwitchUserGroup;
import org.openmicroscopy.shoola.env.data.events.ViewInPluginEvent;
import org.openmicroscopy.shoola.env.data.login.LoginService;
import org.openmicroscopy.shoola.env.data.login.UserCredentials;
import org.openmicroscopy.shoola.env.data.model.FileObject;
import org.openmicroscopy.shoola.env.data.util.AgentSaveInfo;
import omero.gateway.SecurityContext;
import omero.gateway.exception.DSOutOfServiceException;
import org.openmicroscopy.shoola.env.event.AgentEvent;
import org.openmicroscopy.shoola.env.event.AgentEventListener;
import org.openmicroscopy.shoola.env.event.EventBus;
import omero.log.LogMessage;
import omero.log.Logger;
import org.openmicroscopy.shoola.util.image.geom.Factory;
import org.openmicroscopy.shoola.util.ui.BrowserLauncher;
import org.openmicroscopy.shoola.util.ui.MacOSMenuHandler;
import org.openmicroscopy.shoola.util.ui.MessageBox;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import org.openmicroscopy.shoola.util.ui.login.LoginCredentials;
import org.openmicroscopy.shoola.util.ui.login.ScreenLogin;
import org.openmicroscopy.shoola.util.ui.login.ScreenLoginDialog;
import org.openmicroscopy.shoola.util.file.IOUtil;
import omero.gateway.model.ExperimenterData;
/**
* Creates and manages the {@link TaskBarView}.
* It acts as a controller.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author <br>Andrea Falconi
* <a href="mailto:a.falconi@dundee.ac.uk">
* a.falconi@dundee.ac.uk</a>
* @version 2.2
* @since OME2.2
*/
public class TaskBarManager
implements AgentEventListener, PropertyChangeListener
{
/** The window's title. */
static final String TITLE_ABOUT = "About";
/** Bound property indicating to display the activity dialog. */
static final String ACTIVITIES_PROPERTY = "activities";
/** The title displayed before closing the application. */
private static final String CLOSE_APP_TITLE = "Exit Application";
/** The text displayed before closing the application. */
private static final String CLOSE_APP_TEXT =
"Do you really want to close the application?";
/** The title displayed before closing the application. */
private static final String CLOSE_PLUGIN_TITLE = "Exit Plugin";
/** The text displayed before closing the application. */
private static final String CLOSE_PLUGIN_TEXT =
"Do you really want to close the plugin?";
/** The title displayed before logging out. */
private static final String LOGOUT_TITLE = "Log out";
/** The text displayed before logging out. */
private static final String LOGOUT_TEXT =
"Do you really want to disconnect from the server?";
/** The view this controller is managing. */
private TaskBarView view;
/** Reference to the container. */
private Container container;
/** The software update dialog. */
private SoftwareUpdateDialog suDialog;
/** Login dialog. */
private ScreenLoginDialog login;
/** Flag indicating if the connection was successful or not. */
private boolean success;
/** Dialog to reconnect to server.*/
private ScreenLoginDialog reconnectDialog;
/** The actions for the help menu */
private Map<Integer, ActionListener> helpMenuActions;
/**
* Returns the icon for the splash screen if none set.
*
* @param splashScreen The icon or <code>null</code>.
* @return See above.
*/
private Icon getSplashScreen(Icon splashScreen)
{
if (splashScreen == null) {
Integer v = (Integer) container.getRegistry().lookup(
LookupNames.ENTRY_POINT);
if (v != null) {
switch (v.intValue()) {
case LookupNames.IMPORTER_ENTRY:
splashScreen = IconManager.getImporterSplashScreen();
break;
default:
splashScreen = IconManager.getSplashScreen();
}
}
}
return splashScreen;
}
/**
* Reads the content of the specified file and returns it as a string.
*
* @param file Absolute pathname to the file.
* @return See above.
*/
private String loadAbout(String file)
{
String message;
try {
InputStream fis = IOUtil.readConfigFile(file);
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
StringBuffer buffer = new StringBuffer();
int number = 0;
String line;
while (true) {
line = in.readLine();
if (line == null) break;
if (number != 0) buffer.append(line);
number++;
}
in.close();
message = buffer.toString();
} catch (Exception e) {
message = "Error: Cannot find the About file.";
Logger logger = container.getRegistry().getLogger();
LogMessage msg = new LogMessage();
msg.print(message);
msg.print(e);
logger.error(this, msg);
}
return message;
}
/**
* Synchronizes the enabled state of the connection-related buttons
* according to the current connection state.
*/
private void synchConnectionButtons()
{
boolean connected = false;
try {
DataServicesFactory f = DataServicesFactory.getInstance(container);
connected = f.isConnected();
} catch (DSOutOfServiceException oose) {}
view.getButton(TaskBarView.CONNECT_BTN).setEnabled(!connected);
view.getButton(TaskBarView.CONNECT_MI).setEnabled(!connected);
view.getButton(TaskBarView.DISCONNECT_BTN).setEnabled(connected);
view.getButton(TaskBarView.DISCONNECT_MI).setEnabled(connected);
}
/** The action associated to the connection-related buttons. */
private void doManageConnection()
{
try {
DataServicesFactory f = DataServicesFactory.getInstance(container);
if (f.isConnected()) {
f.shutdown(null);
synchConnectionButtons();
} else {
EventBus bus = container.getRegistry().getEventBus();
bus.post(new ServiceActivationRequest(
ServiceActivationRequest.DATA_SERVICES));
}
} catch (DSOutOfServiceException oose) {
synchConnectionButtons();
}
}
/**
* Handles event sent when the data has been saved.
*
* @param e The event to handle.
*/
private void handleSaveEventResponse(SaveEventResponse e)
{
if (e == null) return;
/*
Agent a = e.getAgent();
Integer r = exitResponses.get(a);
if (r != null) {
int v = r.intValue()-1;
if (v == 0) exitResponses.remove(a);
//else exitResponses.put(a, v);
}
if (exitResponses.size() == 0) container.exit();
*/
}
/**
* Temporary action to notify the user that the action associated to a
* given button hasn't been implemented yet.
*/
private void notAvailable()
{
UserNotifier un = container.getRegistry().getUserNotifier();
un.notifyInfo("Not Available",
"Sorry, this functionality is not yet available.");
}
/** Brings up on screen a dialog to send comment. */
private void sendComment()
{
Registry reg = container.getRegistry();
UserNotifier un = reg.getUserNotifier();
ExperimenterData exp = (ExperimenterData) reg.lookup(
LookupNames.CURRENT_USER_DETAILS);
String email = "";
if (exp != null) email = exp.getEmail();
un.submitMessage(email, "");
}
/**
* Returns instances of <code>Agent</code> that can be saved.
*
* @return See above.
*/
private Map<Agent, AgentSaveInfo> getInstancesToSave()
{
List agents = (List) container.getRegistry().lookup(LookupNames.AGENTS);
Iterator i = agents.iterator();
Agent agent;
AgentSaveInfo info;
Map<Agent, AgentSaveInfo> l = new HashMap<Agent, AgentSaveInfo>();
AgentInfo ai;
while (i.hasNext()) {
ai = (AgentInfo) i.next();
if (ai.isActive()) {
agent = ai.getAgent();
if (agent != null) {
info = agent.getDataToSave();
if (info != null && info.getCount() > 0)
l.put(agent, info);
}
}
}
return l;
}
/**
* Views the image as an <code>ImageJ</code>.
*
* @param id The image's id to view.
* @param ctx The security context.
*/
private void runAsImageJ(long id, SecurityContext ctx)
{
UserCredentials lc = (UserCredentials) container.getRegistry().lookup(
LookupNames.USER_CREDENTIALS);
StringBuffer buffer = new StringBuffer();
try {
buffer.append("location=[OMERO] open=[omero:server=");
buffer.append(lc.getHostName());
buffer.append("\nuser=");
buffer.append(lc.getUserName());
buffer.append("\nport=");
buffer.append(lc.getPort());
buffer.append("\npass=");
buffer.append(lc.getPassword());
buffer.append("\ngroupID=");
buffer.append(ctx.getGroupID());
buffer.append("\niid=");
buffer.append(id);
buffer.append("]");
IJ.runPlugIn("loci.plugins.LociImporter", buffer.toString());
ImagePlus img = IJ.getImage();
img.setTitle(img.getTitle() + "--" + "OMERO ID:" + id);
img.setProperty(FileObject.OMERO_ID, id);
img.setProperty(FileObject.OMERO_GROUP, ctx.getGroupID());
} catch (Exception e) {
LogMessage message = new LogMessage();
message.println("Opening in image J");
message.print(e);
container.getRegistry().getLogger().debug(this, message);
IJ.showMessage("An error occurred while loading the image.");
}
}
/**
* Handles the event.
*
* @param evt The event to handle.
*/
private void handleViewInPluginEvent(ViewInPluginEvent evt)
{
if (evt == null) return;
switch (evt.getPlugin()) {
case LookupNames.IMAGE_J:
case LookupNames.IMAGE_J_IMPORT:
runAsImageJ(evt.getObjectID(), evt.getSecurityContext());
break;
}
}
/**
* Switches user group, notifies the agents to save data before switching.
*
* @param evt The event to handle.
*/
private void handleSwitchUserGroup(SwitchUserGroup evt)
{
if (evt == null) return;
//Do we have data to save.
/*
CheckoutBox box = new CheckoutBox(view, SWITCH_GROUP_TITLE,
SWITCH_GROUP_TEXT, getInstancesToSave());
if (box.centerMsgBox() == MessageBox.YES_OPTION) {
Map<Agent, AgentSaveInfo> map = box.getInstancesToSave();
UserNotifierImpl un = (UserNotifierImpl)
container.getRegistry().getUserNotifier();
List<Object> nodes = new ArrayList<Object>();
if (map != null) {
Iterator i = map.entrySet().iterator();
Entry entry;
Agent agent;
AgentSaveInfo info;
while (i.hasNext()) {
entry = (Entry) i.next();
agent = (Agent) entry.getKey();
info = (AgentSaveInfo) entry.getValue();
agent.save(info.getInstances());
nodes.add(info);
}
}
//nodes.add(evt.getExperimenterData());
//un.notifySaving(nodes, null);
Registry reg = container.getRegistry();
UserNotifierLoader loader = new SwitchUserLoader(
reg.getUserNotifier(), reg, evt.getExperimenterData(),
evt.getGroupID());
loader.load();
}
*/
}
/**
* Logs off from the current server.
*
* @param evt The event to handle.
*/
private void handleLogOff(LogOff evt)
{
if (evt == null) return;
SecurityContext ctx = evt.getSecurityContext();
if (!evt.isAskQuestion()) {
logOut(ctx);
return;
}
IconManager icons = IconManager.getInstance(container.getRegistry());
Map<Agent, AgentSaveInfo> instances = getInstancesToSave();
CheckoutBox msg = new CheckoutBox(view, LOGOUT_TITLE,
LOGOUT_TEXT, icons.getIcon(IconManager.QUESTION), instances);
if (msg.centerMsgBox() == MessageBox.YES_OPTION) {
Map<Agent, AgentSaveInfo> map = msg.getInstancesToSave();
if (map != null && map.size() > 0) {
List<Object> nodes = new ArrayList<Object>();
Iterator<Entry<Agent, AgentSaveInfo>>
i = map.entrySet().iterator();
Entry<Agent, AgentSaveInfo> entry;
Agent agent;
AgentSaveInfo info;
while (i.hasNext()) {
entry = i.next();
agent = entry.getKey();
info = entry.getValue();
agent.save(info.getInstances());
nodes.add(info);
}
}
logOut(ctx);
}
}
/**
* Removes the group.
*
* @param evt The event to handle.
*/
private void handleRemoveGroupEvent(RemoveGroupEvent evt)
{
if (evt == null) return;
SecurityContext ctx = evt.getContext();
try {
DataServicesFactory f =
DataServicesFactory.getInstance(container);
f.removeGroup(ctx);
} catch (Exception e) {
LogMessage msg = new LogMessage();
msg.print("Remove group");
msg.print(e);
container.getRegistry().getLogger().error(this, msg);
}
}
/**
* Handles the event sent at regular interval to check if rendering
* engines are still active.
*
* @param evt The event to handle.
*/
private void handleHeartbeatEvent(HeartbeatEvent evt)
{
if (evt == null) return;
try {
DataServicesFactory f = DataServicesFactory.getInstance(container);
f.checkServicesStatus();
} catch (Exception e) {
LogMessage msg = new LogMessage();
msg.print("checkServicesStatus");
msg.print(e);
container.getRegistry().getLogger().debug(this, msg);
}
}
/** Reconnects to the server.*/
private void reconnect()
{
Image img = IconManager.getOMEImageIcon();
Object version = container.getRegistry().lookup(
LookupNames.VERSION);
String v = "";
if (version != null && version instanceof String)
v = (String) version;
OMEROInfo omeroInfo = (OMEROInfo) container.getRegistry().lookup(
LookupNames.OMERODS);
String port = ""+omeroInfo.getPortSSL();
String f = container.getConfigFileRelative(Container.CONFIG_DIR);
String n = (String) container.getRegistry().lookup(
LookupNames.SPLASH_SCREEN_LOGO);
reconnectDialog = new ScreenLoginDialog(Container.TITLE,
getSplashScreen(Factory.createIcon(n, f)), img, v, port);
reconnectDialog.setStatusVisible(false);
reconnectDialog.showConnectionSpeed(true);
reconnectDialog.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (ScreenLogin.QUIT_PROPERTY.equals(name))
exitApplication(null);
else if (ScreenLogin.LOGIN_PROPERTY.equals(name)) {
LoginCredentials lc = (LoginCredentials) evt.getNewValue();
if (lc != null) {
collectCredentials(lc,
(ScreenLoginDialog) evt.getSource());
}
}
}
});
reconnectDialog.setModal(true);
UIUtilities.centerAndShow(reconnectDialog);
}
/**
* Disconnects from the current server.
*
* @param ctx The security context.
*/
private void logOut(SecurityContext ctx)
{
//Change group if context not null
if (ctx != null) {
try {
AdminService svc = container.getRegistry().getAdminService();
//To be turned on when
//svc.changeExperimenterGroup(ctx, null, ctx.getGroupID());
} catch (Exception e) {
if (isRunAsIJPlugin()) IJ.log(e.getMessage());
Logger log = container.getRegistry().getLogger();
LogMessage msg = new LogMessage();
msg.print(e);
log.error(this, msg);
}
}
try {
DataServicesFactory f =
DataServicesFactory.getInstance(container);
f.exitApplication(false, false);
reconnect();
} catch (Exception e) {
UserNotifier un = container.getRegistry().getUserNotifier();
un.notifyInfo("Log out", "An error occurred while disconnecting" +
" from the server.");
LogMessage msg = new LogMessage();
msg.print("Log out");
msg.print(e);
container.getRegistry().getLogger().debug(this, msg);
}
}
/**
* The exit action.
* Just forwards to the container.
*
* @param askQuestion Pass <code>true</code> to pop up a message before
* quitting, <code>false</code> otherwise.
* @param ctx The security context so the default group can be set or
* <code>null</code>.
*/
private void doExit(boolean askQuestion, SecurityContext ctx)
{
if (reconnectDialog != null) {
exitApplication(ctx);
return;
}
Environment env = (Environment)
container.getRegistry().lookup(LookupNames.ENV);
String title = CLOSE_APP_TITLE;
String message = CLOSE_APP_TEXT;
if (env != null && env.isRunAsPlugin()) {
title = CLOSE_PLUGIN_TITLE;
message = CLOSE_PLUGIN_TEXT;
}
IconManager icons = IconManager.getInstance(container.getRegistry());
int option = MessageBox.YES_OPTION;
Map<Agent, AgentSaveInfo> instances = getInstancesToSave();
CheckoutBox msg = null;
if (env.isRunAsPlugin()) askQuestion = false;
if (askQuestion) {
msg = new CheckoutBox(view, title, message,
icons.getIcon(IconManager.QUESTION), instances);
msg.setYesText("Quit");
msg.setNoText("Do Not Quit");
option = msg.centerMsgBox();
}
if (option == MessageBox.YES_OPTION) {
if (msg == null) {
exitApplication(ctx);
} else {
Map<Agent, AgentSaveInfo> map = msg.getInstancesToSave();
if (map == null || map.size() == 0) {
exitApplication(ctx);
} else {
List<Object> nodes = new ArrayList<Object>();
Iterator<Entry<Agent, AgentSaveInfo>>
i = map.entrySet().iterator();
Entry<Agent, AgentSaveInfo> entry;
Agent agent;
AgentSaveInfo info;
while (i.hasNext()) {
entry = i.next();
agent = entry.getKey();
info = entry.getValue();
agent.save(info.getInstances());
nodes.add(info);
}
exitApplication(ctx);
}
}
}
}
/**
* Returns <code>true</code> if the application is used as
* plug-in e.g. ImageJ, KNIME, <code>false</code> otherwise.
*
* @return See above.
*/
private boolean isRunAsIJPlugin()
{
Environment env = (Environment)
container.getRegistry().lookup(LookupNames.ENV);
if (env == null) return false;
return env.runAsPlugin() >= 0;
}
/**
* Exits the application.
*
* @param ctx The security context or <code>null</code>.
*/
private void exitApplication(SecurityContext ctx)
{
reconnectDialog = null;
//Change group if context not null
if (ctx != null) {
try {
AdminService svc = container.getRegistry().getAdminService();
//to be reviewed when preferences are available.
//svc.changeExperimenterGroup(ctx, null, ctx.getGroupID());
} catch (Exception e) {
if (isRunAsIJPlugin()) IJ.log(e.getMessage());
Logger log = container.getRegistry().getLogger();
LogMessage msg = new LogMessage();
msg.print(e);
log.error(this, msg);
}
}
try {
DataServicesFactory f = DataServicesFactory.getInstance(container);
f.exitApplication(false, true);
} catch (Exception e) {
if (isRunAsIJPlugin()) IJ.log(e.getMessage());
Logger log = container.getRegistry().getLogger();
LogMessage msg = new LogMessage();
msg.print("Error while exiting");
msg.print(e);
log.error(this, msg);
}
}
/** Displays information about software. */
private void softwareAbout()
{
//READ content of the about file.
String aboutFile = (String) container.getRegistry().lookup(
LookupNames.ABOUT_FILE);
String refFile = container.getConfigFileRelative(aboutFile);
String message = loadAbout(refFile);
String title = (String) container.getRegistry().lookup(
LookupNames.SOFTWARE_NAME);
suDialog = new SoftwareUpdateDialog(view, message);
suDialog.setTitle(TITLE_ABOUT+" "+title+"...");
suDialog.setAlwaysOnTop(true);
suDialog.addPropertyChangeListener(
SoftwareUpdateDialog.OPEN_URL_PROPERTY, this);
UIUtilities.centerAndShow(suDialog);
}
/** Launches a browser with the documentation. */
private void help()
{
String path = (String) container.getRegistry().lookup(
LookupNames.HELP_ON_LINE);
openURL(path);
}
/** Launches a browser with the documentation. */
private void forum()
{
String path = (String) container.getRegistry().lookup(
LookupNames.FORUM);
openURL(path);
}
/** Opens the directory where the log file is. */
private void logFile()
{
//To be reviewed
String logDirName = (String) container.getRegistry().lookup(
LookupNames.LOG_DIR);
String name = (String) container.getRegistry().lookup(
LookupNames.USER_HOME_OMERO);
String path = name+File.separator+logDirName;
String url = path;
try
{
url = new File(path).toURI().toURL().toString();
url = url.replaceAll("^file:/", "file:///");
openURL(url);
} catch (Exception e) {
container.getRegistry().getLogger().error(this,
"Unable to open log directory.");
}
}
/** Instantiates the ActionListeners for the help menu */
private void createHelpMenuActionListeners() {
helpMenuActions = new HashMap<Integer, ActionListener>();
ActionListener noOp = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
notAvailable();
}
};
helpMenuActions.put(TaskBarView.WELCOME_MI, noOp);
helpMenuActions.put(TaskBarView.HELP_MI, new ActionListener() {
public void actionPerformed(ActionEvent e) {
help();
}
});
helpMenuActions.put(TaskBarView.HOWTO_MI, noOp);
helpMenuActions.put(TaskBarView.UPDATES_MI, new ActionListener() {
public void actionPerformed(ActionEvent e) {
softwareAbout();
}
});
helpMenuActions.put(TaskBarView.ABOUT_MI, noOp);
helpMenuActions.put(TaskBarView.HELP_BTN, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
help();
}
});
helpMenuActions.put(TaskBarView.COMMENT_MI, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendComment();
}
});
helpMenuActions.put(TaskBarView.FORUM_MI, new ActionListener() {
public void actionPerformed(ActionEvent e) {
forum();
}
});
helpMenuActions.put(TaskBarView.ACTIVITY_MI, new ActionListener() {
public void actionPerformed(ActionEvent e) {
((UserNotifierImpl)
container.getRegistry().getUserNotifier()).showActivity();
}
});
helpMenuActions.put(TaskBarView.LOG_FILE_MI, new ActionListener() {
public void actionPerformed(ActionEvent e) {
logFile();
}
});
}
/**
* Get the ActionListener for a specific help menu item
* @param id The Id of the action
* @return See above
*/
public ActionListener getHelpMenuAction(int id) {
return helpMenuActions.get(id);
}
/**
* Attaches the {@link #notAvailable() not-available} action to all buttons
* whose functionality hasn't been implemented yet.
*/
private void attachMIListeners()
{
view.getButton(TaskBarView.WELCOME_MI).addActionListener(
getHelpMenuAction(TaskBarView.WELCOME_MI));
view.getButton(TaskBarView.HELP_MI).addActionListener(
getHelpMenuAction(TaskBarView.HELP_MI));
view.getButton(TaskBarView.HOWTO_MI).addActionListener(
getHelpMenuAction(TaskBarView.HOWTO_MI));
view.getButton(TaskBarView.UPDATES_MI).addActionListener(
getHelpMenuAction(TaskBarView.UPDATES_MI));
view.getButton(TaskBarView.ABOUT_MI).addActionListener(
getHelpMenuAction(TaskBarView.ABOUT_MI));
view.getButton(TaskBarView.HELP_BTN).addActionListener(
getHelpMenuAction(TaskBarView.HELP_BTN));
view.getButton(TaskBarView.COMMENT_MI).addActionListener(
getHelpMenuAction(TaskBarView.COMMENT_MI));
view.getButton(TaskBarView.FORUM_MI).addActionListener(
getHelpMenuAction(TaskBarView.FORUM_MI));
view.getButton(TaskBarView.ACTIVITY_MI).addActionListener(
getHelpMenuAction(TaskBarView.ACTIVITY_MI));
view.getButton(TaskBarView.LOG_FILE_MI).addActionListener(
getHelpMenuAction(TaskBarView.LOG_FILE_MI));
}
/**
* Attaches the {@link #doManageConnection() manage-connection} action to
* all connection-related buttons.
*/
private void attachConnectionListeners()
{
ActionListener conx = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
doManageConnection();
}
};
view.getButton(TaskBarView.CONNECT_BTN).addActionListener(conx);
view.getButton(TaskBarView.CONNECT_MI).addActionListener(conx);
view.getButton(TaskBarView.DISCONNECT_BTN).addActionListener(conx);
view.getButton(TaskBarView.DISCONNECT_MI).addActionListener(conx);
}
/**
* Attaches the {@link #doExit() exit} action to all exit buttons and
* fires {@link #synchConnectionButtons()} when the window is first open.
*/
private void attachOpenExitListeners()
{
view.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) { doExit(true, null); }
public void windowOpened(WindowEvent we) {
synchConnectionButtons();
}
});
}
/**
* Registers the necessary listeners with the view and also registers with
* the event bus.
*/
private void attachListeners()
{
attachOpenExitListeners();
attachConnectionListeners();
attachMIListeners();
EventBus bus = container.getRegistry().getEventBus();
bus.register(this, ServiceActivationResponse.class);
bus.register(this, ExitApplication.class);
bus.register(this, SaveEventResponse.class);
bus.register(this, SwitchUserGroup.class);
bus.register(this, LogOff.class);
bus.register(this, ViewInPluginEvent.class);
bus.register(this, RemoveGroupEvent.class);
bus.register(this, HeartbeatEvent.class);
if (UIUtilities.isMacOS()) {
try {
MacOSMenuHandler handler = new MacOSMenuHandler(view);
handler.initialize();
view.addPropertyChangeListener(this);
} catch (Throwable e) {
Logger logger = container.getRegistry().getLogger();
LogMessage message = new LogMessage();
message.print(e);
logger.info(this, message);
}
}
}
/**
* Collects the user credentials.
*
* @param lc The value collected.
* @param dialog the dialog to handle.
*/
private void collectCredentials(LoginCredentials lc,
ScreenLoginDialog dialog)
{
UserCredentials uc = new UserCredentials(lc.getUserName(),
lc.getPassword(), lc.getHostName(), lc.getSpeedLevel());
uc.setPort(lc.getPort());
uc.setEncrypted(lc.isEncrypted());
uc.setGroup(lc.getGroup());
LoginService svc = (LoginService)
container.getRegistry().lookup(LookupNames.LOGIN);
success = false;
switch (svc.login(uc)) {
case LoginService.CONNECTED:
//needed b/c need to retrieve user's details later.
container.getRegistry().bind(LookupNames.USER_CREDENTIALS, uc);
dialog.close();
if (dialog == reconnectDialog) {
reconnectDialog = null;
container.getRegistry().getEventBus().post(
new ReconnectedEvent());
}
success = true;
break;
case LoginService.TIMEOUT:
success = false;
svc.notifyLoginTimeout();
if (dialog != null) {
dialog.cleanField(ScreenLogin.PASSWORD_FIELD);
dialog.onLoginFailure();
}
break;
case LoginService.NOT_CONNECTED:
success = false;
svc.notifyLoginFailure();
if (dialog != null) {
dialog.cleanField(ScreenLogin.PASSWORD_FIELD);
dialog.onLoginFailure();
}
}
}
/**
* Creates this controller along with its view and registers the necessary
* listeners with the view.
*
* @param c Reference to the container.
*/
TaskBarManager(Container c)
{
container = c;
// ActionListeneres for the help menu have to be created
// prior to the TaskBarView:
createHelpMenuActionListeners();
view = new TaskBarView(this, IconManager.getInstance(c.getRegistry()));
attachListeners();
}
/**
* Returns the view component.
*
* @return See above.
*/
TaskBar getView() { return view; }
/**
* Returns the name of the software.
*
* @return See above.
*/
String getSoftwareName()
{
return (String) container.getRegistry().lookup(
LookupNames.SOFTWARE_NAME);
}
/**
* Opens the URL.
*
* @param url The URL to open.
*/
void openURL(String url)
{
BrowserLauncher launcher = new BrowserLauncher(
AbstractIconManager.getOMEImageIcon());
launcher.openURL(url);
if (suDialog != null) suDialog.close();
}
/**
* Notifies that the connection is lost or the server is out of service.
* @param index
*/
void sessionExpired(int index)
{
try {
DataServicesFactory factory =
DataServicesFactory.getInstance(container);
factory.sessionExpiredExit(index, null);
} catch (Exception e) {}
}
/**
* Returns <code>true</code> if already connected,
* <code>false</code> otherwise.
*
* @return See above.
*/
boolean login()
{
try {
DataServicesFactory factory =
DataServicesFactory.getInstance(container);
if (factory.isConnected()) return true;
if (login == null) {
Image img = IconManager.getOMEImageIcon();
Object version = container.getRegistry().lookup(
LookupNames.VERSION);
String v = "";
if (version != null && version instanceof String)
v = (String) version;
OMEROInfo info =
(OMEROInfo) container.getRegistry().lookup(
LookupNames.OMERODS);
String port = ""+info.getPortSSL();
String f = container.getConfigFileRelative(null);
String n = (String) container.getRegistry().lookup(
LookupNames.SPLASH_SCREEN_LOGO);
login = new ScreenLoginDialog(Container.TITLE,
getSplashScreen(Factory.createIcon(n, f)), img, v, port);
login.setEncryptionConfiguration(info.isEncrypted(),
info.isEncryptedConfigurable());
login.setHostNameConfiguration(info.getHostName(),
info.isHostNameConfigurable());
login.setModal(true);
login.setStatusVisible(false);
login.showConnectionSpeed(true);
login.addPropertyChangeListener(this);
}
UIUtilities.centerAndShow(login);
return success;
} catch (Exception e) {
LogMessage msg = new LogMessage();
msg.print(e);
container.getRegistry().getLogger().debug(this, msg);
}
return success;
}
/**
* Returns the relative path to the <code>Libs</code> directory.
*
* @param file The file to handle.
* @return See above.
*/
String getLibFileRelative(String file)
{
if (file == null) return "";
return container.getFileRelative(Container.LIBS_DIR, file);
}
/**
* Intercepts {@link ServiceActivationResponse} events in order to keep
* the connection-related buttons in synch with the actual state of the
* connection.
* @see AgentEventListener#eventFired(AgentEvent)
*/
public void eventFired(AgentEvent e)
{
if (e instanceof ServiceActivationResponse)
synchConnectionButtons();
else if (e instanceof ExitApplication) {
ExitApplication a = (ExitApplication) e;
doExit(a.isAskQuestion(), a.getContext());
} else if (e instanceof SwitchUserGroup)
handleSwitchUserGroup((SwitchUserGroup) e);
else if (e instanceof SaveEventResponse)
handleSaveEventResponse((SaveEventResponse) e);
else if (e instanceof LogOff)
handleLogOff((LogOff) e);
else if (e instanceof ViewInPluginEvent)
handleViewInPluginEvent((ViewInPluginEvent) e);
else if (e instanceof RemoveGroupEvent)
handleRemoveGroupEvent((RemoveGroupEvent) e);
else if (e instanceof HeartbeatEvent)
handleHeartbeatEvent((HeartbeatEvent) e);
}
/**
* Reacts to property change fired by the <code>SoftwareUpdateDialog</code>.
* @see PropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt)
{
String name = evt.getPropertyName();
if (SoftwareUpdateDialog.OPEN_URL_PROPERTY.equals(name)) {
String url = (String) evt.getNewValue();
if (url != null) openURL(url);
} else if (MacOSMenuHandler.ABOUT_APPLICATION_PROPERTY.equals(name)) {
softwareAbout();
} else if (MacOSMenuHandler.QUIT_APPLICATION_PROPERTY.equals(name)) {
Registry reg = container.getRegistry();;
Object exp = reg.lookup(LookupNames.CURRENT_USER_DETAILS);
if (exp == null) container.exit(); //not connected
//else doExit(true, null);
} else if (ScreenLogin.LOGIN_PROPERTY.equals(name)) {
LoginCredentials lc = (LoginCredentials) evt.getNewValue();
if (lc != null) collectCredentials(lc, login);
} else if (ScreenLogin.QUIT_PROPERTY.equals(name)) {
login.close();
success = false;
} else if (ChangesDialog.DONE_PROPERTY.equals(name)) {
SecurityContext value = (SecurityContext) evt.getNewValue();
exitApplication(value);
}
}
}