From e9de32d9ce47a826be4c35997502d0360490f9be Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Wed, 28 Aug 2013 16:32:42 +0300 Subject: [PATCH] Adds web page button, if contacts has web page detail, shows a button to open that page. --- resources/images/images.properties | 3 + .../images/impl/gui/buttons/webButton.png | Bin 0 -> 1516 bytes .../impl/gui/buttons/webButtonPressed.png | Bin 0 -> 1750 bytes .../impl/gui/buttons/webButtonSelected.png | Bin 0 -> 1861 bytes resources/languages/resources.properties | 1 + .../ContactListTreeCellRenderer.java | 269 ++++++++++++++++++ .../impl/gui/utils/ImageLoader.java | 18 ++ .../impl/protocol/jabber/InfoRetreiver.java | 9 + .../plugin/desktoputil/ExtendedPopupMenu.java | 139 +++++++++ 9 files changed, 439 insertions(+) create mode 100644 resources/images/impl/gui/buttons/webButton.png create mode 100644 resources/images/impl/gui/buttons/webButtonPressed.png create mode 100644 resources/images/impl/gui/buttons/webButtonSelected.png create mode 100644 src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java diff --git a/resources/images/images.properties b/resources/images/images.properties index 845549752..3ba9849cf 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -150,6 +150,9 @@ service.gui.buttons.CHAT_BUTTON_SMALL_WHITE=resources/images/impl/gui/buttons/ch service.gui.buttons.ADD_CONTACT_BUTTON_SMALL=resources/images/impl/gui/buttons/addContactSmall.png service.gui.buttons.ADD_CONTACT_BUTTON_SMALL_PRESSED=resources/images/impl/gui/buttons/addContactSmallPressed.png service.gui.buttons.ADD_CONTACT_BUTTON_SMALL_ROLLOVER=resources/images/impl/gui/buttons/addContactSmallRollover.png +service.gui.buttons.WEB_BUTTON=resources/images/impl/gui/buttons/webButton.png +service.gui.buttons.WEB_BUTTON_PRESSED=resources/images/impl/gui/buttons/webButtonPressed.png +service.gui.buttons.WEB_BUTTON_ROLLOVER=resources/images/impl/gui/buttons/webButtonSelected.png service.gui.buttons.HANGUP_BUTTON_BG=resources/images/impl/gui/buttons/hangupButton.png service.gui.buttons.HANGUP_BUTTON_ROLLOVER=resources/images/impl/gui/buttons/hangupButtonRollover.png service.gui.buttons.HANGUP_BUTTON_PRESSED=resources/images/impl/gui/buttons/hangupButtonPressed.png diff --git a/resources/images/impl/gui/buttons/webButton.png b/resources/images/impl/gui/buttons/webButton.png new file mode 100644 index 0000000000000000000000000000000000000000..496991fc42bddb9380a4fd16da3356d5df2555df GIT binary patch literal 1516 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)t!3HFg#O7xMDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49ppsArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XRMoSU}&gdW~OIo zVrph)sH0$HU}&Uo07PcGh9*{~W>!Y#3Q(W~w5=#5%__*n4QdyVXRDM^Qc_^0uU}qX zu2*iXmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY0?5R~r2Ntn zTP2`NAzsKW@b!fooL3ADC}5E3S0onb8|oS8=jMX^1y)^L5|oN?23FO@A(aKG`a!A1 z`K3k4!1zd0hG_np+{nPp!qCvt+`_`i(bC1z$jQyX(#;WO1~$DGrj8b-PG(MS&c=?0hOUNAP8ODq z#%4|~Zq6}%WQgQ3eRC^EULXqRPSE4kcG`56r^DS+TU1PDOyJOq+rP*vJ#e`bc zXr7(q$RW}+h3oBuC-SSh7nZE>d|<%A&K}Ao-k*@PV#g70l?f>xC-!^mU4P%ad2)G{ zkkwuOeRtk}uiIZOf3Ny`-SLcB*S_1cB{%9^*zdStbxHI0WeaUraHcN!eqqAG{eBKN z=4WodE$N{t!WFbN%C_A%duvp;E%VC>+)W>B_A^~xa{qmNhKW?=ixuh$O)FM;WnNSn7hf#* zP%-L$$^F7k!T!WNzvYX|cGoV_7P$6ZYpR#b%9AZl3(Z&b^Bj1ewt1(EK;*Q_*=N6T zx&O9iOZ+FqXD`xyG=9eFr$v>T6Ft@lGCW{*6xjEpX5V%TtAty6X$m�n>$-=(awp z_Fj5P)8Y5Qgb%WfMLT8Mll>R$zW#0LMYb;@0)m-Af(Nx~Y*h~c6``}O?fdbQou{8xEzmf{=D6wRng?I2mhWNQr(EAyp_4V$;*pIusQmSG^>bP0l+XkKfGjJx literal 0 HcmV?d00001 diff --git a/resources/images/impl/gui/buttons/webButtonPressed.png b/resources/images/impl/gui/buttons/webButtonPressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9b91e44a06296524440fc39a813c01f709ee375f GIT binary patch literal 1750 zcmbVNc~BE~6b=>;0%8wT3bt+|mmo`A%9~rXz<>iQrfw8cQa!R5(HrX|N;&km*$^hyqb* zveTQ901D*;Evk$qV&!3w8q?EN78|-*ZzRzaO2BHfQKi-)1dxQJpavmrto|AeKs7?z zdXAhaH%bsK8k&P6(K+Etb&gIg(9l)~0s&@-B+w&-3NY)_3?|4dq)qce}Hc4{^8)NzLeLxK^0&kW(`=&1lrhXIBLk!}8G5}Xu4!u%p+NqX@lI=# zGTVqS6o?7Sz}4h=Brl%>lev4pBa0!a28zH@@=#Q1Fs9DXBL+eS3u)vRx(3xiQkW+N zL7qR8$6|8%ASmGR`C^d(7O=!pra&s1<9HXA&k^xCVlGcAVT(X87!-^70uh@lhNTji z$>Ff(urh;*P#M(7oL`jmJB#JM7Yj*nL`7h@62sEwDj-se5tvDf839Q&7x0#=)TqI- zvBGjdGx5R*j%FenDURuZ=?p{YI~0ic{%o;`#}i3rBIh&tY^exjvDjR`h@8`Av6}yr zH3lh$VJVOQl*`-}S%a48+u|n|Z`%hkkUfKw&GAct(;KqqtYxrBY3{zfE+VX5< zZ7QxQX=s4&d76^CHdZ?staa>&_>#MVj2&qi={vdc$nd}|`xYo@?SU=&3tI(@?cqUP zUmQE)(FkjO!nWcc`aH>X>uva>Z0y;teyo4~!aFYm$DZeVINEO6oM;t8S$Hgp`boic z`dOzNYl7g=hgMKIKb^uy?ZD6Z2Y$C%lo)w;$R~5W!ltGcxxC?F$+!pS^tDKSV&1m5ci;s;lpFT^th} zju-AB2qHilH}2`_*;fc356R2R>%Ma3N~lEAI2zV}B4urRU*FW8X3e4E-Mif;(qO3= zDDv7bYd=<=-Bs9e^30i0tDQF?9t2HN-S;bfIPUwKZx6)Z9K>5{)>ZqBxfT}}SN_`4 zQVx|G+J}hlL0qsv8v5Yrq*Y+qSDk}+-pJ5U+t|p+$e$&3-Q62JkG5WQDT2jL1&x6$ z7RzPlO)+&_1NC&gslK;tLtI=!PQd30w|8tWDDZf3x@#}X$~k7jeEIsrhpEm^^_x3N zzay`Z(Z2hmnM-QDOjUc=lvh1`^l05$_kD3}Hv93u4aK393^(w7Cxda5ca25z^uu4r4eb?`huOCe2`D-|#SAlrO;w4K;fBUhlv!qEgwr!iuvi4hBsUJN% z8|6^1sLU;`oyf0E(MW@DOh)2?2iKI!uZ0BtRO-wbC>fvSI={#T=x#}wbj&BS^hM#;Bfc{apLBG E0Gd#uJOBUy literal 0 HcmV?d00001 diff --git a/resources/images/impl/gui/buttons/webButtonSelected.png b/resources/images/impl/gui/buttons/webButtonSelected.png new file mode 100644 index 0000000000000000000000000000000000000000..9ed5ad04ea4dfd096af230a596b69a53e6026865 GIT binary patch literal 1861 zcmbVNX;c$u6paX?2vk5Vg5nTSkt3Oz1VR#wk`)3ZVn{L6iiBj4KsF~s2~?;>Q9)^o z7FM~x>V`-S&`wxve|Y@SIWzMu^X`53z3;s+dlVai8SS(3~A_SH~8-oA>wQM~iMr4ZQ z4Oft51j6Jvr9_HJg`o_&R!x$bZAb>S4o4FR%T^e4GI;`m0WrvWrG`m-T62*IC>2cN zYF{BF)NznFWl#!=gr|rk@{|NQT|r#299U*x-~?&}lK}>`N~32On8ZqYxD~y7`TXD zjw*GSQmX;XjItPQBE}@*O2x9C$#2Wp0qVSY~2AK|oNf4-3o8ua_)?;GiUm5ST z)=QFg2q;GM+C)^2pGWM12{4|!_d7Bh;%XQxQ6+vTG8I=VPgElsOu%Il@h>EWQo-PJ z{rE8K=L7kXAu0`q>3%dCn?>i+$!tDE=d&g_-ihV#I1r6Zg>XC!^T=#2i$#NA7MIMY z^VlqS0xQtyF_}h=O!!rr{f=RM--~5%P(+4lQHfTony7%VI4!2t$7yu{C!7j+3T1Mo z#=Nn_d_ZIIauHPdDWc$`S~W15VTSS@3OFn_4Udz>hsGkOK{N`V1(V4XDvgEDiQ`zs z|H&GNivi8$@t<;;*urbjJbhdI_~LE*AR4@9P`o*Euf4FqdrmLlvLuG~%DlBfyH`2? z^tulV4hgBuxp~8O+tJRJj8ve6uZZg7H@JJH**;lxHNXU&o6&M(=@T~lxRY&`aRyki zL?7rJ(fUXK)f_0lcg!?E!8<9?M*25J{! z8FJ)k>>oeQEx%P57PmS0ND~U3%xH?9t;Qb;0|YpiT#LDisgLE?N%(z zJ)maE)*;s>A1J7f9XM?@eq~;JC>|V6>l_#uus$eS{P4Nq`eZjdCxqKX|739Y7oIb- zrh9vP-=a_`J0cvFC+T$0E(8FE z_V)H7V`t~92#Lg)`O0lUWKe4AuoE@^AQOTPUq0>P5NX{o-+r6Gh8&X@O{SkLF8=JB zLx<9es;XYk12~@FCZ3XRbkrx~4hQ=CE8SyPLHk0dp_Pfwjq#_K_q_b;j_J*ttvx+G z{ngdg{@vZ(e|B|sS$n1j|Ijw{kymbQWk+9#HQr){w{!FID(G|V@BRL&G(U8aeC5iO z$8SAavnR;o7t5Ga(%R;hmRhTZISF>+#D&j`N^5G?{Ax6Av~ure@!a=ZOKek}QA=7E zZXu~L40EhDDSTXRY-smLYrgXEMcuJu$Lw>0umqJ#^>g?0p)Kh>O7lx(k0u@k&zL%y33^}PflYT6n**e_qC=E z)7?^-{{AMWLt|kf$Cp`BRCF%0bRFxC_3f{Dn}!0;-tB$$Ci#V*=(oVe?8v*};o+h! z*>*CP$BWKl`qb@tbrkk_2ahbT zLQli>tf2?GT~oq(V6=`988pA`h_%x$EX8J$;%SFP!X@5IJ69mC~7px=b*ybOb MfG6UXvZK@g0R)8CdH?_b literal 0 HcmV?d00001 diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 96a10e60a..20fbea494 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -507,6 +507,7 @@ service.gui.UNMUTE=Unmute service.gui.USER_IDENTIFIER=User identifier: service.gui.USER_EXISTS_ERROR=This user already exists on the selected network. Please choose another user or network. service.gui.USERNAME_NULL=Please fill your username and password. +service.gui.WEBPAGE=Open web page service.gui.ACCOUNT_CREATION_FAILED=We failed to create your account due to the following error: {0} service.gui.UNKNOWN=Unknown user service.gui.UNKNOWN_STATUS=Unknown state diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java index 991281ca9..25e1f8648 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java @@ -169,6 +169,11 @@ public class ContactListTreeCellRenderer */ private final SIPCommButton chatButton = new SIPCommButton(); + /** + * The web button. + */ + private final SIPCommButton webButton = new SIPCommButton(); + /** * The add contact button. */ @@ -338,6 +343,13 @@ public void actionPerformed(ActionEvent e) } } }); + webButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + openURL(treeContactList, treeNode, webButton); + } + }); initButtonToolTips(); this.setToolTipText(""); @@ -483,6 +495,7 @@ else if (value instanceof GroupNode) this.remove(desktopSharingButton); this.remove(chatButton); this.remove(addContactButton); + this.remove(webButton); clearCustomActionButtons(); @@ -748,6 +761,7 @@ private void initButtonsPanel(UIContact uiContact) this.remove(callVideoButton); this.remove(desktopSharingButton); this.remove(addContactButton); + this.remove(webButton); clearCustomActionButtons(); @@ -848,6 +862,13 @@ private void initButtonsPanel(UIContact uiContact) x += addButton(addContactButton, ++gridX, x, false); } + //webButton + if (uiContact.getDescriptor() instanceof MetaContact) + { + if(containsWebPageDetail(uiContact)) + x += addButton(webButton, ++gridX, x, false); + } + // The list of the contact actions // we will create a button for every action Collection contactActions @@ -1245,6 +1266,7 @@ public void resetRolloverState() callVideoButton.getModel().setRollover(false); desktopSharingButton.getModel().setRollover(false); addContactButton.getModel().setRollover(false); + webButton.getModel().setRollover(false); if (customActionButtons != null) { @@ -1290,6 +1312,9 @@ public void resetRolloverState(Component excludeComponent) if (!addContactButton.equals(excludeComponent)) addContactButton.getModel().setRollover(false); + if (!webButton.equals(excludeComponent)) + webButton.getModel().setRollover(false); + if (customActionButtons != null) { Iterator buttonsIter = customActionButtons.iterator(); @@ -1376,6 +1401,247 @@ public void loadSkin() ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_ROLLOVER)); addContactButton.setPressedIcon( ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED)); + + webButton.setIconImage( + ImageLoader.getImage(ImageLoader.WEB_BUTTON)); + webButton.setRolloverIcon( + ImageLoader.getImage(ImageLoader.WEB_BUTTON_ROLLOVER)); + webButton.setPressedIcon( + ImageLoader.getImage(ImageLoader.WEB_BUTTON_PRESSED)); + } + + /** + * Listens for contact details if not cached, we will receive when they + * are retrieved to update current web button state, if meanwhile + * user hasn't changed the current contact. + */ + private class WebDetailsListener + implements OperationSetServerStoredContactInfo.DetailsResponseListener + { + /** + * The source this listener is created for, if current tree node + * changes ignore any event. + */ + private Object source; + + /** + * The button to change. + */ + private JButton webButton; + + /** + * The ui contact to update after changes. + */ + private UIContact uiContact; + + /** + * Create listener. + * @param source the contact this listener is for, if different + * than current ignore. + * @param webButton + * @param uiContact the contact to refresh + */ + WebDetailsListener(Object source, JButton webButton, UIContact uiContact) + { + this.source = source; + this.webButton = webButton; + this.uiContact = uiContact; + } + + /** + * Details have been retrieved. + * @param details the details retrieved if any. + */ + public void detailsRetrieved(Iterator details) + { + // if treenode has changed ignore + if(!source.equals(treeNode)) + return; + + while(details.hasNext()) + { + GenericDetail d = details.next(); + + if(d instanceof WebPageDetail) + { + final WebPageDetail webd = (WebPageDetail)d; + if(webd.getDetailValue() != null) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + webButton.setEnabled(true); + + treeContactList.refreshContact(uiContact); + } + }); + + return; + } + } + } + } + } + + /** + * Checks for existence of at least single web page detail. + * @param uiContact the contact to check + * @return true if at least one detail available, false otherwise. + */ + private boolean containsWebPageDetail(UIContact uiContact) + { + WebDetailsListener webDetailsListener = + new WebDetailsListener(treeNode, webButton, uiContact); + + return getWebPageDetails(uiContact, webDetailsListener, true) != null; + } + + /** + * Retrieves all web page details for the supplied uiContact. + * @param uiContact the contacts + * @param webDetailsListener the listener to wait for details retrieval, + * or null of we do not want to wait + * @param returnFirst should we return after founding the first one, + * used for check whether such detail exist + * @return list of details or null if currently not available + */ + private static List getWebPageDetails( + UIContact uiContact, + WebDetailsListener webDetailsListener, + boolean returnFirst) + { + Iterator contacts + = ((MetaContact)uiContact.getDescriptor()) + .getContactsForOperationSet( + OperationSetServerStoredContactInfo.class).iterator(); + + List res = new ArrayList(); + + boolean foundWebLink = false; + while (contacts.hasNext()) + { + Contact contact = contacts.next(); + OperationSetServerStoredContactInfo opset + = contact.getProtocolProvider().getOperationSet( + OperationSetServerStoredContactInfo.class); + + Iterator iter = + opset.requestAllDetailsForContact( + contact, webDetailsListener); + + if(iter == null) + continue; + + while(iter.hasNext()) + { + GenericDetail d = iter.next(); + if(d instanceof WebPageDetail) + { + final WebPageDetail webd = (WebPageDetail)d; + if(webd.getDetailValue() != null) + { + res.add(webd); + + if(returnFirst) + { + foundWebLink = true; + break; + } + } + } + } + + if(returnFirst && foundWebLink) + break; + } + + if(returnFirst) + { + if(res.isEmpty()) + return null; + } + + return res; + } + + /** + * Opens url, used from webButton. + * @param treeContactList the contactlist component + * @param treeNode the currently selected node + * @param button the button that was clicked + */ + private static void openURL( + TreeContactList treeContactList, TreeNode treeNode, JButton button) + { + if (treeNode != null && treeNode instanceof ContactNode) + { + UIContact contactDescriptor + = ((ContactNode) treeNode).getContactDescriptor(); + + if (contactDescriptor instanceof MetaUIContact) + { + List details = + getWebPageDetails(contactDescriptor, null, false); + + if(details == null) + return; + + if(details.size() == 1) + { + GuiActivator.getBrowserLauncher().openURL( + details.get(0).getURL().toString()); + } + else + { + Point location = new Point(button.getX(), + button.getY() + button.getHeight()); + + SwingUtilities.convertPointToScreen( + location, treeContactList); + + location.y = location.y + + treeContactList.getPathBounds( + treeContactList.getSelectionPath()).y; + location.x += 8; + location.y -= 8; + + List items = new ArrayList(); + Iterator detailIterator = details.iterator(); + while(detailIterator.hasNext()) + { + final WebPageDetail wd = detailIterator.next(); + String url = wd.getDetailValue().toString(); + + String displayStr = url; + // do not display too long links + if(displayStr.length() > 60) + { + displayStr = displayStr.substring(0, 60); + displayStr += "..."; + } + final JMenuItem menuItem = new JMenuItem(displayStr); + menuItem.setName(url); + menuItem.setToolTipText(url); + + menuItem.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + GuiActivator.getBrowserLauncher().openURL( + menuItem.getName()); + } + }); + items.add(menuItem); + } + + new ExtendedPopupMenu( + treeContactList, + null, + items).showPopupMenu(location.x, location.y); + } + } + } } /** @@ -1572,6 +1838,8 @@ private void initButtonToolTips() .getI18NString("service.gui.SEND_MESSAGE")); addContactButton.setToolTipText(GuiActivator.getResources() .getI18NString("service.gui.ADD_CONTACT")); + webButton.setToolTipText(GuiActivator.getResources() + .getI18NString("service.gui.WEBPAGE")); // We need to explicitly remove the buttons from the tooltip manager, // because we're going to manager the tooltip ourselves in the @@ -1583,5 +1851,6 @@ private void initButtonToolTips() ttManager.unregisterComponent(desktopSharingButton); ttManager.unregisterComponent(chatButton); ttManager.unregisterComponent(addContactButton); + ttManager.unregisterComponent(webButton); } } 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 cbb4780a4..5598b87c9 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java +++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java @@ -328,6 +328,24 @@ public class ImageLoader public static final ImageID ADD_CONTACT_BUTTON_SMALL_PRESSED = new ImageID("service.gui.buttons.ADD_CONTACT_BUTTON_SMALL_PRESSED"); + /** + * The web button image. + */ + public static final ImageID WEB_BUTTON + = new ImageID("service.gui.buttons.WEB_BUTTON"); + + /** + * The call web pressed image. + */ + public static final ImageID WEB_BUTTON_ROLLOVER + = new ImageID("service.gui.buttons.WEB_BUTTON_ROLLOVER"); + + /** + * The web button pressed image. + */ + public static final ImageID WEB_BUTTON_PRESSED + = new ImageID("service.gui.buttons.WEB_BUTTON_PRESSED"); + /** * The chat button small image. */ 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 5f087c5ab..af1be57e1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java @@ -7,6 +7,7 @@ package net.java.sip.communicator.impl.protocol.jabber; import java.lang.reflect.*; +import java.net.*; import java.util.*; import net.java.sip.communicator.service.protocol.ServerStoredDetails.*; @@ -288,6 +289,14 @@ protected List retrieveDetails(String contactAddress) 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))); + } + catch(MalformedURLException e){} } catch (Throwable exc) { diff --git a/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java b/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java new file mode 100644 index 000000000..796d306cd --- /dev/null +++ b/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java @@ -0,0 +1,139 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.desktoputil; + +import net.java.sip.communicator.util.skin.*; + +import javax.swing.*; +import java.awt.*; +import java.util.List; + +/** + * The ExtendedPopupMenu is the dialog shown to let the user choose + * from several options. + * + * @author Damian Minkov + */ +public class ExtendedPopupMenu + extends SIPCommPopupMenu + implements Skinnable +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The invoker component. + */ + private final JComponent invoker; + + /** + * Creates this dialog by specifying a list of items to choose from. + * + * @param invoker the invoker of this pop up + * @param title + * @param menuItems the list of items to select through + */ + public ExtendedPopupMenu(JComponent invoker, + String title, + List menuItems) + { + if (invoker != null) + this.invoker = invoker; + else + this.invoker = new JPanel(); + + this.init(title); + + for (JMenuItem menuItem : menuItems) + { + this.add(menuItem); + } + } + + /** + * Initializes and add some common components. + * + * @param infoString the string we'd like to show on the top of this + * popup menu + */ + private void init(String infoString) + { + setInvoker(invoker); + + if(infoString != null) + { + this.add(createInfoLabel(infoString)); + + this.addSeparator(); + } + + this.setFocusable(true); + } + + /** + * Shows the dialog at the given location. + * + * @param x the x coordinate + * @param y the y coordinate + */ + public void showPopupMenu(int x, int y) + { + setLocation(x, y); + setVisible(true); + } + + /** + * Shows this popup menu regarding to its invoker location. + */ + public void showPopupMenu() + { + Point location = new Point(invoker.getX(), + invoker.getY() + invoker.getHeight()); + + SwingUtilities + .convertPointToScreen(location, invoker.getParent()); + setLocation(location); + setVisible(true); + } + + /** + * Creates the info label. + * + * @param infoString the string we'd like to show on the top of this + * popup menu + * @return the created info label + */ + private Component createInfoLabel(String infoString) + { + JMenuItem infoLabel = new JMenuItem(); + + infoLabel.setEnabled(false); + infoLabel.setFocusable(false); + + infoLabel.setText("" + infoString + ""); + + return infoLabel; + } + + /** + * Reloads all menu items. + */ + public void loadSkin() + { + Component[] components = getComponents(); + for(Component component : components) + { + if(component instanceof Skinnable) + { + Skinnable skinnableComponent = (Skinnable) component; + skinnableComponent.loadSkin(); + } + } + } +}