[sip-comm-dev] Re: svn commit: r5981 - trunk/src/net/java/sip/communicator/plugin/otr


#1

This breaks the OTR menu in ChatWindow on Mac OS X by leaving it with
no menu items in it. I guess the problem is that PopupMenuListener
doesn't behave as expected for the Apple screen menu bar because it
works fine on Ubuntu. I'll look into it.

···

On Thu, Sep 17, 2009 at 2:38 AM, <lubomir_m@dev.java.net> wrote:

Author: lubomir_m
Date: 2009-09-16 23:38:49+0000
New Revision: 5981

Modified:
trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java
trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java

Log:
Fixes a relatively serious memory leak and a somewhat unnecessary performance penalty in the OTR menu which causes it to create OtrContactMenu instances whenever the current MetaContact selection changes and all these instances are retained globally though they are never to be shown.

Modified: trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java?view=diff&rev=5981&p1=trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java&p2=trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java&r1=5980&r2=5981

--- trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java (original)
+++ trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java 2009-09-16 23:38:49+0000
@@ -9,77 +9,208 @@
import java.awt.event.*;

import javax.swing.*;
+import javax.swing.event.*;

import net.java.otr4j.*;
import net.java.otr4j.session.*;
import net.java.sip.communicator.service.protocol.*;

/**
- *
* @author George Politis
- *
+ * @author Lubomir Marinov
*/
@SuppressWarnings("serial")
class OtrContactMenu
extends JMenu
+ implements ActionListener,
+ PopupMenuListener,
+ ScOtrEngineListener,
+ ScOtrKeyManagerListener
{
+ private static final String ACTION_COMMAND_AUTHENTICATE_BUDDY
+ = "AUTHENTICATE_BUDDY";
+
+ private static final String ACTION_COMMAND_CB_AUTO = "CB_AUTO";
+
+ private static final String ACTION_COMMAND_CB_ENABLE = "CB_ENABLE";
+
+ private static final String ACTION_COMMAND_CB_REQUIRE = "CB_REQUIRE";
+
+ private static final String ACTION_COMMAND_CB_RESET = "CB_RESET";
+
+ private static final String ACTION_COMMAND_END_OTR = "END_OTR";
+
+ private static final String ACTION_COMMAND_REFRESH_OTR = "REFRESH_OTR";
+
+ private static final String ACTION_COMMAND_START_OTR = "START_OTR";
+
+ private final Contact contact;
+
+ private OtrPolicy otrPolicy;
+
+ private SessionStatus sessionStatus;
+
public OtrContactMenu(Contact contact)
{
this.contact = contact;
+
this.setText(contact.getDisplayName());
-
- OtrActivator.scOtrEngine.addListener(new ScOtrEngineListener()
- {
- public void sessionStatusChanged(Contact contact)
- {
- SessionStatus status =
- OtrActivator.scOtrEngine.getSessionStatus(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setSessionStatus(status);
- }
-
- public void contactPolicyChanged(Contact contact)
- {
- // Update the corresponding to the contact menu.
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setOtrPolicy(policy);
- }
-
- public void globalPolicyChanged()
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine
- .getContactPolicy(OtrContactMenu.this.contact);
-
- setOtrPolicy(policy);
- }
- });

- OtrActivator.scOtrKeyManager.addListener(new ScOtrKeyManagerListener()
- {
- public void contactVerificationStatusChanged(Contact contact)
- {
- SessionStatus status =
- OtrActivator.scOtrEngine.getSessionStatus(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setSessionStatus(status);
- }
- });
+ /*
+ * Setup populating this JMenu on demand because it's not always
+ * necessary.
+ */
+ getPopupMenu().addPopupMenuListener(this);
+
+ OtrActivator.scOtrEngine.addListener(this);
+ OtrActivator.scOtrKeyManager.addListener(this);

    setSessionStatus\(OtrActivator\.scOtrEngine\.getSessionStatus\(contact\)\);
    setOtrPolicy\(OtrActivator\.scOtrEngine\.getContactPolicy\(contact\)\);
\}

- private SessionStatus sessionStatus;
+ /*
+ * Implements ActionListener#actionPerformed(ActionEvent).
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ String actionCommand = e.getActionCommand();

- private OtrPolicy otrPolicy;
+ if (ACTION_COMMAND_END_OTR.equals(actionCommand))
+ // End session.
+ OtrActivator.scOtrEngine.endSession(contact);
+
+ else if (ACTION_COMMAND_START_OTR.equals(actionCommand))
+ // Start session.
+ OtrActivator.scOtrEngine.startSession(contact);
+
+ else if (ACTION_COMMAND_REFRESH_OTR.equals(actionCommand))
+ // Refresh session.
+ OtrActivator.scOtrEngine.refreshSession(contact);
+
+ else if (ACTION_COMMAND_AUTHENTICATE_BUDDY.equals(actionCommand))
+ {
+ // Launch auth buddy dialog.
+ OtrBuddyAuthenticationDialog authenticateBuddyDialog
+ = new OtrBuddyAuthenticationDialog(contact);
+ Dimension screenSize
+ = Toolkit.getDefaultToolkit().getScreenSize();
+
+ authenticateBuddyDialog.setLocation(
+ screenSize.width / 2
+ - authenticateBuddyDialog.getWidth() / 2,
+ screenSize.height / 2
+ - authenticateBuddyDialog.getHeight() / 2);
+ authenticateBuddyDialog.setVisible(true);
+ }
+
+ else if (ACTION_COMMAND_CB_ENABLE.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
+
+ policy.setEnableManual(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+
+ else if (ACTION_COMMAND_CB_AUTO.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();

- public void rebuildMenu()
+ policy.setEnableAlways(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+
+ else if (ACTION_COMMAND_CB_REQUIRE.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
+
+ policy.setEnableAlways(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+ else if (ACTION_COMMAND_CB_RESET.equals(actionCommand))
+ OtrActivator.scOtrEngine.setContactPolicy(contact, null);
+ }
+
+ /*
+ * Implements ScOtrEngineListener#contactPolicyChanged(Contact).
+ */
+ public void contactPolicyChanged(Contact contact)
+ {
+ // Update the corresponding to the contact menu.
+ if (contact.equals(OtrContactMenu.this.contact))
+ setOtrPolicy(
+ OtrActivator.scOtrEngine.getContactPolicy(contact));
+ }
+
+ /*
+ * Implements ScOtrKeyManagerListener#contactVerificationStatusChanged(
+ * Contact).
+ */
+ public void contactVerificationStatusChanged(Contact contact)
+ {
+ if (contact.equals(OtrContactMenu.this.contact))
+ setSessionStatus(
+ OtrActivator.scOtrEngine.getSessionStatus(contact));
+ }
+
+ /**
+ * Disposes of this instance by making it available for garage collection
+ * e.g. removes the listeners it has installed on global instances such as
+ * <tt>OtrActivator#scOtrEngine</tt> and
+ * <tt>OtrActivator#scOtrKeyManager</tt>.
+ */
+ void dispose()
+ {
+ OtrActivator.scOtrEngine.removeListener(this);
+ OtrActivator.scOtrKeyManager.removeListener(this);
+ }
+
+ private SessionStatus getSessionStatus()
+ {
+ return sessionStatus;
+ }
+
+ /*
+ * Implements ScOtrEngineListener#globalPolicyChanged().
+ */
+ public void globalPolicyChanged()
+ {
+ setOtrPolicy(
+ OtrActivator.scOtrEngine
+ .getContactPolicy(OtrContactMenu.this.contact));
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuCanceled(PopupMenuEvent).
+ */
+ public void popupMenuCanceled(PopupMenuEvent e)
+ {
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeInvisible(
+ * PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
+ {
+ popupMenuCanceled(e);
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeVisible(PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e)
+ {
+ rebuildMenu();
+ }
+
+ private void rebuildMenu()
{
this.removeAll();

@@ -88,198 +219,142 @@
JMenuItem endOtr = new JMenuItem();
endOtr.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.END_OTR"));
- endOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // End session.
- OtrActivator.scOtrEngine.endSession(contact);
- }
- });
+ endOtr.setActionCommand(ACTION_COMMAND_END_OTR);
+ endOtr.addActionListener(this);

    JMenuItem startOtr = new JMenuItem\(\);
    startOtr\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.START\_OTR&quot;\)\);

- startOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Start session.
- OtrActivator.scOtrEngine.startSession(contact);
- }
- });
startOtr.setEnabled(policy.getEnableManual());
+ startOtr.setActionCommand(ACTION_COMMAND_START_OTR);
+ startOtr.addActionListener(this);

