001 /*
002 * Copyright (C) 2003 Adam Olsen
003 * This program is free software; you can redistribute it and/or modify
004 * it under the terms of the GNU General Public License as published by
005 * the Free Software Foundation; either version 1, or (at your option)
006 * any later version.
007 * This program is distributed in the hope that it will be useful,
008 * but WITHOUT ANY WARRANTY; without even the implied warranty of
009 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010 * GNU General Public License for more details.
011 * You should have received a copy of the GNU General Public License
012 * along with this program; if not, write to the Free Software
013 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
014 */
015 package com.valhalla.jbother;
016
017 import java.awt.Container;
018 import java.awt.GridBagConstraints;
019 import java.awt.GridBagLayout;
020 import java.awt.event.ActionEvent;
021 import java.awt.event.ActionListener;
022 import java.awt.event.ItemEvent;
023 import java.awt.event.ItemListener;
024 import java.awt.event.WindowAdapter;
025 import java.awt.event.WindowEvent;
026 import java.util.Iterator;
027 import java.util.Locale;
028 import java.util.ResourceBundle;
029
030 import javax.swing.BorderFactory;
031 import javax.swing.BoxLayout;
032 import javax.swing.DefaultComboBoxModel;
033 import javax.swing.JButton;
034 import javax.swing.JComboBox;
035 import javax.swing.JDialog;
036 import javax.swing.JFrame;
037 import javax.swing.JLabel;
038 import javax.swing.JPanel;
039 import javax.swing.SwingUtilities;
040
041 import org.jivesoftware.smack.Roster;
042 import org.jivesoftware.smack.RosterEntry;
043 import org.jivesoftware.smack.RosterGroup;
044 import org.jivesoftware.smack.XMPPException;
045
046 import com.valhalla.gui.DialogTracker;
047 import com.valhalla.gui.MJTextField;
048 import com.valhalla.gui.NMOptionDialog;
049 import com.valhalla.gui.Standard;
050 import com.valhalla.gui.WaitDialog;
051 import com.valhalla.jbother.jabber.BuddyStatus;
052
053 /**
054 * Displays a dialog allowing to you add or modify a buddy. It displays their
055 * JID, Alias, and group
056 *
057 *@author Adam Olsen
058 *@created September 26, 2005
059 *@version 1.0
060 */
061 public class AddBuddyDialog extends JDialog {
062 private ResourceBundle resources = ResourceBundle.getBundle(
063 "JBotherBundle", Locale.getDefault());
064
065 private JComboBox buddyGroups;
066
067 private MJTextField buddyIDBox = new MJTextField(20);
068
069 private MJTextField buddyAliasBox = new MJTextField(20);
070
071 private MJTextField newGroupBox;
072
073 private JPanel container = new JPanel();
074
075 private RosterEntry entry;
076
077 private String currentGroup = "";
078
079 //the buttons
080 private JButton okButton = new JButton(resources.getString("okButton"));
081
082 private JButton cancelButton = new JButton(resources.getString("cancelButton"));
083
084 //this part is for laying out the rows for the dialog
085 private int row = 0;
086
087 private GridBagLayout grid = new GridBagLayout();
088
089 private GridBagConstraints c = new GridBagConstraints();
090
091 private boolean modify = false;
092
093
094 /**
095 * The add buddy constructor
096 */
097 public AddBuddyDialog() {
098 super(BuddyList.getInstance().getContainerFrame(), "Add/Modify Buddy", false);
099 setTitle(resources.getString("addBuddyDialogTitle"));
100
101 this.initComponents();
102 container.setBorder(BorderFactory.createEmptyBorder(5, 25, 5, 25));
103 container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
104
105 JLabel newBuddyLabel = new JLabel(resources.getString("addBuddyDialogTitle"));
106 newBuddyLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
107 newBuddyLabel.setAlignmentX(Container.CENTER_ALIGNMENT);
108 container.add(newBuddyLabel);
109
110 JPanel newBuddyPanel = new JPanel();
111 newBuddyPanel.setLayout(grid);
112
113 createInputBox(newBuddyPanel, grid, resources.getString("buddyId")
114 + ":", buddyIDBox);
115 createInputBox(newBuddyPanel, grid, resources.getString("alias") + ":",
116 buddyAliasBox);
117 createInputBox(newBuddyPanel, grid, resources.getString("buddyGroup")
118 + ":", buddyGroups);
119 createInputBox(newBuddyPanel, grid, resources.getString("newGroup")
120 + ":", newGroupBox);
121
122 container.add(newBuddyPanel);
123
124 //add the buttons
125 JPanel buttonPanel = new JPanel();
126 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
127 buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
128 buttonPanel.add(okButton);
129 buttonPanel.add(cancelButton);
130
131 container.add(buttonPanel);
132
133 DialogTracker.addDialog(this, true, true);
134 setResizable(false);
135
136 pack();
137 setLocationRelativeTo(null);
138
139 }
140
141
142 /**
143 * Destroys the dialog
144 */
145 public void delete() {
146 DialogTracker.removeDialog(this);
147 }
148
149
150 /**
151 * The modify buddy constructor
152 *
153 *@param entry the entry to modify
154 */
155 public void setBuddy(RosterEntry entry) {
156 this.entry = entry;
157 this.buddyIDBox.setText(entry.getUser());
158 this.buddyIDBox.setEnabled(false);
159 this.modify = true;
160 this.buddyAliasBox.setText(entry.getName());
161
162 String currentGroup = "";
163
164 Iterator iterator = entry.getGroups();
165 while (iterator.hasNext()) {
166 RosterGroup group = (RosterGroup) iterator.next();
167 currentGroup = group.getName();
168 }
169
170 if (!currentGroup.equals("")) {
171 this.currentGroup = currentGroup;
172 }
173
174 //buddyGroups = new JComboBox( getRosterGroups() );
175 buddyGroups.setModel(new DefaultComboBoxModel(getRosterGroups()));
176
177 validate();
178 }
179
180
181 /**
182 * Called by the cancel button - destroys the dialog
183 */
184 private void cancelButtonHandler() {
185 DialogTracker.removeDialog(this);
186 }
187
188
189 /**
190 * Sets the JID in the dialog
191 *
192 *@param id the JID
193 */
194 public void setBuddyId(String id) {
195 buddyIDBox.setText(id);
196 validate();
197 }
198
199
200 /**
201 * Sets up visual components
202 */
203 private void initComponents() {
204 setContentPane(container);
205 buddyGroups = new JComboBox(getRosterGroups());
206 newGroupBox = new MJTextField(15);
207 newGroupBox.setText(resources.getString("newGroup"));
208 newGroupBox.setEnabled(false);
209
210 //add the handlers
211 cancelButton.addActionListener(new ActionHandler());
212 okButton.addActionListener(new ActionHandler());
213 newGroupBox.addActionListener(new ActionHandler());
214 buddyAliasBox.addActionListener(new ActionHandler());
215 buddyGroups.addItemListener(
216 new ItemListener() {
217 public void itemStateChanged(ItemEvent e) {
218 String item = (String) e.getItem();
219 if (item.equals(resources.getString("newGroup"))) {
220 newGroupBox.setEnabled(true);
221 newGroupBox.setText("");
222 newGroupBox.grabFocus();
223 } else {
224 newGroupBox.setEnabled(false);
225 if (newGroupBox.getText().equals("")) {
226 newGroupBox.setText(resources.getString("newGroup"));
227 }
228 }
229 }
230 });
231
232 addWindowListener(
233 new WindowAdapter() {
234 public void windowClosing(WindowEvent e) {
235 cancelButtonHandler();
236 }
237 });
238 }
239
240
241 /**
242 * assures that all required information has been filled out in the dialog
243 *
244 *@return Description of the Return Value
245 */
246 private boolean checkInformation() {
247 if (buddyIDBox.getText().equals("")) {
248 return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("noIdError"));
249 }
250
251 if (buddyAliasBox.getText().equals("")) {
252 return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("noAliasError"));
253 }
254
255 if (buddyGroups.getSelectedItem().equals(
256 resources.getString("newGroup"))) {
257 if (newGroupBox.getText().equals("")
258 || newGroupBox.getText().equals(
259 resources.getString("newGroup"))) {
260 return Standard.warningMessage(this, resources.getString("addBuddyDialogTitle"), resources.getString("newGroupError"));
261 }
262 }
263
264 return true;
265 }
266
267
268 /**
269 * Called by OK button - checks information and adds the buddy
270 */
271 private void okButtonHandler() {
272 if (checkInformation()) {
273 String buddyGroup = (String) buddyGroups.getSelectedItem();
274 if (buddyGroup.equals(resources.getString("newGroup"))) {
275 buddyGroup = newGroupBox.getText();
276 }
277 if (buddyGroup.equals(resources.getString("none"))) {
278 buddyGroup = null;
279 }
280
281 addBuddy(buddyGroup, buddyAliasBox.getText(), buddyIDBox.getText());
282 }
283 }
284
285
286 /**
287 * Handles all button events
288 *
289 *@author Adam Olsen
290 *@created September 26, 2005
291 *@version 1.0
292 */
293 class ActionHandler implements ActionListener {
294 /**
295 * Description of the Method
296 *
297 *@param e Description of the Parameter
298 */
299 public void actionPerformed(ActionEvent e) {
300 if (e.getSource() != cancelButton) {
301 okButtonHandler();
302 } else {
303 cancelButtonHandler();
304 }
305 }
306 }
307
308
309 /**
310 * Creates an input box with a corresponding label
311 *
312 *@param container the container to add the input box to
313 *@param grid the GridBagLayout to use
314 *@param label the label to use
315 *@param box the input box to use
316 */
317 private void createInputBox(Container container, GridBagLayout grid,
318 String label, Container box) {
319 JLabel labelBox = new JLabel(label + " ");
320
321 c.gridy = row++;
322 c.gridx = 0;
323 c.anchor = GridBagConstraints.EAST;
324 grid.setConstraints(labelBox, c);
325 container.add(labelBox);
326
327 c.gridx = 1;
328 c.anchor = GridBagConstraints.WEST;
329 grid.setConstraints(box, c);
330 container.add(box);
331 }
332
333
334 /**
335 * Gets the different available RosterGroups
336 *
337 *@return an array of strings representing the RosterGroups
338 */
339 private String[] getRosterGroups() {
340 Roster roster = ConnectorThread.getInstance().getRoster();
341 String rosterGroups[] = new String[roster.getGroupCount() + 2];
342
343 int i = 0;
344
345 if ((!currentGroup.equals(""))) {
346 rosterGroups[i] = currentGroup;
347 i++;
348 }
349
350 rosterGroups[i++] = resources.getString("none");
351 rosterGroups[i++] = resources.getString("newGroup");
352
353 Iterator iterator = roster.getGroups();
354 while (iterator.hasNext()) {
355 RosterGroup rosterGroup = (RosterGroup) iterator.next();
356 if ((currentGroup.equals(""))
357 || (!rosterGroup.getName().equals(currentGroup))) {
358 rosterGroups[i] = rosterGroup.getName();
359 i++;
360 }
361 }
362
363 return rosterGroups;
364 }
365
366
367 /**
368 * Runs the add buddy thread and adds or modifies a buddy in the Roster
369 *
370 *@param groupName the group to put the buddy in
371 *@param buddyAlias the alias of the buddy
372 *@param buddyId the buddy's JID
373 */
374 private void addBuddy(String groupName, String buddyAlias, String buddyId) {
375 Roster buddyGroups = ConnectorThread.getInstance()
376 .getRoster();
377
378 WaitDialog wait = new WaitDialog(this, null, resources.getString("pleaseWait"));
379 wait.setVisible(true);
380 setVisible(false);
381
382 Thread thread = new Thread(new AddBuddyThread(wait, groupName,
383 buddyAlias, buddyId, this));
384 thread.start();
385 }
386
387
388 /**
389 * Actually adds the buddy to the Roster
390 *
391 *@author Adam Olsen
392 *@created September 26, 2005
393 *@version 1.0
394 */
395 class AddBuddyThread implements Runnable {
396 private String errorMessage;
397
398 private String groupName;
399
400 private String buddyAlias;
401
402 private String buddyId;
403
404 private AddBuddyDialog dialog;
405
406 private WaitDialog wait;
407
408
409 /**
410 * Default constructor
411 *
412 *@param wait the wait dialog
413 *@param groupName the group to use
414 *@param buddyAlias the buddy's alias
415 *@param buddyId the buddy's JID
416 *@param dialog the AddBuddyDialog that called this thread
417 */
418 public AddBuddyThread(WaitDialog wait, String groupName,
419 String buddyAlias, String buddyId, AddBuddyDialog dialog) {
420 this.wait = wait;
421 this.groupName = groupName;
422 this.buddyAlias = buddyAlias;
423 this.buddyId = buddyId.trim();
424 this.dialog = dialog;
425 }
426
427
428 /**
429 * Called by the enclosing Thread - will attempt to add the buddy to
430 * the Roster, and will display an error if it wasn't successfull
431 */
432 public void run() {
433 final Roster roster = BuddyList.getInstance().getConnection().getRoster();
434 final BuddyStatus buddy = BuddyList.getInstance().getBuddyStatus(
435 buddyId);
436 if (modify) {
437 SwingUtilities.invokeLater(
438 new Runnable() {
439 public void run() {
440 BuddyList.getInstance().getBuddyListTree().removeBuddy(
441 buddy, buddy.getGroup(), true);
442 }
443 });
444 }
445
446 try {
447
448
449 if (modify) {
450 com.valhalla.Logger.debug("modifying roster item");
451 RosterEntry entry = buddy.getRosterEntry();
452 entry.setName(buddyAlias);
453 int c = 0;
454 Iterator groups = entry.getGroups();
455 while (groups.hasNext()) {
456 RosterGroup g = (RosterGroup) groups.next();
457 if(!g.contains(entry)) continue;
458 g.removeEntry(entry);
459 c++;
460 }
461
462 buddy.setTempGroup(groupName);
463 SwingUtilities.invokeLater(new Runnable()
464 {
465 public void run()
466 {
467 dialog.setVisible(false);
468 buddy.setRemoved(false);
469
470 NMOptionDialog.createMessageDialog(null, resources.getString("addBuddyDialogTitle"), resources.getString("buddyAdded"));
471
472 BuddyList.getInstance().getBuddyListTree().addBuddy(
473 buddy);
474 }
475 });
476
477 if (groupName != null && !groupName.equals("")) {
478 RosterGroup newGroup = null;
479 newGroup = roster.getGroup(groupName);
480 if (newGroup == null) {
481 com.valhalla.Logger.debug("had to create new group" + groupName);
482 newGroup = roster.createGroup(groupName);
483 } else {
484 com.valhalla.Logger.debug("found group " + newGroup.getName());
485 }
486
487 if (c != 0) {
488 com.valhalla.Logger.debug("Moving buddy to " + newGroup.getName());
489 newGroup.addEntry(entry);
490 } else {
491 roster.createEntry(buddyId, buddyAlias,
492 new String[]{groupName});
493
494 }
495 }
496 }
497 /*
498 * if it's a new entry
499 */else {
500
501 if (groupName == null) {
502 roster.createEntry(buddyId, buddyAlias, null);
503 } else {
504 roster.createEntry(buddyId, buddyAlias,
505 new String[]{groupName});
506 buddy.setTempGroup(groupName);
507 }
508
509 SwingUtilities.invokeLater(new Runnable()
510 {
511 public void run()
512 {
513 dialog.setVisible(false);
514 buddy.setRemoved(false);
515
516 NMOptionDialog.createMessageDialog(null, resources.getString("addBuddyDialogTitle"), resources.getString("buddyAdded"));
517
518 BuddyList.getInstance().getBuddyListTree().addBuddy(
519 buddy);
520 }
521 });
522 }
523 } catch (XMPPException e) {
524 if (e.getXMPPError() == null) {
525 errorMessage = e.getMessage();
526 } else {
527 errorMessage = resources.getString("xmppError"
528 + e.getXMPPError().getCode());
529 }
530 }
531
532 SwingUtilities.invokeLater(
533 new Runnable() {
534 public void run() {
535 wait.dispose();
536
537 if (errorMessage != null) {
538 Standard.warningMessage(dialog, resources.getString("addBuddyDialogTitle"),
539 errorMessage);
540 dialog.setVisible(true);
541 } else {
542 DialogTracker.removeDialog(dialog);
543
544 }
545 }
546
547 });
548 }
549 }
550 }
551