New skin management interface, provided by Adam Netocny.

cusax-fix
Yana Stamcheva 16 years ago
parent f040cae84a
commit 45bef74da8

@ -763,12 +763,10 @@ plugin.sipaccregwizz.XCAP_PASSWORD=Password
plugin.sipaccregwizz.XCAP_SERVER_URI=Server URI
# skin manager
plugin.skinmanager.INSTALL=Install
plugin.skinmanager.UNINSTALL=Uninstall
plugin.skinmanager.SKINS=Skins
plugin.skinmanager.URL=Url
plugin.skinmanager.CHOOSE_FILE=Select Zip
plugin.skinmanager.NEW=New
plugin.skinmanager.DEFAULT_SKIN=Default skin
plugin.skinmanager.ADD_NEW_SKIN=Add new skin...
plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=The default skin of the application.
# ssh accregwizz
plugin.sshaccregwizz.PROTOCOL_NAME=SSH

@ -44,7 +44,7 @@ public class ManageButtonsPanel
* The uninstall button.
*/
private JButton uninstallButton = new JButton(
Resources.getString("plugin.skinmanager.UNINSTALL"));
Resources.getString("plugin.pluginmanager.UNINSTALL"));
/**
* The update button.
@ -56,7 +56,7 @@ public class ManageButtonsPanel
* The new button.
*/
private JButton newButton
= new JButton(Resources.getString("plugin.skinmanager.NEW"));
= new JButton(Resources.getString("plugin.pluginmanager.NEW"));
/**
* The panel, containing all buttons.

@ -1,245 +0,0 @@
/*
* 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
*/
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);
}
}

@ -1,261 +0,0 @@
/*
* 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.getClass() + ": "
+ 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();
}
}

@ -1,311 +0,0 @@
/*
* 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
*/
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);
}
}

@ -7,125 +7,115 @@
package net.java.sip.communicator.plugin.skinmanager;
import java.awt.*;
import java.awt.event.*;
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
*/
public class SkinManagerPanel
extends TransparentPanel
{
/**
* The table containing all skins.
*/
private final JTable skinTable = new JTable();
/**
* The table model.
* Remove button.
*/
private final SkinTableModel tableModel = new SkinTableModel();
private final JButton rmButton = new JButton("Remove selected skin");
/**
* The panel containing manage buttons.
* <tt>SkinSelector</tt> component.
*/
private final ManageButtonsPanel buttonsPanel;
private final SkinSelector skinSelector = new SkinSelector();
/**
* 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();
super(new FlowLayout(FlowLayout.CENTER));
skinTable.getSelectionModel().addListSelectionListener(
selectionListener);
skinTable.getColumnModel().getSelectionModel()
.addListSelectionListener(selectionListener);
JPanel selectorPanel = new TransparentPanel();
selectorPanel.setLayout(new BoxLayout(selectorPanel, BoxLayout.Y_AXIS));
skinTable.setRowHeight(48);
skinSelector.setAlignmentX(Component.CENTER_ALIGNMENT);
skinSelector.addItemListener(new EnableDisableListener());
selectorPanel.add(skinSelector);
skinTable.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
rmButton.setAlignmentX(Component.CENTER_ALIGNMENT);
rmButton.addActionListener(new RemoveListener());
selectorPanel.add(rmButton);
skinTable.setTableHeader(null);
enableDisableButton();
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());
add(selectorPanel, BorderLayout.NORTH);
}
/**
* Listens for events triggered when a selection is made in the plugin list.
* Enables(if a skin <tt>Bundle</tt> is selected) or disables the remove
* button.
*/
private class SkinListSelectionListener
implements ListSelectionListener
private void enableDisableButton()
{
public void valueChanged(ListSelectionEvent e)
Object tmp = skinSelector.getSelectedItem();
if(tmp != null)
{
int selectedRow = skinTable.getSelectedRow();
if(tmp instanceof Bundle)
{
rmButton.setEnabled(true);
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
}
rmButton.setEnabled(false);
}
/**
* Listener for the remove button events.
*/
private class RemoveListener implements ActionListener
{
/**
* Invoked when an action occurs.
* @param e <tt>ActionEvent</tt>.
*/
public void actionPerformed(ActionEvent e)
{
Object tmp = skinSelector.getSelectedItem();
if(tmp != null)
{
buttonsPanel.enableActivateButton(false);
buttonsPanel.enableDeactivateButton(true);
if(tmp instanceof Bundle)
{
try
{
((Bundle) tmp).uninstall();
}
catch (BundleException ex)
{
}
}
}
}
}
/**
* Listens for <tt>BundleEvents</tt> triggered by the bundle context.
* Selection listener for enabling/disabling of remove button.
*/
private class SkinListBundleListener
implements BundleListener
private class EnableDisableListener
implements ItemListener
{
public void bundleChanged(BundleEvent event)
public void itemStateChanged(ItemEvent e)
{
tableModel.update();
if (event.getType() == BundleEvent.INSTALLED)
SwingUtilities.invokeLater(new Runnable()
{
skinTable.scrollRectToVisible(
new Rectangle( 0, skinTable.getHeight(),
1, skinTable.getHeight()));
}
public void run()
{
enableDisableButton();
}
});
}
}
}