- switch (this.getSessionStatus())
+ switch (getSessionStatus())
{
case ENCRYPTED:
- this
- .setIcon(OtrActivator.resourceService
- .getImage((OtrActivator.scOtrKeyManager
- .isVerified(contact))
- ? "plugin.otr.ENCRYPTED_ICON_16x16"
- : "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_16x16"));
-
- this.add(endOtr);
-
JMenuItem refreshOtr = new JMenuItem();
refreshOtr.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.REFRESH_OTR"));
- refreshOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Refresh session.
- OtrActivator.scOtrEngine.refreshSession(contact);
- }
- });
refreshOtr.setEnabled(policy.getEnableManual());
- this.add(refreshOtr);
+ refreshOtr.setActionCommand(ACTION_COMMAND_REFRESH_OTR);
+ refreshOtr.addActionListener(this);

        JMenuItem authBuddy = new JMenuItem\(\);
        authBuddy\.setText\(OtrActivator\.resourceService
            \.getI18NString\(&quot;plugin\.otr\.menu\.AUTHENTICATE\_BUDDY&quot;\)\);

- authBuddy.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Launch auth buddy dialog.
- OtrBuddyAuthenticationDialog authenticateBuddyDialog =
- new OtrBuddyAuthenticationDialog(contact);
-
- authenticateBuddyDialog.setLocation(Toolkit
- .getDefaultToolkit().getScreenSize().width
- / 2 - authenticateBuddyDialog.getWidth() / 2, Toolkit
- .getDefaultToolkit().getScreenSize().height
- / 2 - authenticateBuddyDialog.getHeight() / 2);
-
- authenticateBuddyDialog.setVisible(true);
- }
- });
+ authBuddy.setActionCommand(ACTION_COMMAND_AUTHENTICATE_BUDDY);
+ authBuddy.addActionListener(this);
+
+ this.add(endOtr);
+ this.add(refreshOtr);
this.add(authBuddy);
break;
- case FINISHED:
- this.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.FINISHED_ICON_16x16"));

