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.*;
018    import java.awt.event.*;
019    import javax.swing.*;
020    import com.valhalla.misc.*;
021    import com.valhalla.gui.*;
022    import com.valhalla.settings.*;
023    import org.jivesoftware.smack.packet.*;
024    import java.io.*;
025    import java.util.*;
026    
027    /**
028     * Shows a graphical chooser for different JBother profiles
029     *
030     * @author     Adam Olsen
031     * @created    Oct 28, 2004
032     * @version    1.0
033     */
034    public class ProfileManager extends JFrame
035    {
036            private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() );
037            private JList profileList = new JList();
038            private JButton newButton = new JButton( resources.getString( "newButton" ) );
039            private JButton editButton = new JButton( resources.getString( "editButton" ) );
040            private JButton deleteButton = new JButton( resources.getString( "deleteButton" ) );
041            private JButton openButton = new JButton( resources.getString( "openButton" ) );
042            private JButton cancelButton = new JButton( resources.getString( "cancelButton" ) );
043            private JPanel main = null;
044            private ProfileManager thisPointer = this;
045            private String defaultString = "     <-";
046    
047            private static File profDir = new File( JBother.settingsDir, "profiles" );
048            private ProfileListModel model = null;
049            private boolean exitOnClose = false;
050            private static String currentProfile = "default";
051    
052            /**
053             * Default constructor
054             */
055            public ProfileManager()
056            {
057                    super( "JBother" );
058                    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
059    
060                    loadProfileList();
061    
062                    main = (JPanel)getContentPane();
063                    main.setBorder( BorderFactory.createTitledBorder( resources.getString( "profileManager" ) ) );
064                    main.setLayout( new BorderLayout( 5, 5 ) );
065    
066                    JPanel rightPanel = new JPanel();
067                    rightPanel.setLayout( new BoxLayout( rightPanel, BoxLayout.Y_AXIS ) );
068    
069                    newButton.setMaximumSize( new Dimension( 100, 100 ) );
070                    editButton.setMaximumSize( new Dimension( 100, 100 ) );
071                    deleteButton.setMaximumSize( new Dimension( 100, 100 ) );
072                    rightPanel.add( newButton );
073                    rightPanel.add( editButton );
074                    rightPanel.add( deleteButton );
075    
076                    rightPanel.add( Box.createVerticalGlue() );
077    
078                    JPanel bottomPanel = new JPanel();
079                    bottomPanel.setLayout( new BoxLayout( bottomPanel, BoxLayout.X_AXIS ) );
080                    bottomPanel.add( Box.createHorizontalGlue() );
081                    bottomPanel.add( cancelButton );
082                    bottomPanel.add( openButton );
083                    main.add( new JScrollPane( profileList ), BorderLayout.CENTER );
084                    main.add( rightPanel, BorderLayout.WEST );
085                    main.add( bottomPanel, BorderLayout.SOUTH );
086    
087                    addListeners();
088                    pack();
089                    setSize( 350, 200 );
090                    setLocationRelativeTo( null );
091                    setVisible( true );
092                    addWindowListener(
093                            new WindowAdapter()
094                            {
095                                    public void windowClosing( WindowEvent e )
096                                    {
097                                            cancelHandler();
098                                    }
099                            } );
100            }
101    
102            public static String getCurrentProfile() { return currentProfile; }
103            public static void setCurrentProfile( String profile ) { currentProfile = profile; }
104    
105            /**
106             * @param  exitOnClose  set to true to have this dialog close the app on close
107             */
108            public void setExitOnClose( boolean exitOnClose )
109            {
110                    this.exitOnClose = exitOnClose;
111            }
112    
113            /**
114             * cancels this dialog, and if exitOnClose is set, the application quits
115             */
116            private void cancelHandler()
117            {
118                    if( exitOnClose )
119                    {
120                            System.exit( 0 );
121                    }
122                    else
123                    {
124                            thisPointer.dispose();
125                            BuddyList.getInstance().setVisible( true );
126                    }
127            }
128    
129            /**
130             *  Adds event listeners
131             */
132            private void addListeners()
133            {
134                    cancelButton.addActionListener(
135                            new ActionListener()
136                            {
137                                    public void actionPerformed( ActionEvent e )
138                                    {
139                                            cancelHandler();
140                                    }
141                            } );
142    
143                    editButton.addActionListener(
144                            new ActionListener()
145                            {
146                                    public void actionPerformed( ActionEvent e )
147                                    {
148                                            String string = (String)profileList.getSelectedValue();
149                                            if( string != null && string.endsWith( defaultString ) )
150                                            {
151                                                    int index = string.indexOf( defaultString );
152                                                    string = string.substring( 0, index );
153                                            }
154    
155                                            new ProfileEditorDialog( thisPointer, string ).show();
156                                    }
157                            } );
158    
159                    newButton.addActionListener(
160                            new ActionListener()
161                            {
162                                    public void actionPerformed( ActionEvent e )
163                                    {
164                                            new ProfileEditorDialog( thisPointer, null ).show();
165                                    }
166                            } );
167    
168                    deleteButton.addActionListener(
169                            new ActionListener()
170                            {
171                                    public void actionPerformed( ActionEvent e )
172                                    {
173                                            String string = (String)profileList.getSelectedValue();
174                                            if( string != null && string.endsWith( defaultString ) )
175                                            {
176                                                    int index = string.indexOf( defaultString );
177                                                    string = string.substring( 0, index );
178                                            }
179    
180                                            int result = JOptionPane.showConfirmDialog( null,
181                                                            resources.getString( "deleteProfile" ), "JBother", JOptionPane.YES_NO_OPTION );
182    
183                                            if( result == 0 )
184                                            {
185                                                    try
186                                                    {
187                                                            MiscUtils.recursivelyDeleteDirectory( profDir.getPath() + File.separatorChar + string );
188                                                    }
189                                                    catch( Exception ex )
190                                                    {
191                                                            Standard.warningMessage( thisPointer, "JBother", resources.getString( "errorDeletingProfile" ) );
192                                                            com.valhalla.Logger.logException( ex );
193                                                            return;
194                                                    }
195    
196                                                    loadProfileList();
197                                            }
198                                    }
199                            } );
200    
201                    openButton.addActionListener(
202                            new ActionListener()
203                            {
204                                    public void actionPerformed( ActionEvent e )
205                                    {
206                                            String string = (String)profileList.getSelectedValue();
207                                            if( string != null && string.endsWith( defaultString ) )
208                                            {
209                                                    int index = string.indexOf( defaultString );
210                                                    string = string.substring( 0, index );
211                                            }
212    
213                                            loadProfile( string );
214                                            thisPointer.dispose();
215                                    }
216                            } );
217            }
218    
219            /**
220             * Loads a profile
221             *
222             * @param  profile  the profile to load
223             */
224            public static void loadProfile( String profile )
225            {
226                    Settings.getInstance().loadSettings( profDir.getPath() + File.separatorChar + profile, "settings.properties" );
227                    JBotherLoader.loadSettings();
228    
229                    JBother.profileDir = JBother.settingsDir + File.separatorChar + "profiles" + File.separatorChar + profile;
230    
231                    String fontString = Settings.getInstance().getProperty( "applicationFont" );
232                    if( fontString == null )
233                    {
234                            fontString = "Default-PLAIN-12";
235                    }
236    
237                    Font newFont = Font.decode( fontString );
238                    com.valhalla.jbother.preferences.AppearancePreferencesPanel.updateApplicationFonts( newFont, null );
239                    Emoticons.getInstance().switchTheme( Settings.getInstance().getProperty( "emoticonTheme" ) );
240                    StatusIconCache.clearStatusIconCache();
241    
242                    BuddyList.getInstance().loadBlockedUsers();
243                    BuddyList.getInstance().setPreferredDimensions();
244                    BuddyList.getInstance().setPreferredLocation();
245                    BuddyList.getInstance().setVisible( true );
246                    BuddyList.getInstance().getTopMenu().getStatusMenu().reloadStatusIcons();
247                    BuddyList.getInstance().getTopMenu().getStatusMenu().setModeChecked( null );
248    
249                    if( Settings.getInstance().getBoolean( "autoLogin" ) )
250                    {
251                            Thread thread = new Thread( new ConnectorThread( Presence.Mode.AVAILABLE, "Available", false ) );
252                            thread.start();
253                    }
254                    currentProfile = profile;
255            }
256    
257            /**
258             *  Loads a list of profiles
259             */
260            protected void loadProfileList()
261            {
262                    if( !profDir.isDirectory() && !profDir.mkdirs() )
263                    {
264                            com.valhalla.Logger.debug( "Could not create profile directory!  Please check permissions on ~/.jbother" );
265                            System.exit( -1 );
266                    }
267    
268                    model = new ProfileListModel();
269    
270                    String list[] = profDir.list(
271                            new FilenameFilter()
272                            {
273                                    public boolean accept( File dir, String name )
274                                    {
275                                            if( new File( dir, name ).isDirectory() )
276                                            {
277                                                    return true;
278                                            }
279                                            else
280                                            {
281                                                    return false;
282                                            }
283                                    }
284                            } );
285    
286                    for( int i = 0; i < list.length; i++ )
287                    {
288                            model.addElement( list[i] );
289                    }
290    
291                    profileList.setModel( model );
292    
293                    selectDefault();
294            }
295    
296            /**
297             * Selects the default profile and labels it (default)
298             */
299            private void selectDefault()
300            {
301                    String defaultProfile = getDefaultProfile();
302                    if( defaultProfile == null )
303                    {
304                            selectAsDefault( 0 );
305                            return;
306                    }
307    
308                    int index = model.indexOf( defaultProfile );
309                    if( index != -1 )
310                    {
311                            selectAsDefault( index );
312                    }
313                    else
314                    {
315                            selectAsDefault( 0 );
316                    }
317            }
318    
319            /**
320             * Gets the current default profile, or the first profile in the profiles directory
321             *
322             * @return    The default profile
323             */
324            public static String getDefaultProfile()
325            {
326                    File file = new File( profDir, "default.properties" );
327                    if( !file.exists() )
328                    {
329                            return getOnlyProfile();
330                    }
331    
332                    Properties def = new Properties();
333                    try
334                    {
335                            InputStream stream = new FileInputStream( file );
336    
337                            def.load( stream );
338                            stream.close();
339                    }
340                    catch( IOException e )
341                    {
342                            com.valhalla.Logger.logException( e );
343                            return getOnlyProfile();
344                    }
345    
346                    return def.getProperty( "defaultProfile" );
347            }
348    
349            /**
350             * Gets the first profile in the profile directory
351             *
352             * @return    The first profile in the profile directory, or <tt>null</tt> if there are no profiles
353             */
354            public static String getOnlyProfile()
355            {
356                    String[] list = profDir.list();
357                    if( list != null && list.length > 0 )
358                    {
359                            return list[0];
360                    }
361                    else
362                    {
363                            return null;
364                    }
365            }
366    
367            /**
368             * Sets the default profile
369             *
370             * @param  profile  The profile to set
371             */
372            public static void setDefaultProfile( String profile )
373            {
374                    File file = new File( profDir, "default.properties" );
375    
376                    try
377                    {
378                            OutputStream stream = new FileOutputStream( file );
379                            Properties def = new Properties();
380                            def.setProperty( "defaultProfile", profile );
381                            def.store( stream, "default profile setting" );
382                            stream.close();
383                    }
384                    catch( Exception e )
385                    {
386                            com.valhalla.Logger.logException( e );
387                    }
388            }
389    
390            /**
391             * Selects the item at <code>index</code> as default
392             *
393             * @param  index  the default to select
394             */
395            private void selectAsDefault( int index )
396            {
397                    String string = (String)model.getElementAt( index );
398                    setDefaultProfile( string );
399    
400                    string += defaultString;
401                    model.setValueAt( index, string );
402                    profileList.setSelectedIndex( index );
403            }
404    
405            /**
406             * The JList model for the profiles list
407             *
408             * @author     synic
409             * @created    November 30, 2004
410             */
411            class ProfileListModel extends DefaultListModel
412            {
413                    /**
414                     *  Sets the valueAt attribute of the ProfileListModel object
415                     *
416                     * @param  index  The new valueAt value
417                     * @param  value  The new valueAt value
418                     */
419                    public void setValueAt( int index, String value )
420                    {
421                            model.removeElementAt( index );
422                            model.insertElementAt( value, index );
423                            fireContentsChanged( model, index, index + 1 );
424                    }
425            }
426    }
427