@ -0,0 +1,218 @@
/*
* 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.event.*;
import java.io.*;
import java.net.*;
import java.util.zip.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
import org.osgi.framework.*;
/**
* Selection listener for the <tt>SkinSelector</tt>.
* @author Adam Netocny
*/
public class SkinSelectionListener implements ActionListener
{
/**
* The object used for logging.
*/
private Logger logger = Logger.getLogger(SkinSelectionListener.class);
/**
* Currently selected item.
*/
private Object current = null;
/**
* Suppress value for events. If true the event will be ignored.
*/
private boolean suppressed = false;
/**
* Invoked when an action occurs.
* @param e <tt>ActionEvent</tt>
*/
public void actionPerformed(ActionEvent e)
{
SkinSelector selector = (SkinSelector) e.getSource();
if (current != null && current.equals(selector.getSelectedItem()))
return;
if(suppressed)
{
current = selector.getSelectedItem();
return;
}
if(selector.getSelectedItem() instanceof String)
{
String selectedItem = (String) selector.getSelectedItem();
if(selectedItem.equals(SkinSelector.ADD_TEXT))
{
selector.hidePopup();
SipCommFileChooser chooser = createFileChooser();
File newBundleFile = chooser.getFileFromDialog();
if(newBundleFile != null)
{
try
{
File jar = null;
try
{
jar = Resources.getResources()
.prepareSkinBundleFromZip(newBundleFile);
}
catch (Exception ex)
{
logger.info("Failed to load skin from zip.", ex);
SkinManagerActivator.getUIService().getPopupDialog()
.showMessagePopupDialog(ex.getClass() + ": "
+ ex.getMessage(), "Error",
PopupDialog.ERROR_MESSAGE);
}
if (jar != null)
{
try
{
Bundle newBundle = SkinManagerActivator
.bundleContext.installBundle(
jar.toURI().toURL().toString());
selector.selectNoSkin();
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);
}
}
else
{
if(current != null)
{
selector.setSelectedItem(current);
}
else
{
selector.setSelectedIndex(0);
}
}
}
else if(selectedItem.equals(SkinSelector.DEFAULT_TEXT))
{
selector.selectNoSkin();
}
else if(selectedItem.equals(SkinSelectorRenderer.SEPARATOR))
{
if(current != null)
{
selector.setSelectedItem(current);
}
else
{
selector.setSelectedIndex(0);
}
}
}
else if(selector.getSelectedItem() instanceof Bundle)
{
Bundle select = (Bundle)selector.getSelectedItem();
selector.selectNoSkin();
try
{
select.start();
}
catch (BundleException ex)
{
// ex.printStackTrace();
}
}
current = selector.getSelectedItem();
}
/**
* Sets if the catched event should be ignored or not.
* @param supp If true the event will be ignored.
*/
public void suppressAction(boolean supp)
{
suppressed = supp;
}
/**
* Creates the file chooser used to install a new skin.
*
* @return the created file chooser
*/
private SipCommFileChooser createFileChooser()
{
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
{
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)";
}
});
return chooser;
}
}