+ case FINISHED:
this.add(endOtr);
this.add(startOtr);
break;
- case PLAINTEXT:
- this.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.PLAINTEXT_ICON_16x16"));

+ case PLAINTEXT:
this.add(startOtr);
break;
}

- this.addSeparator();
-
JCheckBoxMenuItem cbEnable = new JCheckBoxMenuItem();
cbEnable.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.CB_ENABLE"));
-
cbEnable.setState(policy.getEnableManual());
-
- cbEnable.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableManual(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbEnable);
+ cbEnable.setActionCommand(ACTION_COMMAND_CB_ENABLE);
+ cbEnable.addActionListener(this);

    JCheckBoxMenuItem cbAlways = new JCheckBoxMenuItem\(\);
    cbAlways\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_AUTO&quot;\)\);

-
cbAlways.setEnabled(policy.getEnableManual());
cbAlways.setState(policy.getEnableAlways());
-
- cbAlways.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableAlways(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbAlways);
+ cbAlways.setActionCommand(ACTION_COMMAND_CB_AUTO);
+ cbAlways.addActionListener(this);

    JCheckBoxMenuItem cbRequire = new JCheckBoxMenuItem\(\);
    cbRequire\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_REQUIRE&quot;\)\);

-
cbRequire.setEnabled(policy.getEnableManual());
cbRequire.setState(policy.getRequireEncryption());
-
- cbRequire.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableAlways(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbRequire);
-
- this.addSeparator();
+ cbRequire.setActionCommand(ACTION_COMMAND_CB_REQUIRE);
+ cbRequire.addActionListener(this);

    JMenuItem cbReset = new JMenuItem\(\);
    cbReset\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_RESET&quot;\)\);

+ cbReset.setActionCommand(ACTION_COMMAND_CB_RESET);
+ cbReset.addActionListener(this);

- cbReset.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrActivator.scOtrEngine.setContactPolicy(contact, null);
- }
- });
+ this.addSeparator();
+ this.add(cbEnable);
+ this.add(cbAlways);
+ this.add(cbRequire);
+ this.addSeparator();
this.add(cbReset);
}

- public void setSessionStatus(SessionStatus sessionStatus)
+ /*
+ * Implements ScOtrEngineListener#sessionStatusChanged(Contact).
+ */
+ public void sessionStatusChanged(Contact contact)
{
- if (sessionStatus == this.sessionStatus)
- return;
-
- this.sessionStatus = sessionStatus;
- this.rebuildMenu();
+ if (contact.equals(OtrContactMenu.this.contact))
+ setSessionStatus(
+ OtrActivator.scOtrEngine.getSessionStatus(contact));
}

- public SessionStatus getSessionStatus()
+ private void setSessionStatus(SessionStatus sessionStatus)
{
- return sessionStatus;
+ if (sessionStatus != this.sessionStatus)
+ {
+ this.sessionStatus = sessionStatus;
+
+ updateIcon();
+ if (isPopupMenuVisible())
+ rebuildMenu();
+ }
}

- public void setOtrPolicy(OtrPolicy otrPolicy)
+ private void setOtrPolicy(OtrPolicy otrPolicy)
{
- if (otrPolicy.equals(this.otrPolicy))
- return;
+ if (!otrPolicy.equals(this.otrPolicy))
+ {
+ this.otrPolicy = otrPolicy;

- this.otrPolicy = otrPolicy;
- this.rebuildMenu();
+ if (isPopupMenuVisible())
+ rebuildMenu();
+ }
}

- public OtrPolicy getOtrPolicy()
+ private void updateIcon()
{
- return otrPolicy;
- }
+ String imageID;

- public Contact contact;
+ switch (getSessionStatus())
+ {
+ case ENCRYPTED:
+ imageID
+ = OtrActivator.scOtrKeyManager.isVerified(contact)
+ ? "plugin.otr.ENCRYPTED_ICON_16x16"
+ : "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_16x16";
+ break;
+
+ case FINISHED:
+ imageID = "plugin.otr.FINISHED_ICON_16x16";
+ break;
+
+ case PLAINTEXT:
+ imageID = "plugin.otr.PLAINTEXT_ICON_16x16";
+ break;
+
+ default:
+ return;
+ }
+
+ setIcon(OtrActivator.resourceService.getImage(imageID));
+ }
}

Modified: trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java?view=diff&rev=5981&p1=trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java&p2=trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java&r1=5980&r2=5981

--- trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java (original)
+++ trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java 2009-09-16 23:38:49+0000
@@ -10,6 +10,7 @@
import java.util.*;

import javax.swing.*;
+import javax.swing.event.*;

import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
@@ -18,22 +19,79 @@

