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    }