Patch provided by Adam Netocny improving skin management process (work in progress).

cusax-fix
Yana Stamcheva 15 years ago
parent 8f571ffedc
commit 3282cb2d2e

@ -894,7 +894,6 @@
bundle-slick-runner,bundle-sip,bundle-sip-slick,bundle-fileaccess,
bundle-fileaccess-slick,bundle-neomedia,
bundle-resource-manager,bundle-resources-defaultpack,
bundle-resources-skinpack,
bundle-protocol,bundle-protocol-media,bundle-icq,
bundle-icq-slick,bundle-mock,bundle-smacklib,
bundle-jabber,bundle-jabber-slick,bundle-swing-ui,bundle-ui-service,
@ -2138,8 +2137,21 @@ org.apache.http.util"/>
</jar>
</target>
<!--BUNDLE-RESOURCES-SKINPACK-->
<target name="bundle-resources-skinpack">
<!-- Copy manifest for skinresourcepack. -->
<copy file="${src}/net/java/sip/communicator/plugin/skinresourcepack/skinresourcepack.manifest.mf"
tofile="${dest}/net/java/sip/communicator/plugin/skinresourcepack/skinresourcepack.manifest.mf"/>
<!-- Copy skinresourcepack folder. -->
<copy todir="${resources}/skinresourcepack">
<fileset dir="${dest}/net/java/sip/communicator/plugin/skinresourcepack">
</fileset>
</copy>
</target>
<!--BUNDLE-DEFAULT-RESOURCES-->
<target name="bundle-resources-defaultpack">
<target name="bundle-resources-defaultpack" depends="bundle-resources-skinpack">
<!-- Copy the default resources to english one, as our defualt
language is English and without the resource we cannot excplictly set it.-->
<copy file="${sc.basedir}/resources/languages/resources.properties"
@ -2163,16 +2175,10 @@ org.apache.http.util"/>
prefix="resources/sounds"/>
<zipfileset dir="${resources}/styles"
prefix="resources/styles"/>
</jar>
</target>
<!--BUNDLE-SKIN-RESOURCES-->
<target name="bundle-resources-skinpack">
<jar
compress="false" destfile="${bundles.dest}/skinresources.jar"
manifest="${src}/net/java/sip/communicator/plugin/skinresourcepack/skinresourcepack.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/skinresourcepack"
prefix="net/java/sip/communicator/plugin/skinresourcepack"/>
<!-- Include skinresourcepack folder. -->
<zipfileset dir="${resources}/skinresourcepack"
prefix="resources/skinresourcepack"/>
</jar>
</target>

@ -46,6 +46,7 @@
* @author Yana Stamcheva
* @author Lubomir Marinov
* @author Dmitri Melnikov
* @author Adam Netocny
*/
public class UIServiceImpl
implements UIService,
@ -1227,4 +1228,20 @@ public String getMasterPassword(boolean prevSuccess)
{
return MasterPasswordInputDialog.showInput(prevSuccess);
}
/**
* Repaints and revalidates the whole UI Tree.
*
* Calls {@link SwingUtilities#updateComponentTreeUI(Component c)}
* for every window owned by the application which cause UI skin and
* layout repaint.
*/
public void repaintUI()
{
Window[] windows = GuiUtils.getWindows();
for(Window win : windows)
{
GuiUtils.updateComponentTreeUI(win);
}
}
}