/**
* @author George Politis
+ * @author Lubomir Marinov
*/
public class OtrMetaContactMenu
extends AbstractPluginComponent
+ implements ActionListener,
+ PopupMenuListener
{

/\*\*

+ * The last known <tt>MetaContact</tt> to be currently selected and to be
+ * depcited by this instance and the <tt>OtrContactMenu</tt>s it contains.
+ */
+ private MetaContact currentContact;
+
+ /**
* The <code>JMenu</code> which is the component of this plugin.
*/
private JMenu menu;

+ /**
+ * The "What's this?" <tt>JMenuItem</tt> which launches help on the subject
+ * of off-the-record messaging.
+ */
+ private JMenuItem whatsThis;
+
public OtrMetaContactMenu(Container container)
{
super(container);
}

/\*

+ * Implements ActionListener#actionPerformed(ActionEvent). Handles the
+ * invocation of the whatsThis menu item i.e. launches help on the subject
+ * of off-the-record messaging.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ OtrActivator.scOtrEngine.launchHelp();
+ }
+
+ private void createOtrContactMenus(MetaContact metaContact)
+ {
+ // Remove any existing OtrContactMenu items.
+ for (int itemIndex = 0, itemCount = menu.getItemCount();
+ itemIndex < itemCount;)
+ {
+ JMenuItem menuItem = menu.getItem(itemIndex);
+
+ if (menuItem instanceof OtrContactMenu)
+ {
+ menu.remove(itemIndex);
+ itemCount--;
+
+ ((OtrContactMenu) menuItem).dispose();
+ }
+ else
+ itemIndex++;
+ }
+
+ // Create the new OtrContactMenu items.
+ if (metaContact != null)
+ {
+ Iterator<Contact> contacts = metaContact.getContacts();
+ int itemIndex = 0;
+ while (contacts.hasNext())
+ {
+ menu.insert(new OtrContactMenu(contacts.next()), itemIndex);
+ itemIndex++;
+ }
+ }
+ }
+
+ /*
* Implements PluginComponent#getComponent(). Returns the JMenu which is
* the component of this plugin creating it first if it doesn't exist.
*/
@@ -53,6 +111,7 @@
if (menu == null)
{
menu = new JMenu();
+ menu.setText(getName());

        if \(Container\.CONTAINER\_CONTACT\_RIGHT\_BUTTON\_MENU
                \.equals\(getContainer\(\)\)\)

@@ -65,8 +124,8 @@
if (icon != null)
menu.setIcon(icon);
}
-
- menu.setText(getName());
+
+ menu.getPopupMenu().addPopupMenuListener(this);
}
return menu;
}
@@ -82,37 +141,54 @@
.getI18NString("plugin.otr.menu.TITLE");
}

- public void setCurrentContact(MetaContact metaContact)
+ /*
+ * Implements PopupMenuListener#popupMenuCanceled(PopupMenuEvent).
+ */
+ public void popupMenuCanceled(PopupMenuEvent e)
{
- // Rebuild menu.
- if (menu != null)
- menu.removeAll();
+ createOtrContactMenus(null);
+ }

- if (metaContact == null)
- return;
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeInvisible(
+ * PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
+ {
+ popupMenuCanceled(e);
+ }

- JMenu menu = getMenu();
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeVisible(PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e)
+ {
+ createOtrContactMenus(currentContact);

- Iterator<Contact> contacts = metaContact.getContacts();
- while (contacts.hasNext())
+ if (whatsThis == null)
{
- menu.add(new OtrContactMenu(contacts.next()));
- }
+ menu.addSeparator();

- menu.addSeparator();
+ whatsThis = new JMenuItem();
+ whatsThis.setIcon(
+ OtrActivator.resourceService
+ .getImage("plugin.otr.HELP_ICON_15x15"));
+ whatsThis.setText(
+ OtrActivator.resourceService
+ .getI18NString("plugin.otr.menu.WHATS_THIS"));
+ whatsThis.addActionListener(this);
+ menu.add(whatsThis);
+ }
+ }

- JMenuItem whatsThis = new JMenuItem();
- whatsThis.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.HELP_ICON_15x15"));
- whatsThis.setText(OtrActivator.resourceService
- .getI18NString("plugin.otr.menu.WHATS_THIS"));
- whatsThis.addActionListener(new ActionListener()
+ public void setCurrentContact(MetaContact metaContact)
+ {
+ if (this.currentContact != metaContact)
{
- public void actionPerformed(ActionEvent e)
- {
- OtrActivator.scOtrEngine.launchHelp();
- }
- });
- menu.add(whatsThis);
+ this.currentContact = metaContact;
+
+ if ((menu != null) && menu.isPopupMenuVisible())
+ createOtrContactMenus(currentContact);
+ }
}
}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#2

To close this thread:

- The problem was discovered and reported by Emil Ivov. I'm sorry for
not mentioning it in my previous message.

- r5987 is supposed to fix the problem and has the following comment:

