/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.gui; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.lang.ref.*; import java.util.*; import java.util.List; import javax.swing.*; import javax.swing.UIManager.LookAndFeelInfo; import net.java.sip.communicator.impl.gui.event.*; 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.call.*; import net.java.sip.communicator.impl.gui.main.chat.*; import net.java.sip.communicator.impl.gui.main.chat.conference.*; import net.java.sip.communicator.impl.gui.main.chat.history.*; import net.java.sip.communicator.impl.gui.main.chatroomslist.*; 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.login.*; import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.impl.gui.utils.Constants; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.service.contactlist.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.gui.Container; import net.java.sip.communicator.service.gui.event.*; import net.java.sip.communicator.service.muc.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.shutdown.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; import net.java.sip.communicator.util.account.*; import net.java.sip.communicator.util.skin.*; import org.jitsi.service.resources.*; import org.jitsi.util.*; import org.osgi.framework.*; import com.sun.jna.platform.WindowUtils; /** * An implementation of the UIService that gives access to other * bundles to this particular swing ui implementation. * * @author Yana Stamcheva * @author Lyubomir Marinov * @author Dmitri Melnikov * @author Adam Netocny * @author Hristo Terezov */ public class UIServiceImpl implements UIService, ShutdownService, ServiceListener, PropertyChangeListener, UINotificationListener { /** * The Logger used by the UIServiceImpl class and its * instances for logging output. */ private static final Logger logger = Logger.getLogger(UIServiceImpl.class); private PopupDialogImpl popupDialog; private AccountRegWizardContainerImpl wizardContainer; /** * The PluginComponentListeners interested into when * PluginComponents gets added and removed. *
* Because UIServiceImpl is global with respect to the lifetime of * the application and, consequently, PluginComponentListeners get * leaked, the listeners are referenced by WeakReferences. *
*/ private final ListUISercie.getSupportedContainers
. Returns the
* list of supported containers by this implementation .
*
* @see UIService#getSupportedContainers()
* @return an Iterator over all supported containers.
*/
public IteratorisVisible
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()
{
return mainFrame.isFrameVisible();
}
/**
* 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(final boolean isVisible)
{
this.mainFrame.setFrameVisible(isVisible);
}
/**
* Locates the main application window to the new x and y coordinates.
*
* @param x The new x coordinate.
* @param y The new y coordinate.
*/
public void setLocation(int x, int y)
{
mainFrame.setLocation(x, y);
}
/**
* Returns the current location of the main application window. The returned
* point is the top left corner of the window.
*
* @return The top left corner coordinates of the main application window.
*/
public Point getLocation()
{
return mainFrame.getLocation();
}
/**
* Returns the size of the main application window.
*
* @return the size of the main application window.
*/
public Dimension getSize()
{
return mainFrame.getSize();
}
/**
* Sets the size of the main application window.
*
* @param width The width of the window.
* @param height The height of the window.
*/
public void setSize(int width, int height)
{
mainFrame.setSize(width, height);
}
/**
* Implements minimize
in the UIService interface. Minimizes
* the main application window.
*
* @see UIService#minimize()
*/
public void minimize()
{
this.mainFrame.minimize();
}
/**
* Implements maximize
in the UIService interface. Maximizes
* the main application window.
*
* @see UIService#maximize()
*/
public void maximize()
{
this.mainFrame.maximize();
}
/**
* Implements restore
in the UIService interface. Restores
* the main application window.
*
* @see UIService#restore()
*/
public void restore()
{
if (mainFrame.isFrameVisible())
{
if (mainFrame.getState() == JFrame.ICONIFIED)
mainFrame.setState(JFrame.NORMAL);
mainFrame.toFront();
}
else
mainFrame.setFrameVisible(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);
}
/**
* Brings the focus to the main application window.
*/
public void bringToFront()
{
if (mainFrame.getState() == Frame.ICONIFIED)
mainFrame.setState(Frame.NORMAL);
// Because toFront() method gives us no guarantee that our frame would
// go on top we'll try to also first request the focus and set our
// window always on top to put all the chances on our side.
mainFrame.requestFocus();
mainFrame.setAlwaysOnTop(true);
mainFrame.toFront();
mainFrame.setAlwaysOnTop(false);
}
/**
* Called from the systray service when a tray has been initialized and
* hiding (instead of minimizing or exiting) is possible). If hiding is
* possible and the option to minimize is not selected, the application
* gets hidden on clicking 'X'.
*
* @param true if a tray icon was loaded.
*/
public void setMainWindowCanHide(boolean canHide)
{
mainFrame.updateCloseAction(canHide);
}
/**
* 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()
{
registerExportedWindow(new AddContactDialog(mainFrame));
}
/**
* 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);
}
/**
* Unregisters the given ExportedWindow from the list of windows
* that could be accessed from other bundles.
*
* @param window the window to no longer be exported
*/
public void unregisterExportedWindow(ExportedWindow window)
{
WindowID identifier = window.getIdentifier();
ExportedWindow removed = exportedWindows.remove(identifier);
/*
* In case the unexpected happens and we happen to have the same
* WindowID for multiple ExportedWindows going through
* #registerExportedWindow(), we have to make sure we're not
* unregistering some other ExportedWindow which has overwritten the
* registration of the specified window.
*/
if ((removed != null) && !removed.equals(window))
{
/*
* We accidentally unregistered another window so bring back its
* registration.
*/
exportedWindows.put(identifier, removed);
/* Now unregister the right window. */
for (IteratorgetSupportedExportedWindows
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 IteratorgetExportedWindow
in the UIService interface.
* Returns the window corresponding to the given WindowID.
*
* @param windowID the id of the window we'd like to retrieve.
* @param params the params to be passed to the returned window.
* @return a reference to the ExportedWindow instance corresponding
* to windowID.
* @see UIService#getExportedWindow(WindowID)
*/
public ExportedWindow getExportedWindow(WindowID windowID, Object[] params)
{
ExportedWindow win = exportedWindows.get(windowID);
if (win != null)
win.setParams(params);
return win;
}
/**
* 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)
{
return getExportedWindow(windowID, 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 {@link UIService#getChat(Contact)}. 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 the Chat corresponding to the specified contact.
* @see UIService#getChat(Contact)
*/
public ChatPanel getChat(Contact contact)
{
return this.getChat(contact, null);
}
/**
* Implements {@link UIService#getChat(Contact)}. 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.
* @param escapedMessageUID the message ID of the message that should be
* excluded from the history when the last one is loaded in the chat
* @return the Chat corresponding to the specified contact.
* @see UIService#getChat(Contact)
*/
public ChatPanel getChat(Contact contact, String escapedMessageUID)
{
MetaContact metaContact
= GuiActivator.getContactListService()
.findMetaContactByContact(contact);
if(metaContact == null)
return null;
return chatWindowManager.getContactChat(
metaContact,
true,
escapedMessageUID);
}
/**
* Returns the Chat corresponding to the given ChatRoom.
*
* @param chatRoom the ChatRoom for which the searched chat is
* about.
* @return the Chat corresponding to the given ChatRoom.
*/
public ChatPanel getChat(ChatRoom chatRoom)
{
return chatWindowManager.getMultiChat(chatRoom, true);
}
/**
* Returns the selected Chat.
*
* @return the selected Chat.
*/
public ChatPanel getCurrentChat()
{
return chatWindowManager.getSelectedChat();
}
/**
* Returns the phone number currently entered in the phone number field.
*
* @return the phone number currently entered in the phone number field.
*/
public String getCurrentPhoneNumber()
{
return null;
}
/**
* Changes the phone number currently entered in the phone number field.
*
* @param phoneNumber the phone number to enter in the phone number field.
*/
public void setCurrentPhoneNumber(String phoneNumber)
{
}
/**
* Implements the UIService.isContainerSupported
method.
* Checks if the plugable container with the given Container 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(Container)
*/
public boolean isContainerSupported(Container 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 WizardContainer getAccountRegWizardContainer()
{
return this.wizardContainer;
}
/**
* Returns a default implementation of the SecurityAuthority
* interface that can be used by non-UI components that would like to launch
* the registration process for a protocol provider. Initially this method
* was meant for use by the systray bundle and the protocol URI handlers.
*
* @param protocolProvider the ProtocolProviderService for which
* the authentication window is about.
*
* @return a default implementation of the SecurityAuthority
* interface that can be used by non-UI components that would like to launch
* the registration process for a protocol provider.
*/
public SecurityAuthority getDefaultSecurityAuthority(
ProtocolProviderService protocolProvider)
{
SecurityAuthority secAuthority = GuiActivator.getSecurityAuthority(
protocolProvider.getProtocolName());
if (secAuthority == null)
secAuthority = GuiActivator.getSecurityAuthority();
if (secAuthority == null)
secAuthority = new DefaultSecurityAuthority(protocolProvider);
return secAuthority;
}
/**
* Returns the LoginManager.
* @return the LoginManager
*/
public LoginManager getLoginManager()
{
return loginManager;
}
/**
* Returns the chat conference manager.
*
* @return the chat conference manager.
*/
public ConferenceChatManager getConferenceChatManager()
{
return conferenceChatManager;
}
/**
* Returns the chat window manager.
*
* @return the chat window manager.
*/
public ChatWindowManager getChatWindowManager()
{
return chatWindowManager;
}
/**
* Returns the HistoryWindowManager.
* @return the HistoryWindowManager
*/
public HistoryWindowManager getHistoryWindowManager()
{
return historyWindowManager;
}
/**
* 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();
}
}
/**
* Sets the look&feel and the theme.
*/
private void setDefaultThemePack()
{
// Show tooltips immediately and specify a custom background.
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
UIManager.put(
"ToolTip.background",
new Color(
GuiActivator.getResources().getColor(
"service.gui.TOOLTIP_BACKGROUND")));
toolTipManager.setInitialDelay(500);
toolTipManager.setDismissDelay(60000);
toolTipManager.setEnabled(true);
// we need to set the UIDefaults class loader so that it may access
// resources packed inside OSGI bundles
UIManager.put("ClassLoader", getClass().getClassLoader());
/*
* Attempt to use the OS-native LookAndFeel instead of
* SIPCommLookAndFeel.
*/
String laf = UIManager.getSystemLookAndFeelClassName();
boolean lafIsSet = false;
/*
* SIPCommLookAndFeel used to be set in case the system L&F was the same
* as the cross-platform L&F. Unfortunately, SIPCommLookAndFeel is now
* broken because its classes are loaded by different ClassLoaders which
* results in exceptions. That's why the check
* !laf.equals(UIManager.getCrossPlatformLookAndFeelClassName()) is
* removed from the if statement bellow and thus the cross-platform L&F
* is preferred over SIPCommLookAndFeel.
*/
if (laf != null)
{
/*
* Swing does not have a LookAndFeel which integrates with KDE and
* the cross-platform LookAndFeel is plain ugly. KDE integrates with
* GTK+ so try to use the GTKLookAndFeel when running in KDE.
*/
String gtkLookAndFeel
= "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
if ((OSUtils.IS_FREEBSD || OSUtils.IS_LINUX)
&& laf.equals(
UIManager.getCrossPlatformLookAndFeelClassName()))
{
try
{
String kdeFullSession = System.getenv("KDE_FULL_SESSION");
if ((kdeFullSession != null)
&& (kdeFullSession.length() != 0))
{
for (LookAndFeelInfo lafi
: UIManager.getInstalledLookAndFeels())
{
if (gtkLookAndFeel.equals(lafi.getClassName()))
{
laf = gtkLookAndFeel;
break;
}
}
}
}
catch (Throwable t)
{
if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
}
}
try
{
UIManager.setLookAndFeel(laf);
lafIsSet = true;
UIDefaults uiDefaults = UIManager.getDefaults();
if (OSUtils.IS_WINDOWS)
fixWindowsUIDefaults(uiDefaults);
// Workaround for SC issue #516
// "GNOME SCScrollPane has rounded and rectangular borders"
if (laf.equals(gtkLookAndFeel)
|| laf.equals("com.sun.java.swing.plaf.motif.MotifLookAndFeel"))
{
uiDefaults.put(
"ScrollPaneUI",
new javax.swing.plaf.metal.MetalLookAndFeel()
.getDefaults().get("ScrollPaneUI"));
}
}
catch (ClassNotFoundException ex)
{
/*
* Ignore the exceptions because we're only trying to set the
* native LookAndFeel and, if it fails, we'll use
* SIPCommLookAndFeel.
*/
}
catch (InstantiationException ex)
{
}
catch (IllegalAccessException ex)
{
}
catch (UnsupportedLookAndFeelException ex)
{
}
}
if (!lafIsSet)
{
try
{
SIPCommLookAndFeel lf = new SIPCommLookAndFeel();
SIPCommLookAndFeel.setCurrentTheme(new SIPCommDefaultTheme());
// Check the isLookAndFeelDecorated property and set the
// appropriate default decoration.
if (Boolean.parseBoolean(
GuiActivator.getResources().getSettingsString(
"impl.gui.IS_LOOK_AND_FEEL_DECORATED")))
{
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
}
UIManager.setLookAndFeel(lf);
}
catch (UnsupportedLookAndFeelException ex)
{
logger.error("The provided Look & Feel is not supported.", ex);
}
}
}
private void fixWindowsUIDefaults(UIDefaults uiDefaults)
{
/*
* Windows actually uses different fonts for the controls in windows and
* the controls in dialogs. Unfortunately, win.defaultGUI.font may not
* be the font Windows will use for controls in windows but the one to
* be used for dialogs. And win.messagebox.font will be the font for
* windows but the L&F will use it for OptionPane which in turn should
* rather use the font for dialogs. So swap the meanings of the two to
* get standard fonts in the windows while compromizing that dialogs may
* appear in it as well (if the dialogs are created as non-OptionPanes
* and in this case SIP Communicator will behave as Mozilla Firfox and
* Eclipse with respect to using the window font for the dialogs).
*/
Toolkit toolkit = Toolkit.getDefaultToolkit();
Object menuFont = toolkit.getDesktopProperty("win.menu.font");
Object messageboxFont
= toolkit.getDesktopProperty("win.messagebox.font");
if ((messageboxFont != null) && messageboxFont.equals(menuFont))
{
Object defaultGUIFont
= toolkit.getDesktopProperty("win.defaultGUI.font");
if ((defaultGUIFont != null)
&& !defaultGUIFont.equals(messageboxFont))
{
Object messageFont = uiDefaults.get("OptionPane.font");
Object controlFont = uiDefaults.get("Panel.font");
if ((messageFont != null) && !messageFont.equals(controlFont))
{
uiDefaults.put("OptionPane.font", controlFont);
uiDefaults.put("OptionPane.messageFont", controlFont);
uiDefaults.put("OptionPane.buttonFont", controlFont);
uiDefaults.put("Button.font", messageFont);
uiDefaults.put("CheckBox.font", messageFont);
uiDefaults.put("ComboBox.font", messageFont);
uiDefaults.put("EditorPane.font", messageFont);
uiDefaults.put("FormattedTextField.font", messageFont);
uiDefaults.put("Label.font", messageFont);
uiDefaults.put("List.font", messageFont);
uiDefaults.put("RadioButton.font", messageFont);
uiDefaults.put("Panel.font", messageFont);
uiDefaults.put("PasswordField.font", messageFont);
uiDefaults.put("ProgressBar.font", messageFont);
uiDefaults.put("ScrollPane.font", messageFont);
uiDefaults.put("Slider.font", messageFont);
uiDefaults.put("Spinner.font", messageFont);
uiDefaults.put("TabbedPane.font", messageFont);
uiDefaults.put("Table.font", messageFont);
uiDefaults.put("TableHeader.font", messageFont);
uiDefaults.put("TextField.font", messageFont);
uiDefaults.put("TextPane.font", messageFont);
uiDefaults.put("TitledBorder.font", messageFont);
uiDefaults.put("ToggleButton.font", messageFont);
uiDefaults.put("Tree.font", messageFont);
uiDefaults.put("Viewport.font", messageFont);
}
}
}
// Workaround for bug 6396936 (http://bugs.sun.com): WinL&F : font for
// text area is incorrect.
uiDefaults.put("TextArea.font", uiDefaults.get("TextField.font"));
}
/**
* Notifies all plugin containers of a PluginComponent
* registration.
* @param event the ServiceEvent that notified us
*/
public void serviceChanged(ServiceEvent event)
{
Object sService = GuiActivator.bundleContext.getService(
event.getServiceReference());
// we don't care if the source service is not a plugin component
if (! (sService instanceof PluginComponentFactory))
return;
PluginComponentFactory factory = (PluginComponentFactory) sService;
switch (event.getType())
{
case ServiceEvent.REGISTERED:
if (logger.isInfoEnabled())
logger.info("Handling registration of a new Plugin Component.");
this.firePluginEvent(factory,
PluginComponentEvent.PLUGIN_COMPONENT_ADDED);
break;
case ServiceEvent.UNREGISTERING:
this.firePluginEvent(factory,
PluginComponentEvent.PLUGIN_COMPONENT_REMOVED);
break;
}
}
/**
* Returns the corresponding BorderLayout constraint from the given
* Container constraint.
*
* @param containerConstraints constraints defined in the Container
* @return the corresponding BorderLayout constraint from the given
* Container constraint.
*/
public static Object getBorderLayoutConstraintsFromContainer(
Object containerConstraints)
{
Object layoutConstraint = null;
if (containerConstraints == null)
return null;
if (containerConstraints.equals(Container.START))
layoutConstraint = BorderLayout.LINE_START;
else if (containerConstraints.equals(Container.END))
layoutConstraint = BorderLayout.LINE_END;
else if (containerConstraints.equals(Container.TOP))
layoutConstraint = BorderLayout.NORTH;
else if (containerConstraints.equals(Container.BOTTOM))
layoutConstraint = BorderLayout.SOUTH;
else if (containerConstraints.equals(Container.LEFT))
layoutConstraint = BorderLayout.WEST;
else if (containerConstraints.equals(Container.RIGHT))
layoutConstraint = BorderLayout.EAST;
return layoutConstraint;
}
/**
* Indicates that a PropertyChangeEvent has occurred.
*
* @param evt the PropertyChangeEvent that notified us
*/
public void propertyChange(PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if (propertyName.equals(
"impl.gui.IS_TRANSPARENT_WINDOW_ENABLED"))
{
String isTransparentString = (String) evt.getNewValue();
boolean isTransparentWindowEnabled
= Boolean.parseBoolean(isTransparentString);
try
{
WindowUtils.setWindowTransparent( mainFrame,
isTransparentWindowEnabled);
}
catch (UnsupportedOperationException ex)
{
logger.error(ex.getMessage(), ex);
if (isTransparentWindowEnabled)
{
ResourceManagementService resources
= GuiActivator.getResources();
new ErrorDialog(
mainFrame,
resources.getI18NString("service.gui.ERROR"),
resources.getI18NString(
"service.gui.TRANSPARENCY_NOT_ENABLED"))
.showDialog();
}
ConfigurationUtils.setTransparentWindowEnabled(false);
}
}
else if (propertyName.equals(
"impl.gui.WINDOW_TRANSPARENCY"))
{
mainFrame.repaint();
}
}
/**
* Initialize main window font.
*/
private void initCustomFonts()
{
JComponent layeredPane = mainFrame.getLayeredPane();
ResourceManagementService resources = GuiActivator.getResources();
String fontName = resources.getSettingsString("service.gui.FONT_NAME");
int fontSize = resources.getSettingsInt("service.gui.FONT_SIZE");
Font font = new Font(fontName, Font.BOLD, fontSize);
for (int i = 0; i < layeredPane.getComponentCount(); i++)
layeredPane.getComponent(i).setFont(font);
}
/**
* Implements UIService#useMacOSXScreenMenuBar(). Indicates that the Mac OS
* X screen menu bar is to be used on Mac OS X and the Windows-like
* per-window menu bars are to be used on non-Mac OS X operating systems.
*
* @return true to indicate that MacOSX screen menu bar should be
* used, false - otherwise
*/
public boolean useMacOSXScreenMenuBar()
{
return OSUtils.IS_MAC;
}
/**
* Implements ShutdownService#beginShutdown(). Disposes of the mainFrame
* (if it exists) and then instructs Felix to start shutting down the
* bundles so that the application can gracefully quit.
*/
public void beginShutdown()
{
try
{
// close chats, so we do not start removing plugins one by one
// when we start to stop the application
for(ChatPanel cp : chatWindowManager.getAllChats())
chatWindowManager.closeChat(cp);
if (mainFrame != null)
mainFrame.dispose();
}
finally
{
// Just exit. The shutdown hook in felix ensures that we stop
// everything nicely.
System.exit(0);
}
}
/**
* Returns the ConfigurationContainer associated with this
* UIService.
*
* @return the ConfigurationContainer associated with this
* UIService
*/
public ConfigurationContainer getConfigurationContainer()
{
if (configurationFrame == null)
{
if(!SwingUtilities.isEventDispatchThread())
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
getConfigurationContainer();
}
});
}
catch(Throwable e)
{
logger.error("Error creating config frame in swing thread");
// if still no frame create it outside event dispatch thread
if(configurationFrame == null)
configurationFrame = new ConfigurationFrame(mainFrame);
}
return configurationFrame;
}
configurationFrame = new ConfigurationFrame(mainFrame);
}
return configurationFrame;
}
/**
* Dispatcher which ensures that our custom keybindings will
* be executed before any other focused(or not focused) component
* will consume our key event. This way we override some components
* keybindings.
*/
private static class KeyBindingsDispatching
implements KeyEventDispatcher
{
private final KeyboardFocusManager focusManager;
KeyBindingsDispatching(KeyboardFocusManager focusManager)
{
this.focusManager = focusManager;
}
public boolean dispatchKeyEvent(KeyEvent e)
{
if(e.getID() == KeyEvent.KEY_PRESSED)
{
Window w = focusManager.getActiveWindow();
JRootPane rpane = null;
if(w instanceof JFrame)
rpane = ((JFrame)w).getRootPane();
if(w instanceof JDialog)
rpane = ((JDialog)w).getRootPane();
if(rpane == null)
return false;
Object binding = rpane.
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
get(KeyStroke.getKeyStrokeForEvent(e));
if(binding == null)
return false;
Object actObj = rpane.getActionMap().get(binding);
if(actObj != null && actObj instanceof UIAction)
{
((UIAction)actObj).actionPerformed(
new ActionEvent(w, -1, (String)binding));
return true;
}
}
return false;
}
}
/**
* Returns a list containing all open Chats
*
* @return A list of all open Chats.
*/
public List* The current implementation provided by UIServiceImpl supports a * single participant at the time of this writing. *
* * @param participants an array of String values specifying the * participants to be included into the newly created Call * @see UIService#createCall(String[]) */ public void createCall(String[] participants) { if (participants.length == 1) CallManager.createCall(participants[0], null); else throw new IllegalArgumentException("participants"); } /** * Starts a new Chat with a specific set of participants. ** The current implementation provided by UIServiceImpl supports a * single participant at the time of this writing. *
* * @param participants an array of String values specifying the * participants to be included into the newly created Chat * @see UIService#startChat(String[]) */ public void startChat(String[] participants) { startChat(participants, false); } /** * Starts a new Chat with a specific set of participants. * * @param participants an array of String values specifying the * participants to be included into the newly created Chat * @param isSmsEnabled whether sms option should be enabled if possible */ public void startChat(String[] participants, boolean isSmsEnabled) { if (participants.length == 1) getChatWindowManager().startChat(participants[0], isSmsEnabled); else throw new IllegalArgumentException("participants"); } /** * Opens a chat room window for the given ChatRoomWrapper instance. * * @param chatRoom the chat room associated with the chat room window */ public void openChatRoomWindow(ChatRoomWrapper chatRoom) { ChatWindowManager chatWindowManager = getChatWindowManager(); ChatPanel chatPanel = chatWindowManager.getMultiChat(chatRoom, true); chatWindowManager.openChat(chatPanel, true); } /** * Closes the chat room window for the given ChatRoomWrapper * instance. * * @param chatRoom the chat room associated with the chat room window. */ public void closeChatRoomWindow(ChatRoomWrapper chatRoom) { ChatWindowManager chatWindowManager = getChatWindowManager(); ChatPanel chatPanel = chatWindowManager.getMultiChat(chatRoom, false); if (chatPanel != null) chatWindowManager.closeChat(chatPanel); } /** * Creates a contact list component. * * @param clContainer the parent contact list container * @return the created ContactList */ public ContactList createContactListComponent( ContactListContainer clContainer) { return new TreeContactList(clContainer); } /** * Returns a collection of all currently in progress calls. * * @return a collection of all currently in progress calls. */ public Collection