diff --git a/src/java/org/jivesoftware/spark/search/SearchManager.java b/src/java/org/jivesoftware/spark/search/SearchManager.java index 750d6ab8..e35d78e1 100644 --- a/src/java/org/jivesoftware/spark/search/SearchManager.java +++ b/src/java/org/jivesoftware/spark/search/SearchManager.java @@ -34,6 +34,7 @@ import java.util.List; public class SearchManager { private List searchServices = new ArrayList(); private SearchService ui; + private Collection _searchservicesHosts; private static SearchManager singleton; private static final Object LOCK = new Object(); @@ -64,7 +65,6 @@ public class SearchManager { // By default, the user search is first. SwingWorker worker = new SwingWorker() { UserSearchService searchWizard; - public Object construct() { searchWizard = new UserSearchService(); return searchWizard; @@ -74,6 +74,7 @@ public class SearchManager { if (searchWizard.getSearchServices() != null) { ui.setActiveSearchService(searchWizard); addSearchService(searchWizard); + _searchservicesHosts = searchWizard.getSearchServices(); } } }; @@ -115,6 +116,15 @@ public class SearchManager { public Collection getSearchServices() { return searchServices; } + /** + * Returns all registered search services. + * + * @return the collection of search services. + */ + public Collection getSearchServicesAsString() + { + return _searchservicesHosts; + } private void checkSearchService() { Collection searchables = getSearchServices(); diff --git a/src/java/org/jivesoftware/spark/ui/RosterDialog.java b/src/java/org/jivesoftware/spark/ui/RosterDialog.java index ae3da619..4997c449 100644 --- a/src/java/org/jivesoftware/spark/ui/RosterDialog.java +++ b/src/java/org/jivesoftware/spark/ui/RosterDialog.java @@ -19,39 +19,6 @@ */ package org.jivesoftware.spark.ui; -import org.jivesoftware.resource.Default; -import org.jivesoftware.resource.Res; -import org.jivesoftware.smack.Roster; -import org.jivesoftware.smack.RosterEntry; -import org.jivesoftware.smack.RosterGroup; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.packet.VCard; -import org.jivesoftware.spark.SparkManager; -import org.jivesoftware.spark.UserManager; -import org.jivesoftware.spark.component.TitlePanel; -import org.jivesoftware.spark.component.borders.ComponentTitledBorder; -import org.jivesoftware.spark.component.renderer.JPanelRenderer; -import org.jivesoftware.spark.util.ModelUtil; -import org.jivesoftware.spark.util.ResourceUtils; -import org.jivesoftware.spark.util.SwingWorker; -import org.jivesoftware.spark.util.log.Log; -import org.jivesoftware.sparkimpl.plugin.gateways.Gateway; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; -import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -63,12 +30,59 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Vector; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTextField; +import javax.swing.UIManager; + +import org.jivesoftware.resource.Default; +import org.jivesoftware.resource.Res; +import org.jivesoftware.resource.SparkRes; +import org.jivesoftware.smack.Roster; +import org.jivesoftware.smack.RosterEntry; +import org.jivesoftware.smack.RosterGroup; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.Form; +import org.jivesoftware.smackx.ReportedData; +import org.jivesoftware.smackx.ReportedData.Column; +import org.jivesoftware.smackx.ReportedData.Row; +import org.jivesoftware.smackx.packet.VCard; +import org.jivesoftware.smackx.search.UserSearchManager; +import org.jivesoftware.spark.SparkManager; +import org.jivesoftware.spark.UserManager; +import org.jivesoftware.spark.component.TitlePanel; +import org.jivesoftware.spark.component.borders.ComponentTitledBorder; +import org.jivesoftware.spark.component.renderer.JPanelRenderer; +import org.jivesoftware.spark.search.SearchManager; +import org.jivesoftware.spark.util.ModelUtil; +import org.jivesoftware.spark.util.ResourceUtils; +import org.jivesoftware.spark.util.SwingWorker; +import org.jivesoftware.spark.util.log.Log; +import org.jivesoftware.sparkimpl.plugin.gateways.Gateway; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.Transport; +import org.jivesoftware.sparkimpl.plugin.gateways.transports.TransportUtils; + /** * The RosterDialog is used to add new users to the users XMPP Roster. @@ -86,12 +100,16 @@ public class RosterDialog implements PropertyChangeListener, ActionListener { private JDialog dialog; private ContactList contactList; private JCheckBox publicBox; + private JButton _searchForName ; + private Collection _usersearchservice; /** * Create a new instance of RosterDialog. */ public RosterDialog() { contactList = SparkManager.getWorkspace().getContactList(); + + _usersearchservice = SearchManager.getInstance().getSearchServicesAsString(); panel = new JPanel(); JLabel contactIDLabel = new JLabel(); @@ -108,12 +126,45 @@ public class RosterDialog implements PropertyChangeListener, ActionListener { publicBox = new JCheckBox(Res.getString("label.user.on.public.network")); ResourceUtils.resLabel(accountsLabel, publicBox, Res.getString("label.network")); + + _searchForName = new JButton(); + _searchForName.setIcon(SparkRes.getImageIcon(SparkRes.TRANSFER_IMAGE_24x24)); + + _searchForName.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + try { + searchForContact(jidField.getText(), e); + } catch (XMPPException e1) { + Log.error("search contact", e1); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + }); pane = null; dialog = null; panel.setLayout(new GridBagLayout()); panel.add(contactIDLabel, new GridBagConstraints(0, 0, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); - panel.add(jidField, new GridBagConstraints(1, 0, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(jidField , new GridBagConstraints(1, 0, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(_searchForName, new GridBagConstraints(2, 0, 1, 1, 1.0D, 0.0D, 17, 0, new Insets(5, 5, 5, 5), 0, 0)); + + panel.add(nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); panel.add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0)); @@ -469,6 +520,87 @@ public class RosterDialog implements PropertyChangeListener, ActionListener { rosterEntryThread.start(); } + + /** + * Creates a Popupdialog above the Search Button displaying matching Contacts + * @param byname, the Searchname, atleast 5 Chars long + * @param event, the MouseEvent which triggered it + * @throws XMPPException + */ + public void searchForContact(String byname, MouseEvent event) + throws XMPPException { + + if (byname.length() <= 4) { + JOptionPane.showMessageDialog(jidField, Res.getString("message.search.input.short"), + Res.getString("title.notification"), + JOptionPane.ERROR_MESSAGE); + return; + } + + JPopupMenu popup = new JPopupMenu(); + JMenuItem header = new JMenuItem(Res.getString("group.search.results")+":"); + header.setBackground(UIManager.getColor("List.selectionBackground")); + header.setForeground(Color.red); + popup.add(header); + + for (String search : _usersearchservice) { + + ReportedData data; + UserSearchManager usersearchManager = new UserSearchManager( + SparkManager.getConnection()); + + Form f = usersearchManager.getSearchForm(search); + + Form answer = f.createAnswerForm(); + answer.setAnswer("Name", true); + answer.setAnswer("Email", true); + answer.setAnswer("search", jidField.getText()); + answer.setAnswer("Username", true); + + data = usersearchManager.getSearchResults(answer, + "search.jabber.int.kn"); + + ArrayList columnnames = new ArrayList(); + Iterator columns = data.getColumns(); + while (columns.hasNext()) { + ReportedData.Column column = (ReportedData.Column) columns + .next(); + String label = column.getLabel(); + columnnames.add(label); + } + + Iterator rows = data.getRows(); + while (rows.hasNext()) { + ReportedData.Row row = (ReportedData.Row) rows.next(); + if (row.getValues(columnnames.get(0)).hasNext()) { + String s = (String) row.getValues(columnnames.get(0)) + .next(); + final JMenuItem item = new JMenuItem(s); + popup.add(item); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + jidField.setText(item.getText()); + } + }); + } + + } + } + + if (popup.getComponentCount() > 2) { + popup.setVisible(true); + popup.show(_searchForName, event.getX(), event.getY()); + } else if (popup.getComponentCount() == 2) { + jidField.setText(((JMenuItem) popup.getComponent(1)).getText()); + }else + { + JOptionPane.showMessageDialog(jidField, Res.getString("message.no.results.found"), + Res.getString("title.notification"),JOptionPane.ERROR_MESSAGE); + } + + } + /** * Adds a new entry to the users Roster. diff --git a/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java b/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java index b6da3ff3..c943f416 100644 --- a/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java +++ b/src/java/org/jivesoftware/spark/ui/themes/ThemePanel.java @@ -33,7 +33,6 @@ import org.jivesoftware.sparkimpl.plugin.emoticons.EmoticonManager; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; -import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -49,7 +48,10 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.text.BadLocationException; -import java.awt.*; +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; @@ -156,7 +158,7 @@ public class ThemePanel extends JPanel { _lookandfeel = new JComboBox(lafname); if (Default.getBoolean(Default.LOOK_AND_FEEL_DISABLED)){ - _lookandfeel.disable(); + _lookandfeel.setEnabled(false); } _lookandfeelLabel = new JLabel(Res.getString("lookandfeel.select")); _lookandfeelpreview = new JButton(Res.getString("lookandfeel.change.now")); diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java b/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java index 61dd086c..385fe7b7 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java +++ b/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchResults.java @@ -57,6 +57,8 @@ import java.util.List; * UserSearchResults displays the UI for all users found using the JEP-055 search service. */ public class UserSearchResults extends JPanel { + + private static final long serialVersionUID = 4196389090818949068L; private UsersInfoTable resultsTable; /** diff --git a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java b/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java index 288e3dff..db25196b 100644 --- a/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java +++ b/src/java/org/jivesoftware/sparkimpl/search/users/UserSearchService.java @@ -39,7 +39,7 @@ import java.util.Iterator; import java.util.Set; public class UserSearchService implements Searchable { - private Collection searchServices; + private Collection searchServices; public UserSearchService() { loadSearchServices(); @@ -132,7 +132,7 @@ public class UserSearchService implements Searchable { * @return a Collection of search services found on the server. * @throws XMPPException thrown if a server error has occurred. */ - private Collection getServices() throws Exception { + private Collection getServices() throws Exception { final Set searchServices = new HashSet(); ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); DiscoverItems items = SparkManager.getSessionManager().getDiscoveredItems(); @@ -172,7 +172,7 @@ public class UserSearchService implements Searchable { * * @return the discovered search services. */ - public Collection getSearchServices() { + public Collection getSearchServices() { return searchServices; } diff --git a/src/resources/i18n/spark_i18n.properties b/src/resources/i18n/spark_i18n.properties index 86deecbf..588bf2bf 100644 --- a/src/resources/i18n/spark_i18n.properties +++ b/src/resources/i18n/spark_i18n.properties @@ -734,6 +734,7 @@ message.room.destruction.reason = Reason for destroying the room? message.room.information.for = Room information for {0} message.save.profile = To save changes to your profile, click save message.search.for.contacts = Search for contacts +message.search.input.short = Please provide atleast five letters. message.search.for.other.people = Search for other people on the server message.search.service.not.available = Unable to contact search service message.searching.please.wait = Searching, please wait... diff --git a/src/resources/i18n/spark_i18n_de.properties b/src/resources/i18n/spark_i18n_de.properties index 5c9140c9..524e796e 100644 --- a/src/resources/i18n/spark_i18n_de.properties +++ b/src/resources/i18n/spark_i18n_de.properties @@ -357,6 +357,7 @@ message.send.picture = Bildschirminhalt versenden. message.sent.offline.files = Sie haben offline Dateien gesendet. message.spark.secure = Sichere Verbindung aktiv. message.search.for.contacts = Nach Kontakten suchen. +message.search.input.short = Bitte gib mehr als fünf Zeichen ein. message.end.conversation = Soll diese Sitzung beendet werden? message.end.chat = Soll dieser Chat beendet werden? message.close.this.chat = Diesen Chat schließen