Fixes a problem reported by Emil Ivov which leaves the OTR menu of
ChatWindow on Mac OS X with no menu items. The cause is that
PopupMenuListener is not invoked for the Mac OS X screen menu bar
(which is a known problem as indicated at
http://lists.apple.com/archives/Java-dev/2005/Jun/msg00041.html).
Unfortunately, this fix brings back the multiple unnecessary
allocations performed by OtrMetaContactMenu and OtrContactMenu on Mac
OS X upon changes in the currently selected MetaContact (at least, the
previous memory leak is gone). These can be remedied to some extent by
making the update procedures of these two menus act as actual updates
and not as full-blown rebuilds.

···

On Fri, Sep 18, 2009 at 12:57 PM, Lubomir Marinov <lubomir.marinov@gmail.com> wrote:

This breaks the OTR menu in ChatWindow on Mac OS X by leaving it with
no menu items in it. I guess the problem is that PopupMenuListener
doesn't behave as expected for the Apple screen menu bar because it
works fine on Ubuntu. I'll look into it.

On Thu, Sep 17, 2009 at 2:38 AM, <lubomir_m@dev.java.net> wrote:

Author: lubomir_m
Date: 2009-09-16 23:38:49+0000
New Revision: 5981

Modified:
trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java
trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java

Log:
Fixes a relatively serious memory leak and a somewhat unnecessary performance penalty in the OTR menu which causes it to create OtrContactMenu instances whenever the current MetaContact selection changes and all these instances are retained globally though they are never to be shown.

Modified: trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java?view=diff&rev=5981&p1=trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java&p2=trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java&r1=5980&r2=5981

--- trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java (original)
+++ trunk/src/net/java/sip/communicator/plugin/otr/OtrContactMenu.java 2009-09-16 23:38:49+0000
@@ -9,77 +9,208 @@
import java.awt.event.*;

import javax.swing.*;
+import javax.swing.event.*;

import net.java.otr4j.*;
import net.java.otr4j.session.*;
import net.java.sip.communicator.service.protocol.*;

/**
- *
* @author George Politis
- *
+ * @author Lubomir Marinov
*/
@SuppressWarnings("serial")
class OtrContactMenu
extends JMenu
+ implements ActionListener,
+ PopupMenuListener,
+ ScOtrEngineListener,
+ ScOtrKeyManagerListener
{
+ private static final String ACTION_COMMAND_AUTHENTICATE_BUDDY
+ = "AUTHENTICATE_BUDDY";
+
+ private static final String ACTION_COMMAND_CB_AUTO = "CB_AUTO";
+
+ private static final String ACTION_COMMAND_CB_ENABLE = "CB_ENABLE";
+
+ private static final String ACTION_COMMAND_CB_REQUIRE = "CB_REQUIRE";
+
+ private static final String ACTION_COMMAND_CB_RESET = "CB_RESET";
+
+ private static final String ACTION_COMMAND_END_OTR = "END_OTR";
+
+ private static final String ACTION_COMMAND_REFRESH_OTR = "REFRESH_OTR";
+
+ private static final String ACTION_COMMAND_START_OTR = "START_OTR";
+
+ private final Contact contact;
+
+ private OtrPolicy otrPolicy;
+
+ private SessionStatus sessionStatus;
+
public OtrContactMenu(Contact contact)
{
this.contact = contact;
+
this.setText(contact.getDisplayName());
-
- OtrActivator.scOtrEngine.addListener(new ScOtrEngineListener()
- {
- public void sessionStatusChanged(Contact contact)
- {
- SessionStatus status =
- OtrActivator.scOtrEngine.getSessionStatus(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setSessionStatus(status);
- }
-
- public void contactPolicyChanged(Contact contact)
- {
- // Update the corresponding to the contact menu.
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setOtrPolicy(policy);
- }
-
- public void globalPolicyChanged()
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine
- .getContactPolicy(OtrContactMenu.this.contact);
-
- setOtrPolicy(policy);
- }
- });

- OtrActivator.scOtrKeyManager.addListener(new ScOtrKeyManagerListener()
- {
- public void contactVerificationStatusChanged(Contact contact)
- {
- SessionStatus status =
- OtrActivator.scOtrEngine.getSessionStatus(contact);
-
- if (contact.equals(OtrContactMenu.this.contact))
- setSessionStatus(status);
- }
- });
+ /*
+ * Setup populating this JMenu on demand because it's not always
+ * necessary.
+ */
+ getPopupMenu().addPopupMenuListener(this);
+
+ OtrActivator.scOtrEngine.addListener(this);
+ OtrActivator.scOtrKeyManager.addListener(this);

    setSessionStatus\(OtrActivator\.scOtrEngine\.getSessionStatus\(contact\)\);
    setOtrPolicy\(OtrActivator\.scOtrEngine\.getContactPolicy\(contact\)\);
\}

- private SessionStatus sessionStatus;
+ /*
+ * Implements ActionListener#actionPerformed(ActionEvent).
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ String actionCommand = e.getActionCommand();

- private OtrPolicy otrPolicy;
+ if (ACTION_COMMAND_END_OTR.equals(actionCommand))
+ // End session.
+ OtrActivator.scOtrEngine.endSession(contact);
+
+ else if (ACTION_COMMAND_START_OTR.equals(actionCommand))
+ // Start session.
+ OtrActivator.scOtrEngine.startSession(contact);
+
+ else if (ACTION_COMMAND_REFRESH_OTR.equals(actionCommand))
+ // Refresh session.
+ OtrActivator.scOtrEngine.refreshSession(contact);
+
+ else if (ACTION_COMMAND_AUTHENTICATE_BUDDY.equals(actionCommand))
+ {
+ // Launch auth buddy dialog.
+ OtrBuddyAuthenticationDialog authenticateBuddyDialog
+ = new OtrBuddyAuthenticationDialog(contact);
+ Dimension screenSize
+ = Toolkit.getDefaultToolkit().getScreenSize();
+
+ authenticateBuddyDialog.setLocation(
+ screenSize.width / 2
+ - authenticateBuddyDialog.getWidth() / 2,
+ screenSize.height / 2
+ - authenticateBuddyDialog.getHeight() / 2);
+ authenticateBuddyDialog.setVisible(true);
+ }
+
+ else if (ACTION_COMMAND_CB_ENABLE.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
+
+ policy.setEnableManual(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+
+ else if (ACTION_COMMAND_CB_AUTO.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();

- public void rebuildMenu()
+ policy.setEnableAlways(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+
+ else if (ACTION_COMMAND_CB_REQUIRE.equals(actionCommand))
+ {
+ OtrPolicy policy =
+ OtrActivator.scOtrEngine.getContactPolicy(contact);
+ boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
+
+ policy.setEnableAlways(state);
+ OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
+ }
+ else if (ACTION_COMMAND_CB_RESET.equals(actionCommand))
+ OtrActivator.scOtrEngine.setContactPolicy(contact, null);
+ }
+
+ /*
+ * Implements ScOtrEngineListener#contactPolicyChanged(Contact).
+ */
+ public void contactPolicyChanged(Contact contact)
+ {
+ // Update the corresponding to the contact menu.
+ if (contact.equals(OtrContactMenu.this.contact))
+ setOtrPolicy(
+ OtrActivator.scOtrEngine.getContactPolicy(contact));
+ }
+
+ /*
+ * Implements ScOtrKeyManagerListener#contactVerificationStatusChanged(
+ * Contact).
+ */
+ public void contactVerificationStatusChanged(Contact contact)
+ {
+ if (contact.equals(OtrContactMenu.this.contact))
+ setSessionStatus(
+ OtrActivator.scOtrEngine.getSessionStatus(contact));
+ }
+
+ /**
+ * Disposes of this instance by making it available for garage collection
+ * e.g. removes the listeners it has installed on global instances such as
+ * <tt>OtrActivator#scOtrEngine</tt> and
+ * <tt>OtrActivator#scOtrKeyManager</tt>.
+ */
+ void dispose()
+ {
+ OtrActivator.scOtrEngine.removeListener(this);
+ OtrActivator.scOtrKeyManager.removeListener(this);
+ }
+
+ private SessionStatus getSessionStatus()
+ {
+ return sessionStatus;
+ }
+
+ /*
+ * Implements ScOtrEngineListener#globalPolicyChanged().
+ */
+ public void globalPolicyChanged()
+ {
+ setOtrPolicy(
+ OtrActivator.scOtrEngine
+ .getContactPolicy(OtrContactMenu.this.contact));
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuCanceled(PopupMenuEvent).
+ */
+ public void popupMenuCanceled(PopupMenuEvent e)
+ {
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeInvisible(
+ * PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
+ {
+ popupMenuCanceled(e);
+ }
+
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeVisible(PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e)
+ {
+ rebuildMenu();
+ }
+
+ private void rebuildMenu()
{
this.removeAll();

@@ -88,198 +219,142 @@
JMenuItem endOtr = new JMenuItem();
endOtr.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.END_OTR"));
- endOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // End session.
- OtrActivator.scOtrEngine.endSession(contact);
- }
- });
+ endOtr.setActionCommand(ACTION_COMMAND_END_OTR);
+ endOtr.addActionListener(this);

    JMenuItem startOtr = new JMenuItem\(\);
    startOtr\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.START\_OTR&quot;\)\);

- startOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Start session.
- OtrActivator.scOtrEngine.startSession(contact);
- }
- });
startOtr.setEnabled(policy.getEnableManual());
+ startOtr.setActionCommand(ACTION_COMMAND_START_OTR);
+ startOtr.addActionListener(this);

