mirror of https://github.com/sipwise/jitsi.git
parent
f6c822cc9e
commit
45cf662978
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* 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.impl.resources.util;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
/**
|
||||
* Class for building of skin bundles from zip files.
|
||||
* @author Adam Netocny, CircleTech, s.r.o.
|
||||
*/
|
||||
public class SkinJarBuilder
|
||||
{
|
||||
/**
|
||||
* Creates bundle from zip file.
|
||||
* @param zip Zip file with skin contents.
|
||||
* @return Jar <tt>File</tt>.
|
||||
* @throws Exception When something goes wrong.
|
||||
*/
|
||||
public static File createBundleFromZip(File zip)
|
||||
throws Exception
|
||||
{
|
||||
File tmpDir = unzipIntoTmp(zip);
|
||||
if (!test(tmpDir))
|
||||
{
|
||||
deleteDir(tmpDir);
|
||||
throw new Exception(
|
||||
"Zip file doesn't contain all necessary files and folders.");
|
||||
}
|
||||
File jar = cpTmp();
|
||||
insertIntoZip(jar, tmpDir);
|
||||
deleteDir(tmpDir);
|
||||
return jar;
|
||||
}
|
||||
|
||||
private static File cpTmp()
|
||||
throws IOException
|
||||
{
|
||||
File jar = new File(System.getProperty("user.dir"),
|
||||
"sc-bundles/skinresources.jar");
|
||||
|
||||
if (!jar.exists())
|
||||
{
|
||||
throw new IOException("Cannot find skinresources.jar file");
|
||||
}
|
||||
|
||||
File tmp = File.createTempFile("skinresources", ".jar");
|
||||
|
||||
InputStream in = new FileInputStream(jar);
|
||||
|
||||
OutputStream out = new FileOutputStream(tmp);
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
|
||||
while ((len = in.read(buf)) > 0)
|
||||
{
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static File unzipIntoTmp(File zip)
|
||||
throws Exception
|
||||
{
|
||||
File dest = File.createTempFile("zip", null);
|
||||
|
||||
if (!dest.delete())
|
||||
{
|
||||
throw new IOException("Cannot unzip given zip file");
|
||||
}
|
||||
|
||||
if (!dest.mkdirs())
|
||||
{
|
||||
throw new IOException("Cannot unzip given zip file");
|
||||
}
|
||||
|
||||
ZipFile archive = new ZipFile(zip);
|
||||
Enumeration<? extends ZipEntry> e = archive.entries();
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
ZipEntry entry = (ZipEntry) e.nextElement();
|
||||
File file = new File(dest, entry.getName());
|
||||
if (entry.isDirectory() && !file.exists())
|
||||
{
|
||||
file.mkdirs();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!file.getParentFile().exists())
|
||||
{
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
InputStream in = archive.getInputStream(entry);
|
||||
BufferedOutputStream out
|
||||
= new BufferedOutputStream(new FileOutputStream(file));
|
||||
byte[] buffer = new byte[8192];
|
||||
int read;
|
||||
while (-1 != (read = in.read(buffer)))
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
private static void insertIntoZip(File jar, File tmpDir)
|
||||
throws IOException
|
||||
{
|
||||
File tempFile = File.createTempFile(jar.getName(), null);
|
||||
tempFile.delete();
|
||||
|
||||
boolean renameOk = jar.renameTo(tempFile);
|
||||
if (!renameOk)
|
||||
{
|
||||
throw new IOException("Error moving file " + jar.getAbsolutePath()
|
||||
+ " to " + tempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
byte[] buf = new byte[8192];
|
||||
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
|
||||
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(jar));
|
||||
|
||||
ZipEntry entry = zin.getNextEntry();
|
||||
while (entry != null)
|
||||
{
|
||||
String name = entry.getName();
|
||||
out.putNextEntry(new ZipEntry(name));
|
||||
|
||||
int len;
|
||||
while ((len = zin.read(buf)) > 0)
|
||||
{
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
entry = zin.getNextEntry();
|
||||
}
|
||||
zin.close();
|
||||
|
||||
tempFile.delete();
|
||||
|
||||
zipDir(tmpDir.getAbsolutePath(), out);
|
||||
|
||||
out.close();
|
||||
}
|
||||
|
||||
private static void zipDir(String dir2zip, ZipOutputStream zos)
|
||||
throws IOException
|
||||
{
|
||||
File directory = new File(dir2zip);
|
||||
zip(directory, directory, zos);
|
||||
}
|
||||
|
||||
private static final void zip(File directory, File base, ZipOutputStream zos)
|
||||
throws IOException
|
||||
{
|
||||
File[] files = directory.listFiles();
|
||||
byte[] buffer = new byte[8192];
|
||||
int read = 0;
|
||||
for (int i = 0, n = files.length; i < n; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
zip(files[i], base, zos);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileInputStream in = new FileInputStream(files[i]);
|
||||
ZipEntry entry = new ZipEntry(files[i].getPath().substring(
|
||||
base.getPath().length() + 1));
|
||||
zos.putNextEntry(entry);
|
||||
while (-1 != (read = in.read(buffer))) {
|
||||
zos.write(buffer, 0, read);
|
||||
}
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDir(File tmp)
|
||||
{
|
||||
if (tmp.exists())
|
||||
{
|
||||
File[] files = tmp.listFiles();
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{
|
||||
if (files[i].isDirectory())
|
||||
{
|
||||
deleteDir(files[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
tmp.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean test(File tmpDir)
|
||||
{
|
||||
boolean colors = false;
|
||||
boolean images = false;
|
||||
boolean styles = false;
|
||||
|
||||
File[] list = tmpDir.listFiles();
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (File f : list)
|
||||
{
|
||||
if (f.getName().equals("info.properties"))
|
||||
{
|
||||
if (!f.isFile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (f.getName().equals("colors"))
|
||||
{
|
||||
if (f.isFile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
File[] ff = f.listFiles();
|
||||
if (ff == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (File x : ff)
|
||||
{
|
||||
if (x.getName().equals("colors.properties"))
|
||||
{
|
||||
colors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (f.getName().equals("images"))
|
||||
{
|
||||
if (f.isFile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
File[] ff = f.listFiles();
|
||||
if (ff == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (File x : ff)
|
||||
{
|
||||
if (x.getName().equals("images.properties"))
|
||||
{
|
||||
images = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (f.getName().equals("styles"))
|
||||
{
|
||||
if (f.isFile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
File[] ff = f.listFiles();
|
||||
if (ff == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (File x : ff)
|
||||
{
|
||||
if (x.getName().equals("styles.properties"))
|
||||
{
|
||||
styles = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return styles && (colors && images);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* 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.skinresourcepack;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
|
||||
import net.java.sip.communicator.service.resources.*;
|
||||
|
||||
/**
|
||||
* The skin resource pack.
|
||||
* @author Adam Netocny, CircleTech, s.r.o.
|
||||
*/
|
||||
public class SkinResourcesPack
|
||||
implements BundleActivator, SkinPack
|
||||
{
|
||||
/**
|
||||
* The default resource path.
|
||||
*/
|
||||
private static final String DEFAULT_RESOURCE_PATH = "info";
|
||||
|
||||
/**
|
||||
* The resource path of skin images.
|
||||
*/
|
||||
private static final String DEFAULT_IMAGE_RESOURCE_PATH = "images.images";
|
||||
|
||||
/**
|
||||
* The resource path of skin colors.
|
||||
*/
|
||||
private static final String DEFAULT_COLOR_RESOURCE_PATH = "colors.colors";
|
||||
|
||||
/**
|
||||
* The resource path f skin styles.
|
||||
*/
|
||||
private static final String DEFAULT_STYLE_RESOURCE_PATH = "styles.styles";
|
||||
|
||||
/**
|
||||
* The bundle context.
|
||||
*/
|
||||
private static BundleContext bundleContext;
|
||||
|
||||
/**
|
||||
* Buffer for resource files found.
|
||||
*/
|
||||
private static Hashtable<String, Iterator<String>> ressourcesFiles
|
||||
= new Hashtable<String, Iterator<String>>();
|
||||
|
||||
/**
|
||||
* A map of all skin image resources.
|
||||
*/
|
||||
private Map<String, String> imageResources = null;
|
||||
|
||||
/**
|
||||
* A map of all skin style resources.
|
||||
*/
|
||||
private Map<String, String> styleResources = null;
|
||||
|
||||
/**
|
||||
* A map of all skin color resources.
|
||||
*/
|
||||
private Map<String, String> colorResources = null;
|
||||
|
||||
/**
|
||||
* Starts the bundle.
|
||||
* @param bc BundleContext
|
||||
* @throws Exception -
|
||||
*/
|
||||
public void start(BundleContext bc)
|
||||
throws Exception
|
||||
{
|
||||
bundleContext = bc;
|
||||
|
||||
Hashtable<String, String> props = new Hashtable<String, String>();
|
||||
props.put(ResourcePack.RESOURCE_NAME,
|
||||
SkinPack.RESOURCE_NAME_DEFAULT_VALUE);
|
||||
|
||||
bundleContext.registerService(SkinPack.class.getName(),
|
||||
this,
|
||||
props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the bundle.
|
||||
* @param bc BundleContext
|
||||
* @throws Exception -
|
||||
*/
|
||||
public void stop(BundleContext bc) throws Exception {}
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for image
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for image
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getImageResources()
|
||||
{
|
||||
if(imageResources != null)
|
||||
{
|
||||
return imageResources;
|
||||
}
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(DEFAULT_IMAGE_RESOURCE_PATH);
|
||||
|
||||
Map<String, String> resources = new TreeMap<String, String>();
|
||||
|
||||
this.initResources(resourceBundle, resources);
|
||||
|
||||
this.initImagePluginResources(resources);
|
||||
|
||||
imageResources = resources;
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for style
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for style
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getStyleResources()
|
||||
{
|
||||
if(styleResources != null)
|
||||
{
|
||||
return styleResources;
|
||||
}
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(DEFAULT_STYLE_RESOURCE_PATH);
|
||||
|
||||
Map<String, String> resources = new TreeMap<String, String>();
|
||||
|
||||
this.initResources(resourceBundle, resources);
|
||||
|
||||
this.initStylePluginResources(resources);
|
||||
|
||||
styleResources = resources;
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for color
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for color
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getColorResources()
|
||||
{
|
||||
if(colorResources != null)
|
||||
{
|
||||
return colorResources;
|
||||
}
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(DEFAULT_COLOR_RESOURCE_PATH);
|
||||
|
||||
Map<String, String> resources = new TreeMap<String, String>();
|
||||
|
||||
this.initResources(resourceBundle, resources);
|
||||
|
||||
this.initColorPluginResources(resources);
|
||||
|
||||
colorResources = resources;
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for this
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for this
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getResources()
|
||||
{
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(DEFAULT_RESOURCE_PATH);
|
||||
|
||||
Map<String, String> resources = new TreeMap<String, String>();
|
||||
|
||||
this.initResources(resourceBundle, resources);
|
||||
|
||||
resources.putAll(getImageResources());
|
||||
|
||||
resources.putAll(getStyleResources());
|
||||
|
||||
resources.putAll(getColorResources());
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this resource pack.
|
||||
*
|
||||
* @return the name of this resource pack.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
Map<String, String> resources = getResources();
|
||||
String name = resources.get("display_name");
|
||||
if(name != null)
|
||||
{
|
||||
return name + " Skin Resources";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Skin Resources";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of this resource pack.
|
||||
*
|
||||
* @return the description of this resource pack.
|
||||
*/
|
||||
public String getDescription()
|
||||
{
|
||||
Map<String, String> resources = getResources();
|
||||
String name = resources.get("display_name");
|
||||
if(name != null)
|
||||
{
|
||||
return "Provide SIP Communicator " + name + " skin resource pack.";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Provide SIP Communicator skin resource pack.";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the given resource map with all (key,value) pairs obtained from the
|
||||
* given <tt>ResourceBundle</tt>. This method will look in the properties
|
||||
* files for references to other properties files and will include in the
|
||||
* final map data from all referenced files.
|
||||
*
|
||||
* @param resourceBundle The initial <tt>ResourceBundle</tt>, corresponding
|
||||
* to the "main" properties file.
|
||||
* @param resources A <tt>Map</tt> that would store the data.
|
||||
*/
|
||||
private void initResources( ResourceBundle resourceBundle,
|
||||
Map<String, String> resources)
|
||||
{
|
||||
Enumeration<String> colorKeys = resourceBundle.getKeys();
|
||||
|
||||
while (colorKeys.hasMoreElements())
|
||||
{
|
||||
String key = colorKeys.nextElement();
|
||||
String value = resourceBundle.getString(key);
|
||||
|
||||
resources.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all plugin image resources, matching the "images-*.properties"
|
||||
* pattern and adds them to this resource pack.
|
||||
* @param resources the map of key, value image resource pairs
|
||||
*/
|
||||
private void initImagePluginResources(Map<String, String> resources)
|
||||
{
|
||||
Iterator<String> pluginProperties
|
||||
= findResourcePaths("images", "images-*.properties");
|
||||
|
||||
while (pluginProperties.hasNext())
|
||||
{
|
||||
String resourceBundleName = pluginProperties.next();
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(
|
||||
resourceBundleName.substring(
|
||||
0, resourceBundleName.indexOf(".properties")));
|
||||
|
||||
initResources(resourceBundle, resources);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all plugin style resources, matching the "styles-*.properties"
|
||||
* pattern and adds them to this resource pack.
|
||||
* @param resources the map of key, value stype resource pairs
|
||||
*/
|
||||
private void initStylePluginResources(Map<String, String> resources)
|
||||
{
|
||||
Iterator<String> pluginProperties
|
||||
= findResourcePaths("styles", "styles-*.properties");
|
||||
|
||||
while (pluginProperties.hasNext())
|
||||
{
|
||||
String resourceBundleName = pluginProperties.next();
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(
|
||||
resourceBundleName.substring(
|
||||
0, resourceBundleName.indexOf(".properties")));
|
||||
|
||||
initResources(resourceBundle, resources);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all plugin color resources, matching the "colors-*.properties"
|
||||
* pattern and adds them to this resource pack.
|
||||
* @param resources the map of key, value color resource pairs
|
||||
*/
|
||||
private void initColorPluginResources(Map<String, String> resources)
|
||||
{
|
||||
Iterator<String> pluginProperties
|
||||
= findResourcePaths("colors", "colors-*.properties");
|
||||
|
||||
while (pluginProperties.hasNext())
|
||||
{
|
||||
String resourceBundleName = pluginProperties.next();
|
||||
|
||||
ResourceBundle resourceBundle
|
||||
= ResourceBundle.getBundle(
|
||||
resourceBundleName.substring(
|
||||
0, resourceBundleName.indexOf(".properties")));
|
||||
|
||||
initResources(resourceBundle, resources);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all properties files for the given path in this bundle.
|
||||
*
|
||||
* @param path the path pointing to the properties files.
|
||||
* @param pattern the pattern for properties files
|
||||
* (ex. "colors-*.properties")
|
||||
* @return an <tt>Iterator</tt> over a list of all properties files found
|
||||
* for the given path and pattern
|
||||
*/
|
||||
protected static Iterator<String> findResourcePaths(String path,
|
||||
String pattern)
|
||||
{
|
||||
Iterator<String> bufferedResult
|
||||
= ressourcesFiles.get(path + "/" + pattern);
|
||||
if (bufferedResult != null) {
|
||||
return bufferedResult;
|
||||
}
|
||||
|
||||
ArrayList<String> propertiesList = new ArrayList<String>();
|
||||
|
||||
@SuppressWarnings ("unchecked")
|
||||
Enumeration<URL> propertiesUrls = bundleContext.getBundle()
|
||||
.findEntries(path,
|
||||
pattern,
|
||||
false);
|
||||
|
||||
if (propertiesUrls != null)
|
||||
{
|
||||
while (propertiesUrls.hasMoreElements())
|
||||
{
|
||||
URL propertyUrl = propertiesUrls.nextElement();
|
||||
|
||||
// Remove the first slash.
|
||||
String propertyFilePath
|
||||
= propertyUrl.getPath().substring(1);
|
||||
|
||||
// Replace all slashes with dots.
|
||||
propertyFilePath = propertyFilePath.replaceAll("/", ".");
|
||||
|
||||
propertiesList.add(propertyFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<String> result = propertiesList.iterator();
|
||||
ressourcesFiles.put(path + pattern, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
Bundle-Activator: net.java.sip.communicator.plugin.skinresourcepack.SkinResourcesPack
|
||||
Bundle-Name: Skin Resource Pack
|
||||
Bundle-Description: The plugin offering skin related data.
|
||||
Bundle-Vendor: sip-communicator.org, Adam Netocny, CircleTech, s.r.o.
|
||||
Bundle-Version: 0.0.1
|
||||
System-Bundle: no
|
||||
Import-Package: org.osgi.framework,
|
||||
net.java.sip.communicator.service.resources
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.service.resources;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Default Skin Pack interface.
|
||||
* @author Adam Netocny, CircleTech, s.r.o.
|
||||
*/
|
||||
public interface SkinPack
|
||||
extends ResourcePack
|
||||
{
|
||||
/**
|
||||
* Default resource name.
|
||||
*/
|
||||
public String RESOURCE_NAME_DEFAULT_VALUE = "SkinPack";
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for image
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for image
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getImageResources();
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for style
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for style
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getStyleResources();
|
||||
|
||||
/**
|
||||
* Returns a <tt>Map</tt>, containing all [key, value] pairs for color
|
||||
* resource pack.
|
||||
*
|
||||
* @return a <tt>Map</tt>, containing all [key, value] pairs for color
|
||||
* resource pack.
|
||||
*/
|
||||
public Map<String, String> getColorResources();
|
||||
}
|
||||
Loading…
Reference in new issue