Fixes the issue with OTR padlock icon not being transparent when displaying .gifs for animation. Instead of .gif, a series of .png images will be displayed in a predetermined sequence.

cusax-fix 4945
Marin 12 years ago
parent 93f526c1b2
commit fc55fff305

@ -558,6 +558,9 @@ plugin.otr.LOADING_ICON_22x22=resources/images/plugin/otr/padlockLoading.gif
plugin.otr.BROKEN_ICON_22x22=resources/images/plugin/otr/padlockBrokenOpen.png
plugin.otr.HELP_ICON_15x15=resources/images/plugin/otr/help15x15.png
plugin.otr.MENU_ITEM_ICON_16x16=resources/images/plugin/otr/otr_menu_icon.png
plugin.otr.LOADING_ICON1_22x22=resources/images/plugin/otr/padlock1.png
plugin.otr.LOADING_ICON2_22x22=resources/images/plugin/otr/padlock2.png
plugin.otr.LOADING_ICON3_22x22=resources/images/plugin/otr/padlock3.png
#Global proxy config form
plugin.globalproxy.PLUGIN_ICON=resources/images/plugin/globalproxyconfig/configureIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

@ -0,0 +1,443 @@
/*
* Jitsi, 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.desktoputil;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.Timer;
/**
* AnimatedImage will display a series of Images in a predetermined sequence.
* This sequence can be configured to keep repeating or stop after a specified
* number of cycles.
*
* An AnimatedImage cannot be shared by different components. However,
* the Images added to the AnimatedImage can be shared.
*
* The animation sequence is a simple sequential display of each Image. When the
* end is reached the animation restarts at the first Image. Images are
* displayed in the order in which they were added. To create custom animation
* sequences you will need to override the getNextIconIndex() and
* isCycleCompleted() methods.
*
* @author Marin Dzhigarov
*/
public class AnimatedImage
extends BufferedImage
implements ActionListener
{
/**
* The default delay between switching over the next image.
*/
private final static int DEFAULT_DELAY = 500;
/**
* The default number of cycles for the animation.
* -1 means that the animation will go on forever.
*/
private final static int DEFAULT_CYCLES = -1;
/**
* The list of actual images that are going to be displayed
*/
private List<Image> images = new ArrayList<Image>();
/**
* The JComponent that will display the Image
*/
private JComponent component;
/**
* The number of cycles for the animation.
* -1 means that the animation will go on forever.
*/
private int cycles;
private boolean showFirstImage = false;
private int imageWidth;
private int imageHeight;
/**
* The index of the currently displayed Image
*/
private int currentImageIndex;
/**
* The current number of completed cycles. The animation will go on while
* cyclesCompleted < cycles.
*/
private int cyclesCompleted;
private boolean animationFinished = true;
/**
* The Timer that handles switching between Images.
*/
private Timer timer;
/**
* The Graphics2D object used for painting.
*/
private final Graphics2D g2d;
/**
* Create an AnimatedImage that will continuously cycle with the
* default (500ms).
*
* @param component the component the image will be painted on
* @param images the Images to be painted as part of the animation
*/
public AnimatedImage(JComponent component, Image... images)
{
this(component, DEFAULT_DELAY, images);
}
/**
* Create an AnimatedImage that will continuously cycle with the specified
* delay
*
* @param component the component the image will be painted on
* @param delay the delay between painting each image, in milli seconds
* @param images the Images to be painted as part of the animation
*/
public AnimatedImage(JComponent component, int delay, Image... images)
{
this(component, delay, DEFAULT_CYCLES, images);
}
/**
* Create an AnimatedImage specifying the required delay between painting
* each image and the number of times to repeat the animation sequence
*
* @param component the component the image will be painted on
* @param delay the delay between painting each image, in milli seconds
* @param cycles the number of times to repeat the animation sequence
* @param images the Images to be painted as part of the animation
*/
public AnimatedImage(
JComponent component, int delay, int cycles, Image... images)
{
super( images[0].getWidth(null),
images[0].getHeight(null),
BufferedImage.TYPE_INT_ARGB);
this.component = component;
g2d = (Graphics2D) getGraphics();
setCycles( cycles );
for (int i = 0; i < images.length; i++)
{
if (images[i] == null)
{
throw new IllegalArgumentException("Images can not be null");
}
else
{
addImage(images[i]);
}
}
timer = new Timer(delay, this);
}
/**
* Add Image to be used in the animation.
*
* @param image the image to be added
*/
public void addImage(Image image)
{
if (image != null)
{
this.images.add(image);
calculateImageDimensions();
}
}
/**
* Calculate the width and height of the Image based on the maximum
* width and height of any individual Image.
*/
private void calculateImageDimensions()
{
imageWidth = 0;
imageHeight = 0;
for (Image image : images)
{
imageWidth = Math.max(imageWidth, image.getWidth(null));
imageHeight = Math.max(imageHeight, image.getHeight(null));
}
}
/**
* Get the index of the currently visible Image
*
* @return the index of the Icon
*/
public int getCurrentImageIndex()
{
return currentImageIndex;
}
/**
* Set the index of the Image to be displayed and then repaint the Image.
*
* @param index the index of the Image to be displayed
*/
public void setCurrentImageIndex(int index)
{
currentImageIndex = index;
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC);
g2d.setComposite(ac);
g2d.drawImage(getImage(currentImageIndex), 0, 0, component);
component.repaint();
}
/**
* Get the remaining cycles to complete before the animation stops.
*
* @return the number of remaining cycles
*/
public int getRemainingCycles()
{
return cycles;
}
/**
* Specify the number of times to repeat each animation sequence, or cycle.
*
* @param cycles the number of cycles to complete before the animation
* stops. The default is -1, which means the animation is
* continuous.
*/
public void setCycles(int cycles)
{
this.cycles = cycles;
}
/**
* Returns the delay between painting each Image
*
* @return the delay
*/
public int getDelay()
{
return timer.getDelay();
}
/**
* Specify the delay between painting each Image
*
* @param delay the delay between painting each Image (in milli seconds)
*/
public void setDelay(int delay)
{
timer.setDelay(delay);
}
/**
* Returns the Image at the specified index.
*
* @param index the index of the Image to be returned
* @return the Image at the specifed index
* @exception IndexOutOfBoundsException if the index is out of range
*/
public Image getImage(int index)
{
return images.get( index );
}
/**
* Returns the number of Images that are contained in the animation
*
* @return the total number of Images
*/
public int getImagesCount()
{
return images.size();
}
/**
* Get the showFirstImage
*
* @return the showFirstImage value
*/
public boolean isShowFirstImage()
{
return showFirstImage;
}
/**
* Displays the first image of the animation after the last cycle has passed
* If set to false, the last image will remain set after the last
* animation cycle.
*
* @param showFirstImage true when the first image is to be displayed,
* false otherwise
*/
public void setShowFirstImage(boolean showFirstImage)
{
this.showFirstImage = showFirstImage;
}
/**
* Pauses the animation. The animation can be restarted from the
* current Image using the restart() method.
*/
public void pause()
{
timer.stop();
}
/**
* Start the animation from the beginning.
*/
public void start()
{
if (!timer.isRunning())
{
setCurrentImageIndex(0);
animationFinished = false;
cyclesCompleted = 0;
timer.start();
}
}
/**
* Restarts the animation from where the animation was paused. Or, if the
* animation has finished, it will be restarted from the beginning.
*/
public void restart()
{
if (!timer.isRunning())
{
if (animationFinished)
start();
else
timer.restart();
}
}
/**
* Stops the animation. The first icon will be redisplayed.
*/
public void stop()
{
timer.stop();
setCurrentImageIndex(0);
animationFinished = true;
}
/**
* Gets the width of this image.
*
* @return the width of the image in pixels.
*/
public int getWidth(ImageObserver obs)
{
return imageWidth;
}
/**
* Gets the height of this image.
*
* @return the height of the image in pixels.
*/
public int getHeight(ImageObserver obs)
{
return imageHeight;
}
/**
* Controls the image animation that is scheduled by the Timer
*/
public void actionPerformed(ActionEvent e)
{
// Display the next Image in the animation sequence
setCurrentImageIndex(
getNextImageIndex(currentImageIndex, images.size()));
// Track the number of cycles that have been completed
if (isCycleCompleted(currentImageIndex, images.size()))
{
cyclesCompleted++;
}
// Stop the animation when the specified number of cycles is completed
if (cycles > 0
&& cycles <= cyclesCompleted)
{
timer.stop();
animationFinished = true;
// Display the first Image when required
if (isShowFirstImage()
&& getCurrentImageIndex() != 0)
{
new Thread(new Runnable() {
@Override
public void run()
{
// Wait one more delay interval before displaying the
// first Image
try
{
Thread.sleep( timer.getDelay() );
setCurrentImageIndex(0);
}
catch(InterruptedException e) {}
}
}).start();
}
}
}
/**
* Gets the index of the next Image to be displayed. Normally, images will
* be displayed in the order they were added to the AnimatedImage.
* If however, a custom animation sequence is required one can extend this
* method and achieve a greater control over the animation sequence.
*
* @param currentIndex the index of the Image currently displayed
* @param imageCount the number of Images to be displayed
* @return the index of the next Image to be displayed
*/
protected int getNextImageIndex(int currentIndex, int imageCount)
{
return ++currentIndex % imageCount;
}
/**
* Checks if the currently displayed Image is the last image of the
* animation sequence. This marks the completion of a single animation
* cycle.
* If a custom animation sequence is required one can extend this
* method to achieve a greater control over the animation sequence.
*
* @param currentIndex the index of the Image currently displayed
* @param imageCount the number of Images to be displayed
* @return the index of the next Image to be displayed
*/
protected boolean isCycleCompleted(int currentIndex, int imageCount)
{
return currentIndex == imageCount - 1;
}
}