@ -0,0 +1,290 @@
/*
* 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.*;
import org.osgi.framework.*;
/**
* <tt>SkinSelector</tt> is extending a <tt>JComboBox</tt> and represents
* a selector for selecting of SIP Communicator skins.
*
* @author Adam Netocny
* @author Yana Stamcheva
*/
public class SkinSelector
extends JComboBox
implements BundleListener
{
/**
* Text for the default skin menu item.
*/
public static final String DEFAULT_TEXT
= Resources.getString("plugin.skinmanager.DEFAULT_SKIN");
/**
* Text for the default skin menu item description section.
*/
public static final String DEFAULT_DESCRIPTION_TEXT
= Resources.getString("plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION");
/**
* Text for the add skin menu item.
*/
public static final String ADD_TEXT
= Resources.getString("plugin.skinmanager.ADD_NEW_SKIN");
/**
* Action listener for skin selection.
*/
private SkinSelectionListener listener;
/**
* Thread lock.
*/
private final Object lock = new Object();
/**
* Casts the data model to <tt>DefaultComboBoxModel</tt>.
*/
private final DefaultComboBoxModel dataModel
= (DefaultComboBoxModel) super.dataModel;
/**
* Constructor.
*/
public SkinSelector()
{
SkinManagerActivator.bundleContext.addBundleListener(this);
listener = new SkinSelectionListener();
addActionListener(listener);
setRenderer(new SkinSelectorRenderer());
init();
}
/**
* Reloads the skin list.
*/
private void init()
{
if(listener != null)
listener.suppressAction(true);
synchronized(lock)
{
removeAllItems();
addItem(DEFAULT_TEXT);
addSkinBundles();
addItem(SkinSelectorRenderer.SEPARATOR);
addItem(ADD_TEXT);
}
selectActiveSkin();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if(listener != null)
listener.suppressAction(false);
}
});
}
/**
* Selects the active skin.
*/
public void selectActiveSkin()
{
// If we're not in the event dispatch thread should first move to it.
if(!SwingUtilities.isEventDispatchThread())
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
selectActiveSkin();
}
});
if(listener != null)
listener.suppressAction(true);
synchronized(lock)
{
boolean found = false;
for (int i = 0; i < dataModel.getSize(); i++)
{
Object o = dataModel.getElementAt(i);
if (!(o instanceof Bundle))
continue;
Bundle b = (Bundle) o;
if(b.getState() == Bundle.ACTIVE
|| b.getState() == Bundle.STARTING)
{
setSelectedItem(b);
found = true;
}
}
if(!found)
setSelectedIndex(0);
}
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if(listener != null)
listener.suppressAction(false);
}
});
}
/**
* Selects the default skin(no-skin).
*/
public void selectNoSkin()
{
// If we're not in the event dispatch thread should first move to it.
if(!SwingUtilities.isEventDispatchThread())
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
selectNoSkin();
}
});
setSelectedIndex(0);
synchronized(lock)
{
for (int i = 0; i < getModel().getSize(); i++)
{
Object o = getModel().getElementAt(i);
if (!(o instanceof Bundle))
continue;
Bundle b = (Bundle) o;
try
{
if (b.getState() == Bundle.ACTIVE)
b.stop();
}
catch (BundleException ex)
{
//ex.printStackTrace();
}
}
}
}
/**
* Adds all selectable skin bundles into the list.
*/
private void addSkinBundles()
{
Bundle[] list = SkinManagerActivator.bundleContext.getBundles();
Arrays.sort(list, new BundleComparator());
if (list != null && list.length != 0)
{
for (Bundle b : list)
{
if(isSkin(b))
addItem(b);
}
}
}
/**
* Bundle listener implementation. Reloads the list.
*
* @param be <tt>BundleEvent</tt>.
*/
public void bundleChanged(final BundleEvent be)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Bundle b = be.getBundle();
int eventType = be.getType();
if (eventType == BundleEvent.INSTALLED && isSkin(b))
{
insertItemAt(b, dataModel.getSize() - 2);
return;
}
else if (eventType == BundleEvent.UNINSTALLED && isSkin(b))
{
if (getSelectedItem().equals(b))
{
selectNoSkin();
removeItem(b);
}
return;
}
// We're only interested in bundle events related to our
// skin list.
if (dataModel.getIndexOf(b) < 0)
return;
if ((eventType == BundleEvent.STOPPING
|| eventType == BundleEvent.STARTING)
&& getSelectedItem().equals(b))
{
selectNoSkin();
}
else if (eventType == BundleEvent.STARTED
&& !getSelectedItem().equals(b))
{
selectActiveSkin();
}
}
});
}
/**
* Checks if the given <tt>bundle</tt> is a skin.
*
* @param bundle the <tt>Bundle</tt> to check
* @return <tt>true</tt> if the given <tt>bundle</tt> is a skin,
* <tt>false</tt> otherwise
*/
private boolean isSkin(Bundle bundle)
{
Dictionary<?, ?> headers = bundle.getHeaders();
if (headers.get(Constants.BUNDLE_ACTIVATOR) != null)
{
if (headers.get(Constants.BUNDLE_ACTIVATOR).toString()
.equals("net.java.sip.communicator.plugin." +
"skinresourcepack.SkinResourcePack"))
{
return true;
}
}
return false;
}
}