@ -14,6 +14,7 @@
import javax.swing.*;
import net.java.sip.communicator.impl.resources.util.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
@ -105,6 +106,11 @@ public class ResourceManagementServiceImpl
*/
private SkinPack skinPack = null;
/**
* UI Service reference.
*/
private UIService uiService = null;
/**
* Initializes already registered default resource packs.
*/
@ -166,6 +172,12 @@ public class ResourceManagementServiceImpl
imageResources.putAll(skinPack.getImageResources());
colorResources.putAll(skinPack.getColorResources());
}
UIService serv = getUIService();
if (serv != null)
{
serv.repaintUI();
}
}
/**
@ -206,6 +218,32 @@ private ResourcePack getDefaultResourcePack(String className,
return null;
}
/**
* Returns the <tt>UIService</tt> obtained from the bundle context.
*
* @return the <tt>UIService</tt> obtained from the bundle context
*/
private UIService getUIService()
{
if (uiService == null)
{
ServiceReference uiReference =
ResourceManagementActivator
.bundleContext.getServiceReference(UIService.class.getName());
if (uiReference == null)
{
return null;
}
uiService =
(UIService) ResourceManagementActivator
.bundleContext.getService(uiReference);
}
return uiService;
}
/**
* Returns the <tt>Map</tt> of (key, value) pairs contained in the given
* resource pack.
@ -224,6 +262,8 @@ private Map<String, String> getResources(ResourcePack resourcePack)
* Handles all <tt>ServiceEvent</tt>s corresponding to <tt>ResourcePack</tt>
* being registered or unregistered.
*
* Also handles <tt>UIService</tt> reference.
*
* @param event the <tt>ServiceEvent</tt> that notified us
*/
public void serviceChanged(ServiceEvent event)
@ -231,6 +271,21 @@ public void serviceChanged(ServiceEvent event)
Object sService = ResourceManagementActivator.bundleContext.getService(
event.getServiceReference());
if (sService instanceof UIService && uiService == null
&& event.getType() == ServiceEvent.REGISTERED)
{
uiService = (UIService) sService;
uiService.repaintUI();
}
else if (sService instanceof UIService
&& event.getType() == ServiceEvent.UNREGISTERING)
{
if (uiService != null && uiService.equals(sService))
{
uiService = null;
}
}
if (!(sService instanceof ResourcePack))
{
return;
@ -288,6 +343,12 @@ else if(resourcePack instanceof SkinPack && skinPack == null)
skinResources = resources;
imageResources.putAll(skinPack.getImageResources());
colorResources.putAll(skinPack.getColorResources());
UIService serv = getUIService();
if (serv != null)
{
serv.repaintUI();
}
}
}
else if (event.getType() == ServiceEvent.UNREGISTERING)
@ -363,6 +424,12 @@ else if(resourcePack instanceof SkinPack
imageResources.putAll(skinPack.getImageResources());
colorResources.putAll(skinPack.getColorResources());
}
UIService serv = getUIService();
if (serv != null)
{
serv.repaintUI();
}
}
}
}
@ -817,6 +884,6 @@ public ImageIcon getImage(String imageID)
public File prepareSkinBundleFromZip(File zipFile)
throws Exception
{
return SkinJarBuilder.createBundleFromZip(zipFile);
return SkinJarBuilder.createBundleFromZip(zipFile, imagePack);
}
}

@ -9,5 +9,6 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.configuration.event,
net.java.sip.communicator.util,
net.java.sip.communicator.service.gui,
javax.imageio,
javax.swing

