001 /*
002 Copyright (C) 2003 Adam Olsen
003
004 This program is free software; you can redistribute it and/or modify
005 it under the terms of the GNU General Public License as published by
006 the Free Software Foundation; either version 1, or (at your option)
007 any later version.
008
009 This program is distributed in the hope that it will be useful,
010 but WITHOUT ANY WARRANTY; without even the implied warranty of
011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012 GNU General Public License for more details.
013
014 You should have received a copy of the GNU General Public License
015 along with this program; if not, write to the Free Software
016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
017 */
018
019 package com.valhalla.jbother.groupchat;
020
021 import java.awt.*;
022 import java.awt.event.*;
023 import java.io.BufferedReader;
024
025 import java.util.*;
026
027 import javax.swing.*;
028 import java.io.*;
029 import com.valhalla.jbother.jabber.smack.*;
030 import org.jivesoftware.smackx.*;
031 import org.jivesoftware.smack.packet.*;
032 import org.jivesoftware.smack.*;
033 import com.valhalla.gui.*;
034 import com.valhalla.settings.*;
035 import com.valhalla.jbother.BuddyList;
036 import com.valhalla.jbother.JBother;
037
038 /**
039 * Allows the user to create bookmarks for each of their favorite group chat
040 * rooms
041 *
042 * @author Adam Olsen
043 * @version 1.0
044 */
045 public class GroupChatBookmarks extends JDialog {
046 private ResourceBundle resources = ResourceBundle.getBundle(
047 "JBotherBundle", Locale.getDefault());
048
049 private JPanel container = new JPanel();
050
051 private JList bookMarkList;
052
053 private JPanel rightPanel = new JPanel();
054
055 private JPanel leftPanel = new JPanel();
056
057 private JPanel buttonPanel = new JPanel();
058
059 private JPanel inputPanel = new JPanel();
060
061 private JButton saveButton = new JButton(resources.getString("saveButton")),
062 openButton = new JButton(resources.getString("openButton")),
063 cancelButton = new JButton(resources.getString("cancelButton"));
064
065 private MJTextField roomBox = new MJTextField(15),
066 serverBox = new MJTextField(20), nickBox = new MJTextField(15);
067
068 private JPasswordField passBox = new JPasswordField(15);
069
070 private int row = 0;
071
072 private GridBagLayout grid = new GridBagLayout();
073
074 private GridBagConstraints c = new GridBagConstraints();
075
076 private JPopupMenu deleteMenu = new JPopupMenu();
077 private Vector bookmarks = new Vector();
078
079 private JMenuItem deleteItem = new JMenuItem(resources
080 .getString("deleteButton"));
081
082 private JCheckBox auto = new JCheckBox(resources.getString("autoJoinRoom"));
083
084 private WaitDialog wait = new WaitDialog(this,null,resources.getString("pleaseWait"));
085 private Bookmark bookmark;
086 private PrivateDataManager pDataManager;
087 private boolean pdBookmark = false;
088 private File bookmarksDir = new File(JBother.profileDir + File.separator + "gcbookmarks");
089
090 /**
091 * Sets up the visual components of the bookmark dialog
092 */
093 public GroupChatBookmarks(Component parent) {
094 super(BuddyList.getInstance().getContainerFrame(), "Group Chat Bookmarks");
095 setTitle(resources.getString("groupChatBookmarksDialogTitle"));
096
097 container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
098 container.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
099
100 if( !bookmarksDir.isDirectory() )
101 {
102 bookmarksDir.mkdirs();
103 }
104
105 bookMarkList = new JList();
106 bookMarkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
107 bookMarkList.setCellRenderer(new ListRenderer());
108
109 leftPanel.setBackground(Color.WHITE);
110 leftPanel.setLayout(new GridLayout(0, 1));
111 setContentPane(container);
112
113 deleteMenu.add(deleteItem);
114
115 leftPanel.add(new JScrollPane(bookMarkList));
116 leftPanel.setPreferredSize(new Dimension(120, 200));
117
118 inputPanel.setBorder(BorderFactory.createTitledBorder(resources
119 .getString("groupChatBookmarksDialogTitle")));
120 rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
121
122 inputPanel.setLayout(grid);
123 c.anchor = GridBagConstraints.WEST;
124
125 passBox.setFont(nickBox.getFont());
126
127 createInputBox(resources.getString("room") + ":", roomBox);
128 createInputBox(resources.getString("server") + ":", serverBox);
129 createInputBox(resources.getString("nickname") + ":", nickBox);
130 createInputBox(resources.getString("password") + ":", passBox);
131 c.gridx = 1;
132 c.gridy++;
133 grid.setConstraints(auto, c);
134 inputPanel.add(auto);
135
136 container.add(leftPanel);
137 container.add(Box.createRigidArea(new Dimension(5, 0)));
138
139 //this is the space taker
140 JLabel blankLabel = new JLabel("");
141 c.weighty = 1;
142 c.weightx = 1;
143 c.gridx = 0;
144 c.gridwidth = 3;
145 c.gridy++;
146 grid.setConstraints(blankLabel, c);
147 inputPanel.add(blankLabel);
148 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
149 buttonPanel.add(Box.createHorizontalGlue());
150 buttonPanel.add(saveButton);
151 buttonPanel.add(openButton);
152 buttonPanel.add(cancelButton);
153
154 rightPanel.add(inputPanel);
155 rightPanel.add(buttonPanel);
156 container.add(rightPanel);
157
158 setListeners();
159
160 setSize(400, 200);
161 pack();
162 setLocationRelativeTo(parent);
163 DialogTracker.addDialog(this, true, true);
164 }
165
166 public static void showDialog(String room, String user, String password) {
167 int index = room.indexOf("@");
168 String server = room.substring(index + 1);
169 room = room.substring(0, index);
170 index = user.indexOf("@");
171 String nick = user.substring(0, index);
172
173 GroupChatBookmarks gc = new GroupChatBookmarks(null);
174 gc.load();
175 gc.roomBox.setText(room);
176 gc.serverBox.setText(server);
177 gc.nickBox.setText(nick);
178 gc.passBox.setText(password);
179 gc.setVisible(true);
180
181 }
182
183 public void load()
184 {
185 new Thread( new CollectBookmarks(false) ).start();
186 }
187
188 /**
189 * Adds event listeners to components in the bookmark window
190 */
191 private void setListeners() {
192 addWindowListener(new WindowAdapter()
193 {
194 public void windowClosed(WindowEvent e )
195 {
196 bookmarks.clear();
197 //dispose();
198 }
199 } );
200
201 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
202 cancelButton.addActionListener(new ActionListener() {
203 public void actionPerformed(ActionEvent e) {
204 bookmarks.clear();
205 dispose();
206 }
207 });
208
209 saveButton.addActionListener(new ActionListener() {
210 public void actionPerformed(ActionEvent e) {
211 saveBookmark();
212 }
213 });
214
215 openButton.addActionListener(new ActionListener() {
216 public void actionPerformed(ActionEvent e) {
217 openHandler();
218 }
219 });
220
221 bookMarkList.addMouseListener(new RightClickListener());
222 deleteItem.addActionListener(new DeleteListener());
223 }
224
225 /**
226 * Writes a bookmark to the bookmarks file on disk
227 */
228 private void saveBookmark() {
229 if (!checkData())
230 return;
231
232 String defaultString = roomBox.getText();
233
234 String result = (String) JOptionPane.showInputDialog(this, resources
235 .getString("enterBookmarkName"), resources
236 .getString("saveBookmark"), JOptionPane.QUESTION_MESSAGE, null,
237 null, defaultString);
238
239 if (result == null || result.equals(""))
240 return;
241
242 if( pdBookmark )
243 {
244 for( int i = 0; i < bookmarks.size(); i++ )
245 {
246 Bookmark.Conference c = (Bookmark.Conference)bookmarks.get(i);
247 if( c.getName().toLowerCase().equals(result.toLowerCase()))
248 {
249 bookmark.removeConference(c);
250 }
251 }
252
253 bookmark.addConference(result,roomBox.getText() + "@" + serverBox.getText(),
254 nickBox.getText(), new String(passBox.getPassword()),auto.isSelected());
255
256 new Thread(new SaveBookmark()).start();
257 }
258 else {
259
260
261 try {
262 File bm = new File( bookmarksDir, result + ".gcb" );
263 FileWriter fw = new FileWriter(bm);
264 PrintWriter out = new PrintWriter(fw);
265 out.println(roomBox.getText());
266 out.println(serverBox.getText());
267 out.println(nickBox.getText());
268 out.println(new String(passBox.getPassword()));
269 out.println(auto.isSelected());
270 fw.close();
271 }
272 catch( IOException ex ) { }
273 }
274
275 loadBookmarks();
276 }
277
278 class SaveBookmark implements Runnable
279 {
280 public void run()
281 {
282 try {
283 pDataManager.setPrivateData(bookmark);
284 }
285 catch( Exception ex ) { com.valhalla.Logger.logException(ex);}
286 }
287 }
288
289 /**
290 * Makes sure all of the required information to save a bookmark is filled
291 * in
292 *
293 * @return true if the information is completely filled out
294 */
295 private boolean checkData() {
296 if (roomBox.getText().equals("") || serverBox.getText().equals("")
297 || nickBox.getText().equals("")) {
298 Standard.warningMessage(this, resources
299 .getString("groupChatBookmarksDialogTitle"), resources
300 .getString("enterAllFields"));
301 return false;
302 }
303
304 return true;
305 }
306
307 /**
308 * Deletes a bookmark from disk
309 *
310 * @author Adam Olsen
311 * @version 1.0
312 */
313 class DeleteListener implements ActionListener {
314 public void actionPerformed(ActionEvent e) {
315 int result = JOptionPane.showConfirmDialog(GroupChatBookmarks.this, resources
316 .getString("sureDelete"), resources
317 .getString("deleteBookmark"), JOptionPane.YES_NO_OPTION);
318
319 if (result != 0)
320 return;
321
322 ListModel model = bookMarkList.getModel();
323
324 try {
325 Bookmark.Conference c = (Bookmark.Conference)model.getElementAt(bookMarkList
326 .getSelectedIndex());
327 bookmark.removeConference(c);
328 }
329 catch(ClassCastException ex) {
330 String f = (String)model.getElementAt(bookMarkList.getSelectedIndex());
331 File bm = new File(bookmarksDir, f + ".gcb");
332 bm.delete();
333 }
334
335 loadBookmarks();
336 validate();
337
338 new Thread(new SaveBookmark()).start();
339 }
340 }
341
342 /**
343 * Shows a menu on the bookmark items allowing you to delete one of them
344 *
345 * @author Adam Olsen
346 * @version 1.0
347 */
348 class RightClickListener extends MouseAdapter {
349 public void mousePressed(MouseEvent e) {
350 checkPop(e);
351 }
352
353 public void mouseReleased(MouseEvent e) {
354 checkPop(e);
355 }
356
357 public void mouseClicked(MouseEvent e) {
358 checkPop(e);
359 }
360
361 public void checkPop(MouseEvent e) {
362 if (e.isPopupTrigger()) {
363 int index = bookMarkList.locationToIndex(new Point(e.getX(), e
364 .getY()));
365 bookMarkList.setSelectedIndex(index);
366 deleteMenu.show(e.getComponent(), e.getX(), e.getY());
367 } else {
368 loadBookmark();
369 if (e.getClickCount() >= 2)
370 openHandler();
371 }
372 }
373 }
374
375 /**
376 * Opens a bookmark and fills out the fields with it's information
377 */
378 private void loadBookmark() {
379 ListModel model = bookMarkList.getModel();
380 try {
381 Bookmark.Conference c = (Bookmark.Conference)model.getElementAt(bookMarkList.getSelectedIndex());
382
383 String jid = c.getJid();
384 int b = jid.indexOf("@");
385 roomBox.setText(jid.substring(0,b));
386 serverBox.setText(jid.substring(b+1));
387 nickBox.setText(c.getNick());
388 passBox.setText(c.getPassword());
389 auto.setSelected(c.getAutojoin());
390 }
391 catch( ClassCastException ex ) {
392 // it's a local bookmark
393 String sel = (String)model.getElementAt(bookMarkList.getSelectedIndex());
394 File bm = new File(bookmarksDir, sel + ".gcb");
395 try {
396 BufferedReader in = new BufferedReader(new FileReader(bm));
397 roomBox.setText(in.readLine());
398 serverBox.setText(in.readLine());
399 nickBox.setText(in.readLine());
400 passBox.setText(in.readLine());
401 String a = in.readLine();
402 if( a.equals("true") )
403 {
404 auto.setSelected(true);
405 }
406 else {
407 auto.setSelected(false);
408 }
409 in.close();
410 }
411 catch( IOException iox ) { }
412 }
413 }
414
415 /**
416 * Opens a connection to a groupchat room
417 */
418 private void openHandler() {
419 if (!checkData())
420 return;
421
422 if (BuddyList.getInstance().getTabFrame() != null
423 && BuddyList.getInstance().getTabFrame().isRoomOpen(
424 roomBox.getText() + "@" + serverBox.getText())) {
425 Standard.warningMessage(this, resources.getString("openBookmark"),
426 resources.getString("alreadyInRoom"));
427 return;
428 }
429
430 ChatRoomPanel window = new ChatRoomPanel(roomBox.getText() + "@"
431 + serverBox.getText(), nickBox.getText(), new String(passBox
432 .getPassword()));
433 window.startChat();
434 dispose();
435 }
436
437 /**
438 * Loads all the bookmarks and puts them in the list of bookmarks
439 */
440 private void loadBookmarks() {
441
442 wait.setVisible(false);
443 bookmarks.clear();
444
445 if( pdBookmark )
446 {
447 if( bookmark != null )
448 {
449 Iterator i = bookmark.getConferences();
450
451 while( i.hasNext() )
452 {
453 bookmarks.add(i.next());
454 }
455 }
456 }
457 String marks[] = bookmarksDir.list();
458 for( int i = 0; i < marks.length; i++ )
459 {
460 bookmarks.add(marks[i].replace(".gcb", ""));
461 }
462
463 bookMarkList.setListData(bookmarks.toArray());
464 bookMarkList.validate();
465 }
466
467 class CollectBookmarks implements Runnable
468 {
469 private boolean autojoin = false;
470
471 public CollectBookmarks( boolean autojoin )
472 {
473 this.autojoin = autojoin;
474 if( !autojoin ) wait.setVisible(true);
475 }
476
477 public void run()
478 {
479 try {
480 pDataManager = new PrivateDataManager(BuddyList.getInstance().getConnection());
481 bookmark = (Bookmark)pDataManager.getPrivateData("storage", "storage:bookmarks");
482 pdBookmark = true;
483
484 if( !Settings.getInstance().getBoolean( "jbotherMucAdded" ) )
485 {
486 // we save this bookmark locally, so as not to get anyone
487 // distrought about JBother doing things to their global
488 // private data storage without asking
489 String user = BuddyList.getInstance().getConnection().getUser();
490 int b = user.indexOf("@");
491 user = user.substring( 0, b );
492 File bm = new File(bookmarksDir, "jbother.gcb");
493 PrintWriter out = new PrintWriter(new FileWriter(bm));
494 out.println("jbother");
495 out.println("muc.jbother.org");
496 out.println(user);
497 out.println("");
498 out.println("true");
499 out.close();
500 Settings.getInstance().setBoolean( "jbotherMucAdded", true );
501 }
502 }
503 catch( XMPPException ex ) {
504 // do nothing, private data is not implemented
505 com.valhalla.Logger.debug("Private Data is not supported, using local storage");
506 }
507 catch( Exception ex ) {
508 com.valhalla.Logger.logException(ex);
509 }
510
511 if( !autojoin )
512 {
513 loadBookmarks();
514 }
515 else performAutoJoin();
516 }
517 }
518
519 private void performAutoJoin()
520 {
521 if( bookmark != null ) {
522 Iterator i = bookmark.getConferences();
523 while(i.hasNext())
524 {
525 final Bookmark.Conference c=(Bookmark.Conference)i.next();
526
527 if (c.getAutojoin()) {
528
529 SwingUtilities.invokeLater( new Runnable()
530 {
531 public void run()
532 {
533 ChatRoomPanel window = new ChatRoomPanel(c.getJid(), c.getNick(), c.getPassword());
534 window.startChat();
535 }
536 } );
537 }
538
539 try {
540 Thread.sleep(5);
541 }
542 catch( Exception ex ) { }
543 }
544 }
545
546 String list[] = bookmarksDir.list();
547 for( int i = 0; i < list.length; i ++ )
548 {
549 try {
550 File bm = new File(bookmarksDir, list[i]);
551 BufferedReader in = new BufferedReader(new FileReader(bm));
552 final String room = in.readLine();
553 final String server = in.readLine();
554 final String nick = in.readLine();
555 final String pass = in.readLine();
556 boolean a = false;
557 if( in.readLine().equals("true") )
558 {
559 a = true;
560 }
561
562 final boolean tempAuto = a;
563 in.close();
564
565 if( a )
566 {
567 SwingUtilities.invokeLater ( new Runnable()
568 {
569 public void run()
570 {
571 ChatRoomPanel window = new ChatRoomPanel(room + "@" + server,
572 nick, pass);
573 window.startChat();
574 }
575 } );
576
577 try {
578 Thread.sleep(5);
579 }
580 catch( Exception ex ) { }
581 }
582 }
583 catch( IOException iox )
584 {
585 com.valhalla.Logger.logException(iox);
586 }
587 }
588 }
589
590 public void autoJoin() {
591 new Thread(new CollectBookmarks(true)).start();
592 }
593
594 /**
595 * Creates a MJTextField with a label
596 *
597 * @param label
598 * the name of the the label
599 * @param box
600 * the MJTextField
601 */
602 private void createInputBox(String label, Container box) {
603 JLabel labelBox = new JLabel(label + " ");
604
605 c.gridy = row++;
606 c.gridx = 0;
607 grid.setConstraints(labelBox, c);
608 inputPanel.add(labelBox);
609
610 c.gridx = 1;
611 grid.setConstraints(box, c);
612 inputPanel.add(box);
613 }
614 }
615
616 /**
617 * Displays the different group chat bookmarks
618 *
619 * @author Adam Olsen
620 * @version 1.0
621 */
622
623 class ListRenderer extends JLabel implements ListCellRenderer {
624 public ListRenderer() {
625 setOpaque(true);
626 }
627
628 public Component getListCellRendererComponent(JList list, Object value,
629 int index, boolean isSelected, boolean cellHasFocus) {
630
631 try {
632 Bookmark.Conference c = (Bookmark.Conference)value;
633 setText(c.getName());
634 }
635 catch( ClassCastException ex )
636 {
637 setText((String)value);
638 }
639
640 setBackground(isSelected ? list.getSelectionBackground() : list
641 .getBackground());
642 setForeground(isSelected ? list.getSelectionForeground() : list
643 .getForeground());
644 list.validate();
645
646 return this;
647 }
648 }