diff --git a/.classpath b/.classpath
index 9a9bf4cae..fb0eda4a2 100755
--- a/.classpath
+++ b/.classpath
@@ -83,5 +83,6 @@
+
diff --git a/build.xml b/build.xml
index 3d14c5e0a..d513fa163 100644
--- a/build.xml
+++ b/build.xml
@@ -1079,8 +1079,8 @@
bundle-globalshortcut,bundle-plugin-msofficecomm,bundle-libjitsi,
bundle-customcontactactions, bundle-phonenumbercontactsource,
bundle-demuxcontactsource, bundle-muc,
- bundle-desktoputil,
- bundle-globaldisplaydetails,bundle-plugin-propertieseditor"/>
+ bundle-desktoputil,bundle-globaldisplaydetails,
+ bundle-plugin-propertieseditor,bundle-plugin-accountinfo"/>
@@ -2226,6 +2226,7 @@ javax.swing.event, javax.swing.border"/>
manifest="${src}/net/java/sip/communicator/plugin/accountinfo/accountinfo.manifest.mf">
+
diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties
index cf8c6e429..f567442e7 100644
--- a/lib/felix.client.run.properties
+++ b/lib/felix.client.run.properties
@@ -134,6 +134,7 @@ felix.auto.start.60= \
felix.auto.start.66= \
reference:file:sc-bundles/swing-ui.jar \
reference:file:sc-bundles/update.jar \
+ reference:file:sc-bundles/accountinfo.jar \
reference:file:sc-bundles/swingnotification.jar \
reference:file:sc-bundles/systray-service.jar \
reference:file:sc-bundles/osdependent.jar \
diff --git a/lib/installer-exclude/jcalendar-1.4.jar b/lib/installer-exclude/jcalendar-1.4.jar
new file mode 100644
index 000000000..8b0bff616
Binary files /dev/null and b/lib/installer-exclude/jcalendar-1.4.jar differ
diff --git a/resources/images/images.properties b/resources/images/images.properties
index b313f79ba..eed832ebf 100644
--- a/resources/images/images.properties
+++ b/resources/images/images.properties
@@ -123,6 +123,7 @@ service.gui.statusicons.USER_FFC_ICON=resources/images/impl/gui/common/statusico
service.gui.statusicons.USER_ON_THE_PHONE_ICON=resources/images/impl/gui/common/statusicons/onThePhone.png
# service gui buttons
+service.gui.buttons.ACCOUNT_EDIT_ICON=resources/images/impl/gui/buttons/accountEditIcon.png
service.gui.buttons.CONTACT_LIST_BUTTON_BG_LEFT=resources/images/impl/gui/buttons/contactListButtonBgLeft.png
service.gui.buttons.CONTACT_LIST_BUTTON_BG_RIGHT=resources/images/impl/gui/buttons/contactListButtonBgRight.png
service.gui.buttons.CONTACT_LIST_BUTTON_BG_MIDDLE=resources/images/impl/gui/buttons/contactListButtonBgMiddle.png
diff --git a/resources/images/impl/gui/buttons/accountEditIcon.png b/resources/images/impl/gui/buttons/accountEditIcon.png
new file mode 100644
index 000000000..a13ecc14f
Binary files /dev/null and b/resources/images/impl/gui/buttons/accountEditIcon.png differ
diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties
index bee961c46..a41049430 100644
--- a/resources/languages/resources.properties
+++ b/resources/languages/resources.properties
@@ -857,15 +857,33 @@ impl.googlecontacts.WRONG_CREDENTIALS=Wrong credentials for Google account {0}
plugin.accountinfo.TITLE=Account Info
plugin.accountinfo.EXTENDED=Extended
plugin.accountinfo.NOT_SUPPORTED=Account info not available.
+plugin.accountinfo.SELECT_ACCOUNT=Please select an account:
+plugin.accountinfo.DISPLAY_NAME=Display name:
plugin.accountinfo.FIRST_NAME=First Name:
plugin.accountinfo.MIDDLE_NAME=Middle Name:
plugin.accountinfo.LAST_NAME=Last Name:
+plugin.accountinfo.NICKNAME=Nickname:
+plugin.accountinfo.URL=URL:
plugin.accountinfo.AGE=Age:
plugin.accountinfo.BDAY=Birth Date:
+plugin.accountinfo.BDAY_FORMAT=MMM dd, yyyy
plugin.accountinfo.GENDER=Gender:
+plugin.accountinfo.STREET=Street Address:
+plugin.accountinfo.CITY=City:
+plugin.accountinfo.REGION=Region:
+plugin.accountinfo.POST=Postal code:
+plugin.accountinfo.COUNTRY=Country:
plugin.accountinfo.EMAIL=E-mail:
+plugin.accountinfo.WORK_EMAIL=Work E-mail:
plugin.accountinfo.PHONE=Phone:
+plugin.accountinfo.WORK_PHONE=Work Phone:
+plugin.accountinfo.ORGANIZATION=Organization Name:
+plugin.accountinfo.JOB_TITLE=Job Title:
+plugin.accountinfo.ABOUT_ME=About Me:
+plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200
plugin.accountinfo.USER_PICTURES=User Pictures
+plugin.accountinfo.GLOBAL_ICON=Use global icon
+plugin.accountinfo.LOCAL_ICON=Use this icon:
plugin.accountinfo.CHANGE=Change
plugin.accountinfo.ONLY_MESSAGE=Only messages
diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
index 2313cdbea..a0fd2aeb6 100644
--- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
@@ -186,7 +186,7 @@ public MainFrame()
this.contactListPanel = new ContactListPane(this);
- this.accountStatusPanel = new AccountStatusPanel(this);
+ this.accountStatusPanel = new AccountStatusPanel();
this.searchField = new SearchField( this,
TreeContactList.searchFilter,
diff --git a/src/net/java/sip/communicator/impl/gui/main/account/AccountList.java b/src/net/java/sip/communicator/impl/gui/main/account/AccountList.java
index ae0a105a1..c2cc0ae4f 100644
--- a/src/net/java/sip/communicator/impl/gui/main/account/AccountList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/account/AccountList.java
@@ -56,6 +56,12 @@ public class AccountList
*/
private final JButton editButton;
+ /**
+ * The menu that appears when right click on account is detected.
+ */
+ private final AccountRightButtonMenu rightButtonMenu
+ = new AccountRightButtonMenu();
+
/**
* Creates an instance of this account list by specifying the parent
* container of the list.
@@ -69,6 +75,29 @@ public AccountList(AccountsConfigurationPanel parentConfigPanel)
this.addMouseListener(this);
+ this.addMouseListener(new MouseAdapter()
+ {
+ public void mousePressed(MouseEvent e)
+ {
+ if (SwingUtilities.isRightMouseButton(e))
+ {
+ Point point = e.getPoint();
+
+ AccountList.this.setSelectedIndex(getRow(point));
+
+ rightButtonMenu.setAccount(getSelectedAccount());
+
+ SwingUtilities.convertPointToScreen(
+ point, AccountList.this);
+
+ ((JPopupMenu) rightButtonMenu).setInvoker(AccountList.this);
+
+ rightButtonMenu.setLocation(point.x, point.y);
+ rightButtonMenu.setVisible(true);
+ }
+ }
+ });
+
this.accountsInit();
GuiActivator.bundleContext.addServiceListener(this);
@@ -76,6 +105,11 @@ public AccountList(AccountsConfigurationPanel parentConfigPanel)
this.editButton = parentConfigPanel.getEditButton();
}
+ private int getRow(Point point)
+ {
+ return locationToIndex(point);
+ }
+
/**
* Initializes the accounts table.
*/
diff --git a/src/net/java/sip/communicator/impl/gui/main/account/AccountRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/account/AccountRightButtonMenu.java
new file mode 100644
index 000000000..f74ffb9c5
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/account/AccountRightButtonMenu.java
@@ -0,0 +1,260 @@
+/*
+ * 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.impl.gui.main.account;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.impl.gui.event.*;
+import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.plugin.desktoputil.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.gui.Container;
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.util.skin.*;
+
+import org.jitsi.service.resources.*;
+import org.osgi.framework.*;
+
+/**
+ * AccountRightButtonMenu is the menu that opens when user right clicks on any
+ * of his accounts in the account list section.
+ *
+ * @author Marin Dzhigarov
+ */
+public class AccountRightButtonMenu
+ extends SIPCommPopupMenu
+ implements ActionListener,
+ PluginComponentListener,
+ Skinnable
+{
+ /**
+ * The serial version UID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The logger of this class.
+ */
+ private final Logger logger
+ = Logger.getLogger(AccountRightButtonMenu.class);
+
+ /**
+ * The Account that is clicked on.
+ */
+ private Account account = null;
+
+ /**
+ * A list of all PluginComponents that are registered through the OSGi
+ * bundle context.
+ */
+ private java.util.List pluginComponents
+ = new ArrayList();
+
+ /**
+ * The edit item.
+ */
+ private final JMenuItem editItem = new JMenuItem(
+ GuiActivator.getResources().getI18NString(
+ "service.gui.EDIT"));
+
+ /**
+ * Creates an instance of AccountRightButtonMenu
+ */
+ public AccountRightButtonMenu()
+ {
+ super();
+
+ this.setLocation(getLocation());
+
+ this.init();
+
+ loadSkin();
+ }
+
+ /**
+ * Sets the current Account that is clicked on.
+ * @param account the Account that is clicked on.
+ */
+ public void setAccount(Account account)
+ {
+ this.account = account;
+ editItem.setEnabled(account != null && this.account.isEnabled());
+ for (PluginComponent pluginComponent : pluginComponents)
+ pluginComponent.setCurrentAccountID(account.getAccountID());
+ }
+
+ /**
+ * Returns the Account that was last clicked on.
+ * @return the Account that was last clicked on.
+ */
+ public Account getAccount()
+ {
+ return account;
+ }
+
+ /**
+ * Initialized the menu by adding all containing menu items.
+ */
+ private void init()
+ {
+ initPluginComponents();
+ add(editItem);
+ editItem.addActionListener(this);
+ }
+
+ /**
+ * Initializes plug-in components for this container.
+ */
+ private void initPluginComponents()
+ {
+ // Search for plugin components registered through the OSGI bundle
+ // context.
+ ServiceReference[] serRefs = null;
+
+ String osgiFilter = "("
+ + Container.CONTAINER_ID
+ + "="+Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU.getID()+")";
+
+ try
+ {
+ serRefs = GuiActivator.bundleContext.getServiceReferences(
+ PluginComponentFactory.class.getName(),
+ osgiFilter);
+ }
+ catch (InvalidSyntaxException exc)
+ {
+ logger.error("Could not obtain plugin reference.", exc);
+ }
+
+ if (serRefs != null)
+ {
+ for (int i = 0; i < serRefs.length; i ++)
+ {
+ PluginComponentFactory factory =
+ (PluginComponentFactory) GuiActivator
+ .bundleContext.getService(serRefs[i]);
+
+ PluginComponent component =
+ factory.getPluginComponentInstance(this);
+
+ if (component.getComponent() == null)
+ continue;
+
+ pluginComponents.add(component);
+
+ if (factory.getPositionIndex() != -1)
+ this.add((Component)component.getComponent(),
+ factory.getPositionIndex());
+ else
+ this.add((Component)component.getComponent());
+ }
+ }
+ GuiActivator.getUIService().addPluginComponentListener(this);
+ }
+
+ /**
+ * Reloads skin related information.
+ */
+ public void loadSkin()
+ {
+ editItem.setIcon(new ImageIcon(
+ ImageLoader.getImage(ImageLoader.ACCOUNT_EDIT_ICON)));
+ }
+
+ /**
+ * Indicates that a plugin component has been added to this container.
+ *
+ * @param event the PluginComponentEvent that notified us
+ */
+ /**
+ * Indicates that a new plugin component has been added. Adds it to this
+ * container if it belongs to it.
+ *
+ * @param event the PluginComponentEvent that notified us
+ */
+ public void pluginComponentAdded(PluginComponentEvent event)
+ {
+ PluginComponentFactory factory = event.getPluginComponentFactory();
+
+ if (!factory.getContainer().equals(
+ Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU))
+ return;
+
+ PluginComponent c = factory.getPluginComponentInstance(this);
+
+ this.add((Component) c.getComponent());
+
+ this.repaint();
+ }
+
+ /**
+ * Removes the according plug-in component from this container.
+ * @param event the PluginComponentEvent that notified us
+ */
+ public void pluginComponentRemoved(PluginComponentEvent event)
+ {
+ PluginComponentFactory factory = event.getPluginComponentFactory();
+
+ if(factory.getContainer()
+ .equals(Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU))
+ {
+ Component c =
+ (Component)factory.getPluginComponentInstance(this)
+ .getComponent();
+ this.remove(c);
+ pluginComponents.remove(c);
+ }
+ }
+
+ /**
+ * Handles the ActionEvent. Determines which menu item was
+ * selected and performs the appropriate operations.
+ * @param e the ActionEvent, which notified us of the action
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ JMenuItem menuItem = (JMenuItem) e.getSource();
+
+ if (menuItem.equals(editItem))
+ {
+ if (account == null)
+ return;
+
+ AccountRegWizardContainerImpl wizard =
+ (AccountRegWizardContainerImpl) GuiActivator.getUIService()
+ .getAccountRegWizardContainer();
+
+ AccountRegistrationWizard protocolWizard =
+ wizard.getProtocolWizard(account.getProtocolProvider());
+
+ ResourceManagementService resources = GuiActivator.getResources();
+ if (protocolWizard != null)
+ {
+ wizard.setTitle(resources.getI18NString(
+ "service.gui.ACCOUNT_REGISTRATION_WIZARD"));
+
+ wizard.modifyAccount(account.getProtocolProvider());
+ wizard.showDialog(false);
+ }
+ else
+ {
+ // There is no wizard for this account - just show an error
+ // dialog:
+ String title = resources.getI18NString("service.gui.ERROR");
+ String message =
+ resources.getI18NString("service.gui.EDIT_NOT_SUPPORTED");
+ ErrorDialog dialog = new ErrorDialog(null, title, message);
+ dialog.setVisible(true);
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java b/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
index 9b39b5dff..5e7d615f8 100644
--- a/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
@@ -14,9 +14,9 @@
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.event.*;
import net.java.sip.communicator.impl.gui.lookandfeel.*;
-import net.java.sip.communicator.impl.gui.main.*;
-import net.java.sip.communicator.impl.gui.main.presence.avatar.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.plugin.desktoputil.*;
+import net.java.sip.communicator.plugin.desktoputil.presence.avatar.*;
import net.java.sip.communicator.service.globaldisplaydetails.event.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.gui.Container;
@@ -25,8 +25,6 @@
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.skin.*;
-import net.java.sip.communicator.plugin.desktoputil.*;
-
import org.jitsi.util.*;
/**
@@ -126,15 +124,13 @@ public class AccountStatusPanel
/**
* Creates an instance of AccountStatusPanel by specifying the
* main window, where this panel is added.
- * @param mainFrame the main window, where this panel is added
*/
- public AccountStatusPanel(MainFrame mainFrame)
+ public AccountStatusPanel()
{
super(new BorderLayout(10, 0));
FramedImageWithMenu imageWithMenu
= new FramedImageWithMenu(
- mainFrame,
new ImageIcon(
ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)),
diff --git a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
index ce04afbe4..607dffc6a 100644
--- a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
+++ b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
@@ -58,6 +58,7 @@ Import-Package: com.apple.eawt,
net.java.sip.communicator.plugin.desktoputil.event,
net.java.sip.communicator.plugin.desktoputil.plaf,
net.java.sip.communicator.plugin.desktoputil.presence,
+ net.java.sip.communicator.plugin.desktoputil.presence.avatar,
net.java.sip.communicator.plugin.desktoputil.transparent,
net.java.sip.communicator.service.customcontactactions,
net.java.sip.communicator.service.globaldisplaydetails,
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index 083e2d1c8..c2dba5779 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -160,6 +160,12 @@ public class ImageLoader
public static final ImageID RIGHT_ARROW_ICON
= new ImageID("service.gui.icons.RIGHT_ARROW_ICON");
+ /**
+ * The edit icon that is shown when account is right clicked on.
+ */
+ public static final ImageID ACCOUNT_EDIT_ICON
+ = new ImageID("service.gui.buttons.ACCOUNT_EDIT_ICON");
+
/**
* The call button image.
*/
diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetServerStoredAccountInfoIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetServerStoredAccountInfoIcqImpl.java
index 19c099244..0d10453ca 100644
--- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetServerStoredAccountInfoIcqImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetServerStoredAccountInfoIcqImpl.java
@@ -52,6 +52,7 @@ public class OperationSetServerStoredAccountInfoIcqImpl
public static final Map, int[]> supportedTypes
= new Hashtable, int[]>();
static {
+ supportedTypes.put(ServerStoredDetails.ImageDetail.class, new int[]{1});
supportedTypes.put(ServerStoredDetails.CountryDetail.class, new int[]{1, 0x01A4});
supportedTypes.put(ServerStoredDetails.NicknameDetail.class, new int[]{1, 0x0154});
supportedTypes.put(ServerStoredDetails.FirstNameDetail.class, new int[]{1, 0x0140});
@@ -226,6 +227,23 @@ public boolean isDetailClassSupported(
return supportedTypes.get(detailClass) != null;
}
+ /**
+ * Determines whether the underlying implementation supports edition
+ * of this detail class.
+ *
+ * @param detailClass the class whose edition we'd like to determine if it's
+ * possible
+ * @return true if the underlying implementation supports edition of this
+ * type of detail and false otherwise.
+ */
+ public boolean isDetailClassEditable(
+ Class extends GenericDetail> detailClass)
+ {
+ return
+ isDetailClassSupported(detailClass)
+ && ImageDetail.class.isAssignableFrom(detailClass);
+ }
+
/**
* Utility method throwing an exception if the icq stack is not properly
* initialized.
@@ -794,6 +812,18 @@ else if(newDetailValue.equals(ServerStoredDetails.GenderDetail.MALE))
return false;
}
+ /*
+ * (non-Javadoc)
+ * @see net.java.sip.communicator.service.protocol.OperationSetServerStoredAccountInfo#save()
+ * This method is currently unimplemented.
+ * The idea behind this method is for users to call it only once, meaning
+ * that all ServerStoredDetails previously modified by addDetail/removeDetail
+ * and/or replaceDetail will be saved online on the server in one step.
+ * Currently, addDetail/removeDetail/replaceDetail methods are doing the
+ * actual saving but in the future the saving part must be carried here.
+ */
+ public void save() throws OperationFailedException {}
+
/**
* Requests the account image if its missing.
* @return the new image or the one that has been already downloaded.
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java
index af1be57e1..869e51d82 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java
@@ -8,6 +8,7 @@
import java.lang.reflect.*;
import java.net.*;
+import java.text.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.*;
@@ -175,6 +176,24 @@ protected List retrieveDetails(String contactAddress)
if(tmp != null)
result.add(new NicknameDetail(tmp));
+ tmp = card.getField("BDAY");
+ if (tmp != null)
+ {
+ try
+ {
+ Calendar birthDateCalendar = Calendar.getInstance();
+ DateFormat dateFormat =
+ new SimpleDateFormat(
+ JabberActivator.getResources().getI18NString(
+ "plugin.accountinfo.BDAY_FORMAT"));
+ Date birthDate =
+ dateFormat.parse(tmp);
+ birthDateCalendar.setTime(birthDate);
+ BirthDateDetail bd = new BirthDateDetail(birthDateCalendar);
+ result.add(bd);
+ }
+ catch (ParseException e) {}
+ }
// Home Details
// addrField one of
// POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
@@ -195,9 +214,9 @@ protected List retrieveDetails(String contactAddress)
if(tmp != null)
result.add(new PostalCodeDetail(tmp));
-// tmp = card.getAddressFieldHome("CTRY");
-// if(tmp != null)
-// result.add(new CountryDetail(tmp);
+ tmp = card.getAddressFieldHome("CTRY");
+ if(tmp != null)
+ result.add(new CountryDetail(tmp));
// phoneType one of
//VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
@@ -276,7 +295,7 @@ protected List retrieveDetails(String contactAddress)
tmp = card.getEmailWork();
if(tmp != null)
- result.add(new EmailAddressDetail(tmp));
+ result.add(new WorkEmailAddressDetail(tmp));
tmp = card.getOrganization();
if(tmp != null)
@@ -286,15 +305,25 @@ protected List retrieveDetails(String contactAddress)
if(tmp != null)
result.add(new WorkDepartmentNameDetail(tmp));
+ tmp = card.getField("TITLE");
+ if(tmp != null)
+ result.add(new JobTitleDetail(tmp));
+
+ tmp = card.getField("ABOUTME");
+ if (tmp != null)
+ result.add(new AboutMeDetail(tmp));
+
byte[] imageBytes = card.getAvatar();
if(imageBytes != null && imageBytes.length > 0)
+ {
result.add(new ImageDetail("Image", imageBytes));
+ }
try
{
tmp = card.getField("URL");
if(tmp != null)
- result.add(new WebPageDetail(new URL(tmp)));
+ result.add(new URLDetail("URL", new URL(tmp)));
}
catch(MalformedURLException e){}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetServerStoredAccountInfoJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetServerStoredAccountInfoJabberImpl.java
index 9d148e8d3..09b9e5f11 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetServerStoredAccountInfoJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetServerStoredAccountInfoJabberImpl.java
@@ -6,11 +6,12 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
+import java.net.*;
+import java.text.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail;
-import net.java.sip.communicator.service.protocol.ServerStoredDetails.ImageDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
@@ -22,6 +23,7 @@
* provider.
*
* @author Damian Minkov
+ * @author Marin Dzhigarov
*/
public class OperationSetServerStoredAccountInfoJabberImpl
extends AbstractOperationSetServerStoredAccountInfo
@@ -42,6 +44,35 @@ public class OperationSetServerStoredAccountInfoJabberImpl
*/
private ProtocolProviderServiceJabberImpl jabberProvider = null;
+ /**
+ * List of all supported ServerStoredDetails
+ * for this implementation.
+ */
+ public static final List> supportedTypes
+ = new ArrayList>();
+
+ static {
+ supportedTypes.add(ImageDetail.class);
+ supportedTypes.add(FirstNameDetail.class);
+ supportedTypes.add(MiddleNameDetail.class);
+ supportedTypes.add(LastNameDetail.class);
+ supportedTypes.add(NicknameDetail.class);
+ supportedTypes.add(AddressDetail.class);
+ supportedTypes.add(CityDetail.class);
+ supportedTypes.add(ProvinceDetail.class);
+ supportedTypes.add(PostalCodeDetail.class);
+ supportedTypes.add(CountryDetail.class);
+ supportedTypes.add(EmailAddressDetail.class);
+ supportedTypes.add(WorkEmailAddressDetail.class);
+ supportedTypes.add(PhoneNumberDetail.class);
+ supportedTypes.add(WorkPhoneDetail.class);
+ supportedTypes.add(WorkOrganizationNameDetail.class);
+ supportedTypes.add(URLDetail.class);
+ supportedTypes.add(BirthDateDetail.class);
+ supportedTypes.add(JobTitleDetail.class);
+ supportedTypes.add(AboutMeDetail.class);
+ }
+
/**
* Our account UIN.
*/
@@ -124,14 +155,7 @@ public Iterator getAllAvailableDetails()
*/
public Iterator> getSupportedDetailTypes()
{
- List details = infoRetreiver.getContactDetails(uin);
- List> result
- = new Vector>();
-
- for (GenericDetail obj : details)
- result.add(obj.getClass());
-
- return result.iterator();
+ return supportedTypes.iterator();
}
/**
@@ -150,12 +174,7 @@ public Iterator> getSupportedDetailTypes()
public boolean isDetailClassSupported(
Class extends GenericDetail> detailClass)
{
- List details = infoRetreiver.getContactDetails(uin);
-
- for (GenericDetail obj : details)
- if(detailClass.isAssignableFrom(obj.getClass()))
- return true;
- return false;
+ return supportedTypes.contains(detailClass);
}
/**
@@ -173,7 +192,7 @@ public int getMaxDetailInstances(Class extends GenericDetail> detailClass)
}
/**
- * Adds the specified detail to the list of details registered on-line
+ * Adds the specified detail to the list of details ready to be saved online
* for this account. If such a detail already exists its max instance number
* is consulted and if it allows it - a second instance is added or otherwise
* and illegal argument exception is thrown. An IllegalArgumentException is
@@ -187,67 +206,50 @@ public int getMaxDetailInstances(Class extends GenericDetail> detailClass)
* max instances number has been attained or if the underlying
* implementation does not support setting details of the corresponding
* class.
- * @throws OperationFailedException with code Network Failure if putting the
- * new value online has failed
* @throws java.lang.ArrayIndexOutOfBoundsException if the number of
* instances currently registered by the application is already equal to the
* maximum number of supported instances (@see getMaxDetailInstances())
*/
public void addDetail(ServerStoredDetails.GenericDetail detail)
throws IllegalArgumentException,
- OperationFailedException,
ArrayIndexOutOfBoundsException
{
- assertConnected();
-
- /*
- Currently as the function only provided the list of classes that
- currently have data associated with them
- in Jabber InfoRetreiver we have to skip this check*/
- //if (!isDetailClassSupported(detail.getClass())) {
- // throw new IllegalArgumentException(
- // "implementation does not support such details " +
- // detail.getClass());
- //}
+ if (!isDetailClassSupported(detail.getClass())) {
+ throw new IllegalArgumentException(
+ "implementation does not support such details " +
+ detail.getClass());
+ }
Iterator iter = getDetails(detail.getClass());
int currentDetailsSize = 0;
while (iter.hasNext())
{
currentDetailsSize++;
+ iter.next();
}
- if (currentDetailsSize >= getMaxDetailInstances(detail.getClass()))
+ if (currentDetailsSize > getMaxDetailInstances(detail.getClass()))
{
throw new ArrayIndexOutOfBoundsException(
"Max count for this detail is already reached");
}
- if(detail instanceof ImageDetail)
- {
- // Push the avatar photo to the server.
- this.uploadImageDetail(
- ServerStoredDetailsChangeEvent.DETAIL_ADDED,
- null,
- detail);
- }
+ infoRetreiver.getCachedContactDetails(uin).add(detail);
}
/**
- * Removes the specified detail from the list of details stored online for
- * this account. The method returns a boolean indicating if such a detail
- * was found (and removed) or not.
+ * Removes the specified detail from the list of details ready to be saved
+ * online this account. The method returns a boolean indicating if such a
+ * detail was found (and removed) or not.
*
* @param detail the detail to remove
* @return true if the specified detail existed and was successfully removed
* and false otherwise.
- * @throws OperationFailedException with code Network Failure if removing the
- * detail from the server has failed
*/
public boolean removeDetail(ServerStoredDetails.GenericDetail detail)
- throws OperationFailedException
{
- return false;
+
+ return infoRetreiver.getCachedContactDetails(uin).remove(detail);
}
/**
@@ -264,16 +266,12 @@ public boolean removeDetail(ServerStoredDetails.GenericDetail detail)
* call to addDetail is required).
* @throws ClassCastException if newDetailValue is not an instance of the
* same class as currentDetailValue.
- * @throws OperationFailedException with code Network Failure if putting the
- * new value back online has failed
*/
public boolean replaceDetail(
ServerStoredDetails.GenericDetail currentDetailValue,
ServerStoredDetails.GenericDetail newDetailValue)
- throws ClassCastException, OperationFailedException
+ throws ClassCastException
{
- assertConnected();
-
if (!newDetailValue.getClass().equals(currentDetailValue.getClass()))
{
throw new ClassCastException(
@@ -304,22 +302,130 @@ public boolean replaceDetail(
return false;
}
- if(newDetailValue instanceof ImageDetail)
+ removeDetail(currentDetailValue);
+ addDetail(newDetailValue);
+ return true;
+ }
+
+ /**
+ * Saves the list of details for this account that were ready to be stored
+ * online on the server. This method performs the actual saving of details
+ * online on the server and is supposed to be invoked after addDetail(),
+ * replaceDetail() and/or removeDetail().
+ *
+ * @throws OperationFailedException with code Network Failure if putting the
+ * new values back online has failed.
+ */
+ public void save() throws OperationFailedException
+ {
+ assertConnected();
+
+ List details = infoRetreiver.getContactDetails(uin);
+ VCardXEP0153 vCard = new VCardXEP0153();
+ for (GenericDetail detail : details)
+ {
+ if (detail instanceof ImageDetail)
+ {
+ byte[] avatar = ((ImageDetail) detail).getBytes();
+ if (avatar == null) vCard.setAvatar(new byte[0]);
+ else vCard.setAvatar(avatar);
+ fireServerStoredDetailsChangeEvent(
+ jabberProvider,
+ ServerStoredDetailsChangeEvent.DETAIL_ADDED,
+ null,
+ detail);
+ }
+ else if (detail.getClass().equals(FirstNameDetail.class))
+ vCard.setFirstName((String)detail.getDetailValue());
+ else if (detail.getClass().equals(MiddleNameDetail.class))
+ vCard.setMiddleName((String)detail.getDetailValue());
+ else if (detail.getClass().equals(LastNameDetail.class))
+ vCard.setLastName((String)detail.getDetailValue());
+ else if (detail.getClass().equals(NicknameDetail.class))
+ vCard.setNickName((String)detail.getDetailValue());
+ else if (detail.getClass().equals(URLDetail.class))
+ {
+ if (detail.getDetailValue() != null)
+ vCard.setField(
+ "URL", ((URL)detail.getDetailValue()).toString());
+ }
+ else if (detail.getClass().equals(BirthDateDetail.class))
+ {
+ if (detail.getDetailValue() != null)
+ {
+ Calendar c = ((BirthDateDetail)detail).getCalendar();
+ DateFormat dateFormat =
+ new SimpleDateFormat(
+ JabberActivator.getResources().getI18NString(
+ "plugin.accountinfo.BDAY_FORMAT"));
+ String strdate = dateFormat.format(c.getTime());
+ vCard.setField("BDAY", strdate);
+ }
+ }
+ else if (detail.getClass().equals(AddressDetail.class))
+ vCard.setAddressFieldHome(
+ "STREET", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(CityDetail.class))
+ vCard.setAddressFieldHome(
+ "LOCALITY", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(ProvinceDetail.class))
+ vCard.setAddressFieldHome(
+ "REGION", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(PostalCodeDetail.class))
+ vCard.setAddressFieldHome(
+ "PCODE", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(CountryDetail.class))
+ vCard.setAddressFieldHome(
+ "CTRY", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(PhoneNumberDetail.class))
+ vCard.setPhoneHome("VOICE", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(WorkPhoneDetail.class))
+ vCard.setPhoneWork("VOICE", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(EmailAddressDetail.class))
+ vCard.setEmailHome((String)detail.getDetailValue());
+ else if (detail.getClass().equals(WorkEmailAddressDetail.class))
+ vCard.setEmailWork((String)detail.getDetailValue());
+ else if (detail.getClass().equals(WorkOrganizationNameDetail.class))
+ vCard.setOrganization((String)detail.getDetailValue());
+ else if (detail.getClass().equals(JobTitleDetail.class))
+ vCard.setField("TITLE", (String)detail.getDetailValue());
+ else if (detail.getClass().equals(AboutMeDetail.class))
+ vCard.setField("ABOUTME", (String)detail.getDetailValue());
+ }
+ try
{
- // Push the new avatar photo to the server.
- return this.uploadImageDetail(
- ServerStoredDetailsChangeEvent.DETAIL_REPLACED,
- currentDetailValue,
- newDetailValue);
+ vCard.save(jabberProvider.getConnection());
}
+ catch (XMPPException xmppe)
+ {
+ logger.error("Error loading/saving vcard: ", xmppe);
+ throw new OperationFailedException(
+ "Error loading/saving vcard: ", 1, xmppe);
+ }
+ }
+ /**
+ * Determines whether the underlying implementation supports edition
+ * of this detail class.
+ *
+ * @param detailClass the class whose edition we'd like to determine if it's
+ * possible
+ * @return true if the underlying implementation supports edition of this
+ * type of detail and false otherwise.
+ */
+ public boolean isDetailClassEditable(
+ Class extends GenericDetail> detailClass)
+ {
+ if (isDetailClassSupported(detailClass)) {
+ return true;
+ }
return false;
}
/**
- * Utility method throwing an exception if the icq stack is not properly
+ * Utility method throwing an exception if the jabber stack is not properly
* initialized.
- * @throws java.lang.IllegalStateException if the underlying ICQ stack is
+ * @throws java.lang.IllegalStateException if the underlying jabber stack is
* not registered and initialized.
*/
private void assertConnected() throws IllegalStateException
@@ -333,73 +439,4 @@ private void assertConnected() throws IllegalStateException
"The jabber provider must be signed on before "
+"being able to communicate.");
}
-
- /**
- * Uploads the new avatar image to the server via the vCard mechanism
- * (XEP-0153).
- *
- * @param changeEventID the int ID of the event to dispatch
- * @param currentDetailValue the detail value we'd like to replace.
- * @param newDetailValue the value of the detail that we'd like to replace
- * currentDetailValue with. If ((ImageDetail) newDetailValue).getBytes() is
- * null, then this function removes the current avatar from the server by
- * sending a vCard with a "photo" tag without any content.
- *
- * @return "true" if the new avatar image has been uploaded (even if the
- * current avatar image is removed). "false" if an XMPPException occurs.
- */
- private boolean uploadImageDetail(
- int changeEventID,
- ServerStoredDetails.GenericDetail currentDetailValue,
- ServerStoredDetails.GenericDetail newDetailValue)
- {
- boolean isPhotoChanged = false;
-
- try
- {
- byte[] newAvatar = ((ImageDetail) newDetailValue).getBytes();
-
- VCardXEP0153 v1 = new VCardXEP0153();
- // Retrieve the old vCard.
- v1.load(jabberProvider.getConnection());
- // Checks if the new avatar photo is diferent form the server one.
- // If yes, then upload the new avatar photo.
- if(!Arrays.equals(v1.getAvatar(), newAvatar))
- {
- if(newAvatar == null)
- {
- v1.setAvatar(new byte[0]);
- }
- else
- {
- v1.setAvatar(newAvatar);
- }
- // Saves the new vCard.
- v1.save(jabberProvider.getConnection());
- }
-
- // Sets the new avatar photo advertised in all presence messages,
- // and send one presence messge immediately.
- ((OperationSetPersistentPresenceJabberImpl)
- this.jabberProvider.getOperationSet(
- OperationSetPersistentPresence.class))
- .updateAccountPhotoPresenceExtension(newAvatar);
-
- // Advertises all detail change listeners, that the server stored
- // details have changed.
- fireServerStoredDetailsChangeEvent(
- jabberProvider,
- changeEventID,
- currentDetailValue,
- newDetailValue);
-
- isPhotoChanged = true;
- }
- catch (XMPPException xmppe)
- {
- logger.error("Error loading/saving vcard: ", xmppe);
- }
-
- return isPhotoChanged;
- }
-}
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java
index 81aa89a4c..fb43723c5 100644
--- a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetServerStoredAccountInfoMsnImpl.java
@@ -267,6 +267,23 @@ public boolean isDetailClassSupported(
return false;
}
+ /**
+ * Determines whether the underlying implementation supports edition
+ * of this detail class.
+ *
+ * @param detailClass the class whose edition we'd like to determine if it's
+ * possible
+ * @return true if the underlying implementation supports edition of this
+ * type of detail and false otherwise.
+ */
+ public boolean isDetailClassEditable(
+ Class extends GenericDetail> detailClass)
+ {
+ return
+ isDetailClassSupported(detailClass)
+ && ImageDetail.class.isAssignableFrom(detailClass);
+ }
+
/**
* The method returns the number of instances supported for a particular
* detail type. Some protocols offer storing multiple values for a
@@ -518,6 +535,18 @@ public boolean replaceDetail(
return false;
}
+ /*
+ * (non-Javadoc)
+ * @see net.java.sip.communicator.service.protocol.OperationSetServerStoredAccountInfo#save()
+ * This method is currently unimplemented.
+ * The idea behind this method is for users to call it only once, meaning
+ * that all ServerStoredDetails previously modified by addDetail/removeDetail
+ * and/or replaceDetail will be saved online on the server in one step.
+ * Currently, addDetail/removeDetail/replaceDetail methods are doing the
+ * actual saving but in the future the saving part must be carried here.
+ */
+ public void save() throws OperationFailedException {}
+
/**
* Utility method throwing an exception if the icq stack is not properly
* initialized.
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetServerStoredAccountInfoSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetServerStoredAccountInfoSipImpl.java
index 4ad22a72f..6b528aee4 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetServerStoredAccountInfoSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetServerStoredAccountInfoSipImpl.java
@@ -194,6 +194,23 @@ && isImageDetailSupported())
|| DisplayNameDetail.class.isAssignableFrom(detailClass);
}
+ /**
+ * Determines whether the underlying implementation supports the edition
+ * of this detail class.
+ *
+ * @param detailClass the class whose edition we'd like to determine if it's
+ * possible
+ * @return true if the underlying implementation supports edition of this
+ * type of detail and false otherwise.
+ */
+ public boolean isDetailClassEditable(
+ Class extends GenericDetail> detailClass)
+ {
+ return
+ isDetailClassSupported(detailClass)
+ && ImageDetail.class.isAssignableFrom(detailClass);
+ }
+
/**
* The method returns the number of instances supported for a particular
* detail type.
@@ -411,6 +428,18 @@ public boolean replaceDetail(
return true;
}
+ /*
+ * (non-Javadoc)
+ * @see net.java.sip.communicator.service.protocol.OperationSetServerStoredAccountInfo#save()
+ * This method is currently unimplemented.
+ * The idea behind this method is for users to call it only once, meaning
+ * that all ServerStoredDetails previously modified by addDetail/removeDetail
+ * and/or replaceDetail will be saved online on the server in one step.
+ * Currently, addDetail/removeDetail/replaceDetail methods are doing the
+ * actual saving but in the future the saving part must be carried here.
+ */
+ public void save() throws OperationFailedException {}
+
/**
* Determines if image details is supported.
*
diff --git a/src/net/java/sip/communicator/plugin/accountinfo/AccountDetailsPanel.java b/src/net/java/sip/communicator/plugin/accountinfo/AccountDetailsPanel.java
index 7ddf425e9..fa96f0367 100644
--- a/src/net/java/sip/communicator/plugin/accountinfo/AccountDetailsPanel.java
+++ b/src/net/java/sip/communicator/plugin/accountinfo/AccountDetailsPanel.java
@@ -7,75 +7,150 @@
import java.awt.*;
import java.awt.event.*;
-import java.io.*;
-import java.text.*;
+import java.beans.*;
+import java.net.*;
import java.util.*;
-import javax.imageio.*;
import javax.swing.*;
+import javax.swing.text.*;
+
+import org.jitsi.util.*;
import net.java.sip.communicator.plugin.desktoputil.*;
+import net.java.sip.communicator.plugin.desktoputil.presence.avatar.*;
+import net.java.sip.communicator.service.globaldisplaydetails.*;
import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.service.protocol.ServerStoredDetails.BinaryDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.AboutMeDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.AddressDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.BirthDateDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.CityDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.CountryDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.DisplayNameDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.EmailAddressDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.FirstNameDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenderDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.ImageDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.JobTitleDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.LastNameDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.MiddleNameDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.NicknameDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.PhoneNumberDetail;
-import net.java.sip.communicator.util.*;
-import net.java.sip.communicator.util.skin.*;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.PostalCodeDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.ProvinceDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.URLDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkEmailAddressDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkOrganizationNameDetail;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkPhoneDetail;
+
+import net.java.sip.communicator.util.Logger;
+
+import com.toedter.calendar.*;
/**
- * The right side panel of AccountDetailsDialog. Shows one tab of a summary of
- * contact information for the selected subcontact, and has an extended tab
- * listing all of the details.
+ * The main panel that allows users to view and edit their account information.
+ * Different instances of this class are created for every registered
+ * ProtocolProviderService.
+ * Currently, supported account details are first/middle/last names, nickname,
+ * street/city/region/country address, postal code, birth date, gender,
+ * organization name, job title, about me, home/work email, home/work phone.
*
* @author Yana Stamcheva
* @author Adam Netocny
+ * @author Marin Dzhigarov
*/
public class AccountDetailsPanel
extends TransparentPanel
- implements Skinnable
{
- private static final long serialVersionUID = 5524135388175045624L;
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 1L;
+ /**
+ * The logger
+ */
private Logger logger = Logger.getLogger(AccountDetailsPanel.class);
+ /**
+ * Mapping between all supported by this plugin ServerStoredDetails
+ * and their respective JTextField that are used for modifying
+ * the details.
+ */
+ private final Map, JTextField>
+ detailToTextField
+ = new HashMap, JTextField>();
+
+ /**
+ * The ProtocolProviderService that this panel is associated with.
+ */
+ ProtocolProviderService protocolProvider;
+
/**
* The operation set giving access to the server stored account details.
*/
private OperationSetServerStoredAccountInfo accountInfoOpSet;
- private JTextField firstNameField = new JTextField();
+ private JTextField displayNameField;
+
+ private JTextField firstNameField;
+
+ private JTextField middleNameField;
+
+ private JTextField lastNameField;
+
+ private JTextField nicknameField;
+
+ private JTextField urlField;
+
+ private JTextField streetAddressField;
+
+ private JTextField cityField;
- private JTextField middleNameField = new JTextField();
+ private JTextField regionField;
- private JTextField lastNameField = new JTextField();
+ private JTextField postalCodeField;
- private JTextField genderField = new JTextField();
+ private JTextField countryField;
- private JTextField ageField = new JTextField();
+ private JTextField phoneField;
- private JTextField birthdayField = new JTextField();
+ private JTextField workPhoneField;
- private JTextField emailField = new JTextField();
+ private JTextField emailField;
- private JTextField phoneField = new JTextField();
+ private JTextField workEmailField;
- private JLabel avatarLabel = new JLabel();
+ private JTextField organizationField;
+ private JTextField jobTitleField;
+
+ private JTextArea aboutMeArea;
+
+ private JTextField genderField;
+
+ private JTextField ageField;
+
+ private JDateChooser birthDayCalendar;
+
+ private JRadioButton globalIcon;
+
+ private JRadioButton localIcon;
+
+ private FramedImageWithMenu imageWithMenu;
+ /**
+ * The "apply" button.
+ */
private JButton applyButton
= new JButton(Resources.getString("service.gui.APPLY"));
+ /**
+ * The panel containing all buttons.
+ */
private JPanel buttonPanel =
new TransparentPanel(new FlowLayout(FlowLayout.CENTER));
- private JScrollPane mainScrollPane = new JScrollPane();
-
- private boolean isDataLoaded = false;
+ private DisplayNameDetail displayNameDetail;
private FirstNameDetail firstNameDetail;
@@ -83,24 +158,47 @@ public class AccountDetailsPanel
private LastNameDetail lastNameDetail;
- private GenderDetail genderDetail;
+ private NicknameDetail nicknameDetail;
- private BirthDateDetail birthDateDetail;
+ private URLDetail urlDetail;
- private EmailAddressDetail emailDetail;
+ private AddressDetail streetAddressDetail;
+
+ private CityDetail cityDetail;
+
+ private ProvinceDetail regionDetail;
+
+ private PostalCodeDetail postalCodeDetail;
+
+ private CountryDetail countryDetail;
private PhoneNumberDetail phoneDetail;
+
+ private WorkPhoneDetail workPhoneDetail;
+
+ private EmailAddressDetail emailDetail;
+
+ private WorkEmailAddressDetail workEmailDetail;
+
+ private WorkOrganizationNameDetail organizationDetail;
+
+ private JobTitleDetail jobTitleDetail;
+
+ private AboutMeDetail aboutMeDetail;
- private BinaryDetail avatarDetail;
+ private GenderDetail genderDetail;
- private byte[] newAvatarImage;
+ private BirthDateDetail birthDateDetail;
- private ImageIcon avatarImageIcon = null;
+ private ImageDetail avatarDetail;
/**
- * The last avatar file directory open.
+ * The panel that contains description labels and text fields
+ * for every account detail.
*/
- private File lastAvatarDir;
+ private JPanel valuesPanel;
+
+ private JScrollPane mainScrollPane;
/**
* Construct a panel containing all account details for the given protocol
@@ -110,10 +208,11 @@ public class AccountDetailsPanel
*/
public AccountDetailsPanel(ProtocolProviderService protocolProvider)
{
- super(new BorderLayout());
-
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ setOpaque(false);
+ this.setPreferredSize(new Dimension(600, 400));
+ this.protocolProvider = protocolProvider;
this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
-// this.setPreferredSize(new Dimension(500, 400));
accountInfoOpSet
= protocolProvider
@@ -134,550 +233,931 @@ public AccountDetailsPanel(ProtocolProviderService protocolProvider)
}
}
+ /**
+ * Creates the panel that indicates to the user that the currently selected
+ * contact does not support server stored contact info.
+ */
+ private void initUnsupportedPanel()
+ {
+ JTextArea unsupportedTextArea =
+ new JTextArea(Resources.getString(
+ "plugin.accountinfo.NOT_SUPPORTED"));
+
+ unsupportedTextArea.setEditable(false);
+ unsupportedTextArea.setOpaque(false);
+
+ JPanel unsupportedPanel
+ = new TransparentPanel();
+
+ unsupportedPanel.setBorder(
+ BorderFactory.createEmptyBorder(50, 20, 50, 20));
+
+ unsupportedPanel.add(unsupportedTextArea);
+
+ this.add(unsupportedPanel, BorderLayout.NORTH);
+ }
+
+ /**
+ * Initialized the main panel that contains all ServerStoredDetails
+ */
private void initSummaryPanel()
{
JPanel summaryPanel = new TransparentPanel(new BorderLayout(10, 10));
summaryPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
- summaryPanel.setSize(this.getWidth(), this.getHeight());
// Create the avatar panel.
JPanel leftPanel = new TransparentPanel(new BorderLayout());
JPanel avatarPanel = new TransparentPanel(new BorderLayout());
- JButton changeAvatarButton = new JButton(Resources.getString("plugin.accountinfo.CHANGE"));
- JPanel changeButtonPanel
- = new TransparentPanel(new FlowLayout(FlowLayout.CENTER));
-
- changeAvatarButton.addActionListener(new ChangeAvatarActionListener());
- changeButtonPanel.add(changeAvatarButton);
-
- avatarPanel.add(avatarLabel, BorderLayout.CENTER);
- avatarPanel.add(changeButtonPanel, BorderLayout.SOUTH);
+ JPanel radioButtonPanel = new TransparentPanel(new GridLayout(2, 1));
+ globalIcon =
+ new JRadioButton(
+ Resources.getString("plugin.accountinfo.GLOBAL_ICON"));
+ globalIcon.setSelected(true);
+ globalIcon.setOpaque(false);
+ globalIcon.setEnabled(false);
+ localIcon =
+ new JRadioButton(
+ Resources.getString("plugin.accountinfo.LOCAL_ICON"));
+ localIcon.setOpaque(false);
+ localIcon.setEnabled(false);
+ ButtonGroup group = new ButtonGroup();
+ group.add(globalIcon);
+ group.add(localIcon);
+ radioButtonPanel.add(globalIcon);
+ radioButtonPanel.add(localIcon);
+ avatarPanel.add(radioButtonPanel, BorderLayout.NORTH);
leftPanel.add(avatarPanel, BorderLayout.NORTH);
-
summaryPanel.add(leftPanel, BorderLayout.WEST);
+ detailToTextField.put(ImageDetail.class, new JTextField());
+
+ imageWithMenu
+ = new FramedImageWithMenu(
+ Resources.getImage(
+ "service.gui.DEFAULT_USER_PHOTO"),
+ Resources.getImage(
+ "service.gui.DEFAULT_USER_PHOTO").getIconWidth(),
+ Resources.getImage(
+ "service.gui.DEFAULT_USER_PHOTO").getIconHeight());
+ SelectAvatarMenu selectAvatarMenu = new SelectAvatarMenu(imageWithMenu);
+ selectAvatarMenu.setAccountID(protocolProvider.getAccountID());
+ imageWithMenu.setPopupMenu(selectAvatarMenu);
+ avatarPanel.add(imageWithMenu, BorderLayout.SOUTH);
+
+ globalIcon.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ imageWithMenu.setEnabled(false);
+ }
+ });
+ localIcon.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ imageWithMenu.setEnabled(true);
+ }
+ });
+ imageWithMenu.setEnabled(false);
+
+ valuesPanel = new TransparentPanel(new GridBagLayout());
+ valuesPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ GridBagConstraints first = new GridBagConstraints();
+ first.gridx = 0;
+ first.gridy = 0;
+ first.weightx = 0;
+ first.anchor = GridBagConstraints.LINE_START;
+ first.gridwidth = 1;
+ first.insets = new Insets(4, 4, 4, 4);
+ first.fill = GridBagConstraints.HORIZONTAL;
+ GridBagConstraints second = new GridBagConstraints();
+ second.gridx = 1;
+ second.gridy = 0;
+ second.weightx = 2;
+ second.anchor = GridBagConstraints.LINE_START;
+ second.gridwidth = 1; // GridBagConstraints.REMAINDER;
+ second.insets = first.insets;
+ second.fill = GridBagConstraints.HORIZONTAL;
+
+ if (accountInfoOpSet.isDetailClassSupported(DisplayNameDetail.class))
+ {
+ displayNameField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.DISPLAY_NAME"))
+ , first);
+ valuesPanel.add(displayNameField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(DisplayNameDetail.class, displayNameField);
+ }
- // Create the summary details panel.
- JPanel detailsPanel = new TransparentPanel(new BorderLayout(10, 10));
- detailsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ firstNameField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.FIRST_NAME"))
+ , first);
+ valuesPanel.add(firstNameField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(FirstNameDetail.class, firstNameField);
+
+ middleNameField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.MIDDLE_NAME"))
+ , first);
+ valuesPanel.add(middleNameField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(MiddleNameDetail.class, middleNameField);
+
+ lastNameField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.LAST_NAME"))
+ , first);
+ valuesPanel.add(lastNameField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(LastNameDetail.class, lastNameField);
+
+ if (accountInfoOpSet.isDetailClassSupported(NicknameDetail.class))
+ {
+ nicknameField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.NICKNAME"))
+ , first);
+ valuesPanel.add(nicknameField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(NicknameDetail.class, nicknameField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(URLDetail.class))
+ {
+ urlField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.URL"))
+ , first);
+ valuesPanel.add(urlField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(URLDetail.class, urlField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(GenderDetail.class))
+ {
+ genderField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.GENDER"))
+ , first);
+ valuesPanel.add(genderField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(GenderDetail.class, genderField);
+ }
- summaryPanel.add(detailsPanel, BorderLayout.CENTER);
+ birthDayCalendar = new JDateChooser();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.BDAY"))
+ , first);
+ valuesPanel.add(birthDayCalendar, second);
+ birthDayCalendar.setDateFormatString(
+ Resources.getString("plugin.accountinfo.BDAY_FORMAT"));
+ birthDayCalendar.addPropertyChangeListener(
+ new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ if (evt.getPropertyName().equals("date"))
+ {
+ Date date = (Date) evt.getNewValue();
+ if (date != null)
+ {
+ Calendar currentDate = Calendar.getInstance();
+ Calendar c = Calendar.getInstance();
+ c.setTime(date);
+ int age =
+ currentDate.get(Calendar.YEAR) -
+ c.get(Calendar.YEAR);
+
+ if (currentDate.get(Calendar.MONTH) <
+ c.get(Calendar.MONTH))
+ age--;
+ if ((currentDate.get(Calendar.MONTH) ==
+ c.get(Calendar.MONTH))
+ &&
+ (currentDate.get(Calendar.DAY_OF_MONTH) <
+ c.get(Calendar.DAY_OF_MONTH)))
+ age--;
+ String ageDetail = Integer.toString(age).trim();
+ ageField.setText(ageDetail);
+ }
+ }
+ }
+ });
+ first.gridy = ++second.gridy;
+ ageField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.AGE")), first);
+ valuesPanel.add(ageField, second);
+ first.gridy = ++second.gridy;
+ ageField.setEditable(false);
+ detailToTextField.put(BirthDateDetail.class, new JTextField());
+
+ if (accountInfoOpSet.isDetailClassSupported(AddressDetail.class))
+ {
+ streetAddressField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.STREET"))
+ , first);
+ valuesPanel.add(streetAddressField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(AddressDetail.class, streetAddressField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(CityDetail.class))
+ {
+ cityField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.CITY")), first);
+ valuesPanel.add(cityField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(CityDetail.class, cityField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(ProvinceDetail.class))
+ {
+ regionField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.REGION"))
+ , first);
+ valuesPanel.add(regionField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(ProvinceDetail.class, regionField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(PostalCodeDetail.class))
+ {
+ postalCodeField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.POST"))
+ , first);
+ valuesPanel.add(postalCodeField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(PostalCodeDetail.class, postalCodeField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(CountryDetail.class))
+ {
+ countryField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.COUNTRY"))
+ , first);
+ valuesPanel.add(countryField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(CountryDetail.class, countryField);
+ }
- // Labels panel.
- JPanel labelsPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5));
+ emailField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.EMAIL"))
+ , first);
+ valuesPanel.add(emailField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(EmailAddressDetail.class, emailField);
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.FIRST_NAME")));
-// labelsPanel.add(new JLabel(Resources.getString("plugin.accountinfo.MIDDLE_NAME")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.LAST_NAME")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.GENDER")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.AGE")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.BDAY")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.EMAIL")));
- labelsPanel.add(new JLabel(
- Resources.getString("plugin.accountinfo.PHONE")));
+ if (accountInfoOpSet.isDetailClassSupported(
+ WorkEmailAddressDetail.class))
+ {
+ workEmailField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.WORK_EMAIL"))
+ , first);
+ valuesPanel.add(workEmailField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(WorkEmailAddressDetail.class, workEmailField);
+ }
- detailsPanel.add(labelsPanel, BorderLayout.WEST);
+ phoneField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.PHONE"))
+ , first);
+ valuesPanel.add(phoneField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(PhoneNumberDetail.class, phoneField);
- // Values panel.
- JPanel valuesPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5));
+ if (accountInfoOpSet.isDetailClassSupported(WorkPhoneDetail.class))
+ {
+ workPhoneField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.WORK_PHONE"))
+ , first);
+ valuesPanel.add(workPhoneField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(
+ WorkPhoneDetail.class, workPhoneField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(
+ WorkOrganizationNameDetail.class))
+ {
+ organizationField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.ORGANIZATION"))
+ , first);
+ valuesPanel.add(organizationField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(
+ WorkOrganizationNameDetail.class, organizationField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(JobTitleDetail.class))
+ {
+ jobTitleField = new JTextField();
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.JOB_TITLE"))
+ , first);
+ valuesPanel.add(jobTitleField, second);
+ first.gridy = ++second.gridy;
+ detailToTextField.put(
+ JobTitleDetail.class, jobTitleField);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(AboutMeDetail.class))
+ {
+ aboutMeArea = new JTextArea(3, 0);
+ valuesPanel.add(new JLabel(
+ Resources.getString("plugin.accountinfo.ABOUT_ME"))
+ , first);
+ second.gridheight = 3;
+ JScrollPane areaScrollPane = new JScrollPane(aboutMeArea);
+ areaScrollPane.setOpaque(false);
+ areaScrollPane.setBorder(BorderFactory.createEmptyBorder());
+ areaScrollPane.setVerticalScrollBarPolicy(
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ valuesPanel.add(areaScrollPane, second);
+ first.gridy = ++second.gridy;
+
+ DefaultStyledDocument doc = new DefaultStyledDocument();
+ doc.setDocumentFilter(new DocumentFilter() {
+
+ private final int MAX_CHARACTERS =
+ Integer.valueOf(Resources.getString(
+ "plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS"));
+
+ public void insertString(FilterBypass fb, int offs,
+ String str, AttributeSet a)
+ throws BadLocationException {
+ //This rejects the entire insertion if it would make
+ //the contents too long. Another option would be
+ //to truncate the inserted string so the contents
+ //would be exactly maxCharacters in length.
+ if ((fb.getDocument().getLength() + str.length())
+ <= MAX_CHARACTERS)
+ super.insertString(fb, offs, str, a);
+ else
+ Toolkit.getDefaultToolkit().beep();
+ }
- valuesPanel.add(firstNameField);
-// valuesPanel.add(middleNameField);
- valuesPanel.add(lastNameField);
- valuesPanel.add(genderField);
- valuesPanel.add(ageField);
- valuesPanel.add(birthdayField);
- valuesPanel.add(emailField);
- valuesPanel.add(phoneField);
+ public void replace(FilterBypass fb, int offs,
+ int length,
+ String str, AttributeSet a)
+ throws BadLocationException {
+ //This rejects the entire replacement if it would make
+ //the contents too long. Another option would be
+ //to truncate the replacement string so the contents
+ //would be exactly maxCharacters in length.
+ if ((fb.getDocument().getLength() + str.length()
+ - length) <= MAX_CHARACTERS)
+ super.replace(fb, offs, length, str, a);
+ else
+ Toolkit.getDefaultToolkit().beep();
+ }
+ });
+
+ aboutMeArea.setDocument(doc);
+ aboutMeArea.setBorder(firstNameField.getBorder());
+ aboutMeArea.setLineWrap(true);
+ aboutMeArea.setWrapStyleWord(true);
+ aboutMeArea.setPreferredSize(new Dimension(50, 100));
+ aboutMeArea.setMinimumSize(new Dimension(50, 100));
+ detailToTextField.put(AboutMeDetail.class, new JTextField());
+ }
- detailsPanel.add(valuesPanel, BorderLayout.CENTER);
+ mainScrollPane = new JScrollPane(summaryPanel,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ mainScrollPane.getViewport().setOpaque(false);
+ mainScrollPane.setOpaque(false);
+ mainScrollPane.setBorder(BorderFactory.createEmptyBorder());
- this.mainScrollPane.getViewport().add(summaryPanel);
+ summaryPanel.add(valuesPanel, BorderLayout.CENTER);
- this.add(mainScrollPane, BorderLayout.NORTH);
+ this.add(mainScrollPane);
this.applyButton.addActionListener(new SubmitActionListener());
+ JButton cancelButton =
+ new JButton(Resources.getString("service.gui.CANCEL"));
+ cancelButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent evt)
+ {
+ AccountInfoMenuItemComponent.dialog.setVisible(false);
+ mainScrollPane.getVerticalScrollBar().setValue(0);
+ }
+ });
this.buttonPanel.add(applyButton);
+ this.buttonPanel.add(cancelButton);
- this.add(buttonPanel, BorderLayout.SOUTH);
+ this.add(buttonPanel);
- // All items are now instantiated and could safely load the skin.
- loadSkin();
+ for (Component component : valuesPanel.getComponents())
+ component.setEnabled(false);
+ if (aboutMeArea != null)
+ aboutMeArea.setEnabled(false);
+ applyButton.setEnabled(false);
}
/**
- * Loads details for
+ * Loads all ServerStoredDetails which are currently supported by
+ * this plugin. Note that some OperationSetServerStoredAccountInfo
+ * implementations may support details that are not supported by this plugin.
+ * In this case they will not be loaded.
*/
public void loadDetails()
{
- this.loadSummaryDetails();
- this.isDataLoaded = true;
+ if (accountInfoOpSet != null)
+ {
+ Iterator allDetails =
+ accountInfoOpSet.getAllAvailableDetails();
+
+ while (allDetails.hasNext())
+ {
+ GenericDetail detail = allDetails.next();
+ loadDetail(detail);
+ }
+
+ boolean isAnyDetailEditable = false;
+ for (Class extends GenericDetail> editable :
+ detailToTextField.keySet())
+ {
+ if (accountInfoOpSet.isDetailClassEditable(editable))
+ {
+ isAnyDetailEditable = true;
+ if (editable.equals(AboutMeDetail.class))
+ aboutMeArea.setEnabled(true);
+ else if (editable.equals(BirthDateDetail.class))
+ birthDayCalendar.setEnabled(true);
+ else if (editable.equals(ImageDetail.class))
+ {
+ globalIcon.setEnabled(true);
+ localIcon.setEnabled(true);
+ imageWithMenu.setEnabled(true);
+ }
+ else
+ {
+ JTextField field = detailToTextField.get(editable);
+ field.setEnabled(true);
+ }
+ }
+ }
+ if (isAnyDetailEditable)
+ applyButton.setEnabled(true);
+ }
}
/**
- * Creates the panel that indicates to the user that the currently selected
- * contact does not support server stored contact info.
+ * Loads a single GenericDetail obtained from the
+ * OperationSetServerStoredAccountInfo into this plugin.
+ * @param detail to be loaded.
*/
- private void initUnsupportedPanel()
+ private void loadDetail(GenericDetail detail)
{
- JTextArea unsupportedTextArea =
- new JTextArea(Resources.getString(
- "plugin.accountinfo.NOT_SUPPORTED"));
-
- unsupportedTextArea.setEditable(false);
- unsupportedTextArea.setLineWrap(true);
-
- JPanel unsupportedPanel
- = new TransparentPanel(new FlowLayout(FlowLayout.CENTER));
-
- unsupportedTextArea.setPreferredSize(new Dimension(200, 200));
+ if (detail.getClass().equals(AboutMeDetail.class))
+ {
+ aboutMeDetail = (AboutMeDetail) detail;
+ aboutMeArea.setText((String) detail.getDetailValue());
+ return;
+ }
+ if (detail instanceof BirthDateDetail)
+ {
+ birthDateDetail = (BirthDateDetail) detail;
- unsupportedPanel.setBorder(
- BorderFactory.createEmptyBorder(50, 20, 50, 20));
+ Calendar calendarDetail =
+ (Calendar) birthDateDetail.getDetailValue();
- unsupportedPanel.add(unsupportedTextArea);
+ birthDayCalendar.setCalendar(calendarDetail);
+ return;
+ }
- this.add(unsupportedPanel);
+ JTextField field = detailToTextField.get(detail.getClass());
+ if (field != null)
+ {
+ if (detail instanceof ImageDetail)
+ {
+ localIcon.setSelected(true);
+ avatarDetail = (ImageDetail) detail;
+ byte[] avatarImage = avatarDetail.getBytes();
+ imageWithMenu.setImageIcon(avatarImage);
+ }
+ else if (detail instanceof URLDetail)
+ {
+ urlDetail = (URLDetail) detail;
+ urlField.setText(urlDetail.getURL().toString());
+ }
+ else
+ {
+ field.setText((String) detail.getDetailValue());
+ if (detail.getClass().equals(DisplayNameDetail.class))
+ displayNameDetail = (DisplayNameDetail) detail;
+ else if (detail.getClass().equals(FirstNameDetail.class))
+ firstNameDetail = (FirstNameDetail) detail;
+ else if (detail.getClass().equals(MiddleNameDetail.class))
+ middleNameDetail = (MiddleNameDetail) detail;
+ else if (detail.getClass().equals(LastNameDetail.class))
+ lastNameDetail = (LastNameDetail) detail;
+ else if (detail.getClass().equals(NicknameDetail.class))
+ nicknameDetail = (NicknameDetail) detail;
+ else if (detail.getClass().equals(URLDetail.class))
+ urlDetail = (URLDetail) detail;
+ else if (detail.getClass().equals(GenderDetail.class))
+ genderDetail = (GenderDetail) detail;
+ else if (detail.getClass().equals(AddressDetail.class))
+ streetAddressDetail = (AddressDetail) detail;
+ else if (detail.getClass().equals(CityDetail.class))
+ cityDetail = (CityDetail) detail;
+ else if (detail.getClass().equals(ProvinceDetail.class))
+ regionDetail = (ProvinceDetail) detail;
+ else if (detail.getClass().equals(PostalCodeDetail.class))
+ postalCodeDetail = (PostalCodeDetail) detail;
+ else if (detail.getClass().equals(CountryDetail.class))
+ countryDetail = (CountryDetail) detail;
+ else if (detail.getClass().equals(PhoneNumberDetail.class))
+ phoneDetail = (PhoneNumberDetail) detail;
+ else if (detail.getClass().equals(WorkPhoneDetail.class))
+ workPhoneDetail = (WorkPhoneDetail) detail;
+ else if (detail.getClass().equals(EmailAddressDetail.class))
+ emailDetail = (EmailAddressDetail) detail;
+ else if (detail.getClass().equals(WorkEmailAddressDetail.class))
+ workEmailDetail = (WorkEmailAddressDetail) detail;
+ else if (detail.getClass().equals(
+ WorkOrganizationNameDetail.class))
+ organizationDetail = (WorkOrganizationNameDetail) detail;
+ else if (detail.getClass().equals(JobTitleDetail.class))
+ jobTitleDetail = (JobTitleDetail) detail;
+ else if (detail.getClass().equals(AboutMeDetail.class))
+ aboutMeDetail = (AboutMeDetail) detail;
+ }
+ }
}
/**
- * Creates a panel that can be added as the summary tab that displays the
- * following details: -
- *
- * Avatar(Contact image) - FirstNameDetail - MiddleNameDetail -
- * LastNameDetail - BirthdateDetail (and calculate age) - GenderDetail -
- * EmailAddressDetail - PhoneNumberDetail. All other details will be* added
- * to our list of extended details.
+ * Attempts to upload all ServerStoredDetails on the server using
+ * OperationSetServerStoredAccountInfo
+ *
*/
- private void loadSummaryDetails()
+ private class SubmitActionListener implements ActionListener
{
- Iterator contactDetails;
-
- // Avatar details.
- contactDetails
- = accountInfoOpSet.getDetails(BinaryDetail.class);
-
- byte[] avatarImage = null;
- if (contactDetails.hasNext())
+ public void actionPerformed(ActionEvent e)
{
- avatarDetail = (BinaryDetail) contactDetails.next();
+ if (accountInfoOpSet.isDetailClassSupported(ImageDetail.class))
+ {
+ if (globalIcon.isSelected())
+ {
+ GlobalDisplayDetailsService serv =
+ AccountInfoActivator.getGlobalDisplayDetailsService();
- avatarImage = avatarDetail.getBytes();
- }
+ byte[] newIcon = serv.getGlobalDisplayAvatar();
- if (avatarImage != null && avatarImage.length > 0)
- {
- avatarImageIcon = new ImageIcon(
- getScaledImageInstance(avatarImage));
- avatarLabel.setIcon(avatarImageIcon);
- }
+ ImageDetail newDetail = null;
+ if (newIcon != null)
+ newDetail =
+ new ImageDetail(
+ "avatar", serv.getGlobalDisplayAvatar());
- // First name details.
- contactDetails =
- accountInfoOpSet.getDetails(FirstNameDetail.class);
+ if (avatarDetail != null || newDetail != null)
+ changeDetail(avatarDetail, newDetail);
+ }
+ }
+ if (accountInfoOpSet.isDetailClassSupported
+ (DisplayNameDetail.class))
+ {
+ String text =
+ detailToTextField.get(DisplayNameDetail.class).getText();
- String firstNameDetailString = "";
- while (contactDetails.hasNext())
- {
- firstNameDetail = (FirstNameDetail) contactDetails.next();
+ DisplayNameDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new DisplayNameDetail(text);
- firstNameDetailString =
- firstNameDetailString + " " + firstNameDetail.getDetailValue();
- }
+ if (displayNameDetail != null || newDetail != null)
+ changeDetail(displayNameDetail, newDetail);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(
+ FirstNameDetail.class))
+ {
+ String text =
+ detailToTextField.get(FirstNameDetail.class).getText();
- firstNameField.setText(firstNameDetailString);
+ FirstNameDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new FirstNameDetail(text);
- // Middle name details.
- contactDetails =
- accountInfoOpSet.getDetails(MiddleNameDetail.class);
+ if (firstNameDetail != null || newDetail != null)
+ changeDetail(firstNameDetail, newDetail);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(
+ MiddleNameDetail.class))
+ {
+ String text =
+ detailToTextField.get(MiddleNameDetail.class).getText();
- String middleNameDetailString = "";
- while (contactDetails.hasNext())
- {
- middleNameDetail = (MiddleNameDetail) contactDetails.next();
- middleNameDetailString =
- middleNameDetailString + " " + middleNameDetail.getDetailValue();
- }
+ MiddleNameDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new MiddleNameDetail(text);
- middleNameField.setText(middleNameDetailString);
+ if (middleNameDetail != null || newDetail != null)
+ changeDetail(middleNameDetail, newDetail);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(
+ LastNameDetail.class))
+ {
+ String text =
+ detailToTextField.get(LastNameDetail.class).getText();
+ LastNameDetail newDetail = null;
- // Last name details.
- contactDetails =
- accountInfoOpSet.getDetails(LastNameDetail.class);
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new LastNameDetail(text);
- String lastNameDetailString = "";
- while (contactDetails.hasNext())
- {
- lastNameDetail = (LastNameDetail) contactDetails.next();
+ if (lastNameDetail != null || newDetail != null)
+ changeDetail(lastNameDetail, newDetail);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(NicknameDetail.class))
+ {
+ String text =
+ detailToTextField.get(NicknameDetail.class).getText();
- lastNameDetailString =
- lastNameDetailString + " " + lastNameDetail.getDetailValue();
- }
+ NicknameDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new NicknameDetail(text);
- lastNameField.setText(lastNameDetailString);
+ if (nicknameDetail != null || newDetail != null)
+ changeDetail(nicknameDetail, newDetail);
+ }
- // Gender details.
- contactDetails =
- accountInfoOpSet.getDetails(GenderDetail.class);
+ if (accountInfoOpSet.isDetailClassSupported(URLDetail.class))
+ {
+ String text
+ = detailToTextField.get(URLDetail.class).getText();
- String genderDetailString = "";
- while (contactDetails.hasNext())
- {
- genderDetail = (GenderDetail) contactDetails.next();
- genderDetailString = genderDetailString + " "
- + genderDetail.getDetailValue();
- }
+ URL url = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ try
+ {
+ url = new URL(text);
+ }
+ catch (MalformedURLException e1)
+ {
+ logger.debug("Failed to update URL detail due to " +
+ "malformed URL.");
+ }
- genderField.setText(genderDetailString);
+ URLDetail newDetail = null;
- // Birthday details.
- contactDetails =
- accountInfoOpSet.getDetails(BirthDateDetail.class);
+ if (url != null)
+ newDetail = new URLDetail("URL", url);
- String birthDateDetailString = "";
- String ageDetail = "";
- if (contactDetails.hasNext())
- {
- birthDateDetail = (BirthDateDetail) contactDetails.next();
+ if (urlDetail != null || newDetail != null)
+ changeDetail(urlDetail, newDetail);
+ }
- Calendar calendarDetail =
- (Calendar) birthDateDetail.getDetailValue();
+ if (accountInfoOpSet.isDetailClassSupported(
+ GenderDetail.class))
+ {
+ String text =
+ detailToTextField.get(GenderDetail.class).getText();
- Date birthDate = calendarDetail.getTime();
- DateFormat dateFormat = DateFormat.getDateInstance();
+ GenderDetail newDetail = null;
- birthDateDetailString = dateFormat.format(birthDate).trim();
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new GenderDetail(text);
- Calendar c = Calendar.getInstance();
- int age = c.get(Calendar.YEAR) - calendarDetail.get(Calendar.YEAR);
+ if (genderDetail != null || newDetail != null)
+ changeDetail(genderDetail, newDetail);
+ }
- if (c.get(Calendar.MONTH) < calendarDetail.get(Calendar.MONTH))
- age--;
+ if (accountInfoOpSet.isDetailClassSupported(
+ BirthDateDetail.class))
+ {
+ BirthDateDetail newDetail = null;
- ageDetail = Integer.toString(age).trim();
- }
+ if (birthDayCalendar.getDate() != null)
+ {
+ newDetail =
+ new BirthDateDetail(birthDayCalendar.getCalendar());
+ }
- birthdayField.setText(birthDateDetailString);
- ageField.setText(ageDetail);
+ if (birthDateDetail != null || newDetail != null)
+ changeDetail(birthDateDetail, newDetail);
+ }
- // Email details.
- contactDetails =
- accountInfoOpSet.getDetails(EmailAddressDetail.class);
+ if (accountInfoOpSet.isDetailClassSupported(
+ AddressDetail.class))
+ {
+ String text =
+ detailToTextField.get(AddressDetail.class).getText();
- String emailDetailString = "";
- while (contactDetails.hasNext())
- {
- emailDetail = (EmailAddressDetail) contactDetails.next();
- emailDetailString = emailDetailString + " "
- + emailDetail.getDetailValue();
- }
+ AddressDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new AddressDetail(text);
- emailField.setText(emailDetailString);
+ if (streetAddressDetail != null || newDetail != null)
+ changeDetail(streetAddressDetail, newDetail);
+ }
- // Phone number details.
- contactDetails =
- accountInfoOpSet.getDetails(PhoneNumberDetail.class);
+ if (accountInfoOpSet.isDetailClassSupported(
+ CityDetail.class))
+ {
+ String text =
+ detailToTextField.get(CityDetail.class).getText();
- String phoneNumberDetailString = "";
- while (contactDetails.hasNext())
- {
- phoneDetail = (PhoneNumberDetail) contactDetails.next();
- phoneNumberDetailString =
- phoneNumberDetailString + " " + phoneDetail.getDetailValue();
- }
+ CityDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new CityDetail(text);
- phoneField.setText(phoneNumberDetailString);
- }
+ if (cityDetail != null || newDetail != null)
+ changeDetail(cityDetail, newDetail);
+ }
- private class SubmitActionListener implements ActionListener
- {
- public void actionPerformed(ActionEvent e)
- {
- String firstName = firstNameField.getText();
-// String middleName = middleNameField.getText();
- String lastName = lastNameField.getText();
- String gender = genderField.getText();
- String email = emailField.getText();
- String phoneNumber = phoneField.getText();
+ if (accountInfoOpSet.isDetailClassSupported(
+ ProvinceDetail.class))
+ {
+ String text =
+ detailToTextField.get(ProvinceDetail.class).getText();
- Calendar birthDateCalendar = Calendar.getInstance();
+ ProvinceDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new ProvinceDetail(text);
- if(birthdayField.getText() != null
- && birthdayField.getText().length() > 0)
+ if (regionDetail != null || newDetail != null)
+ changeDetail(regionDetail, newDetail);
+ }
+
+ if (accountInfoOpSet.isDetailClassSupported(
+ PostalCodeDetail.class))
{
- try
- {
- DateFormat dateFormat
- = DateFormat.getDateInstance(DateFormat.DEFAULT);
+ String text =
+ detailToTextField.get(PostalCodeDetail.class).getText();
- Date birthDate = dateFormat.parse(birthdayField.getText());
+ PostalCodeDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new PostalCodeDetail(text);
- birthDateCalendar.setTime(birthDate);
- }
- catch (ParseException e2)
- {
- logger.error("Failed to parse birth date.", e2);
- }
+ if (postalCodeDetail != null || newDetail != null)
+ changeDetail(postalCodeDetail, newDetail);
}
- try
+ if (accountInfoOpSet.isDetailClassSupported(CountryDetail.class))
{
- FirstNameDetail newFirstNameDetail
- = new ServerStoredDetails.FirstNameDetail(firstName);
+ String text = detailToTextField.get(CountryDetail.class).getText();
- if (firstNameDetail == null)
- accountInfoOpSet.addDetail(newFirstNameDetail);
- else
- accountInfoOpSet.replaceDetail( firstNameDetail,
- newFirstNameDetail);
-
-// MiddleNameDetail newMiddleNameDetail
-// = new ServerStoredDetails.MiddleNameDetail(middleName);
-//
-// if (middleNameDetail == null)
-// accountInfoOpSet.addDetail(newMiddleNameDetail);
-// else
-// accountInfoOpSet.replaceDetail( middleNameDetail,
-// newMiddleNameDetail);
-
- LastNameDetail newLastNameDetail
- = new ServerStoredDetails.LastNameDetail(lastName);
-
- if (lastNameDetail == null)
- accountInfoOpSet.addDetail(newLastNameDetail);
- else
- accountInfoOpSet.replaceDetail( lastNameDetail,
- newLastNameDetail);
+ CountryDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new CountryDetail(text);
- GenderDetail newGenderDetail
- = new ServerStoredDetails.GenderDetail(gender);
+ if (countryDetail != null || newDetail != null)
+ changeDetail(countryDetail, newDetail);
+ }
- if (genderDetail == null)
- accountInfoOpSet.addDetail(newGenderDetail);
- else
- accountInfoOpSet.replaceDetail( genderDetail,
- newGenderDetail);
+ if (accountInfoOpSet.isDetailClassSupported(
+ EmailAddressDetail.class))
+ {
+ String text =
+ detailToTextField.get(EmailAddressDetail.class).getText();
- BirthDateDetail newBirthDateDetail
- = new ServerStoredDetails.BirthDateDetail(birthDateCalendar);
+ EmailAddressDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new EmailAddressDetail(text);
- if (birthDateDetail == null)
- accountInfoOpSet.addDetail(newBirthDateDetail);
- else
- accountInfoOpSet.replaceDetail( birthDateDetail,
- newBirthDateDetail);
+ if (emailDetail != null || newDetail != null)
+ changeDetail(emailDetail, newDetail);
+ }
- EmailAddressDetail newEmailDetail
- = new ServerStoredDetails.EmailAddressDetail(email);
+ if (accountInfoOpSet.isDetailClassSupported(
+ WorkEmailAddressDetail.class))
+ {
+ String text =
+ detailToTextField.get(WorkEmailAddressDetail.class)
+ .getText();
- if (emailDetail == null)
- accountInfoOpSet.addDetail(newEmailDetail);
- else
- accountInfoOpSet.replaceDetail( emailDetail,
- newEmailDetail);
+ WorkEmailAddressDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new WorkEmailAddressDetail(text);
- PhoneNumberDetail newPhoneDetail
- = new ServerStoredDetails.PhoneNumberDetail(phoneNumber);
+ if (workEmailDetail != null || newDetail != null)
+ changeDetail(workEmailDetail, newDetail);
+ }
- if (phoneDetail == null)
- accountInfoOpSet.addDetail(newPhoneDetail);
- else
- accountInfoOpSet.replaceDetail( phoneDetail,
- newPhoneDetail);
+ if (accountInfoOpSet.isDetailClassSupported(
+ PhoneNumberDetail.class))
+ {
+ String text =
+ detailToTextField.get(PhoneNumberDetail.class).getText();
- BinaryDetail newAvatarDetail
- = new ServerStoredDetails.BinaryDetail(
- "Avatar",
- newAvatarImage);
+ PhoneNumberDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new PhoneNumberDetail(text);
- if (avatarDetail == null)
- accountInfoOpSet.addDetail(newAvatarDetail);
- else
- accountInfoOpSet.replaceDetail( avatarDetail,
- newAvatarDetail);
+ if (phoneDetail != null || newDetail != null)
+ changeDetail(phoneDetail, newDetail);
}
- catch (ClassCastException e1)
+ if (accountInfoOpSet.isDetailClassSupported(
+ WorkPhoneDetail.class))
{
- logger.error("Failed to update account details.", e1);
+ String text =
+ detailToTextField.get(WorkPhoneDetail.class).getText();
+
+ WorkPhoneDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new WorkPhoneDetail(text);
+
+ if (workPhoneDetail != null || newDetail != null)
+ changeDetail(workPhoneDetail, newDetail);
}
- catch (OperationFailedException e1)
+ if (accountInfoOpSet.isDetailClassSupported(
+ WorkOrganizationNameDetail.class))
{
- logger.error("Failed to update account details.", e1);
- }
- }
- }
+ String text =
+ detailToTextField.get(WorkOrganizationNameDetail.class)
+ .getText();
- private class ChangeAvatarActionListener implements ActionListener
- {
- public void actionPerformed(ActionEvent e)
- {
- SipCommFileChooser chooser = GenericFileDialog.create(
- null, "Change avatar...",
- SipCommFileChooser.LOAD_FILE_OPERATION,
- lastAvatarDir.getAbsolutePath());
- chooser.addFilter(new ImageFilter());
+ WorkOrganizationNameDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new WorkOrganizationNameDetail(text);
- File file = chooser.getFileFromDialog();
+ if (organizationDetail != null || newDetail != null)
+ changeDetail(organizationDetail, newDetail);
+ }
- if (file != null)
+ if (accountInfoOpSet.isDetailClassSupported(JobTitleDetail.class))
{
- try
- {
- lastAvatarDir = file.getParentFile();
+ String text =
+ detailToTextField.get(JobTitleDetail.class)
+ .getText();
- FileInputStream in = new FileInputStream(file);
- byte[] buffer;
+ JobTitleDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new JobTitleDetail(text);
- try
- {
- buffer = new byte[in.available()];
- in.read(buffer);
- }
- finally
- {
- in.close();
- }
- if (buffer == null || buffer.length <= 0)
- return;
+ if (jobTitleDetail != null || newDetail != null)
+ changeDetail(jobTitleDetail, newDetail);
+ }
+ if (accountInfoOpSet.isDetailClassSupported(AboutMeDetail.class))
+ {
+ String text =
+ aboutMeArea.getText();
- newAvatarImage = buffer;
+ AboutMeDetail newDetail = null;
+ if (!StringUtils.isNullOrEmpty(text, true))
+ newDetail = new AboutMeDetail(text);
- avatarImageIcon = new ImageIcon(
- getScaledImageInstance(newAvatarImage));
- avatarLabel.setIcon(avatarImageIcon);
- }
- catch (IOException ex)
- {
- logger.error("Failed to load image.", ex);
- }
+ if (aboutMeDetail != null || newDetail != null)
+ changeDetail(aboutMeDetail, newDetail);
+ }
+
+ try
+ {
+ AccountInfoMenuItemComponent.dialog.setVisible(false);
+ mainScrollPane.getVerticalScrollBar().setValue(0);
+ accountInfoOpSet.save();
+ }
+ catch (OperationFailedException e1)
+ {
+ logger.debug("Failed to update account details.", e1);
}
}
- }
- /**
- * A custom filter that would accept only image files.
- */
- private static class ImageFilter extends SipCommFileFilter
- {
/**
- * Accept all directories and all gif, jpg, tiff, or png files.
- * Method implemented from FileFilter abstract class.
- *
- * @param f a file to accept or not
+ * A helper method to decide whether to add new
+ * ServerStoredDetails or to replace an old one.
+ * @param oldDetail the detail to be replaced.
+ * @param newDetail the replacement.
*/
- @Override
- public boolean accept(File f)
+ private void changeDetail( GenericDetail oldDetail,
+ GenericDetail newDetail)
{
- if (f.isDirectory())
- {
- return true;
- }
-
- String extension = getExtension(f);
- if (extension != null)
+ try
{
- if (extension.equals("tiff") ||
- extension.equals("tif") ||
- extension.equals("gif") ||
- extension.equals("jpeg") ||
- extension.equals("jpg") ||
- extension.equals("png"))
+ if (newDetail == null)
+ {
+ accountInfoOpSet.removeDetail(oldDetail);
+ }
+ else if (oldDetail == null)
{
- return true;
+ accountInfoOpSet.addDetail(newDetail);
}
else
{
- return false;
+ accountInfoOpSet.replaceDetail(oldDetail, newDetail);
}
}
-
- return false;
- }
-
- /**
- * Get the extension of a file.
- *
- * @param f the file
- * @return the extension of the file
- */
- public String getExtension(File f)
- {
- String ext = null;
- String s = f.getName();
- int i = s.lastIndexOf('.');
-
- if (i > 0 && i < s.length() - 1) {
- ext = s.substring(i+1).toLowerCase();
+ catch (ArrayIndexOutOfBoundsException e1)
+ {
+ logger.debug("Failed to update account details. " +
+ newDetail.getDetailDisplayName() + " " + e1);
+ }
+ catch (OperationFailedException e1)
+ {
+ logger.debug("Failed to update account details. " +
+ newDetail.getDetailDisplayName() + " " + e1);
}
- return ext;
- }
-
- /**
- * The description of this filter.
- */
- @Override
- public String getDescription()
- {
- return Resources.getString("plugin.accountinfo.ONLY_MESSAGE");
- }
-
- }
-
- /**
- * Returns a scaled Image instance of the given byte image.
- *
- * @param image the image in bytes
- * @return a scaled Image instance of the given byte image.
- */
- private Image getScaledImageInstance(byte[] image)
- {
- Image resultImage = null;
-
- try
- {
- resultImage = ImageIO.read(
- new ByteArrayInputStream(image));
- }
- catch (Exception e)
- {
- logger.error("Failed to convert bytes to image.", e);
}
-
- if(resultImage == null)
- return null;
-
- return resultImage.getScaledInstance(
- avatarLabel.getWidth(),
- avatarLabel.getHeight(),
- Image.SCALE_SMOOTH);
- }
-
- /**
- * Returns true if the account details are loaded,
- * false - otherwise.
- *
- * @return true if the account details are loaded,
- * false - otherwise
- */
- public boolean isDataLoaded()
- {
- return isDataLoaded;
- }
-
- /**
- * Loads the avatar default icon.
- */
- public void loadSkin()
- {
- avatarLabel.setIcon(Resources.getImage("accountInfoDefaultPersonIcon"));
}
}
diff --git a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java
index 9f34c9ca9..6e1692b8e 100644
--- a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java
+++ b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java
@@ -8,7 +8,8 @@
import java.util.*;
-import net.java.sip.communicator.service.browserlauncher.*;
+import net.java.sip.communicator.service.globaldisplaydetails.*;
+import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
@@ -18,6 +19,7 @@
* Starts the account info bundle.
*
* @author Adam Glodstein
+ * @author Marin Dzhigarov
*/
public class AccountInfoActivator
implements BundleActivator
@@ -30,21 +32,52 @@ public class AccountInfoActivator
*/
public static BundleContext bundleContext;
- private static BrowserLauncherService browserLauncherService;
+ private static GlobalDisplayDetailsService globalDisplayDetailsService;
public void start(BundleContext bc) throws Exception
{
AccountInfoActivator.bundleContext = bc;
-// new LazyConfigurationForm(
-// "net.java.sip.communicator.plugin.accountinfo.AccountInfoPanel",
-// getClass().getClassLoader(), "plugin.accountinfo.PLUGIN_ICON",
-// "plugin.accountinfo.TITLE");
+ Hashtable containerFilter
+ = new Hashtable();
+ containerFilter.put(
+ Container.CONTAINER_ID,
+ Container.CONTAINER_TOOLS_MENU.getID());
+
+ bundleContext.registerService(
+ PluginComponentFactory.class.getName(),
+ new PluginComponentFactory(Container.CONTAINER_TOOLS_MENU)
+ {
+ @Override
+ protected PluginComponent getPluginInstance()
+ {
+ return new AccountInfoMenuItemComponent(
+ getContainer(), this);
+ }
+ },
+ containerFilter);
+
+ containerFilter = new Hashtable();
+ containerFilter.put(
+ Container.CONTAINER_ID,
+ Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU.getID());
+
+ bundleContext.registerService(
+ PluginComponentFactory.class.getName(),
+ new PluginComponentFactory(
+ Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU)
+ {
+ @Override
+ protected PluginComponent getPluginInstance()
+ {
+ return new AccountInfoMenuItemComponent(
+ getContainer(), this);
+ }
+ },
+ containerFilter);
}
- public void stop(BundleContext bc) throws Exception
- {
- }
+ public void stop(BundleContext bc) throws Exception {}
/**
* Returns all ProtocolProviderFactorys obtained from the bundle
@@ -53,7 +86,8 @@ public void stop(BundleContext bc) throws Exception
* @return all ProtocolProviderFactorys obtained from the bundle
* context
*/
- public static Map