diff options
author | Yana Stamcheva <yana@jitsi.org> | 2010-09-02 22:50:23 +0000 |
---|---|---|
committer | Yana Stamcheva <yana@jitsi.org> | 2010-09-02 22:50:23 +0000 |
commit | 45cf66297884d51760202c3213fde1e909a8d482 (patch) | |
tree | a93fa8aab3fb949ae0c24ddd5c819da166cf96bf /src/net/java/sip/communicator/plugin/skinmanager | |
parent | f6c822cc9e1486b59575fdc48a9b0e223e584a16 (diff) | |
download | jitsi-45cf66297884d51760202c3213fde1e909a8d482.zip jitsi-45cf66297884d51760202c3213fde1e909a8d482.tar.gz jitsi-45cf66297884d51760202c3213fde1e909a8d482.tar.bz2 |
Skin implementation bases provided by Adam Netočný (work in progress).
Diffstat (limited to 'src/net/java/sip/communicator/plugin/skinmanager')
10 files changed, 1456 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java b/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java new file mode 100644 index 0000000..41e4382 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java @@ -0,0 +1,43 @@ +/* + * 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.skinmanager; + +import java.util.*; +import org.osgi.framework.*; + +/** + * Comparator for bundle array sort + * + * @author ROTH Damien + */ +public class BundleComparator + implements Comparator<Bundle> +{ + /** + * Compares the bundles using their "Bundle-Name"s. + * @param arg0 the first bundle to compare + * @param arg1 the second bundle to compare + * @return the result of the string comparison between the names of the two + * bundles + */ + public int compare(Bundle arg0, Bundle arg1) + { + String n1 = (String) arg0.getHeaders().get(Constants.BUNDLE_NAME); + String n2 = (String) arg1.getHeaders().get(Constants.BUNDLE_NAME); + + if (n1 == null) + { + n1 = "unknown"; + } + if (n2 == null) + { + n2 = "unknown"; + } + + return n1.compareTo(n2); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/ManageButtonsPanel.java b/src/net/java/sip/communicator/plugin/skinmanager/ManageButtonsPanel.java new file mode 100644 index 0000000..34eaac1 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/ManageButtonsPanel.java @@ -0,0 +1,245 @@ +/* + * 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.skinmanager; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; + +import org.osgi.framework.*; + +/** + * The panel containing all buttons for the <tt>PluginManagerConfigForm</tt>. + * + * @author Yana Stamcheva + * @author Adam Netocony, CircleTech, s.r.o. + */ +public class ManageButtonsPanel + extends TransparentPanel + implements ActionListener +{ + /** + * The object used for logging. + */ + private Logger logger = Logger.getLogger(ManageButtonsPanel.class); + + /** + * The deactivate skin button. + */ + private JButton deactivateButton = new JButton( + Resources.getString("service.gui.DEACTIVATE")); + + /** + * The activate skin button. + */ + private JButton activateButton = new JButton( + Resources.getString("service.gui.ACTIVATE")); + + /** + * The uninstall button. + */ + private JButton uninstallButton = new JButton( + Resources.getString("plugin.skinmanager.UNINSTALL")); + + /** + * The new button. + */ + private JButton newButton + = new JButton(Resources.getString("plugin.skinmanager.NEW")); + + /** + * The panel, containing all buttons. + */ + private JPanel buttonsPanel + = new TransparentPanel(new GridLayout(0, 1, 8, 8)); + + /** + * The table of skins. + */ + private JTable skinTable; + + /** + * Creates an instance of <tt>ManageButtonsPanel</tt>. + * @param pluginTable the table of skins + */ + public ManageButtonsPanel(JTable pluginTable) + { + this.skinTable = pluginTable; + + this.setLayout(new BorderLayout()); + + this.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + + this.newButton.setOpaque(false); + this.activateButton.setOpaque(false); + this.deactivateButton.setOpaque(false); + this.uninstallButton.setOpaque(false); + + this.buttonsPanel.add(newButton); + this.buttonsPanel.add(activateButton); + this.buttonsPanel.add(deactivateButton); + this.buttonsPanel.add(uninstallButton); + + this.add(buttonsPanel, BorderLayout.NORTH); + + this.newButton.addActionListener(this); + this.activateButton.addActionListener(this); + this.deactivateButton.addActionListener(this); + this.uninstallButton.addActionListener(this); + + //default as nothing is selected + defaultButtonState(); + } + + /** + * Performs corresponding operations when a button is pressed. + * @param e the <tt>ActionEvent</tt> that notified us + */ + public void actionPerformed(ActionEvent e) + { + JButton sourceButton = (JButton) e.getSource(); + + if (sourceButton.equals(newButton)) + { + NewBundleDialog dialog = new NewBundleDialog(skinTable); + + dialog.pack(); + dialog.setLocation( + Toolkit.getDefaultToolkit().getScreenSize().width / 2 + - dialog.getWidth() / 2, + Toolkit.getDefaultToolkit().getScreenSize().height / 2 + - dialog.getHeight() / 2); + + dialog.setVisible(true); + } + else if (sourceButton.equals(activateButton)) + { + int[] selectedRows = skinTable.getSelectedRows(); + + for (int i = 0; i < skinTable.getModel().getRowCount(); i++) + { + try + { + ((Bundle) skinTable.getModel().getValueAt(i, 0)).stop(); + } + catch (BundleException ex) { } + } + + for (int i = 0; i < selectedRows.length; i++) + { + try + { + ((Bundle) skinTable.getModel() + .getValueAt(selectedRows[i], 0)).start(); + } + catch (BundleException ex) + { + logger.error("Failed to activate bundle.", ex); + + SkinManagerActivator.getUIService().getPopupDialog() + .showMessagePopupDialog(ex.getMessage(), "Error", + PopupDialog.ERROR_MESSAGE); + } + } + + defaultButtonState(); + } + else if (sourceButton.equals(deactivateButton)) + { + int[] selectedRows = skinTable.getSelectedRows(); + + for (int i = 0; i < selectedRows.length; i++) + { + try + { + ((Bundle) skinTable.getModel() + .getValueAt(selectedRows[i], 0)).stop(); + } + catch (BundleException ex) + { + logger.error("Failed to desactivate bundle.", ex); + + SkinManagerActivator.getUIService().getPopupDialog() + .showMessagePopupDialog(ex.getMessage(), "Error", + PopupDialog.ERROR_MESSAGE); + } + } + + defaultButtonState(); + } + else if (sourceButton.equals(uninstallButton)) + { + int[] selectedRows = skinTable.getSelectedRows(); + + for (int i = selectedRows.length - 1; i >= 0; i--) + { + try + { + ((Bundle) skinTable.getModel() + .getValueAt(selectedRows[i], 0)).uninstall(); + } + catch (BundleException ex) + { + logger.error("Failed to uninstall bundle.", ex); + + SkinManagerActivator.getUIService().getPopupDialog() + .showMessagePopupDialog(ex.getMessage(), "Error", + PopupDialog.ERROR_MESSAGE); + } + } + + defaultButtonState(); + } + } + + /** + * Default state of buttons, as nothing is selected + */ + public void defaultButtonState() + { + enableActivateButton(false); + enableDeactivateButton(false); + enableUninstallButton(false); + } + + /** + * Enable or disable the activate button. + * + * @param enable TRUE - to enable the activate button, FALSE - to disable it + */ + public void enableActivateButton(boolean enable) + { + this.activateButton.setEnabled(enable); + } + + /** + * Enable or disable the deactivate button. + * + * @param enable TRUE - to enable the deactivate button, FALSE - to + * disable it + */ + public void enableDeactivateButton(boolean enable) + { + this.deactivateButton.setEnabled(enable); + } + + /** + * Enable or disable the uninstall button. + * + * @param enable TRUE - to enable the uninstall button, FALSE - to + * disable it + */ + public void enableUninstallButton(boolean enable) + { + this.uninstallButton.setEnabled(enable); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/NewBundleDialog.java b/src/net/java/sip/communicator/plugin/skinmanager/NewBundleDialog.java new file mode 100644 index 0000000..217b15b --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/NewBundleDialog.java @@ -0,0 +1,260 @@ +/* + * 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.skinmanager; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.util.zip.ZipFile; + +import javax.swing.*; + +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; + +import org.osgi.framework.*; + +/** + * + * @author Yana Stamcheva + * @author Adam Netcony + */ +public class NewBundleDialog + extends SIPCommDialog + implements ActionListener +{ + private static final long serialVersionUID = 7638976584338100969L; + + /** + * The object used for logging. + */ + private Logger logger = Logger.getLogger(NewBundleDialog.class); + + /** + * The install button. + */ + private JButton installButton + = new JButton(Resources.getString("plugin.pluginmanager.INSTALL")); + + /** + * The cancel button. + */ + private JButton cancelButton + = new JButton(Resources.getString("service.gui.CANCEL")); + + /** + * The bundle path field. + */ + private JTextField bundlePathField = new JTextField(); + + /** + * The bundle path label. + */ + private JLabel bundlePathLabel + = new JLabel(Resources.getString("plugin.pluginmanager.URL") + ": "); + + /** + * The panel, containing all buttons. + */ + private JPanel buttonsPanel + = new TransparentPanel(new FlowLayout(FlowLayout.CENTER)); + + /** + * The panel containing new bundle information. + */ + private JPanel dataPanel = new TransparentPanel(new BorderLayout(5, 5)); + + /** + * The main panel, where all other panels are added. + */ + private JPanel mainPanel = new TransparentPanel(new BorderLayout()); + + /** + * The button, from which to choose a file from the file system. + */ + private JButton fileChooserButton = new JButton( + Resources.getString("plugin.pluginmanager.CHOOSE_FILE")); + + private JTable skinTable; + + /** + * Creates an instance of <tt>NewBundleDialog</tt>. + * @param table the skin table + */ + public NewBundleDialog(JTable table) + { + skinTable = table; + + this.mainPanel.setPreferredSize(new Dimension(450, 150)); + + this.getContentPane().add(mainPanel); + + this.mainPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + this.mainPanel.add(dataPanel, BorderLayout.NORTH); + + this.mainPanel.add(buttonsPanel, BorderLayout.SOUTH); + + this.buttonsPanel.add(installButton); + this.buttonsPanel.add(cancelButton); + + this.installButton.addActionListener(this); + this.cancelButton.addActionListener(this); + this.fileChooserButton.addActionListener(this); + this.fileChooserButton.setOpaque(false); + + this.dataPanel.add(bundlePathLabel, BorderLayout.WEST); + + this.dataPanel.add(bundlePathField, BorderLayout.CENTER); + + this.dataPanel.add(fileChooserButton, BorderLayout.EAST); + } + + /** + * Performs corresponding actions, when a buttons is pressed. + * @param e the <tt>ActionEvent</tt> that notified us + */ + public void actionPerformed(ActionEvent e) + { + JButton sourceButton = (JButton) e.getSource(); + + if (sourceButton.equals(installButton)) + { + if (bundlePathField.getText().length() > 0) + { + try + { + File jar = null; + try + { + jar = Resources.getResources() + .prepareSkinBundleFromZip( + new File(bundlePathField.getText())); + } + catch (Exception ex) + { + logger.info("Failed to load skin from zip.", ex); + + SkinManagerActivator.getUIService().getPopupDialog() + .showMessagePopupDialog(ex.getMessage(), "Error", + PopupDialog.ERROR_MESSAGE); + } + + if (jar != null) + { + try + { + Bundle newBundle = SkinManagerActivator + .bundleContext.installBundle( + jar.toURI().toURL().toString()); + + for (int i = 0; + i < skinTable.getModel().getRowCount(); i++) + { + try + { + ((Bundle) skinTable.getModel() + .getValueAt(i, 0)).stop(); + } + catch (BundleException ex) + { + logger.info("Failed to stop bundle.", ex); + } + } + newBundle.start(); + } + catch (MalformedURLException ex) + { + logger.info("Failed to load skin from zip.", ex); + } + } + } + catch (BundleException ex) + { + logger.info("Failed to install bundle.", ex); + SkinManagerActivator.getUIService().getPopupDialog() + .showMessagePopupDialog(ex.getMessage(), "Error", + PopupDialog.ERROR_MESSAGE); + } + catch (Throwable ex) + { + logger.info("Failed to install bundle.", ex); + } + finally + { + dispose(); + } + } + } + else if (sourceButton.equals(fileChooserButton)) + { + SipCommFileChooser chooser = GenericFileDialog.create( + null, "New bundle...", + SipCommFileChooser.LOAD_FILE_OPERATION); + + chooser.addFilter(new SipCommFileFilter() + { + @Override + public boolean accept(File f) + { + if (f.isDirectory()) + return true; + + boolean good = true; + try + { + ZipFile zip = new ZipFile(f); + } + catch (IOException ex) + { + good = false; + } + + if (!f.getName().toLowerCase().endsWith(".zip")) + { + good = false; + } + return good; + } + + @Override + public String getDescription() + { + return "Zip files (*.zip)"; + } + }); + + File newBundleFile = chooser.getFileFromDialog(); + + if (newBundleFile != null) + { + try + { + bundlePathField.setText(newBundleFile.getCanonicalPath()); + } + catch (Exception ex) + { + bundlePathField.setText(newBundleFile.getAbsolutePath()); + } + } + } + else + { + dispose(); + } + } + + /** + * Presses programatically the cancel button, when Esc key is pressed. + * @param isEscaped indicates if the Esc button was pressed on close + */ + protected void close(boolean isEscaped) + { + cancelButton.doClick(); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/Resources.java b/src/net/java/sip/communicator/plugin/skinmanager/Resources.java new file mode 100644 index 0000000..2f7fcf3 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/Resources.java @@ -0,0 +1,57 @@ +/* + * 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.skinmanager; + +import net.java.sip.communicator.service.resources.*; + +/** + * The <tt>Resources</tt> class manages the access to the internationalization + * properties files and the image resources used in this plugin. + * + * @author Yana Stamcheva + */ +public class Resources +{ + private static ResourceManagementService resourcesService; + + /** + * Returns an internationalized string corresponding to the given key. + * + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + return getResources().getI18NString(key); + } + + /** + * Returns an int RGB color corresponding to the given key. + * + * @param key The key of the string. + * + * @return An internationalized string corresponding to the given key. + */ + public static int getColor(String key) + { + return getResources().getColor(key); + } + + /** + * Returns an instance of <tt>ResourceManagementService</tt> registered in + * the <tt>bundleContext</tt>. + * @return an instance of <tt>ResourceManagementService</tt> + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(SkinManagerActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/SkinListCellRenderer.java b/src/net/java/sip/communicator/plugin/skinmanager/SkinListCellRenderer.java new file mode 100644 index 0000000..0a3faf2 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/SkinListCellRenderer.java @@ -0,0 +1,311 @@ +/* + * 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.skinmanager; + +import java.awt.*; +import java.io.IOException; +import java.net.*; +import java.util.*; + +import javax.swing.*; +import javax.swing.table.*; + +import net.java.sip.communicator.util.swing.*; + +import org.osgi.framework.*; + +/** + * The <tt>ContactListCellRenderer</tt> is the custom cell renderer used in the + * SIP-Communicator's <tt>ContactList</tt>. It extends JPanel instead of JLabel, + * which allows adding different buttons and icons to the contact cell. + * The cell border and background are repainted. + * + * @author Yana Stamcheva + * @author Adam Netocny, CircleTech, s.r.o. + */ +public class SkinListCellRenderer + extends JPanel + implements TableCellRenderer +{ + /** + * The end color used to paint a gradient selected background. + */ + private static final Color SELECTED_START_COLOR + = new Color(Resources.getColor("service.gui.LIST_SELECTION_COLOR")); + + /** + * The start color used to paint a gradient selected background. + */ + private static final Color SELECTED_END_COLOR + = new Color(Resources.getColor("service.gui.GRADIENT_LIGHT_COLOR")); + + /** + * The panel containing name and version information. + */ + private JPanel nameVersionPanel + = new JPanel(new FlowLayout(FlowLayout.LEFT)); + + /** + * The name label. + */ + private JLabel nameLabel = new JLabel(); + + /** + * The version label. + */ + private JLabel versionLabel = new JLabel(); + + /** + * The description label. + */ + private JLabel descriptionLabel = new JLabel(); + + /** + * The state label. + */ + private JLabel stateLabel = new JLabel(); + + /** + * The icon label. + */ + private JLabel iconLabel = new JLabel(); + + /** + * Indicates if a skin is selected. + */ + private boolean isSelected = false; + + /** + * The cache of the <code>ImageIcon</code> values returned by + * {@link #getStateIcon(int)} because the method in question is called + * whenever a table cell is painted and reading the image data out of a file + * and loading it into a new <code>ImageIcon</code> at such a time + * noticeably affects execution the speed. + */ + private final ImageIcon[] stateIconCache = new ImageIcon[5]; + + /** + * Initialize the panel containing the node. + */ + public SkinListCellRenderer() + { + super(new BorderLayout(8, 8)); + + JPanel mainPanel = new JPanel(new BorderLayout()); + + this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + this.setBackground(Color.WHITE); + + this.setOpaque(true); + + mainPanel.setOpaque(false); + this.nameVersionPanel.setOpaque(false); + + this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + this.nameLabel.setIconTextGap(2); + + this.nameLabel.setFont(this.getFont().deriveFont(Font.BOLD)); + + this.nameVersionPanel.add(nameLabel); + this.nameVersionPanel.add(versionLabel); + + mainPanel.add(nameVersionPanel, BorderLayout.NORTH); + mainPanel.add(descriptionLabel, BorderLayout.CENTER); + + this.add(iconLabel, BorderLayout.WEST); + + this.add(mainPanel, BorderLayout.CENTER); + this.add(stateLabel, BorderLayout.WEST); + } + + /** + * Implements the <tt>ListCellRenderer</tt> method. + * Returns this panel that has been configured to display bundle name, + * version and description. + * @param table the parent table + * @param value the value of the rendered cell + * @param isSelected indicates if the rendered cell is selected + * @param hasFocus indicates if the rendered cell has the focus + * @param rowIndex the row index of the rendered cell + * @param vColIndex the column index of the rendered cell + * @return the rendering component + */ + @SuppressWarnings("unchecked") + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) + { + Bundle bundle = (Bundle) value; + URL res = bundle.getResource("info.properties"); + Dictionary<Object, Object> headers = bundle.getHeaders(); + Object bundleName = headers.get(Constants.BUNDLE_NAME); + Object bundleVersion = headers.get(Constants.BUNDLE_VERSION); + Object bundleDescription = headers.get(Constants.BUNDLE_DESCRIPTION); + + if (res != null) { + Properties props = new Properties(); + try { + props.load(res.openStream()); + String disp = props.getProperty("display_name"); + if (disp != null) { + bundleName = disp; + } + + disp = props.getProperty("version"); + if (disp != null) { + bundleVersion = disp; + } + + disp = props.getProperty("author"); + String desc = props.getProperty("description"); + String bundString = ""; + if (disp != null) { + bundString = disp; + } + if (desc != null) { + if (disp != null) { + bundString += " - "; + } + bundString += desc; + } + + if(!bundString.equals("")){ + bundleDescription = bundString; + } + } catch (IOException ex) { + } + } + + Icon stateIcon = getStateIcon(bundle.getState()); + + if (bundleName != null) + { + this.nameLabel.setText(bundleName.toString()); + } + else + { + this.nameLabel.setText("unknown"); + } + + if (bundleVersion != null) + { + this.versionLabel.setText(bundleVersion.toString()); + } + else + { + this.versionLabel.setText(""); + } + + if (bundleDescription != null) + { + this.descriptionLabel.setText(bundleDescription.toString()); + } + else + { + this.descriptionLabel.setText(""); + } + + if (stateIcon != null) + { + this.stateLabel.setIcon(stateIcon); + } + + this.isSelected = isSelected; + + return this; + } + + /** + * Returns an icon corresponding to the given <tt>state</tt>. + * @param state the state, for which we're looking for an icon + * @return the icon corresponding to the given state + */ + private ImageIcon getStateIcon(int state) + { + int cacheIndex; + String imageID; + switch (state) + { + case Bundle.INSTALLED: + cacheIndex = 0; + imageID = "plugin.pluginmanager.INSTALLED_STATE"; + break; + case Bundle.RESOLVED: + cacheIndex = 1; + imageID = "plugin.pluginmanager.DEACTIVATED_STATE"; + break; + case Bundle.STARTING: + cacheIndex = 2; + imageID = "plugin.pluginmanager.STARTING_STATE"; + break; + case Bundle.STOPPING: + cacheIndex = 3; + imageID = "plugin.pluginmanager.STOPPING_STATE"; + break; + case Bundle.ACTIVE: + cacheIndex = 4; + imageID = "plugin.pluginmanager.ACTIVATE_STATE"; + break; + default: + return null; + } + + ImageIcon stateIcon = stateIconCache[cacheIndex]; + if (stateIcon == null) + { + stateIconCache[cacheIndex] + = stateIcon = Resources.getResources().getImage(imageID); + } + return stateIcon; + } + + /** + * Paints a custom background of the cell. + */ + @Override + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + g = g.create(); + try + { + internalPaintComponent(g); + } + finally + { + g.dispose(); + } + } + + /** + * Paints a custom gradient background for selected cells. + * @param g the <tt>Graphics</tt> object used for painting + */ + private void internalPaintComponent(Graphics g) + { + AntialiasingManager.activateAntialiasing(g); + + Graphics2D g2 = (Graphics2D) g; + int width = getWidth(); + int height = getHeight(); + + if (this.isSelected) + { + GradientPaint p = + new GradientPaint(width / 2, 0, SELECTED_START_COLOR, + width / 2, height, SELECTED_END_COLOR); + + g2.setPaint(p); + g2.fillRoundRect(1, 1, width, height - 1, 7, 7); + } + + g2.setColor(SELECTED_START_COLOR); + g2.drawLine(0, height - 1, width, height - 1); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerActivator.java b/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerActivator.java new file mode 100644 index 0000000..e7f0c07 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerActivator.java @@ -0,0 +1,86 @@ +/* + * 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.skinmanager; + +import java.util.*; + +import net.java.sip.communicator.service.gui.*; + +import org.osgi.framework.*; + +/** + * The <tt>BundleActivator</tt> of the SkinManager plugin. + * + * @author Yana Stamcheva + * @author Adam Netocny, CircleTech, s.r.o. + */ +public class SkinManagerActivator + implements BundleActivator +{ + /** + * The bundle context. + */ + public static BundleContext bundleContext; + + /** + * The user interface service. + */ + private static UIService uiService; + + /** + * Starts this bundle and adds the + * <td>SkinManagerConfigForm</tt> contained in it to the configuration + * window obtained from the <tt>UIService</tt>. + * @param bc the <tt>BundleContext</tt> + * @throws Exception if one of the operation executed in the start method + * fails + */ + public void start(BundleContext bc) throws Exception + { + bundleContext = bc; + + Dictionary<String, String> properties = new Hashtable<String, String>(); + properties.put( ConfigurationForm.FORM_TYPE, + ConfigurationForm.ADVANCED_TYPE); + bundleContext.registerService( + ConfigurationForm.class.getName(), + new LazyConfigurationForm( + "net.java.sip.communicator.plugin.skinmanager.SkinManagerPanel", + getClass().getClassLoader(), + "plugin.skinmanager.PLUGIN_ICON", + "plugin.skinmanager.SKINS", + 1001, true), + properties); + } + + /** + * Stops this bundles. + * @param bc the <tt>BundleContext</tt> + * @throws Exception if one of the operation executed in the stop method + * fails + */ + public void stop(BundleContext bc) throws Exception {} + + /** + * Returns the <tt>UIService</tt> obtained from the bundle context. + * + * @return the <tt>UIService</tt> obtained from the bundle context + */ + public static UIService getUIService() + { + if (uiService == null) + { + ServiceReference uiReference = + bundleContext.getServiceReference(UIService.class.getName()); + + uiService = + (UIService) bundleContext + .getService(uiReference); + } + + return uiService; + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerPanel.java b/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerPanel.java new file mode 100644 index 0000000..f1b3efc --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/SkinManagerPanel.java @@ -0,0 +1,131 @@ +/* + * 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.skinmanager; + +import java.awt.*; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; + +import net.java.sip.communicator.util.swing.*; + +import org.osgi.framework.*; + +/** + * @author Yana Stamcheva + * @author Adam Netocny, CircleTech, s.r.o. + */ +public class SkinManagerPanel + extends TransparentPanel +{ + /** + * The table containing all skins. + */ + private final JTable skinTable = new JTable(); + + /** + * The table model. + */ + private final SkinTableModel tableModel = new SkinTableModel(); + + /** + * The panel containing manage buttons. + */ + private final ManageButtonsPanel buttonsPanel; + + /** + * Creates an instance of <tt>SkinManagerPanel</tt>. + */ + public SkinManagerPanel() + { + super(new BorderLayout()); + JScrollPane pluginListScrollPane = new JScrollPane(); + + skinTable.setModel(tableModel); + + TableColumn col = skinTable.getColumnModel().getColumn(0); + col.setCellRenderer(new SkinListCellRenderer()); + + SkinListSelectionListener selectionListener = + new SkinListSelectionListener(); + + skinTable.getSelectionModel().addListSelectionListener( + selectionListener); + skinTable.getColumnModel().getSelectionModel() + .addListSelectionListener(selectionListener); + + skinTable.setRowHeight(48); + + skinTable.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + + skinTable.setTableHeader(null); + + buttonsPanel = new ManageButtonsPanel(skinTable); + + this.add(pluginListScrollPane, BorderLayout.CENTER); + + this.add(buttonsPanel, BorderLayout.EAST); + + pluginListScrollPane.getViewport().add(skinTable); + + pluginListScrollPane.getVerticalScrollBar().setUnitIncrement(30); + + SkinManagerActivator.bundleContext + .addBundleListener(new SkinListBundleListener()); + } + + /** + * Listens for events triggered when a selection is made in the plugin list. + */ + private class SkinListSelectionListener + implements ListSelectionListener + { + public void valueChanged(ListSelectionEvent e) + { + int selectedRow = skinTable.getSelectedRow(); + + if (selectedRow == -1) + return; + + Bundle selectedBundle + = (Bundle) skinTable.getValueAt(selectedRow, 0); + + buttonsPanel.enableUninstallButton(true); + + if (selectedBundle.getState() != Bundle.ACTIVE) + { + buttonsPanel.enableActivateButton(true); + buttonsPanel.enableDeactivateButton(false); + } + else + { + buttonsPanel.enableActivateButton(false); + buttonsPanel.enableDeactivateButton(true); + } + } + } + + /** + * Listens for <tt>BundleEvents</tt> triggered by the bundle context. + */ + private class SkinListBundleListener + implements BundleListener + { + public void bundleChanged(BundleEvent event) + { + tableModel.update(); + + if (event.getType() == BundleEvent.INSTALLED) + { + skinTable.scrollRectToVisible( + new Rectangle( 0, skinTable.getHeight(), + 1, skinTable.getHeight())); + } + } + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/SkinTableModel.java b/src/net/java/sip/communicator/plugin/skinmanager/SkinTableModel.java new file mode 100644 index 0000000..eacb2d3 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/SkinTableModel.java @@ -0,0 +1,171 @@ +/* + * 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.skinmanager; + +import java.util.*; + +import javax.swing.table.*; + +import org.osgi.framework.*; + +/** + * The <tt>TableModel</tt> of the table containing all plug-ins. + * + * @author Yana Stamcheva + * @author Adam Netocny, CircleTech, s.r.o. + */ +public class SkinTableModel + extends AbstractTableModel +{ + /** + * The bundle context. + */ + private BundleContext bundleContext = SkinManagerActivator.bundleContext; + + /** + * The array of bundles. + */ + private Bundle[] bundles = null; + + /** + * A bundle comparator. + */ + private final BundleComparator bundleComparator = new BundleComparator(); + + /** + * Create an instance of <tt>SkinTableModel</tt> + */ + public SkinTableModel() + { + refreshSortedBundlesList(); + } + + /** + * Returns the count of table rows. + * @return int the count of table rows + */ + public int getRowCount() + { + if (bundles == null) + { + return 0; + } + else + { + return bundles.length; + } + } + + /** + * Returns TRUE if the given <tt>Bundle</tt> is contained in this table, + * FALSE - otherwise. + * @param bundle the <tt>Bundle</tt> to search for + * @return TRUE if the given <tt>Bundle</tt> is contained in this table, + * FALSE - otherwise. + */ + public boolean contains(Bundle bundle) + { + for (int i = 0; i < bundles.length; i++) + { + Bundle b = bundles[i]; + + if (b.equals(bundle)) + { + return true; + } + } + + return false; + } + + /** + * Returns the count of table columns. + * @return int the count of table columns + */ + public int getColumnCount() + { + return 1; + } + + /** + * Returns FALSE for all cells in this table. + * @param row the row number to check + * @param column the column number to check + * @return false + */ + public boolean isCellEditable(int row, int column) + { + return false; + } + + /** + * Returns the value in the cell given by row and column. + * @param row the row number of the cell, which value we're looking for + * @param column the column of the cell, which value we're looking for + * @return the value of the cell given by <tt>row</tt> and <tt>column</tt> + */ + public Object getValueAt(int row, int column) + { + int bundleCounter = 0; + + for (int i = 0; i < bundles.length; i++) + { + if (bundleCounter == row) + { + return bundles[i]; + } + + bundleCounter++; + } + return null; + } + + /** + * Updates the table content. + */ + public void update() + { + refreshSortedBundlesList(); + fireTableDataChanged(); + } + + /** + * Synchronizes the content of the bundle list with the bundles currently + * available in the bundle context and sorts it again. + */ + private void refreshSortedBundlesList() + { + Bundle[] list = this.bundleContext.getBundles(); + ArrayList<Bundle> show = new ArrayList<Bundle>(); + if (list != null) + { + for (Bundle b : list) + { + Dictionary headers = b.getHeaders(); + if (headers.get(Constants.BUNDLE_ACTIVATOR) != null) + { + if (headers.get(Constants.BUNDLE_ACTIVATOR).toString() + .equals("net.java.sip.communicator.plugin." + + "skinresourcepack.SkinResourcesPack")) + { + show.add(b); + } + } + } + } + + this.bundles = new Bundle[show.size()]; + int i = 0; + for (Bundle b : show) + { + this.bundles[i] = b; + i++; + } + + Arrays.sort(this.bundles, bundleComparator); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/TitlePanel.java b/src/net/java/sip/communicator/plugin/skinmanager/TitlePanel.java new file mode 100644 index 0000000..c2797c3 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/TitlePanel.java @@ -0,0 +1,125 @@ +/* + * 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.skinmanager; + +import java.awt.*; + +import javax.swing.*; + +/** + * The <tt>TitlePanel</tt> is a decorated panel, that could be used for a + * header or a title area. This panel is used for example in the + * <tt>ConfigurationFrame</tt>. + * + * @author Yana Stamcheva + */ +public class TitlePanel + extends JPanel +{ + /** + * A color between blue and gray used to paint some borders. + */ + public static final Color BORDER_COLOR + = new Color(Resources.getColor("service.gui.BORDER_COLOR")); + + /** + * The size of the gradient used for painting the background. + */ + private static final int GRADIENT_SIZE = 10; + + /** + * The start color used to paint a gradient mouse over background. + */ + private static final Color GRADIENT_DARK_COLOR + = new Color(Resources.getColor("service.gui.GRADIENT_DARK_COLOR")); + + /** + * The end color used to paint a gradient mouse over background. + */ + private static final Color GRADIENT_LIGHT_COLOR + = new Color(Resources.getColor("service.gui.GRADIENT_LIGHT_COLOR")); + + private JLabel titleLabel = new JLabel(); + + /** + * Creates an instance of <tt>TitlePanel</tt>. + */ + public TitlePanel() + { + super(new FlowLayout(FlowLayout.CENTER)); + + this.setPreferredSize(new Dimension(0, 30)); + + this.titleLabel.setFont(this.getFont().deriveFont(Font.BOLD, 14)); + } + + /** + * Creates an instance of <tt>TitlePanel</tt> by specifying the title + * String. + * + * @param title A String title. + */ + public TitlePanel(String title) + { + super(new FlowLayout(FlowLayout.CENTER)); + + this.titleLabel.setFont(this.getFont().deriveFont(Font.BOLD, 14)); + + this.titleLabel.setText(title); + + this.add(titleLabel); + } + + /** + * Overrides the <code>paintComponent</code> method of <tt>JPanel</tt> + * to paint a gradient background of this panel. + * @param g the <tt>Graphics</tt> object used for painting + */ + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + Graphics2D g2 = (Graphics2D) g; + + GradientPaint p = new GradientPaint(this.getWidth() / 2, 0, + GRADIENT_DARK_COLOR, this.getWidth() / 2, + GRADIENT_SIZE, + GRADIENT_LIGHT_COLOR); + + GradientPaint p1 = new GradientPaint(this.getWidth() / 2, this + .getHeight() + - GRADIENT_SIZE, + GRADIENT_LIGHT_COLOR, this.getWidth() / 2, + this.getHeight(), GRADIENT_DARK_COLOR); + + g2.setPaint(p); + g2.fillRect(0, 0, this.getWidth(), GRADIENT_SIZE); + + g2.setColor(GRADIENT_LIGHT_COLOR); + g2.fillRect(0, GRADIENT_SIZE, this.getWidth(), + this.getHeight() - GRADIENT_SIZE); + + g2.setPaint(p1); + g2.fillRect(0, this.getHeight() - GRADIENT_SIZE + - 1, this.getWidth(), this.getHeight() - 1); + + g2.setColor(BORDER_COLOR); + g2.drawRoundRect(0, 0, this.getWidth() - 1, this.getHeight() - 1, 5, 5); + } + + /** + * Sets the title String. + * @param title The title String. + */ + public void setTitleText(String title) + { + this.titleLabel.setText(title); + + this.add(titleLabel); + } +} diff --git a/src/net/java/sip/communicator/plugin/skinmanager/skinmanager.manifest.mf b/src/net/java/sip/communicator/plugin/skinmanager/skinmanager.manifest.mf new file mode 100644 index 0000000..8919efa --- /dev/null +++ b/src/net/java/sip/communicator/plugin/skinmanager/skinmanager.manifest.mf @@ -0,0 +1,27 @@ +Bundle-Activator: net.java.sip.communicator.plugin.skinmanager.SkinManagerActivator +Bundle-Name: Skin Manager plugin +Bundle-Description: Manage all SIP Communicator skins. +Bundle-Vendor: sip-communicator.org, Adam Netocny, CircleTech, s.r.o. +Bundle-Version: 0.0.1 +System-Bundle: yes +Import-Package: org.osgi.framework, + net.java.sip.communicator.service.configuration, + net.java.sip.communicator.service.gui, + net.java.sip.communicator.service.gui.event, + net.java.sip.communicator.service.resources, + net.java.sip.communicator.util, + net.java.sip.communicator.util.swing, + javax.swing, + javax.swing.event, + javax.swing.table, + javax.swing.text, + javax.swing.text.html, + javax.accessibility, + javax.swing.plaf, + javax.swing.plaf.metal, + javax.swing.plaf.basic, + javax.imageio, + javax.swing.filechooser, + javax.swing.tree, + javax.swing.undo, + javax.swing.border |