- switch (this.getSessionStatus())
+ switch (getSessionStatus())
{
case ENCRYPTED:
- this
- .setIcon(OtrActivator.resourceService
- .getImage((OtrActivator.scOtrKeyManager
- .isVerified(contact))
- ? "plugin.otr.ENCRYPTED_ICON_16x16"
- : "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_16x16"));
-
- this.add(endOtr);
-
JMenuItem refreshOtr = new JMenuItem();
refreshOtr.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.REFRESH_OTR"));
- refreshOtr.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Refresh session.
- OtrActivator.scOtrEngine.refreshSession(contact);
- }
- });
refreshOtr.setEnabled(policy.getEnableManual());
- this.add(refreshOtr);
+ refreshOtr.setActionCommand(ACTION_COMMAND_REFRESH_OTR);
+ refreshOtr.addActionListener(this);

        JMenuItem authBuddy = new JMenuItem\(\);
        authBuddy\.setText\(OtrActivator\.resourceService
            \.getI18NString\(&quot;plugin\.otr\.menu\.AUTHENTICATE\_BUDDY&quot;\)\);

- authBuddy.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // Launch auth buddy dialog.
- OtrBuddyAuthenticationDialog authenticateBuddyDialog =
- new OtrBuddyAuthenticationDialog(contact);
-
- authenticateBuddyDialog.setLocation(Toolkit
- .getDefaultToolkit().getScreenSize().width
- / 2 - authenticateBuddyDialog.getWidth() / 2, Toolkit
- .getDefaultToolkit().getScreenSize().height
- / 2 - authenticateBuddyDialog.getHeight() / 2);
-
- authenticateBuddyDialog.setVisible(true);
- }
- });
+ authBuddy.setActionCommand(ACTION_COMMAND_AUTHENTICATE_BUDDY);
+ authBuddy.addActionListener(this);
+
+ this.add(endOtr);
+ this.add(refreshOtr);
this.add(authBuddy);
break;
- case FINISHED:
- this.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.FINISHED_ICON_16x16"));

