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