@ -10,6 +10,8 @@
import java.util.*;
import java.util.zip.*;
import net.java.sip.communicator.service.resources.*;
/**
* Class for building of skin bundles from zip files.
* @author Adam Netocny
@ -18,12 +20,13 @@ public class SkinJarBuilder
{
/**
* Creates bundle from zip file.
*
* @param srv <tt>ResourcePack</tt> containing class files and manifest
* for the SkinResourcePack.
* @param zip Zip file with skin contents.
* @return Jar <tt>File</tt>.
* @throws Exception When something goes wrong.
*/
public static File createBundleFromZip(File zip)
public static File createBundleFromZip(File zip, ResourcePack srv)
throws Exception
{
File tmpDir = unzipIntoTmp(zip);
@ -40,36 +43,68 @@ public static File createBundleFromZip(File zip)
throw new Exception(
"Zip file doesn't contain all necessary files and folders.");
}
File jar = cpTmp();
insertIntoZip(jar, tmpDir2);
cpTmp(tmpDir2, srv);
File jar = insertIntoZip(tmpDir2);
deleteDir(tmpDir);
return jar;
}
/**
* Creates a copy of skinresources.jar in temp folder.
*
* @return the location of the temp file.
* @param unzippedBase Base dir where files should appear.
* @param srv <tt>ResourcePack</tt> containing class files and manifest
* for the SkinResourcePack.
* @throws IOException Is thrown if the jar cannot be located or if a file
* operation goes wrong.
*/
private static File cpTmp()
private static void cpTmp(File unzippedBase, ResourcePack srv)
throws IOException
{
File jar = new File(System.getProperty("user.dir"),
"sc-bundles/skinresources.jar");
InputStream in = srv.getClass().getClassLoader()
.getResourceAsStream(
"resources/skinresourcepack/SkinResourcePack.class");
File dest = new File(unzippedBase, "net" + File.separatorChar + "java"
+ File.separatorChar + "sip" + File.separatorChar
+ "communicator" + File.separatorChar + "plugin"
+ File.separatorChar + "skinresourcepack");
if (!jar.exists())
if(!dest.mkdirs())
{
throw new IOException("Cannot find skinresources.jar file");
throw new IOException("Unable to build resource pack.");
}
File tmp = File.createTempFile("skinresources", ".jar");
OutputStream out = new FileOutputStream(
new File(dest, "SkinResourcePack.class"));
copy(in, out);
in = srv.getClass().getClassLoader()
.getResourceAsStream(
"resources/skinresourcepack/skinresourcepack.manifest.mf");
dest = new File(unzippedBase, "META-INF");
if(!dest.mkdirs()) {
throw new IOException("Unable to build resource pack.");
}
InputStream in = new FileInputStream(jar);
out = new FileOutputStream(new File(dest, "MANIFEST.MF"));
OutputStream out = new FileOutputStream(tmp);
copy(in, out);
}
/**
* Simple file copy operation.
* @param in <tt>InputStream</tt> for the source.
* @param out <tt>OutputStream</tt> for the destination file.
* @throws IOException Is thrown if the jar cannot be located or if a file
* operation goes wrong.
*/
private static void copy(InputStream in, OutputStream out) throws IOException
{
byte[] buf = new byte[1024];
int len;
@ -80,8 +115,6 @@ private static File cpTmp()
in.close();
out.close();
return tmp;
}
/**
@ -142,47 +175,22 @@ private static File unzipIntoTmp(File zip)
/**
* Inserts files into ZIP file.
*
* @param jar Destination ZIP file to store the data.
* @param tmpDir Folder which contains the data.
* @return <tt>File</tt> containing reference of the jar file.
* @throws IOException Is thrown if a file operation goes wrong.
*/
private static void insertIntoZip(File jar, File tmpDir)
private static File insertIntoZip(File tmpDir)
throws IOException
{
File tempFile = File.createTempFile(jar.getName(), null);
tempFile.delete();
File jar = File.createTempFile("skinresourcepack", ".jar");
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();
return jar;
}
/**
@ -348,10 +356,6 @@ else if (f.getName().equals("styles"))
}
}
}
else
{
return false;
}
}
return styles || (colors || images);
}

@ -194,36 +194,7 @@ public void setShowSystemBundles(boolean showSystemBundles)
*/
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);
}
}
else
{
show.add(b);
}
}
}
this.bundles = new Bundle[show.size()];
int i = 0;
for(Bundle b : show)
{
this.bundles[i] = b;
i++;
}
this.bundles = this.bundleContext.getBundles();
Arrays.sort(this.bundles, bundleComparator);
}
}

@ -150,7 +150,7 @@ private void refreshSortedBundlesList()
{
if (headers.get(Constants.BUNDLE_ACTIVATOR).toString()
.equals("net.java.sip.communicator.plugin." +
"skinresourcepack.SkinResourcesPack"))
"skinresourcepack.SkinResourcePack"))
{
show.add(b);
}