+ case FINISHED:
this.add(endOtr);
this.add(startOtr);
break;
- case PLAINTEXT:
- this.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.PLAINTEXT_ICON_16x16"));

+ case PLAINTEXT:
this.add(startOtr);
break;
}

- this.addSeparator();
-
JCheckBoxMenuItem cbEnable = new JCheckBoxMenuItem();
cbEnable.setText(OtrActivator.resourceService
.getI18NString("plugin.otr.menu.CB_ENABLE"));
-
cbEnable.setState(policy.getEnableManual());
-
- cbEnable.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableManual(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbEnable);
+ cbEnable.setActionCommand(ACTION_COMMAND_CB_ENABLE);
+ cbEnable.addActionListener(this);

    JCheckBoxMenuItem cbAlways = new JCheckBoxMenuItem\(\);
    cbAlways\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_AUTO&quot;\)\);

-
cbAlways.setEnabled(policy.getEnableManual());
cbAlways.setState(policy.getEnableAlways());
-
- cbAlways.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableAlways(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbAlways);
+ cbAlways.setActionCommand(ACTION_COMMAND_CB_AUTO);
+ cbAlways.addActionListener(this);

    JCheckBoxMenuItem cbRequire = new JCheckBoxMenuItem\(\);
    cbRequire\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_REQUIRE&quot;\)\);

-
cbRequire.setEnabled(policy.getEnableManual());
cbRequire.setState(policy.getRequireEncryption());
-
- cbRequire.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrPolicy policy =
- OtrActivator.scOtrEngine.getContactPolicy(contact);
-
- boolean state = ((JCheckBoxMenuItem) e.getSource()).getState();
- policy.setEnableAlways(state);
- OtrActivator.scOtrEngine.setContactPolicy(contact, policy);
- }
- });
- this.add(cbRequire);
-
- this.addSeparator();
+ cbRequire.setActionCommand(ACTION_COMMAND_CB_REQUIRE);
+ cbRequire.addActionListener(this);

    JMenuItem cbReset = new JMenuItem\(\);
    cbReset\.setText\(OtrActivator\.resourceService
        \.getI18NString\(&quot;plugin\.otr\.menu\.CB\_RESET&quot;\)\);

+ cbReset.setActionCommand(ACTION_COMMAND_CB_RESET);
+ cbReset.addActionListener(this);

- cbReset.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- OtrActivator.scOtrEngine.setContactPolicy(contact, null);
- }
- });
+ this.addSeparator();
+ this.add(cbEnable);
+ this.add(cbAlways);
+ this.add(cbRequire);
+ this.addSeparator();
this.add(cbReset);
}

- public void setSessionStatus(SessionStatus sessionStatus)
+ /*
+ * Implements ScOtrEngineListener#sessionStatusChanged(Contact).
+ */
+ public void sessionStatusChanged(Contact contact)
{
- if (sessionStatus == this.sessionStatus)
- return;
-
- this.sessionStatus = sessionStatus;
- this.rebuildMenu();
+ if (contact.equals(OtrContactMenu.this.contact))
+ setSessionStatus(
+ OtrActivator.scOtrEngine.getSessionStatus(contact));
}

- public SessionStatus getSessionStatus()
+ private void setSessionStatus(SessionStatus sessionStatus)
{
- return sessionStatus;
+ if (sessionStatus != this.sessionStatus)
+ {
+ this.sessionStatus = sessionStatus;
+
+ updateIcon();
+ if (isPopupMenuVisible())
+ rebuildMenu();
+ }
}

- public void setOtrPolicy(OtrPolicy otrPolicy)
+ private void setOtrPolicy(OtrPolicy otrPolicy)
{
- if (otrPolicy.equals(this.otrPolicy))
- return;
+ if (!otrPolicy.equals(this.otrPolicy))
+ {
+ this.otrPolicy = otrPolicy;

- this.otrPolicy = otrPolicy;
- this.rebuildMenu();
+ if (isPopupMenuVisible())
+ rebuildMenu();
+ }
}

- public OtrPolicy getOtrPolicy()
+ private void updateIcon()
{
- return otrPolicy;
- }
+ String imageID;

- public Contact contact;
+ switch (getSessionStatus())
+ {
+ case ENCRYPTED:
+ imageID
+ = OtrActivator.scOtrKeyManager.isVerified(contact)
+ ? "plugin.otr.ENCRYPTED_ICON_16x16"
+ : "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_16x16";
+ break;
+
+ case FINISHED:
+ imageID = "plugin.otr.FINISHED_ICON_16x16";
+ break;
+
+ case PLAINTEXT:
+ imageID = "plugin.otr.PLAINTEXT_ICON_16x16";
+ break;
+
+ default:
+ return;
+ }
+
+ setIcon(OtrActivator.resourceService.getImage(imageID));
+ }
}

Modified: trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java?view=diff&rev=5981&p1=trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java&p2=trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java&r1=5980&r2=5981

--- trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java (original)
+++ trunk/src/net/java/sip/communicator/plugin/otr/OtrMetaContactMenu.java 2009-09-16 23:38:49+0000
@@ -10,6 +10,7 @@
import java.util.*;

import javax.swing.*;
+import javax.swing.event.*;

import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
@@ -18,22 +19,79 @@

/**
* @author George Politis
+ * @author Lubomir Marinov
*/
public class OtrMetaContactMenu
extends AbstractPluginComponent
+ implements ActionListener,
+ PopupMenuListener
{

/\*\*

+ * The last known <tt>MetaContact</tt> to be currently selected and to be
+ * depcited by this instance and the <tt>OtrContactMenu</tt>s it contains.
+ */
+ private MetaContact currentContact;
+
+ /**
* The <code>JMenu</code> which is the component of this plugin.
*/
private JMenu menu;

+ /**
+ * The "What's this?" <tt>JMenuItem</tt> which launches help on the subject
+ * of off-the-record messaging.
+ */
+ private JMenuItem whatsThis;
+
public OtrMetaContactMenu(Container container)
{
super(container);
}

/\*

+ * Implements ActionListener#actionPerformed(ActionEvent). Handles the
+ * invocation of the whatsThis menu item i.e. launches help on the subject
+ * of off-the-record messaging.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ OtrActivator.scOtrEngine.launchHelp();
+ }
+
+ private void createOtrContactMenus(MetaContact metaContact)
+ {
+ // Remove any existing OtrContactMenu items.
+ for (int itemIndex = 0, itemCount = menu.getItemCount();
+ itemIndex < itemCount;)
+ {
+ JMenuItem menuItem = menu.getItem(itemIndex);
+
+ if (menuItem instanceof OtrContactMenu)
+ {
+ menu.remove(itemIndex);
+ itemCount--;
+
+ ((OtrContactMenu) menuItem).dispose();
+ }
+ else
+ itemIndex++;
+ }
+
+ // Create the new OtrContactMenu items.
+ if (metaContact != null)
+ {
+ Iterator<Contact> contacts = metaContact.getContacts();
+ int itemIndex = 0;
+ while (contacts.hasNext())
+ {
+ menu.insert(new OtrContactMenu(contacts.next()), itemIndex);
+ itemIndex++;
+ }
+ }
+ }
+
+ /*
* Implements PluginComponent#getComponent(). Returns the JMenu which is
* the component of this plugin creating it first if it doesn't exist.
*/
@@ -53,6 +111,7 @@
if (menu == null)
{
menu = new JMenu();
+ menu.setText(getName());

        if \(Container\.CONTAINER\_CONTACT\_RIGHT\_BUTTON\_MENU
                \.equals\(getContainer\(\)\)\)

@@ -65,8 +124,8 @@
if (icon != null)
menu.setIcon(icon);
}
-
- menu.setText(getName());
+
+ menu.getPopupMenu().addPopupMenuListener(this);
}
return menu;
}
@@ -82,37 +141,54 @@
.getI18NString("plugin.otr.menu.TITLE");
}

- public void setCurrentContact(MetaContact metaContact)
+ /*
+ * Implements PopupMenuListener#popupMenuCanceled(PopupMenuEvent).
+ */
+ public void popupMenuCanceled(PopupMenuEvent e)
{
- // Rebuild menu.
- if (menu != null)
- menu.removeAll();
+ createOtrContactMenus(null);
+ }

- if (metaContact == null)
- return;
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeInvisible(
+ * PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
+ {
+ popupMenuCanceled(e);
+ }

- JMenu menu = getMenu();
+ /*
+ * Implements PopupMenuListener#popupMenuWillBecomeVisible(PopupMenuEvent).
+ */
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e)
+ {
+ createOtrContactMenus(currentContact);

- Iterator<Contact> contacts = metaContact.getContacts();
- while (contacts.hasNext())
+ if (whatsThis == null)
{
- menu.add(new OtrContactMenu(contacts.next()));
- }
+ menu.addSeparator();

- menu.addSeparator();
+ whatsThis = new JMenuItem();
+ whatsThis.setIcon(
+ OtrActivator.resourceService
+ .getImage("plugin.otr.HELP_ICON_15x15"));
+ whatsThis.setText(
+ OtrActivator.resourceService
+ .getI18NString("plugin.otr.menu.WHATS_THIS"));
+ whatsThis.addActionListener(this);
+ menu.add(whatsThis);
+ }
+ }

- JMenuItem whatsThis = new JMenuItem();
- whatsThis.setIcon(OtrActivator.resourceService
- .getImage("plugin.otr.HELP_ICON_15x15"));
- whatsThis.setText(OtrActivator.resourceService
- .getI18NString("plugin.otr.menu.WHATS_THIS"));
- whatsThis.addActionListener(new ActionListener()
+ public void setCurrentContact(MetaContact metaContact)
+ {
+ if (this.currentContact != metaContact)
{
- public void actionPerformed(ActionEvent e)
- {
- OtrActivator.scOtrEngine.launchHelp();
- }
- });
- menu.add(whatsThis);
+ this.currentContact = metaContact;
+
+ if ((menu != null) && menu.isPopupMenuVisible())
+ createOtrContactMenus(currentContact);
+ }
}
}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net