@ -8,6 +8,9 @@
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.imageio.*;
import net.java.otr4j.*;
import net.java.otr4j.session.*;
@ -38,6 +41,18 @@ public class OtrMetaContactButton
private Contact contact;
private AnimatedImage animatedPadlockImage;
private Image finishedPadlockImage;
private Image verifiedLockedPadlockImage;
private Image unverifiedLockedPadlockImage;
private Image unlockedPadlockImage;
private Image timedoutPadlockImage;
/**
* The timer task that changes the padlock icon to "loading" and
* then to "broken" if the specified timeout passed
@ -69,6 +84,7 @@ public void globalPolicyChanged()
setPolicy(
OtrActivator.scOtrEngine.getContactPolicy(contact));
}
public void contactVerificationStatusChanged(Contact contact)
{
// OtrMetaContactButton.this.contact can be null.
@ -118,6 +134,40 @@ private SIPCommButton getButton()
button.setToolTipText(OtrActivator.resourceService.getI18NString(
"plugin.otr.menu.OTR_TOOLTIP"));
Image i1 = null, i2 = null, i3 = null;
try
{
i1 = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.LOADING_ICON1_22x22"));
i2 = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.LOADING_ICON2_22x22"));
i3 = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.LOADING_ICON3_22x22"));
finishedPadlockImage = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.FINISHED_ICON_22x22"));
verifiedLockedPadlockImage = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.ENCRYPTED_ICON_22x22"));
unverifiedLockedPadlockImage = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.ENCRYPTED_UNVERIFIED_ICON_22x22"));
unlockedPadlockImage = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.PLAINTEXT_ICON_22x22"));
timedoutPadlockImage = ImageIO.read(
OtrActivator.resourceService.getImageURL(
"plugin.otr.BROKEN_ICON_22x22"));
} catch (IOException e)
{
logger.debug("Failed to load padlock image");
}
animatedPadlockImage = new AnimatedImage(button, i1, i2, i3);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
@ -216,34 +266,36 @@ private void setPolicy(OtrPolicy contactPolicy)
*/
private void setStatus(ScSessionStatus status)
{
String urlKey;
animatedPadlockImage.pause();
Image image;
String tipKey;
switch (status)
{
case ENCRYPTED:
urlKey
image
= OtrActivator.scOtrKeyManager.isVerified(contact)
? "plugin.otr.ENCRYPTED_ICON_22x22"
: "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_22x22";
? verifiedLockedPadlockImage
: unverifiedLockedPadlockImage;
tipKey =
OtrActivator.scOtrKeyManager.isVerified(contact)
? "plugin.otr.menu.VERIFIED"
: "plugin.otr.menu.UNVERIFIED";
break;
case FINISHED:
urlKey = "plugin.otr.FINISHED_ICON_22x22";
image = finishedPadlockImage;
tipKey = "plugin.otr.menu.FINISHED";
break;
case PLAINTEXT:
urlKey = "plugin.otr.PLAINTEXT_ICON_22x22";
image = unlockedPadlockImage;
tipKey = "plugin.otr.menu.START_OTR";
break;
case LOADING:
urlKey = "plugin.otr.LOADING_ICON_22x22";
image = animatedPadlockImage;
animatedPadlockImage.start();
tipKey = "plugin.otr.menu.LOADING_OTR";
break;
case TIMED_OUT:
urlKey = "plugin.otr.BROKEN_ICON_22x22";
image = timedoutPadlockImage;
tipKey = "plugin.otr.menu.TIMED_OUT";
break;
default:
@ -251,9 +303,7 @@ private void setStatus(ScSessionStatus status)
}
SIPCommButton button = getButton();
button.setIconImage(
Toolkit.getDefaultToolkit().getImage(
OtrActivator.resourceService.getImageURL(urlKey)));
button.setIconImage(image);
button.setToolTipText(OtrActivator.resourceService
.getI18NString(tipKey));
button.repaint();

Loading…
Cancel
Save