@ -18,13 +18,13 @@
* The skin resource pack.
* @author Adam Netocny
*/
public class SkinResourcesPack
public class SkinResourcePack
implements BundleActivator, SkinPack
{
/**
* The object used for logging.
*/
private static Logger logger = Logger.getLogger(SkinResourcesPack.class);
private static Logger logger = Logger.getLogger(SkinResourcePack.class);
/**
* The default resource path.

@ -45,6 +45,7 @@
*
* @author Yana Stamcheva
* @author Dmitri Melnikov
* @author Adam Netocny
*/
public interface UIService
{
@ -423,4 +424,10 @@ public SecurityAuthority getDefaultSecurityAuthority(
* @return the master password obtained from the user
*/
public String getMasterPassword(boolean prevSuccess);
/**
* Repaints and revalidates the whole UI. This method is meant to be used
* to runtime apply a skin and refresh automatically the user interface.
*/
public void repaintUI();
}

@ -19,9 +19,15 @@
*
* @author Yana Stamcheva
* @author Lubomir Marinov
* @author Adam Netocny
*/
public class GuiUtils
{
/**
* List of all windows owned by the app.
*/
private static final ArrayList<Window> WINDOW_LIST = new ArrayList<Window>();
private static Calendar c1 = Calendar.getInstance();
private static Calendar c2 = Calendar.getInstance();
@ -395,4 +401,100 @@ public static String formatSeconds(long millis)
return buf.toString().trim();
}
/**
* Returns an array of all {@code Window}s, both owned and ownerless,
* created by this application.
* If called from an applet, the array includes only the {@code Window}s
* accessible by that applet.
* <p>
* <b>Warning:</b> this method may return system created windows, such
* as a print dialog. Applications should not assume the existence of
* these dialogs, nor should an application assume anything about these
* dialogs such as component positions, <code>LayoutManager</code>s
* or serialization.
*
* @return Returns an array of all {@code Window}s.
*/
public static Window[] getWindows()
{
Window[] retVal = new Window[WINDOW_LIST.size()];
int c = 0;
for(Window w : WINDOW_LIST)
{
retVal[c++] = w;
}
return retVal;
}
/**
* Adds a {@link Window} into window list
* @param w {@link Window} to be added.
*/
public static void addWindow(Window w)
{
WINDOW_LIST.add(w);
}
/**
* Removes a {@link Window} into window list
* @param w {@link Window} to be removed.
*/
public static void removeWindow(Window w)
{
WINDOW_LIST.remove(w);
}
/**
* A simple minded look and feel change: ask each node in the tree
* to <code>updateUI()</code> -- that is, to initialize its UI property
* with the current look and feel.
*
* @param c UI component.
*/
public static void updateComponentTreeUI(Component c)
{
updateComponentTreeUI0(c);
c.invalidate();
c.validate();
c.repaint();
}
/**
* Repaints UI tree recursively.
* @param c UI component.
*/
private static void updateComponentTreeUI0(Component c)
{
if (c instanceof JComponent)
{
JComponent jc = (JComponent) c;
jc.invalidate();
jc.validate();
jc.repaint();
JPopupMenu jpm =jc.getComponentPopupMenu();
if(jpm != null && jpm.isVisible() && jpm.getInvoker() == jc)
{
updateComponentTreeUI(jpm);
}
}
Component[] children = null;
if (c instanceof JMenu)
{
children = ((JMenu)c).getMenuComponents();
}
else if (c instanceof java.awt.Container)
{
children = ((java.awt.Container)c).getComponents();
}
if (children != null)
{
for(int i = 0; i < children.length; i++)
{
updateComponentTreeUI0(children[i]);
}
}
}
}

@ -131,6 +131,8 @@ private void init()
this.addWindowListener(new DialogWindowAdapter());
this.initInputMap();
GuiUtils.addWindow(this);
}
private void initInputMap()

@ -97,6 +97,8 @@ public SIPCommFrame()
KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK),
"close");
}
GuiUtils.addWindow(this);
}
/**

Loading…
Cancel
Save