@ -0,0 +1,200 @@
/*
* 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.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.util.swing.TransparentPanel;
import org.osgi.framework.*;
/**
* Render class for the <tt>SkinSelector</tt> class.
*
* @author Adam Netocny
* @author Yana Stamcheva
*/
public class SkinSelectorRenderer
extends TransparentPanel
implements ListCellRenderer
{
/**
* Separator string. Will be replaced with a <tt>JSeparator</tt>.
*/
public static final String SEPARATOR = "separator";
/**
* The name label.
*/
private JLabel nameLabel = new JLabel();
/**
* The description label.
*/
private JLabel descriptionLabel = new JLabel();
/**
* Separator
*/
JSeparator separator = new JSeparator();
/**
* Constructor
*/
public SkinSelectorRenderer()
{
super(new BorderLayout(5, 5));
}
/**
* Return a component that has been configured to display the specified
* value. That component's <code>paint</code> method is then called to
* "render" the cell. If it is necessary to compute the dimensions
* of a list because the list cells do not have a fixed size, this method
* is called to generate a component on which <code>getPreferredSize</code>
* can be invoked.
*
* @param list The JList we're painting.
* @param value The value returned by list.getModel().getElementAt(index).
* @param index The cells index.
* @param isSelected True if the specified cell was selected.
* @param cellHasFocus True if the specified cell has the focus.
* @return A component whose paint() method will render the specified value.
*/
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus)
{
this.removeAll();
if(value.equals(SEPARATOR))//Separator
{
add(separator, BorderLayout.CENTER);
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
return this;
}
else if(value.equals(SkinSelector.ADD_TEXT))
{
add(new JLabel(SkinSelector.ADD_TEXT));
}
else if (value.equals(SkinSelector.DEFAULT_TEXT))
{
initBundleView();
nameLabel.setText(SkinSelector.DEFAULT_TEXT);
descriptionLabel.setText(SkinSelector.DEFAULT_DESCRIPTION_TEXT);
}
else if(value instanceof Bundle)
{
initBundleView();
Bundle bundle = (Bundle) value;
URL res;
try
{
res = bundle.getResource("info.properties");
}
catch(Throwable ex)
{
res = null;
}
String bundleName = "unknown";
String bundleDescription = "";
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)
{
bundleName += " " + 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) {
}
}
this.nameLabel.setText(bundleName.toString());
this.descriptionLabel.setText(bundleDescription);
}
if (isSelected)
{
this.setBackground(list.getSelectionBackground());
this.setForeground(list.getSelectionForeground());
}
else
{
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
}
return this;
}
/**
* Adds necessary components to render bundle informations.
*/
private void initBundleView()
{
JPanel mainPanel = new JPanel(new BorderLayout());
this.setBackground(Color.WHITE);
this.setOpaque(true);
mainPanel.setOpaque(false);
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.nameLabel.setIconTextGap(2);
this.nameLabel.setFont(this.getFont().deriveFont(Font.BOLD));
mainPanel.add(nameLabel, BorderLayout.NORTH);
mainPanel.add(descriptionLabel, BorderLayout.SOUTH);
this.add(mainPanel, BorderLayout.NORTH);
}
}

@ -1,171 +0,0 @@
/*
* 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
*/
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.SkinResourcePack"))
{
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);
}
}

@ -1,125 +0,0 @@
/*
* 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);
}
}
Loading…
Cancel
Save