/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui;
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.lookandfeel.*;
import net.java.sip.communicator.impl.gui.main.*;
import net.java.sip.communicator.impl.gui.main.account.*;
import net.java.sip.communicator.impl.gui.main.chat.*;
import net.java.sip.communicator.impl.gui.main.configforms.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.main.contactlist.addcontact.*;
import net.java.sip.communicator.impl.gui.main.login.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.gui.event.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* An implementation of the UIService that gives access to other
* bundles to this particular swing ui implementation.
*
* @author Yana Stamcheva
*/
public class UIServiceImpl
implements UIService
{
private static final Logger logger = Logger.getLogger(UIServiceImpl.class);
private PopupDialogImpl popupDialog;
private AccountRegWizardContainerImpl wizardContainer;
private Map registeredPlugins = new Hashtable();
private Vector pluginComponentListeners = new Vector();
private static final List supportedContainers = new ArrayList();
static
{
supportedContainers.add(UIService.CONTAINER_MAIN_TOOL_BAR);
supportedContainers.add(UIService.CONTAINER_CONTACT_RIGHT_BUTTON_MENU);
supportedContainers.add(UIService.CONTAINER_GROUP_RIGHT_BUTTON_MENU);
supportedContainers.add(UIService.CONTAINER_TOOLS_MENU);
supportedContainers.add(UIService.CONTAINER_CHAT_TOOL_BAR);
supportedContainers.add(UIService.CONTAINER_CALL_HISTORY);
}
private static final Hashtable exportedWindows = new Hashtable();
private MainFrame mainFrame;
private LoginManager loginManager;
private ContactListPanel contactListPanel;
private ConfigurationFrame configurationFrame;
private boolean exitOnClose = true;
/**
* Creates an instance of UIServiceImpl.
*/
public UIServiceImpl()
{}
/**
* Initializes all frames and panels and shows the gui.
*/
public void loadApplicationGui()
{
this.setDefaultThemePack();
this.mainFrame = new MainFrame();
this.loginManager = new LoginManager(mainFrame);
this.contactListPanel = mainFrame.getContactListPanel();
this.popupDialog = new PopupDialogImpl();
this.wizardContainer = new AccountRegWizardContainerImpl(mainFrame);
this.configurationFrame = new ConfigurationFrame(mainFrame);
mainFrame.setContactList(GuiActivator.getMetaContactListService());
if(ConfigurationManager.isApplicationVisible())
SwingUtilities.invokeLater(new RunApplicationGui());
SwingUtilities.invokeLater(new RunLoginGui());
this.initExportedWindows();
}
/**
* Implements addComponent in UIService interface. Stores a plugin component
* and fires a PluginComponentEvent to inform all interested listeners that
* a plugin component has been added.
*
* @param containerID The ContainerID of the plugable container.
* @param component The component to add.
*
* @see UIService#addComponent(ContainerID, Object)
*
* @throws java.lang.ClassCastException if component is not an
* instance of a java.awt.Component
* @throws java.lang.IllegalArgumentException if no component exists for
* the specified container id.
*/
public void addComponent(ContainerID containerID, Object component)
throws ClassCastException, IllegalArgumentException
{
if (!supportedContainers.contains(containerID))
{
throw new IllegalArgumentException(
"The constraint that you specified is not"
+ " supported by this UIService implementation.");
}
else if (!(component instanceof Component))
{
throw new ClassCastException(
"The specified plugin is not a valid swing or awt component.");
}
else
{
if (registeredPlugins.containsKey(containerID))
{
((Vector) registeredPlugins.get(containerID)).add(component);
}
else
{
Vector plugins = new Vector();
plugins.add(component);
registeredPlugins.put(containerID, plugins);
}
this.firePluginEvent(component, containerID,
PluginComponentEvent.PLUGIN_COMPONENT_ADDED);
}
}
/**
* Implements UIService.addComponent(ContainerID, String, Object)
*
.
* For now this method only invokes addComponent(containerID, component).
*
* @param containerID The ContainerID of the plugable container.
* @param constraint a constraint indicating how the component should be
* added to the container.
* @param component the component we are adding.
*
* @see UIService#addComponent(ContainerID, String, Object)
* @throws java.lang.ClassCastException if component is not an
* instance of a java.awt.Component
* @throws java.lang.IllegalArgumentException if no component exists for
* the specified container id.
*/
public void addComponent(ContainerID containerID, String constraint,
Object component) throws ClassCastException, IllegalArgumentException
{
this.addComponent(containerID, component);
}
/**
* Implements UIService.addComponent(ContainerID, String, Object)
*
.
* For now this method only invokes addComponent(containerID, component).
*
* @param containerID The ContainerID of the plugable container.
* @param component the component we are adding.
*
* @throws java.lang.ClassCastException if component is not an
* instance of a java.awt.Component
* @throws java.lang.IllegalArgumentException if no component exists for
* the specified container id.
*/
public void addComponent(ContainerID containerID,
ContactAwareComponent component) throws ClassCastException,
IllegalArgumentException
{
if (!(component instanceof Component))
{
throw new ClassCastException(
"The specified plugin is not a valid swing or awt component.");
}
this.addComponent(containerID, (Component) component);
}
/**
* Implements UIService.addComponent(ContainerID, String, Object)
*
.
* For now this method only invokes addComponent(containerID, component).
*
* @param containerID The ContainerID of the plugable container.
* @param constraint a constraint indicating how the component should be
* added to the container.
* @param component the component we are adding.
*
* @throws java.lang.ClassCastException if component is not an
* instance of a java.awt.Component
* @throws java.lang.IllegalArgumentException if no component exists for
* the specified container id.
*/
public void addComponent(ContainerID containerID, String constraint,
ContactAwareComponent component) throws ClassCastException,
IllegalArgumentException
{
this.addComponent(containerID, constraint, component);
}
/**
* Implements UISercie.getSupportedContainers
. Returns the
* list of supported containers by this implementation .
*
* @see UIService#getSupportedContainers()
* @return an Iterator over all supported containers.
*/
public Iterator getSupportedContainers()
{
return Collections.unmodifiableList(supportedContainers).iterator();
}
/**
* Implements getComponentsForConstraint in UIService interface.
*
* @param containerID the id of the container whose components we'll be
* retrieving.
* @see UIService#getComponentsForContainer(ContainerID)
*
* @return an iterator over all components added in the container with ID
* containerID
*
* @throws java.lang.IllegalArgumentException if containerID does not
* correspond to a container used in this implementation.
*/
public Iterator getComponentsForContainer(ContainerID containerID)
throws IllegalArgumentException
{
if (!supportedContainers.contains(containerID))
throw new IllegalArgumentException(
"The container that you specified is not "
+ "supported by this UIService implementation.");
Vector plugins = new Vector();
Object o = registeredPlugins.get(containerID);
if (o != null)
{
plugins = (Vector) o;
}
return plugins.iterator();
}
/**
* Not yet implemented.
*
* @param containerID the ID of the container whose constraints we'll be
* retrieving.
*
* @see UIService#getConstraintsForContainer(ContainerID)
*
* @return Iterator an Iterator for all constraintes supported by
* the container corresponding to containerID.
*/
public Iterator getConstraintsForContainer(ContainerID containerID)
{
return null;
}
/**
* Creates the corresponding PluginComponentEvent and notifies all
* ContainerPluginListeners that a plugin component is added or
* removed from the container.
*
* @param pluginComponent the plugin component that is added to the
* container.
* @param containerID the containerID that corresponds to the container
* where the component is added.
* @param eventID one of the PLUGIN_COMPONENT_XXX static fields indicating
* the nature of the event.
*/
private void firePluginEvent(Object pluginComponent,
ContainerID containerID, int eventID)
{
PluginComponentEvent evt = new PluginComponentEvent(pluginComponent,
containerID, eventID);
logger.trace("Will dispatch the following plugin component event: "
+ evt);
synchronized (pluginComponentListeners)
{
Iterator listeners = this.pluginComponentListeners.iterator();
while (listeners.hasNext())
{
PluginComponentListener l = (PluginComponentListener) listeners
.next();
switch (evt.getEventID())
{
case PluginComponentEvent.PLUGIN_COMPONENT_ADDED:
l.pluginComponentAdded(evt);
break;
case PluginComponentEvent.PLUGIN_COMPONENT_REMOVED:
l.pluginComponentRemoved(evt);
break;
default:
logger.error("Unknown event type " + evt.getEventID());
}
}
}
}
/**
* Implements isVisible
in the UIService interface. Checks if
* the main application window is visible.
*
* @return true
if main application window is visible,
* false
otherwise
* @see UIService#isVisible()
*/
public boolean isVisible()
{
if (mainFrame.isVisible())
{
if (mainFrame.getExtendedState() == JFrame.ICONIFIED)
return false;
else
return true;
}
else
return false;
}
/**
* Implements setVisible
in the UIService interface. Shows or
* hides the main application window depending on the parameter
* visible
.
*
* @param isVisible true if we are to show the main application frame and
* false otherwise.
*
* @see UIService#setVisible(boolean)
*/
public void setVisible(boolean isVisible)
{
this.mainFrame.setVisible(isVisible);
if(isVisible)
this.mainFrame.toFront();
}
/**
* Implements minimize
in the UIService interface. Minimizes
* the main application window.
*
* @see UIService#minimize()
*/
public void minimize()
{
this.mainFrame.setExtendedState(JFrame.ICONIFIED);
}
/**
* Implements maximize
in the UIService interface. Maximizes
* the main application window.
*
* @see UIService#maximize()
*/
public void maximize()
{
this.mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
/**
* Implements restore
in the UIService interface. Restores
* the main application window.
*
* @see UIService#restore()
*/
public void restore()
{
if (mainFrame.isVisible())
{
if (mainFrame.getState() == JFrame.ICONIFIED)
mainFrame.setState(JFrame.NORMAL);
mainFrame.toFront();
}
else
mainFrame.setVisible(true);
}
/**
* Implements resize
in the UIService interface. Resizes the
* main application window.
*
* @param height the new height of tha main application frame.
* @param width the new width of the main application window.
*
* @see UIService#resize(int, int)
*/
public void resize(int width, int height)
{
this.mainFrame.setSize(width, height);
}
/**
* Implements move
in the UIService interface. Moves the main
* application window to the point with coordinates - x, y.
*
* @param x the value of X where the main application frame is to be placed.
* @param y the value of Y where the main application frame is to be placed.
*
* @see UIService#move(int, int)
*/
public void move(int x, int y)
{
this.mainFrame.setLocation(x, y);
}
/**
* Implements the UIService.setExitOnMainWindowClose
. Sets a
* boolean property, which indicates whether the application should be
* exited when the main application window is closed.
*
* @param exitOnClose specifies if closing the main application window
* should also be exiting the application.
*/
public void setExitOnMainWindowClose(boolean exitOnClose)
{
this.exitOnClose = exitOnClose;
if (exitOnClose)
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
else
mainFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
}
/**
* Implements the UIService.getExitOnMainWindowClose
.
* Returns the boolean property, which indicates whether the application
* should be exited when the main application window is closed.
*
* @return determines whether the UI impl would exit the application when
* the main application window is closed.
*/
public boolean getExitOnMainWindowClose()
{
return this.exitOnClose;
}
/**
* Adds all ExportedWindows to the list of application windows,
* which could be used from other bundles. Once registered in the
* UIService this window could be obtained through the
* getExportedWindow(WindowID) method and could be shown,
* hidden, resized, moved, etc.
*/
public void initExportedWindows()
{
AboutWindow aboutWindow = new AboutWindow(mainFrame);
AddContactWizard addContactWizard = new AddContactWizard(mainFrame);
exportedWindows.put(aboutWindow.getIdentifier(), aboutWindow);
exportedWindows.put(configurationFrame.getIdentifier(), configurationFrame);
exportedWindows.put(addContactWizard.getIdentifier(), addContactWizard);
}
/**
* Registers the given ExportedWindow to the list of windows that
* could be accessed from other bundles.
*
* @param window the window to be exported
*/
public void registerExportedWindow(ExportedWindow window)
{
exportedWindows.put(window.getIdentifier(), window);
}
/**
* Sets the contact list service to this UI Service implementation.
* @param contactList the MetaContactList service
*/
public void setContactList(MetaContactListService contactList)
{
this.mainFrame.setContactList(contactList);
}
public void addPluginComponentListener(PluginComponentListener l)
{
synchronized (pluginComponentListeners)
{
pluginComponentListeners.add(l);
}
}
public void removePluginComponentListener(PluginComponentListener l)
{
synchronized (pluginComponentListeners)
{
pluginComponentListeners.remove(l);
}
}
/**
* Implements getSupportedExportedWindows
in the UIService
* interface. Returns an iterator over a set of all windows exported by
* this implementation.
*
* @return an Iterator over all windows exported by this implementation of
* the UI service.
*
* @see UIService#getSupportedExportedWindows()
*/
public Iterator getSupportedExportedWindows()
{
return Collections.unmodifiableMap(exportedWindows).keySet().iterator();
}
/**
* Implements the getExportedWindow
in the UIService
* interface. Returns the window corresponding to the given
* WindowID.
*
* @param windowID the id of the window we'd like to retrieve.
*
* @return a reference to the ExportedWindow instance corresponding
* to windowID.
* @see UIService#getExportedWindow(WindowID)
*/
public ExportedWindow getExportedWindow(WindowID windowID)
{
if (exportedWindows.containsKey(windowID))
{
return (ExportedWindow) exportedWindows.get(windowID);
}
return null;
}
/**
* Implements the UIService.isExportedWindowSupported
method.
* Checks if there's an exported component for the given
* WindowID.
*
* @param windowID the id of the window that we're making the query for.
*
* @return true if a window with the corresponding windowID is exported by
* the UI service implementation and false otherwise.
*
* @see UIService#isExportedWindowSupported(WindowID)
*/
public boolean isExportedWindowSupported(WindowID windowID)
{
return exportedWindows.containsKey(windowID);
}
/**
* Implements getPopupDialog
in the UIService interface.
* Returns a PopupDialog that could be used to show simple
* messages, warnings, errors, etc.
*
* @return a PopupDialog that could be used to show simple
* messages, warnings, errors, etc.
*
* @see UIService#getPopupDialog()
*/
public PopupDialog getPopupDialog()
{
return this.popupDialog;
}
/**
* Implements getChat
in the UIService interface. If a
* chat for the given contact exists already - returns it, otherwise
* creates a new one.
*
* @param contact the contact that we'd like to retrieve a chat window for.
*
* @return a Chat corresponding to the specified contact.
*
* @see UIService#getChat(Contact)
*/
public Chat getChat(Contact contact)
{
MetaContact metaContact = mainFrame.getContactList()
.findMetaContactByContact(contact);
ChatWindowManager chatWindowManager = mainFrame.getChatWindowManager();
ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact);
return chatPanel;
}
/**
* Returns the selected Chat.
*
* @return the selected Chat.
*/
public Chat getCurrentChat()
{
ChatWindowManager chatWindowManager = mainFrame.getChatWindowManager();
return chatWindowManager.getSelectedChat();
}
/**
* Implements the UIService.isContainerSupported
method.
* Checks if the plugable container with the given ContainerID is supported
* by this implementation.
*
* @param containderID the id of the container that we're making the query
* for.
*
* @return true if the container with the specified id is exported by the
* implementation of the UI service and false otherwise.
*
* @see UIService#isContainerSupported(ContainerID)
*/
public boolean isContainerSupported(ContainerID containderID)
{
return supportedContainers.contains(containderID);
}
/**
* Implements the UIService.getAccountRegWizardContainer
* method. Returns the current implementation of the
* AccountRegistrationWizardContainer.
*
* @see UIService#getAccountRegWizardContainer()
*
* @return a reference to the currently valid instance of
* AccountRegistrationWizardContainer.
*/
public AccountRegistrationWizardContainer getAccountRegWizardContainer()
{
return this.wizardContainer;
}
/**
* Implements the UIService.getConfigurationWindow
. Returns
* the current implementation of the ConfigurationWindow
* interface.
*
* @see UIService#getConfigurationWindow()
*
* @return a reference to the currently valid instance of
* ConfigurationWindow.
*/
public ConfigurationWindow getConfigurationWindow()
{
return this.configurationFrame;
}
public ExportedWindow getAuthenticationWindow(
ProtocolProviderService protocolProvider,
String realm, UserCredentials userCredentials)
{
return new AuthenticationWindow(mainFrame, protocolProvider,
realm, userCredentials);
}
/**
* Returns the LoginManager.
* @return the LoginManager
*/
public LoginManager getLoginManager()
{
return loginManager;
}
/**
* Returns the MainFrame. This is the class defining the main
* application window.
*
* @return the MainFrame
*/
public MainFrame getMainFrame()
{
return mainFrame;
}
/**
* The RunLogin implements the Runnable interface and is used to
* shows the login windows in a seperate thread.
*/
private class RunLoginGui implements Runnable {
public void run() {
loginManager.runLogin(mainFrame);
}
}
/**
* The RunApplication implements the Runnable interface and is used to
* shows the main application window in a separate thread.
*/
private class RunApplicationGui implements Runnable {
public void run() {
mainFrame.setVisible(true);
}
}
/**
* Sets the look&feel and the theme.
*/
private void setDefaultThemePack() {
SIPCommLookAndFeel lf = new SIPCommLookAndFeel();
SIPCommLookAndFeel.setCurrentTheme(new SIPCommDefaultTheme());
// we need to set the UIDefaults class loader so that it may access
// resources packed inside OSGI bundles
UIManager.put("ClassLoader", getClass().getClassLoader());
try {
UIManager.setLookAndFeel(lf);
} catch (UnsupportedLookAndFeelException e) {
logger.error("The provided Look & Feel is not supported.", e);
}
}
}