/* * 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.plugin.branding; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.*; import javax.imageio.*; import javax.swing.*; import javax.swing.event.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.plugin.desktoputil.plaf.*; import net.java.sip.communicator.service.browserlauncher.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.util.Logger; import net.java.sip.communicator.util.skin.*; import org.jitsi.service.resources.*; import org.jitsi.util.*; import org.osgi.framework.*; /** * The <tt>AboutWindow</tt> is containing information about the application * name, version, license etc.. * * @author Yana Stamcheva * @author Adam Netocny * @author Lyubomir Marinov */ public class AboutWindow extends JDialog implements HyperlinkListener, ActionListener, ExportedWindow, Skinnable { /** * Serial version UID. */ private static final long serialVersionUID = 0L; private static AboutWindow aboutWindow; /** * Class id key used in UIDefaults for the version label. */ private static final String uiClassID = AboutWindow.class.getName() + "$VersionTextFieldUI"; /** * Adds the ui class to UIDefaults. */ static { UIManager.getDefaults().put(uiClassID, SIPCommTextFieldUI.class.getName()); } private final JTextField versionLabel; /** * Shows a <code>AboutWindow</code> creating it first if necessary. The * shown instance is shared in order to prevent displaying multiple * instances of one and the same <code>AboutWindow</code>. */ public static void showAboutWindow() { if (aboutWindow == null) { aboutWindow = new AboutWindow(null); /* * When the global/shared AboutWindow closes, don't keep a reference * to it and let it be garbage-collected. */ aboutWindow.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { if (aboutWindow == e.getWindow()) aboutWindow = null; } }); } aboutWindow.setVisible(true); } private static final int DEFAULT_TEXT_INDENT = BrandingActivator.getResources() .getSettingsInt("plugin.branding.ABOUT_TEXT_INDENT"); /** * Creates an <tt>AboutWindow</tt> by specifying the parent frame owner. * @param owner the parent owner */ public AboutWindow(Frame owner) { super(owner); ResourceManagementService resources = BrandingActivator.getResources(); String applicationName = resources.getSettingsString("service.gui.APPLICATION_NAME"); String website = resources.getSettingsString("service.gui.APPLICATION_WEB_SITE"); this.setTitle( resources.getI18NString("plugin.branding.ABOUT_WINDOW_TITLE", new String[]{applicationName})); setModal(false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setResizable(false); JPanel mainPanel = new WindowBackground(); mainPanel.setLayout(new BorderLayout()); JPanel textPanel = new JPanel(); textPanel.setPreferredSize(new Dimension(470, 280)); textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); textPanel.setBorder(BorderFactory .createEmptyBorder(15, 15, 15, 15)); textPanel.setOpaque(false); JLabel titleLabel = new JLabel(applicationName); titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28)); titleLabel.setForeground(Constants.TITLE_COLOR); titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); // Force the use of the custom text field UI in order to fix an // incorrect rendering on Ubuntu. versionLabel = new JTextField(" " + System.getProperty("sip-communicator.version")) { /** * Returns the name of the L&F class that renders this component. * * @return the string "TreeUI" * @see JComponent#getUIClassID * @see UIDefaults#getUI */ @Override public String getUIClassID() { return uiClassID; } }; versionLabel.setBorder(null); versionLabel.setOpaque(false); versionLabel.setEditable(false); versionLabel.setFont(versionLabel.getFont().deriveFont(Font.BOLD, 18)); versionLabel.setForeground(Constants.TITLE_COLOR); versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); versionLabel.setHorizontalAlignment(JTextField.RIGHT); int logoAreaFontSize = resources.getSettingsInt("plugin.branding.ABOUT_LOGO_FONT_SIZE"); JTextArea logoArea = new JTextArea(resources.getI18NString( "plugin.branding.LOGO_MESSAGE")); logoArea.setFont( logoArea.getFont().deriveFont(Font.BOLD, logoAreaFontSize)); logoArea.setForeground(Constants.TITLE_COLOR); logoArea.setOpaque(false); logoArea.setLineWrap(true); logoArea.setWrapStyleWord(true); logoArea.setEditable(false); logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); logoArea.setBorder(BorderFactory .createEmptyBorder(30, DEFAULT_TEXT_INDENT, 0, 0)); StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); rightsArea.setContentType("text/html"); String host = website; try { host = new URL(website).getHost(); } catch (Exception ex) {} rightsArea.appendToEnd(resources.getI18NString( "plugin.branding.COPYRIGHT_LICENSE", new String[] { Constants.TEXT_COLOR, Integer.toString(Calendar.getInstance().get(Calendar.YEAR)), website, host, applicationName, "http://www.apache.org/licenses/LICENSE-2.0", "Apache License 2.0" })); rightsArea.setBorder(BorderFactory .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); rightsArea.setOpaque(false); rightsArea.setEditable(false); rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); rightsArea.addHyperlinkListener(this); textPanel.add(titleLabel); textPanel.add(versionLabel); textPanel.add(logoArea); textPanel.add(rightsArea); JButton okButton = new JButton(resources.getI18NString("service.gui.OK")); this.getRootPane().setDefaultButton(okButton); okButton.setMnemonic(resources.getI18nMnemonic("service.gui.OK")); okButton.addActionListener(this); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); buttonPanel.add(okButton); buttonPanel.setOpaque(false); mainPanel.add(textPanel, BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.SOUTH); this.getContentPane().add(mainPanel); this.pack(); setLocationRelativeTo(getParent()); this.getRootPane().getActionMap().put("close", new CloseAction()); InputMap imap = this.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); if(OSUtils.IS_MAC) { imap.put( KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), "close"); imap.put( KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), "close"); } WindowUtils.addWindow(this); } /** * Reloads text field UI. */ public void loadSkin() { if(versionLabel.getUI() instanceof Skinnable) ((Skinnable)versionLabel.getUI()).loadSkin(); } /** * Constructs the window background in order to have a background image. */ private static class WindowBackground extends JPanel implements Skinnable { /** * Serial version UID. */ private static final long serialVersionUID = 0L; private static final Logger logger = Logger.getLogger(WindowBackground.class); private Image bgImage = null; public WindowBackground() { loadSkin(); } /** * Reloads resources for this component. */ public void loadSkin() { try { bgImage = ImageIO.read(BrandingActivator.getResources(). getImageURL("plugin.branding.ABOUT_WINDOW_BACKGROUND")); this.setPreferredSize(new Dimension(bgImage.getWidth(this), bgImage.getHeight(this))); } catch (IOException e) { logger.error("Error cannot obtain background image", e); bgImage = null; } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g = g.create(); try { AntialiasingManager.activateAntialiasing(g); int bgImageWidth = bgImage.getWidth(null); int bgImageHeight = bgImage.getHeight(null); boolean bgImageHasBeenDrawn = false; if ((bgImageWidth != -1) && (bgImageHeight != -1)) { int width = getWidth(); int height = getHeight(); if ((bgImageWidth < width) || (bgImageHeight < height)) { g.drawImage(bgImage, 0, 0, width, height, null); bgImageHasBeenDrawn = true; } } if (!bgImageHasBeenDrawn) g.drawImage(bgImage, 0, 0, null); } finally { g.dispose(); } } } /** * Opens a browser when the link has been activated (clicked). * @param e the <tt>HyperlinkEvent</tt> that notified us */ public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { ServiceReference<BrowserLauncherService> serviceReference = BrandingActivator.getBundleContext().getServiceReference( BrowserLauncherService.class); if (serviceReference != null) { BrowserLauncherService browserLauncherService = BrandingActivator .getBundleContext().getService(serviceReference); browserLauncherService.openURL(e.getDescription()); } } } /** * Indicates that the ok button has been pressed. Closes the window. * @param e the <tt>ActionEvent</tt> that notified us */ public void actionPerformed(ActionEvent e) { setVisible(false); dispose(); } /** * Implements the <tt>ExportedWindow.getIdentifier()</tt> method. * @return the identifier of this exported window */ 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 <tt>ExportedWindow.bringToFront()</tt> method. Brings * this window to front. */ public void bringToFront() { this.toFront(); } /** * The source of the window * @return the source of the window */ public Object getSource() { return this; } /** * Implementation of {@link ExportedWindow#setParams(Object[])}. */ public void setParams(Object[] windowParams) {} /** * The action invoked when user presses Escape key. */ private class CloseAction extends UIAction { /** * Serial version UID. */ private static final long serialVersionUID = 0L; public void actionPerformed(ActionEvent e) { setVisible(false); dispose(); } } }