diff --git a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java index 58f28bb77..f0bb1e776 100644 --- a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java +++ b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java @@ -54,6 +54,7 @@ public class UIServiceImpl 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_HELP_MENU); supportedContainers.add(UIService.CONTAINER_CHAT_TOOL_BAR); supportedContainers.add(UIService.CONTAINER_CALL_HISTORY); supportedContainers.add(UIService.CONTAINER_MAIN_TABBED_PANE); @@ -75,7 +76,8 @@ public class UIServiceImpl * Creates an instance of UIServiceImpl. */ public UIServiceImpl() - {} + { + } /** * Initializes all frames and panels and shows the gui. @@ -514,11 +516,10 @@ public boolean getExitOnMainWindowClose() */ 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(configurationFrame.getIdentifier(), + configurationFrame); exportedWindows.put(addContactWizard.getIdentifier(), addContactWizard); } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/menus/HelpMenu.java b/src/net/java/sip/communicator/impl/gui/main/chat/menus/HelpMenu.java index 7277108b5..499681b6a 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/menus/HelpMenu.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/menus/HelpMenu.java @@ -7,14 +7,19 @@ package net.java.sip.communicator.impl.gui.main.chat.menus; +import java.awt.Component; import java.awt.event.*; +import java.util.Iterator; import javax.swing.*; +import net.java.sip.communicator.impl.gui.GuiActivator; import net.java.sip.communicator.impl.gui.customcontrols.*; import net.java.sip.communicator.impl.gui.i18n.*; import net.java.sip.communicator.impl.gui.main.*; import net.java.sip.communicator.impl.gui.main.chat.*; +import net.java.sip.communicator.service.gui.UIService; +import net.java.sip.communicator.service.gui.event.*; import net.java.sip.communicator.util.*; /** * The HelpMenu is a menu in the main application menu bar. @@ -23,15 +28,14 @@ */ public class HelpMenu extends SIPCommMenu - implements ActionListener + implements ActionListener, + PluginComponentListener { private Logger logger = Logger.getLogger(HelpMenu.class.getName()); private I18NString aboutString = Messages.getI18NString("about"); - private JMenuItem aboutItem = new JMenuItem(aboutString.getText()); - private ChatWindow chatWindow; /** @@ -44,29 +48,60 @@ public HelpMenu(ChatWindow chatWindow) { this.chatWindow = chatWindow; - this.add(aboutItem); + this.chatWindow = chatWindow; + + this.setMnemonic(Messages.getI18NString("help").getMnemonic()); + + this.initPluginComponents(); + } - this.aboutItem.setName("about"); + /** + * Initialize plugin components already registered for this container. + */ + private void initPluginComponents() + { + Iterator pluginComponents = GuiActivator.getUIService() + .getComponentsForContainer(UIService.CONTAINER_CHAT_HELP_MENU); - this.aboutItem.addActionListener(this); + while (pluginComponents.hasNext()) + { + Component o = (Component) pluginComponents.next(); - this.aboutItem.setMnemonic(aboutString.getMnemonic()); + this.add(o); + } + + GuiActivator.getUIService().addPluginComponentListener(this); } /** - * Handles the ActionEvent when one of the menu items is selected. - * - * @param evt the ActionEvent that has just occurred. + * Handles the ActionEvent when one of the menu items is + * selected. */ - public void actionPerformed(ActionEvent evt) { + public void actionPerformed(ActionEvent e) + { + } - JMenuItem menuItem = (JMenuItem) evt.getSource(); - String itemName = menuItem.getName(); + public void pluginComponentAdded(PluginComponentEvent event) + { + Component c = (Component) event.getSource(); - if (itemName.equals("about")) { - AboutWindow aboutWindow = new AboutWindow(chatWindow); + if (event.getContainerID().equals(UIService.CONTAINER_CHAT_HELP_MENU)) + { + this.add(c); - aboutWindow.setVisible(true); + this.revalidate(); + this.repaint(); } } + + public void pluginComponentRemoved(PluginComponentEvent event) + { + Component c = (Component) event.getSource(); + + if (event.getContainerID().equals(UIService.CONTAINER_CHAT_HELP_MENU)) + { + this.remove(c); + } + } + } diff --git a/src/net/java/sip/communicator/impl/gui/main/menus/HelpMenu.java b/src/net/java/sip/communicator/impl/gui/main/menus/HelpMenu.java index a7fabe57c..4a7aaed0d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/menus/HelpMenu.java +++ b/src/net/java/sip/communicator/impl/gui/main/menus/HelpMenu.java @@ -1,5 +1,4 @@ /* - * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. @@ -7,67 +6,96 @@ package net.java.sip.communicator.impl.gui.main.menus; +import java.awt.*; import java.awt.event.*; +import java.util.*; -import javax.swing.*; - +import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.customcontrols.*; import net.java.sip.communicator.impl.gui.i18n.*; import net.java.sip.communicator.impl.gui.main.*; -import net.java.sip.communicator.util.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.gui.event.*; + /** * The HelpMenu is a menu in the main application menu bar. * * @author Yana Stamcheva + * @author Thomas Hofer */ -public class HelpMenu +public class HelpMenu extends SIPCommMenu - implements ActionListener + implements ActionListener, + PluginComponentListener { - private Logger logger = Logger.getLogger(HelpMenu.class.getName()); - - private I18NString aboutString = Messages.getI18NString("about"); - - private JMenuItem aboutItem - = new JMenuItem(aboutString.getText()); - private MainFrame mainFrame; - + /** * Creates an instance of HelpMenu. - * @param mainFrame the parent window + * + * @param mainFrame + * the parent window */ - public HelpMenu (MainFrame mainFrame) + public HelpMenu(MainFrame mainFrame) { super(Messages.getI18NString("help").getText()); - + this.mainFrame = mainFrame; - - this.add(aboutItem); - - this.aboutItem.setName("about"); - - this.aboutItem.addActionListener(this); - + this.setMnemonic(Messages.getI18NString("help").getMnemonic()); - - this.aboutItem.setMnemonic(aboutString.getMnemonic()); + + this.initPluginComponents(); } /** - * Handles the ActionEvent when one of the menu items is selected. + * Initialize plugin components already registered for this container. */ - public void actionPerformed(ActionEvent e) { + private void initPluginComponents() + { + Iterator pluginComponents = GuiActivator.getUIService() + .getComponentsForContainer(UIService.CONTAINER_HELP_MENU); - JMenuItem menuItem = (JMenuItem) e.getSource(); - String itemName = menuItem.getName(); + while (pluginComponents.hasNext()) + { + Component o = (Component) pluginComponents.next(); - if (itemName.equals("about")) { - AboutWindow aboutWindow = new AboutWindow(mainFrame); - - aboutWindow.setVisible(true); + this.add(o); } + + GuiActivator.getUIService().addPluginComponentListener(this); + } + + /** + * Handles the ActionEvent when one of the menu items is + * selected. + */ + public void actionPerformed(ActionEvent e) + { } + + public void pluginComponentAdded(PluginComponentEvent event) + { + Component c = (Component) event.getSource(); + + if (event.getContainerID().equals(UIService.CONTAINER_HELP_MENU)) + { + this.add(c); + + this.revalidate(); + this.repaint(); + } + } + + public void pluginComponentRemoved(PluginComponentEvent event) + { + Component c = (Component) event.getSource(); + + if (event.getContainerID().equals(UIService.CONTAINER_HELP_MENU)) + { + this.remove(c); + } + } + } diff --git a/src/net/java/sip/communicator/impl/gui/main/AboutWindow.java b/src/net/java/sip/communicator/plugin/splashscreen/AboutWindow.java similarity index 61% rename from src/net/java/sip/communicator/impl/gui/main/AboutWindow.java rename to src/net/java/sip/communicator/plugin/splashscreen/AboutWindow.java index 86f59230d..f83b9ee7f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/AboutWindow.java +++ b/src/net/java/sip/communicator/plugin/splashscreen/AboutWindow.java @@ -1,213 +1,239 @@ -package net.java.sip.communicator.impl.gui.main; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.customcontrols.*; -import net.java.sip.communicator.impl.gui.i18n.*; -import net.java.sip.communicator.impl.gui.utils.*; -import net.java.sip.communicator.service.gui.*; - -public class AboutWindow - extends SIPCommDialog - implements HyperlinkListener, - ActionListener, - ExportedWindow -{ - private WindowBackground mainPanel = new WindowBackground(); - - private JLabel titleLabel = new JLabel("SIP Communicator"); - - private JLabel versionLabel = - new JLabel(" " + System.getProperty("sip-communicator.version")); - - private JTextArea logoArea = - new JTextArea("Open Source VoIP & Instant Messaging"); - - private StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); - - private StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); - - private I18NString okString = Messages.getI18NString("ok"); - - private JButton okButton = new JButton(okString.getText()); - - private JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - - private JPanel textPanel = new JPanel(); - - public AboutWindow(Frame owner) - { - super(owner); - - this.setTitle(Messages.getI18NString("about").getText()); - this.setModal(false); - - this.mainPanel.setLayout(new BorderLayout()); - - this.textPanel.setPreferredSize(new Dimension(470, 280)); - this.textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); - this.textPanel.setBorder(BorderFactory - .createEmptyBorder(15, 15, 15, 15)); - this.textPanel.setOpaque(false); - - this.titleLabel.setFont(Constants.FONT.deriveFont(Font.BOLD, 28)); - this.titleLabel.setForeground(Constants.DARK_BLUE); - this.titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - - this.versionLabel.setFont(Constants.FONT.deriveFont(Font.BOLD, 18)); - this.versionLabel.setForeground(Color.GRAY); - this.versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - - this.logoArea.setFont(Constants.FONT.deriveFont(Font.BOLD, 14)); - this.logoArea.setForeground(Constants.DARK_BLUE); - this.logoArea.setOpaque(false); - this.logoArea.setLineWrap(true); - this.logoArea.setWrapStyleWord(true); - this.logoArea.setEditable(false); - this.logoArea.setPreferredSize(new Dimension(100, 20)); - this.logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - this.logoArea.setBorder(BorderFactory.createEmptyBorder(30, 180, 0, 0)); - - this.rightsArea.setContentType("text/html"); - - String startDivTag = "
"; - String endDivTag = "
"; - - this.rightsArea.appendToEnd(startDivTag - + "(c)2003-2007 Copyright sip-communicator.org." - + " All rights reserved. Visit " - + "" - + "http://sip-communicator.org." + endDivTag); - - this.rightsArea.setPreferredSize(new Dimension(50, 20)); - this.rightsArea - .setBorder(BorderFactory.createEmptyBorder(0, 180, 0, 0)); - this.rightsArea.setOpaque(false); - this.rightsArea.setEditable(false); - this.rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - this.rightsArea.addHyperlinkListener(this); - - this.licenseArea.setContentType("text/html"); - this.licenseArea.appendToEnd(startDivTag - + "The SIP Communicator is distributed under the" - + " terms of the LGPL " + "(" - + "http://www.gnu.org)." + endDivTag); - - this.licenseArea.setPreferredSize(new Dimension(50, 20)); - this.licenseArea.setBorder(BorderFactory.createEmptyBorder(10, 180, 0, - 0)); - this.licenseArea.setOpaque(false); - this.licenseArea.setEditable(false); - this.licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - this.licenseArea.addHyperlinkListener(this); - - this.textPanel.add(titleLabel); - this.textPanel.add(versionLabel); - this.textPanel.add(logoArea); - this.textPanel.add(rightsArea); - this.textPanel.add(licenseArea); - - this.getRootPane().setDefaultButton(okButton); - - this.okButton.setMnemonic(okString.getMnemonic()); - - this.okButton.addActionListener(this); - - this.buttonPanel.add(okButton); - this.buttonPanel.setOpaque(false); - - this.mainPanel.add(textPanel, BorderLayout.CENTER); - this.mainPanel.add(buttonPanel, BorderLayout.SOUTH); - - this.getContentPane().add(mainPanel); - - this.setResizable(false); - } - - protected void close(boolean isEscaped) - { - this.dispose(); - } - - /** - * Constructs the window background in order to have a background image. - */ - private class WindowBackground - extends JPanel - { - private Image bgImage = - ImageLoader.getImage(ImageLoader.ABOUT_WINDOW_BACKGROUND); - - public WindowBackground() - { - this.setPreferredSize(new Dimension(bgImage.getWidth(this), bgImage - .getHeight(this))); - } - - protected void paintComponent(Graphics g) - { - super.paintComponent(g); - - AntialiasingManager.activateAntialiasing(g); - - Graphics2D g2 = (Graphics2D) g; - - g2.drawImage(bgImage, 0, 0, null); - - g2.setColor(new Color(255, 255, 255, 100)); - - g2.fillRect(0, 0, getWidth(), getHeight()); - } - } - - public void hyperlinkUpdate(HyperlinkEvent e) - { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) - { - String href = e.getDescription(); - - GuiActivator.getBrowserLauncher().openURL(href); - } - } - - public void actionPerformed(ActionEvent e) - { - this.dispose(); - } - - /** - * Implements the ExportedWindow.getIdentifier() method. - */ - public WindowID getIdentifier() - { - return ExportedWindow.ABOUT_WINDOW; - } - - /** - * This dialog could not be minimized. - */ - public void minimize() - { - } - - /** - * This dialog could not be maximized. - */ - public void maximize() - { - } - - /** - * Implements the ExportedWindow.bringToFront() method. Brings - * this window to front. - */ - public void bringToFront() - { - this.toFront(); - } -} +package net.java.sip.communicator.plugin.splashscreen; + +import java.awt.*; +import java.awt.event.*; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.service.browserlauncher.BrowserLauncherService; +import net.java.sip.communicator.service.gui.*; + +import org.osgi.framework.ServiceReference; + +public class AboutWindow extends JDialog implements HyperlinkListener, + ActionListener, ExportedWindow +{ + private WindowBackground mainPanel = new WindowBackground(); + + private JLabel titleLabel = new JLabel("SIP Communicator"); + + private JLabel versionLabel = new JLabel(" " + + System.getProperty("sip-communicator.version")); + + private JTextArea logoArea = new JTextArea( + "Open Source VoIP & Instant Messaging"); + + private StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); + + private StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); + + private JButton okButton = new JButton(Resources.getString("ok")); + + private JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + + private JPanel textPanel = new JPanel(); + + public AboutWindow(Frame owner) + { + super(owner); + + this.setTitle(Resources.getString("about")); + this.setModal(false); + + this.mainPanel.setLayout(new BorderLayout()); + + this.textPanel.setPreferredSize(new Dimension(470, 280)); + this.textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); + this.textPanel.setBorder(BorderFactory + .createEmptyBorder(15, 15, 15, 15)); + this.textPanel.setOpaque(false); + + this.titleLabel.setFont(Constants.FONT.deriveFont(Font.BOLD, 28)); + this.titleLabel.setForeground(Constants.DARK_BLUE); + this.titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); + + this.versionLabel.setFont(Constants.FONT.deriveFont(Font.BOLD, 18)); + this.versionLabel.setForeground(Color.GRAY); + this.versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); + + this.logoArea.setFont(Constants.FONT.deriveFont(Font.BOLD, 14)); + this.logoArea.setForeground(Constants.DARK_BLUE); + this.logoArea.setOpaque(false); + this.logoArea.setLineWrap(true); + this.logoArea.setWrapStyleWord(true); + this.logoArea.setEditable(false); + this.logoArea.setPreferredSize(new Dimension(100, 20)); + this.logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + this.logoArea.setBorder(BorderFactory.createEmptyBorder(30, 180, 0, 0)); + + this.rightsArea.setContentType("text/html"); + + String startDivTag = "
"; + String endDivTag = "
"; + + this.rightsArea.appendToEnd(startDivTag + + "(c)2003-2007 Copyright sip-communicator.org." + + " All rights reserved. Visit " + + "" + + "http://sip-communicator.org." + endDivTag); + + this.rightsArea.setPreferredSize(new Dimension(50, 20)); + this.rightsArea + .setBorder(BorderFactory.createEmptyBorder(0, 180, 0, 0)); + this.rightsArea.setOpaque(false); + this.rightsArea.setEditable(false); + this.rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + this.rightsArea.addHyperlinkListener(this); + + this.licenseArea.setContentType("text/html"); + this.licenseArea.appendToEnd(startDivTag + + "The SIP Communicator is distributed under the" + + " terms of the LGPL " + "(" + + "http://www.gnu.org)." + endDivTag); + + this.licenseArea.setPreferredSize(new Dimension(50, 20)); + this.licenseArea.setBorder(BorderFactory.createEmptyBorder(10, 180, 0, + 0)); + this.licenseArea.setOpaque(false); + this.licenseArea.setEditable(false); + this.licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + this.licenseArea.addHyperlinkListener(this); + + this.textPanel.add(titleLabel); + this.textPanel.add(versionLabel); + this.textPanel.add(logoArea); + this.textPanel.add(rightsArea); + this.textPanel.add(licenseArea); + + this.getRootPane().setDefaultButton(okButton); + + this.okButton.setMnemonic(Resources.getString("ok").charAt(0)); + + this.okButton.addActionListener(this); + + this.buttonPanel.add(okButton); + this.buttonPanel.setOpaque(false); + + this.mainPanel.add(textPanel, BorderLayout.CENTER); + this.mainPanel.add(buttonPanel, BorderLayout.SOUTH); + + this.getContentPane().add(mainPanel); + this.setSize(mainPanel.getPreferredSize()); + + this.setResizable(false); + this.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width / 2 + - getWidth() / 2, + Toolkit.getDefaultToolkit().getScreenSize().height / 2 + - getHeight() / 2); + + } + + protected void close(boolean isEscaped) + { + this.dispose(); + } + + /** + * Constructs the window background in order to have a background image. + */ + private class WindowBackground extends JPanel + { + private Image bgImage = null; + + public WindowBackground() + { + try + { + bgImage = ImageIO.read(WindowBackground.class + .getResource("resources/aboutWindowBackground.png")); + } catch (IOException e) + { + bgImage = null; + } + this.setPreferredSize(new Dimension(bgImage.getWidth(this), bgImage + .getHeight(this))); + } + + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + + activateAntialiasing(g); + + Graphics2D g2 = (Graphics2D) g; + + g2.drawImage(bgImage, 0, 0, null); + + g2.setColor(new Color(255, 255, 255, 100)); + + g2.fillRect(0, 0, getWidth(), getHeight()); + } + } + + public void hyperlinkUpdate(HyperlinkEvent e) + { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + { + String href = e.getDescription(); + ServiceReference serviceReference = SplashScreenActivator + .getBundleContext().getServiceReference( + BrowserLauncherService.class.getName()); + + if (serviceReference != null) + { + BrowserLauncherService browserLauncherService = (BrowserLauncherService) SplashScreenActivator + .getBundleContext().getService(serviceReference); + browserLauncherService.openURL(href); + + } + } + } + + public void actionPerformed(ActionEvent e) + { + this.dispose(); + } + + /** + * Implements the ExportedWindow.getIdentifier() method. + */ + public WindowID getIdentifier() + { + return ExportedWindow.ABOUT_WINDOW; + } + + /** + * This dialog could not be minimized. + */ + public void minimize() + { + } + + /** + * This dialog could not be maximized. + */ + public void maximize() + { + } + + /** + * Implements the ExportedWindow.bringToFront() method. Brings + * this window to front. + */ + public void bringToFront() + { + this.toFront(); + } + + public static void activateAntialiasing(Graphics g) + { + Graphics2D g2d = (Graphics2D) g; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + } + +} diff --git a/src/net/java/sip/communicator/plugin/splashscreen/Constants.java b/src/net/java/sip/communicator/plugin/splashscreen/Constants.java new file mode 100644 index 000000000..08999115d --- /dev/null +++ b/src/net/java/sip/communicator/plugin/splashscreen/Constants.java @@ -0,0 +1,141 @@ +/* + * 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.plugin.splashscreen; + +import java.awt.*; +import java.io.*; + +import javax.swing.text.html.StyleSheet; + +/** + * All look and feel related constants are stored here. + * + * @author Yana Stamcheva + */ + +public class Constants +{ + /* + * ====================================================================== + * -------------------- FONTS AND COLOR CONSTANTS ------------------------ + * ====================================================================== + */ + + /** + * The color used to paint the background of an incoming call history + * record. + */ + public static final Color HISTORY_DATE_COLOR = new Color(255, 201, 102); + + /** + * The color used to paint the background of an incoming call history + * record. + */ + public static final Color HISTORY_IN_CALL_COLOR = new Color(249, 255, 197); + + /** + * The color used to paint the background of an outgoing call history + * record. + */ + public static final Color HISTORY_OUT_CALL_COLOR = new Color(243, 244, 247); + + /** + * The start color used to paint a gradient selected background of some + * components. + */ + public static final Color SELECTED_START_COLOR = new Color(151, 169, 198); + + /** + * The end color used to paint a gradient selected background of some + * components. + */ + public static final Color SELECTED_END_COLOR = new Color(209, 212, 225); + + /** + * The start color used to paint a gradient mouse over background of some + * components. + */ + public static final Color MOVER_START_COLOR = new Color(230, 230, 230); + + /** + * The end color used to paint a gradient mouse over background of some + * components. + */ + public static final Color MOVER_END_COLOR = new Color(255, 255, 255); + + /** + * Gray color used to paint some borders, like the button border for + * example. + */ + public static final Color GRAY_COLOR = new Color(154, 154, 154); + + /** + * A color between blue and gray used to paint some borders. + */ + public static final Color BLUE_GRAY_BORDER_COLOR = new Color(142, 160, 188); + + /** + * A color between blue and gray (darker than the other one), used to paint + * some borders. + */ + public static final Color BLUE_GRAY_BORDER_DARKER_COLOR = new Color(131, + 149, 178); + + /** + * Light gray color used in the look and feel. + */ + public static final Color LIGHT_GRAY_COLOR = new Color(200, 200, 200); + + /** + * Dark blue color used in the About Window. + */ + public static final Color DARK_BLUE = new Color(23, 65, 125); + + /* + * ====================================================================== + * --------------------------- FONT CONSTANTS --------------------------- + * ====================================================================== + */ + + /** + * The name of the font used in this ui implementation. + */ + public static final String FONT_NAME = "Verdana"; + + /** + * The size of the font used in this ui implementation. + */ + public static final String FONT_SIZE = "12"; + + /** + * The default Font object used through this ui implementation. + */ + public static final Font FONT = new Font(Constants.FONT_NAME, Font.PLAIN, + new Integer(Constants.FONT_SIZE).intValue()); + + /** + * Temporary method to load the css style used in the chat window. + * + * @param style + */ + public static void loadSimpleStyle(StyleSheet style) + { + + InputStream is = Constants.class + .getResourceAsStream("resources/defaultStyle.css"); + + Reader r = new BufferedReader(new InputStreamReader(is)); + try + { + style.loadRules(r, null); + r.close(); + } catch (IOException e) + { + } + } +} diff --git a/src/net/java/sip/communicator/plugin/splashscreen/SIPCommHTMLEditorKit.java b/src/net/java/sip/communicator/plugin/splashscreen/SIPCommHTMLEditorKit.java new file mode 100644 index 000000000..7125769b5 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/splashscreen/SIPCommHTMLEditorKit.java @@ -0,0 +1,106 @@ +/* + * 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.plugin.splashscreen; + +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.*; +import javax.swing.text.html.ParagraphView; + +/** + * The SIPCommHTMLEditorKit is an HTMLEditorKit which uses + * the SIPCommImageView and an extended ParagraphView. + * + * @author Yana Stamcheva + */ +public class SIPCommHTMLEditorKit extends HTMLEditorKit { + + /** + * Returns the extended HTMLFactory defined here. + */ + public ViewFactory getViewFactory() { + return new HTMLFactoryX(); + } + + /** + * An extended HTMLFactory that uses the SIPCommImageView + * to represent images and the ParagraphViewX to represent + * paragraphs. + */ + static class HTMLFactoryX extends HTMLFactory + implements ViewFactory { + + public View create(Element elem) { + + View v=super.create(elem); + + if(v instanceof ImageView){ + return new SIPCommImageView(elem); + } + else if (v instanceof ParagraphView) { + return new ParagraphViewX(elem); + } + return v; + } + } + + /** + * The ParagraphViewX is created in order to solve the following + * problem (Bug ID: 4855207): + *

+ * When a paragraph in a JTextPane has a large amount of text the + * processing needed to layout the entire paragraph increases as the + * paragraph grows. + */ + static class ParagraphViewX extends ParagraphView { + public ParagraphViewX(Element elem) { + super(elem); + } + + /** + * Calculate equirements along the minor axis. This + * is implemented to forward the request to the logical + * view by calling getMinimumSpan, getPreferredSpan, and + * getMaximumSpan on it. + */ + protected SizeRequirements calculateMinorAxisRequirements ( + int axis, SizeRequirements r) { + if (r == null) { + r = new SizeRequirements(); + } + float pref = layoutPool.getPreferredSpan(axis); + float min = layoutPool.getMinimumSpan(axis); + // Don't include insets, Box.getXXXSpan will include them. + r.minimum = (int)min; + r.preferred = Math.max(r.minimum, (int) pref); + r.maximum = Short.MAX_VALUE; + r.alignment = 0.5f; + return r; + } + } + + + /** + * Create an uninitialized text storage model + * that is appropriate for this type of editor. + * + * @return the model. + */ + public Document createDefaultDocument() { + StyleSheet styles = getStyleSheet(); + StyleSheet ss = new StyleSheet(); + + ss.addStyleSheet(styles); + + HTMLDocument doc = new HTMLDocument(ss); + doc.setParser(getParser()); + doc.setAsynchronousLoadPriority(4); + doc.setTokenThreshold(100); + return doc; + } +} diff --git a/src/net/java/sip/communicator/plugin/splashscreen/SIPCommImageView.java b/src/net/java/sip/communicator/plugin/splashscreen/SIPCommImageView.java new file mode 100644 index 000000000..dbbfc3326 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/splashscreen/SIPCommImageView.java @@ -0,0 +1,861 @@ +/* + * 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.plugin.splashscreen; + +import java.io.*; +import java.net.*; +import java.util.*; +import javax.imageio.*; + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.text.html.*; + +import net.java.sip.communicator.util.*; + +/* + * The content of this file was based on code borrowed from Rob Kenworthy, + * http://www.javaworld.com/javaworld/javatips/jw-javatip109.html#resources. + */ +/** + * The SIPCommImageView is an ImageView which allows to + * specify a related path when describing an image within an html document. + * + * @author Yana Stamcheva + */ +public class SIPCommImageView extends ImageView implements ImageObserver +{ + private Logger logger = Logger.getLogger(SIPCommImageView.class); + + public static final String TOP = "top"; + + public static final String TEXTTOP = "texttop"; + + public static final String MIDDLE = "middle"; + + public static final String ABSMIDDLE = "absmiddle"; + + public static final String CENTER = "center"; + + public static final String BOTTOM = "bottom"; + + /** + * Creates a new view that represents an IMG element. + * + * @param elem + * the element to create a view for. + */ + public SIPCommImageView(Element elem) + { + + super(elem); + + initialize(elem); + + StyleSheet sheet = getStyleSheet(); + + attr = sheet.getViewAttributes(this); + } + + /** + * Initializes this view. + * + * @param elem + * the element. + */ + private void initialize(Element elem) + { + synchronized (this) + { + loading = true; + fWidth = fHeight = 0; + } + + int width = 0; + int height = 0; + boolean customWidth = false; + boolean customHeight = false; + + try + { + fElement = elem; + + if (isURL()) + { + URL src = getSourceURL(); + + if (src != null) + { + + Dictionary cache = (Dictionary) getDocument().getProperty( + IMAGE_CACHE_PROPERTY); + + if (cache != null) + fImage = (Image) cache.get(src); + else + fImage = Toolkit.getDefaultToolkit().getImage(src); + } + } else + { + /*--Code to load from relative path--*/ + String src = (String) fElement.getAttributes().getAttribute( + HTML.Attribute.SRC); + + if (src == null) + return; + + // fImage = Toolkit.getDefaultToolkit().createImage(src); + try + { + fImage = ImageIO.read(SIPCommImageView.class + .getResource(src)); + + try + { + waitForImage(); + } catch (InterruptedException e) + { + fImage = null; + } + + } catch (IOException e) + { + fImage = null; + logger.error("Failed to read image.", e); + } catch (IllegalArgumentException iae) + { + fImage = null; + logger.error("Failed to read image.", iae); + } + } + + // Get height/width from params or image or defaults: + height = getIntAttr(HTML.Attribute.HEIGHT, -1); + + customHeight = (height > 0); + + if (!customHeight && fImage != null) + height = fImage.getHeight(this); + + if (height <= 0) + height = DEFAULT_HEIGHT; + + width = getIntAttr(HTML.Attribute.WIDTH, -1); + + customWidth = (width > 0); + + if (!customWidth && fImage != null) + width = fImage.getWidth(this); + + if (width <= 0) + width = DEFAULT_WIDTH; + + // Make sure the image starts loading: + if (fImage != null) + if (customWidth && customHeight) + Toolkit.getDefaultToolkit().prepareImage(fImage, height, + width, this); + else + Toolkit.getDefaultToolkit().prepareImage(fImage, -1, -1, + this); + } finally + { + + synchronized (this) + { + loading = false; + + if (customWidth || fWidth == 0) + { + fWidth = width; + } + if (customHeight || fHeight == 0) + { + fHeight = height; + } + } + } + } + + /** + * Determines if path is in the form of an URL. + * + * @return TRUE if the source is URL, FALSE otherwise. + */ + private boolean isURL() + { + String src = (String) fElement.getAttributes().getAttribute( + HTML.Attribute.SRC); + + if (src == null) + return false; + + return src.toLowerCase().startsWith("file") + || src.toLowerCase().startsWith("http"); + } + + /** + * Make sure an image is loaded - ie no broken images. So far its used only + * for images loaded off the disk (non-URL). + * + * @throws InterruptedException + */ + private void waitForImage() throws InterruptedException + { + + int w = fImage.getWidth(this); + int h = fImage.getHeight(this); + + while (true) + { + int flags = Toolkit.getDefaultToolkit().checkImage(fImage, w, h, + this); + + if (((flags & ERROR) != 0) || ((flags & ABORT) != 0)) + throw new InterruptedException(); + + else if ((flags & (ALLBITS | FRAMEBITS)) != 0) + return; + + Thread.sleep(10); + } + } + + /** + * Fetches the attributes to use when rendering. This is implemented to + * multiplex the attributes specified in the model with a StyleSheet. + */ + public AttributeSet getAttributes() + { + + return attr; + } + + /** + * Checks if the image is within a link. + */ + boolean isLink() + { + // ! It would be nice to cache this but in an editor it can change + // See if I have an HREF attribute courtesy of the enclosing A tag: + + AttributeSet anchorAttr = (AttributeSet) + + fElement.getAttributes().getAttribute(HTML.Tag.A); + + if (anchorAttr != null) + { + return anchorAttr.isDefined(HTML.Attribute.HREF); + } + return false; + } + + /** + * Returns the size of the border to use. + */ + int getBorder() + { + return getIntAttr(HTML.Attribute.BORDER, isLink() ? DEFAULT_BORDER : 0); + } + + /** + * Returns the amount of extra space to add along an axis. + */ + int getSpace(int axis) + { + return getIntAttr(axis == X_AXIS ? HTML.Attribute.HSPACE + : HTML.Attribute.VSPACE, 0); + } + + /** + * Returns the border's color, or null if this is not a link. + */ + Color getBorderColor() + { + StyledDocument doc = (StyledDocument) getDocument(); + return doc.getForeground(getAttributes()); + } + + /** + * Returns the image's vertical alignment. + */ + float getVerticalAlignment() + { + String align = (String) fElement.getAttributes().getAttribute( + HTML.Attribute.ALIGN); + if (align != null) + { + align = align.toLowerCase(); + if (align.equals(TOP) || align.equals(TEXTTOP)) + return 0.0f; + else if (align.equals(this.CENTER) || align.equals(MIDDLE) + || align.equals(ABSMIDDLE)) + return 0.5f; + } + + return 1.0f; // default alignment is bottom + } + + /** + * Checks if the image is at least one pixel. + * + * @param obs + * The ImageObserver. + * @return true if the image is not null and is at least one + * pixel big, false otherwise. + */ + boolean hasPixels(ImageObserver obs) + { + + return fImage != null && fImage.getHeight(obs) > 0 + && fImage.getWidth(obs) > 0; + } + + /** + * Returns an URL for the image source, or null if it could not be + * determined. + */ + private URL getSourceURL() + { + + String src = (String) fElement.getAttributes().getAttribute( + HTML.Attribute.SRC); + if (src == null) + return null; + + URL reference = ((HTMLDocument) getDocument()).getBase(); + try + { + URL u = new URL(reference, src); + return u; + } catch (MalformedURLException e) + { + return null; + } + } + + /** + * Look up an integer-valued attribute. Not recursive. + */ + private int getIntAttr(HTML.Attribute name, int deflt) + { + AttributeSet attr = fElement.getAttributes(); + if (attr.isDefined(name)) + { // does not check parents! + int i; + String val = (String) attr.getAttribute(name); + if (val == null) + i = deflt; + else + try + { + i = Math.max(0, Integer.parseInt(val)); + } catch (NumberFormatException x) + { + i = deflt; + } + return i; + } else + return deflt; + } + + /** + * Establishes the parent view for this view. Seize this moment to cache the + * AWT Container I'm in. + */ + public void setParent(View parent) + { + super.setParent(parent); + fContainer = parent != null ? getContainer() : null; + if (parent == null && fComponent != null) + { + fComponent.getParent().remove(fComponent); + fComponent = null; + } + } + + /** + * The attributes may have changed. + */ + public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) + { + super.changedUpdate(e, a, f); + float align = getVerticalAlignment(); + + int height = fHeight; + int width = fWidth; + + initialize(getElement()); + + boolean hChanged = fHeight != height; + boolean wChanged = fWidth != width; + if (hChanged || wChanged || getVerticalAlignment() != align) + { + getParent().preferenceChanged(this, hChanged, wChanged); + } + } + + /** + * Paints the image. + * + * @param g + * the rendering surface to use + * @param a + * the allocated region to render into + * @see View#paint + */ + public void paint(Graphics g, Shape a) + { + Color oldColor = g.getColor(); + fBounds = a.getBounds(); + int border = getBorder(); + int x = fBounds.x + border + getSpace(X_AXIS); + int y = fBounds.y + border + getSpace(Y_AXIS); + int width = fWidth; + int height = fHeight; + int sel = getSelectionState(); + + // If no pixels yet, draw gray outline and icon: + if (!hasPixels(this)) + { + g.setColor(Color.lightGray); + g.drawRect(x, y, width - 1, height - 1); + g.setColor(oldColor); + loadIcons(); + Icon icon = fImage == null ? sMissingImageIcon : sPendingImageIcon; + if (icon != null) + icon.paintIcon(getContainer(), g, x, y); + } + + // Draw image: + if (fImage != null) + { + g.drawImage(fImage, x, y, width, height, this); + // Use the following instead of g.drawImage when + // BufferedImageGraphics2D.setXORMode is fixed (4158822). + + // Use Xor mode when selected/highlighted. + // ! Could darken image instead, but it would be more expensive. + /* + * if( sel > 0 ) g.setXORMode(Color.white); g.drawImage(fImage,x, y, + * width,height,this); if( sel > 0 ) g.setPaintMode(); + */ + } + + // If selected exactly, we need a black border & grow-box: + Color bc = getBorderColor(); + if (sel == 2) + { + // Make sure there's room for a border: + int delta = 2 - border; + if (delta > 0) + { + x += delta; + y += delta; + width -= delta << 1; + height -= delta << 1; + border = 2; + } + bc = null; + g.setColor(Color.black); + // Draw grow box: + g.fillRect(x + width - 5, y + height - 5, 5, 5); + } + + // Draw border: + if (border > 0) + { + if (bc != null) + g.setColor(bc); + // Draw a thick rectangle: + for (int i = 1; i <= border; i++) + g.drawRect(x - i, y - i, width - 1 + i + i, height - 1 + i + i); + g.setColor(oldColor); + } + } + + /** + * Request that this view be repainted. Assumes the view is still at its + * last-drawn location. + */ + protected void repaint(long delay) + { + if (fContainer != null && fBounds != null) + { + fContainer.repaint(delay, fBounds.x, fBounds.y, fBounds.width, + fBounds.height); + } + } + + /** + * Determines whether the image is selected, and if it's the only thing + * selected. + * + * @return 0 if not selected, 1 if selected, 2 if exclusively selected. + * "Exclusive" selection is only returned when editable. + */ + protected int getSelectionState() + { + int p0 = fElement.getStartOffset(); + int p1 = fElement.getEndOffset(); + if (fContainer instanceof JTextComponent) + { + JTextComponent textComp = (JTextComponent) fContainer; + int start = textComp.getSelectionStart(); + int end = textComp.getSelectionEnd(); + if (start <= p0 && end >= p1) + { + if (start == p0 && end == p1 && isEditable()) + return 2; + else + return 1; + } + } + return 0; + } + + /** + * Checks whether the container is editable. + * + * @return true if the container is editable, + * false otherwise. + */ + protected boolean isEditable() + { + return fContainer instanceof JEditorPane + && ((JEditorPane) fContainer).isEditable(); + } + + /** + * Returns the text editor's highlight color. + */ + protected Color getHighlightColor() + { + JTextComponent textComp = (JTextComponent) fContainer; + return textComp.getSelectionColor(); + } + + // --- Progressive display --------------------------------------------- + + // This can come on any thread. If we are in the process of reloading + // the image and determining our state (loading == true) we don't fire + // preference changed, or repaint, we just reset the fWidth/fHeight as + // necessary and return. This is ok as we know when loading finishes + // it will pick up the new height/width, if necessary. + public boolean imageUpdate(Image img, int flags, int x, int y, int width, + int height) + { + if (fImage == null || fImage != img) + return false; + + // Bail out if there was an error: + if ((flags & (ABORT | ERROR)) != 0) + { + fImage = null; + repaint(0); + return false; + } + + // Resize image if necessary: + short changed = 0; + if ((flags & ImageObserver.HEIGHT) != 0) + if (!getElement().getAttributes().isDefined(HTML.Attribute.HEIGHT)) + { + changed |= 1; + } + if ((flags & ImageObserver.WIDTH) != 0) + if (!getElement().getAttributes().isDefined(HTML.Attribute.WIDTH)) + { + changed |= 2; + } + synchronized (this) + { + if ((changed & 1) == 1) + { + fWidth = width; + } + if ((changed & 2) == 2) + { + fHeight = height; + } + if (loading) + { + // No need to resize or repaint, still in the process of + // loading. + return true; + } + } + if (changed != 0) + { + // May need to resize myself, asynchronously: + Document doc = getDocument(); + try + { + if (doc instanceof AbstractDocument) + { + ((AbstractDocument) doc).readLock(); + } + preferenceChanged(this, true, true); + } finally + { + if (doc instanceof AbstractDocument) + { + ((AbstractDocument) doc).readUnlock(); + } + } + + return true; + } + + // Repaint when done or when new pixels arrive: + if ((flags & (FRAMEBITS | ALLBITS)) != 0) + repaint(0); + else if ((flags & SOMEBITS) != 0) + if (sIsInc) + repaint(sIncRate); + + return ((flags & ALLBITS) == 0); + } + + /* + * Static properties for incremental drawing. Swiped from Component.java + * + * @see #imageUpdate + */ + private static boolean sIsInc = true; + + private static int sIncRate = 100; + + // --- Layout ---------------------------------------------------------- + + /** + * Determines the preferred span for this view along an axis. + * + * @param axis + * may be either X_AXIS or Y_AXIS + * @return the span the view would like to be rendered into. Typically the + * view is told to render into the span that is returned, although + * there is no guarantee. The parent may choose to resize or break + * the view. + */ + public float getPreferredSpan(int axis) + { + int extra = 2 * (getBorder() + getSpace(axis)); + switch (axis) + { + case View.X_AXIS: + return fWidth + extra; + case View.Y_AXIS: + return fHeight + extra; + default: + throw new IllegalArgumentException("Invalid axis: " + axis); + } + } + + /** + * Determines the desired alignment for this view along an axis. This is + * implemented to give the alignment to the bottom of the icon along the y + * axis, and the default along the x axis. + * + * @param axis + * may be either X_AXIS or Y_AXIS + * @return the desired alignment. This should be a value between 0.0 and 1.0 + * where 0 indicates alignment at the origin and 1.0 indicates + * alignment to the full span away from the origin. An alignment of + * 0.5 would be the center of the view. + */ + public float getAlignment(int axis) + { + switch (axis) + { + case View.Y_AXIS: + return getVerticalAlignment(); + default: + return super.getAlignment(axis); + } + } + + /** + * Provides a mapping from the document model coordinate space to the + * coordinate space of the view mapped to it. + * + * @param pos + * the position to convert + * @param a + * the allocated region to render into + * @return the bounding box of the given position + * @exception BadLocationException + * if the given position does not represent a valid + * location in the associated document + * @see View#modelToView + */ + public Shape modelToView(int pos, Shape a, Position.Bias b) + throws BadLocationException + { + int p0 = getStartOffset(); + int p1 = getEndOffset(); + if ((pos >= p0) && (pos <= p1)) + { + Rectangle r = a.getBounds(); + if (pos == p1) + { + r.x += r.width; + } + r.width = 0; + return r; + } + return null; + } + + /** + * Provides a mapping from the view coordinate space to the logical + * coordinate space of the model. + * + * @param x + * the X coordinate + * @param y + * the Y coordinate + * @param a + * the allocated region to render into + * @return the location within the model that best represents the given + * point of view + * @see View#viewToModel + */ + public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) + { + Rectangle alloc = (Rectangle) a; + if (x < alloc.x + alloc.width) + { + bias[0] = Position.Bias.Forward; + return getStartOffset(); + } + bias[0] = Position.Bias.Backward; + return getEndOffset(); + } + + /** + * Set the size of the view. (Ignored.) + * + * @param width + * the width + * @param height + * the height + */ + public void setSize(float width, float height) + { + // Ignore this -- image size is determined by the tag attrs and + // the image itself, not the surrounding layout! + } + + // --- Static icon accessors ------------------------------------------- + + private Icon makeIcon(final String gifFile) throws IOException + { + /* + * Copy resource into a byte array. This is necessary because several + * browsers consider Class.getResource a security risk because it can be + * used to load additional classes. Class.getResourceAsStream just + * returns raw bytes, which we can convert to an image. + */ + InputStream resource = SIPCommImageView.class + .getResourceAsStream(gifFile); + + if (resource == null) + { + logger.error(SIPCommImageView.class.getName() + "/" + gifFile + + " not found."); + return null; + } + BufferedInputStream in = new BufferedInputStream(resource); + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + byte[] buffer = new byte[1024]; + int n; + while ((n = in.read(buffer)) > 0) + { + out.write(buffer, 0, n); + } + in.close(); + out.flush(); + + buffer = out.toByteArray(); + if (buffer.length == 0) + { + logger.error(gifFile + " is zero-length."); + return null; + } + return new ImageIcon(buffer); + } + + private void loadIcons() + { + try + { + if (sPendingImageIcon == null) + sPendingImageIcon = makeIcon(PENDING_IMAGE_SRC); + if (sMissingImageIcon == null) + sMissingImageIcon = makeIcon(MISSING_IMAGE_SRC); + } catch (Exception ex) + { + logger.error("Couldn't load image icons.", ex); + } + } + + protected StyleSheet getStyleSheet() + { + HTMLDocument doc = (HTMLDocument) getDocument(); + return doc.getStyleSheet(); + } + + // --- member variables ------------------------------------------------ + + private AttributeSet attr; + + private Element fElement; + + private Image fImage; + + private int fHeight, fWidth; + + private Container fContainer; + + private Rectangle fBounds; + + private Component fComponent; + + private Point fGrowBase; // base of drag while growing image + + private boolean fGrowProportionally; // should grow be proportional? + + /** + * Set to true, while the receiver is locked, to indicate the reciever is + * loading the image. This is used in imageUpdate. + */ + private boolean loading; + + // --- constants and static stuff -------------------------------- + + private static Icon sPendingImageIcon, sMissingImageIcon; + + private static final String PENDING_IMAGE_SRC = "icons/image-delayed.gif", // both + // stolen + // from + // HotJava + MISSING_IMAGE_SRC = "icons/image-failed.gif"; + + // $ move this someplace public + static final String IMAGE_CACHE_PROPERTY = "imageCache"; + + // Height/width to use before we know the real size: + private static final int DEFAULT_WIDTH = 32, DEFAULT_HEIGHT = 32, + // Default value of BORDER param: //? possibly move into stylesheet? + DEFAULT_BORDER = 2; + +} diff --git a/src/net/java/sip/communicator/plugin/splashscreen/SplashScreenActivator.java b/src/net/java/sip/communicator/plugin/splashscreen/SplashScreenActivator.java index 7710bf3c8..339e0cc28 100644 --- a/src/net/java/sip/communicator/plugin/splashscreen/SplashScreenActivator.java +++ b/src/net/java/sip/communicator/plugin/splashscreen/SplashScreenActivator.java @@ -6,54 +6,133 @@ */ package net.java.sip.communicator.plugin.splashscreen; -import net.java.sip.communicator.service.gui.*; +import java.awt.event.*; + +import javax.swing.JMenuItem; + +import net.java.sip.communicator.service.gui.UIService; import org.osgi.framework.*; -public class SplashScreenActivator - implements BundleActivator, - ServiceListener, - BundleListener +public class SplashScreenActivator implements BundleActivator, BundleListener { private WelcomeWindow welcomeWindow; - private BundleContext bundleContext; - - public void start(BundleContext bundleContext) throws Exception + private static BundleContext bundleContext; + private JMenuItem aboutEntry; + + public void start(BundleContext bc) throws Exception { - this.bundleContext = bundleContext; - + bundleContext = bc; + welcomeWindow = new WelcomeWindow(); - welcomeWindow.pack(); welcomeWindow.setVisible(true); - - this.bundleContext.addServiceListener(this); - this.bundleContext.addBundleListener(this); + + bundleContext.addBundleListener(this); } public void stop(BundleContext arg0) throws Exception { - + unRegisterMenuEntry(); } - public void serviceChanged(ServiceEvent evt) - { - ServiceReference serviceRef = evt.getServiceReference(); - - if(serviceRef.getBundle().getState() != Bundle.STARTING) + public void bundleChanged(BundleEvent evt) + { + if (welcomeWindow != null && welcomeWindow.isShowing() + && evt.getType() == BundleEvent.STARTED) + welcomeWindow.setBundle(evt.getBundle().getHeaders().get( + "Bundle-Name").toString()); + + ServiceReference[] services = evt.getBundle().getRegisteredServices(); + if (services == null) + { return; - - if (bundleContext.getServiceReference(UIService.class.getName()) - == serviceRef) + } + for (ServiceReference serviceRef : services) { - this.welcomeWindow.close(); + ServiceReference uiServiceRef = bundleContext + .getServiceReference(UIService.class.getName()); + if (serviceRef == uiServiceRef) + { + int state = serviceRef.getBundle().getState(); + if (state == Bundle.ACTIVE) + { + // UI-Service started. + + // register the about dialog menu entry + registerMenuEntry(uiServiceRef); + + welcomeWindow.close(); + } + } } + } - public void bundleChanged(BundleEvent evt) + private void registerMenuEntry(ServiceReference uiServiceRef) { - if(welcomeWindow != null && welcomeWindow.isShowing()) - welcomeWindow.setBundle(evt.getBundle().getHeaders() - .get("Bundle-Name").toString()); - } + final UIService uiService = (UIService) bundleContext + .getService(uiServiceRef); + + // add menu entry to file menu + // Add your menu item to the help menu + if (aboutEntry == null) + { + aboutEntry = new JMenuItem(Resources.getString("menuEntry")); + aboutEntry.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + + AboutWindow aboutWindow = new AboutWindow(null); + aboutWindow.setVisible(true); + } + }); + } + // Check if the help menu is a supported container. + if (uiService.isContainerSupported(UIService.CONTAINER_HELP_MENU)) + { + uiService.addComponent(UIService.CONTAINER_HELP_MENU, aboutEntry); + } + // Check if the help menu is a supported container. + if (uiService.isContainerSupported(UIService.CONTAINER_CHAT_HELP_MENU)) + { + uiService.addComponent(UIService.CONTAINER_CHAT_HELP_MENU, + aboutEntry); + } + } + + private void unRegisterMenuEntry() + { + // Obtain the UI Service + ServiceReference uiServiceRef = bundleContext + .getServiceReference(UIService.class.getName()); + + if (uiServiceRef == null + || uiServiceRef.getBundle().getState() != Bundle.ACTIVE) + { + return; + } + + UIService uiService = (UIService) bundleContext + .getService(uiServiceRef); + + // Check if the tools menu is a supported container. + boolean isContainerSupported = uiService + .isContainerSupported(UIService.CONTAINER_HELP_MENU); + + if (isContainerSupported) + { + // add menu entry to file menu + // Add your menu item to the help menu + uiService + .removeComponent(UIService.CONTAINER_HELP_MENU, aboutEntry); + } + } + + static BundleContext getBundleContext() + { + return bundleContext; + } + } diff --git a/src/net/java/sip/communicator/plugin/splashscreen/StyledHTMLEditorPane.java b/src/net/java/sip/communicator/plugin/splashscreen/StyledHTMLEditorPane.java new file mode 100644 index 000000000..9502a89ae --- /dev/null +++ b/src/net/java/sip/communicator/plugin/splashscreen/StyledHTMLEditorPane.java @@ -0,0 +1,70 @@ +/* + * 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.plugin.splashscreen; + +import java.io.IOException; + +import javax.swing.JEditorPane; +import javax.swing.text.*; +import javax.swing.text.html.*; + +import net.java.sip.communicator.util.Logger; + +public class StyledHTMLEditorPane + extends JEditorPane +{ + private Logger logger = Logger.getLogger(StyledHTMLEditorPane.class); + + private HTMLEditorKit editorKit = new SIPCommHTMLEditorKit(); + + private HTMLDocument document; + + public StyledHTMLEditorPane() + { + this.document = (HTMLDocument) editorKit.createDefaultDocument(); + + this.setContentType("text/html"); + this.setEditorKitForContentType("text/html", editorKit); + this.setEditorKit(editorKit); + this.setDocument(document); + + Constants.loadSimpleStyle(document.getStyleSheet()); + } + + + public void appendToEnd(String text) + { + Element root = document.getDefaultRootElement(); + try + { + document.insertAfterEnd(root + .getElement(root.getElementCount() - 1), text); + } + catch (BadLocationException e) + { + logger.error("Insert in the HTMLDocument failed.", e); + } + catch (IOException e) + { + logger.error("Insert in the HTMLDocument failed.", e); + } + } + + public void insertAfterStart(String text) + { + Element root = this.document.getDefaultRootElement(); + + try { + this.document.insertBeforeStart(root + .getElement(0), text); + } catch (BadLocationException e) { + logger.error("Insert in the HTMLDocument failed.", e); + } catch (IOException e) { + logger.error("Insert in the HTMLDocument failed.", e); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/splashscreen/WindowBackground.java b/src/net/java/sip/communicator/plugin/splashscreen/WindowBackground.java index 014a0b514..78331ef49 100644 --- a/src/net/java/sip/communicator/plugin/splashscreen/WindowBackground.java +++ b/src/net/java/sip/communicator/plugin/splashscreen/WindowBackground.java @@ -12,7 +12,6 @@ public class WindowBackground extends JPanel { - private Image bgImage; public WindowBackground() @@ -22,7 +21,7 @@ public WindowBackground() try { bgImage = ImageIO.read(WindowBackground.class - .getResource("aboutWindowBackground.png")); + .getResource("resources/aboutWindowBackground.png")); } catch (IOException e) { diff --git a/src/net/java/sip/communicator/plugin/splashscreen/WindowTransparentBackground.java b/src/net/java/sip/communicator/plugin/splashscreen/WindowTransparentBackground.java index d428070d9..cbdbc9a0c 100644 --- a/src/net/java/sip/communicator/plugin/splashscreen/WindowTransparentBackground.java +++ b/src/net/java/sip/communicator/plugin/splashscreen/WindowTransparentBackground.java @@ -75,7 +75,7 @@ public WindowTransparentBackground() { robot = new Robot(); bgImage = ImageIO.read( - WindowBackground.class.getResource("aboutWindowBackground.png")); + WindowBackground.class.getResource("resources/aboutWindowBackground.png")); bgWidth = bgImage.getWidth(null); diff --git a/src/net/java/sip/communicator/plugin/splashscreen/resources.properties b/src/net/java/sip/communicator/plugin/splashscreen/resources.properties index fb2d24e15..2b903aa71 100644 --- a/src/net/java/sip/communicator/plugin/splashscreen/resources.properties +++ b/src/net/java/sip/communicator/plugin/splashscreen/resources.properties @@ -1,3 +1,6 @@ +about=About logoMessage=Open Source VoIP & Instant Messaging loading=Loading -welcomeMessage=The SIP Communicator is currently under active development. The version you are running is only experimental and MAY NOT work as expected. Please refer to {0} for more information. \ No newline at end of file +menuEntry=About +ok=OK +welcomeMessage=The SIP Communicator is currently under active development. The version you are running is only experimental and MAY NOT work as expected. Please refer to {0} for more information. diff --git a/src/net/java/sip/communicator/plugin/splashscreen/resources/aboutWindowBackground.png b/src/net/java/sip/communicator/plugin/splashscreen/resources/aboutWindowBackground.png new file mode 100644 index 000000000..4a178171d Binary files /dev/null and b/src/net/java/sip/communicator/plugin/splashscreen/resources/aboutWindowBackground.png differ diff --git a/src/net/java/sip/communicator/plugin/splashscreen/resources/defaultStyle.css b/src/net/java/sip/communicator/plugin/splashscreen/resources/defaultStyle.css new file mode 100644 index 000000000..a9326a68c --- /dev/null +++ b/src/net/java/sip/communicator/plugin/splashscreen/resources/defaultStyle.css @@ -0,0 +1,71 @@ +h1 +{ +background-color:#c6d0e1; +margin:0px; +text-align:center; +font-weight:bold; +font-size:12 +} + +h2 +{ +margin:0px; +font-family:Verdana; +font-size:12; +color:#ef7b1e +} + +h3 +{ +margin:0px; +font-family:Verdana; +font-size:12; +color:#2e538b +} + +h4 +{ +margin:0px; +font-family:Verdana; +font-size:12; +font-weight:bold; +color:#FFC875 +} + +h5 +{ +margin:0px; +font-family:Verdana; +font-size:12; +font-weight:bold; +color:#CC0000 +} + +h6 +{ +margin:0px; +font-family:Verdana; +font-size:12; +font-weight:bold; +color:#990000 +} +p +{ +margin:0px; +font-family:Verdana; +font-size:12; +font-weight:bold; +color:#62BD80 +} + +div +{ +font-family:Verdana; +font-size:12; +color:#000000 +} + +i +{ +background-color:#FFF4AB +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/splashscreen/aboutWindowBackground.png b/src/net/java/sip/communicator/plugin/splashscreen/resources/splashScreenBackground.png similarity index 100% rename from src/net/java/sip/communicator/plugin/splashscreen/aboutWindowBackground.png rename to src/net/java/sip/communicator/plugin/splashscreen/resources/splashScreenBackground.png diff --git a/src/net/java/sip/communicator/plugin/splashscreen/splashscreen.manifest.mf b/src/net/java/sip/communicator/plugin/splashscreen/splashscreen.manifest.mf index 0ac55f24c..12cd0c270 100755 --- a/src/net/java/sip/communicator/plugin/splashscreen/splashscreen.manifest.mf +++ b/src/net/java/sip/communicator/plugin/splashscreen/splashscreen.manifest.mf @@ -4,8 +4,13 @@ Bundle-Description: Splash Screen plugin. Bundle-Vendor: sip-communicator.org Bundle-Version: 0.0.1 Import-Package: org.osgi.framework, + net.java.sip.communicator.service.browserlauncher, net.java.sip.communicator.service.gui, net.java.sip.communicator.service.gui.event, + net.java.sip.communicator.util, javax.swing, javax.swing.event, + javax.swing.border, + javax.swing.text, + javax.swing.text.html, javax.imageio