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.preferences; 020 021 import java.awt.*; 022 import java.awt.event.*; 023 import java.io.*; 024 import java.util.*; 025 026 import javax.swing.*; 027 import com.valhalla.pluginmanager.*; 028 029 import org.jfree.ui.FontChooserDialog; 030 031 import com.valhalla.gui.*; 032 import com.valhalla.pluginmanager.*; 033 import com.valhalla.jbother.*; 034 import com.valhalla.jbother.jabber.BuddyStatus; 035 import com.valhalla.settings.Settings; 036 import com.valhalla.settings.TempSettings; 037 038 /** 039 * Allows the user to change appearance preferences 040 * @author Adam Olsen 041 * @version 1.0 042 */ 043 public class AppearancePreferencesPanel extends JPanel implements PreferencesPanel 044 { 045 private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() ); 046 private PreferencesDialog prefs; 047 private GridBagLayout grid = new GridBagLayout(); 048 private GridBagConstraints c = new GridBagConstraints(); 049 private JLabel lafLabel = new JLabel( resources.getString( "themeLabel" ) + ": " ); 050 private JLabel statusLabel = new JLabel( resources.getString( "statusLabel" ) + ": " ); 051 private JLabel emoticonLabel = new JLabel( resources.getString( "emoticonLabel" ) + ": " ); 052 private JLabel messageLabel = new JLabel( resources.getString( "messageWindowFont" ) + ": " ); 053 private JButton messageFontButton = new JButton( "Font" ); 054 055 private JLabel appFontLabel = new JLabel( resources.getString( "appFontLabel" ) + ": " ); 056 private JButton appFontButton = new JButton( "Font" ); 057 058 private JComboBox lookAndFeel, statusTheme, emoticonTheme; 059 private int current; 060 private UIManager.LookAndFeelInfo[] lfs; 061 private String[] names; 062 063 /** 064 * Sets up the AppearancePreferences 065 * @param dialog the enclosing PreferencesDialog 066 */ 067 public AppearancePreferencesPanel( PreferencesDialog dialog ) 068 { 069 this.prefs = dialog; 070 setBorder( BorderFactory.createTitledBorder( resources.getString( "appearancePreferences" ) ) ); 071 setLayout( grid ); 072 073 lfs = UIManager.getInstalledLookAndFeels(); 074 String lf = UIManager.getLookAndFeel().getClass().getName(); 075 076 ArrayList list = new ArrayList(); 077 078 int index = 0; 079 for( int i = 0; i < lfs.length; i++ ) 080 { 081 list.add( lfs[i].getName() ); 082 if( lf.equals( lfs[i].getClassName() ) ) 083 { 084 index = i; 085 current = index; 086 } 087 } 088 089 names = new String[list.size()]; 090 list.toArray( names ); 091 092 lookAndFeel = new JComboBox( names ); 093 lookAndFeel.setSelectedIndex( index ); 094 095 c.gridx = 0; 096 c.gridy = 0; 097 c.fill = GridBagConstraints.HORIZONTAL; 098 c.anchor = GridBagConstraints.WEST; 099 c.gridwidth = 1; 100 101 //display name stuff 102 lafLabel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 5 ) ); 103 c.weightx = -.1; 104 c.fill = GridBagConstraints.NONE; 105 grid.setConstraints( lafLabel, c ); 106 add( lafLabel ); 107 108 c.gridx = 1; 109 110 grid.setConstraints( lookAndFeel, c ); 111 add( lookAndFeel ); 112 113 c.gridx = 0; 114 c.gridy++; 115 116 statusLabel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 5 ) ); 117 grid.setConstraints( statusLabel, c ); 118 add( statusLabel ); 119 120 statusTheme = getStatusThemes(); 121 c.gridx++; 122 grid.setConstraints( statusTheme, c ); 123 add( statusTheme ); 124 125 c.gridx = 0; 126 c.gridy++; 127 128 emoticonLabel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 5 ) ); 129 grid.setConstraints( emoticonLabel, c ); 130 add( emoticonLabel ); 131 132 emoticonTheme = getEmoticonThemes(); 133 c.gridx++; 134 grid.setConstraints( emoticonTheme, c ); 135 add( emoticonTheme ); 136 137 FontChangeListener fontListener = new FontChangeListener(); 138 139 // get the message window font settings 140 String messageFont = Settings.getInstance().getProperty( "messageWindowFont" ); 141 if( messageFont == null ) messageFont = "Default-PLAIN-12"; 142 143 Font font = Font.decode( messageFont ); 144 messageFontButton.setText( getEncodedFontName( font ).replaceAll( "-", " " ) ); 145 messageFontButton.setFont( font ); 146 147 c.gridx = 0; 148 c.gridy++; 149 messageLabel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 5 ) ); 150 grid.setConstraints( messageLabel, c ); 151 add( messageLabel ); 152 c.gridx++; 153 messageFontButton.addActionListener( fontListener ); 154 grid.setConstraints( messageFontButton, c ); 155 add( messageFontButton ); 156 157 // get the application font settings 158 String appFont = Settings.getInstance().getProperty( "applicationFont" ); 159 if( appFont == null ) appFont = "Default-PLAIN-12"; 160 161 font = Font.decode( appFont ); 162 appFontButton.setText( getEncodedFontName( font ).replaceAll( "-", " " ) ); 163 appFontButton.setFont( font ); 164 165 c.gridx = 0; 166 c.gridy++; 167 appFontLabel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 5 ) ); 168 grid.setConstraints( appFontLabel, c ); 169 add( appFontLabel ); 170 c.gridx++; 171 appFontButton.addActionListener( fontListener ); 172 grid.setConstraints( appFontButton, c ); 173 add( appFontButton ); 174 175 //this is the space taker 176 JLabel blankLabel = new JLabel( "" ); 177 c.weighty = 1; 178 c.weightx = 1; 179 c.gridx = 0; 180 c.gridwidth = 3; 181 c.gridy++; 182 grid.setConstraints( blankLabel, c ); 183 add( blankLabel ); 184 } 185 186 /** 187 * Listens for one of the font buttons to be clicked and displays a FontChooserDialog for it 188 * @author Adam Olsen 189 * @version 1.0 190 */ 191 private class FontChangeListener implements ActionListener 192 { 193 public void actionPerformed( ActionEvent e ) 194 { 195 JButton button = (JButton)e.getSource(); 196 FontChooserDialog dialog = new FontChooserDialog( prefs, resources.getString( "messageWindowFont" ), 197 true, button.getFont() ); 198 199 dialog.show(); 200 201 if( !dialog.isCancelled() ) 202 { 203 Font newFont = dialog.getSelectedFont(); 204 button.setFont( newFont ); 205 button.setText( getEncodedFontName( newFont ).replaceAll( "-", " " ) ); 206 } 207 } 208 } 209 210 /** 211 * Checks the default jar file and the user theme directory for status themes 212 */ 213 private JComboBox getStatusThemes() 214 { 215 JComboBox box = new JComboBox(); 216 String current = Settings.getInstance().getProperty( "statusTheme" ); 217 if( current == null ) current = "default"; 218 box.addItem( current ); 219 220 221 // user defined themes 222 File path = new File(JBother.settingsDir + File.separatorChar + "themes" + File.separatorChar + "statusicons"); 223 224 String[] userThemes = new String[0]; 225 226 if( !path.isDirectory() && !path.mkdirs() ) 227 { 228 com.valhalla.Logger.debug( "Could not create user defined settings directories." ); 229 } 230 else { 231 userThemes = path.list(); 232 for ( int i=0; i<userThemes.length; i++ ) { 233 if (!current.equals(userThemes[i])) box.addItem(userThemes[i]); 234 } 235 } 236 237 // default themes in the jar 238 InputStream stream = getClass().getClassLoader().getResourceAsStream( "imagethemes/statusicons/index.dat" ); 239 if( stream == null ) 240 { 241 com.valhalla.Logger.debug( "Bad status theme file." ); 242 return box; 243 } 244 245 InputStreamReader in = new InputStreamReader( stream ); 246 BufferedReader reader = new BufferedReader( in ); 247 String line; 248 try { 249 while( ( line = reader.readLine() ) != null ) 250 { 251 boolean userTheme = false; 252 for (int i=0; i<userThemes.length; i++) { 253 if (line.equals(userThemes[i])) { 254 userTheme = true; 255 break; 256 } 257 } 258 if( !userTheme && !line.equals( current ) ) box.addItem( line ); 259 } 260 } 261 catch( IOException e ) { } 262 263 return box; 264 } 265 266 /** 267 * Gets a list of emoticon themes 268 */ 269 private JComboBox getEmoticonThemes() 270 { 271 JComboBox box = new JComboBox(); 272 String current = Settings.getInstance().getProperty( "emoticonTheme" ); 273 if( current == null ) current = "default"; 274 box.addItem( current ); 275 276 // default themes in the jar 277 InputStream stream = getClass().getClassLoader().getResourceAsStream( "imagethemes/emoticons/index.dat" ); 278 if( stream == null ) 279 { 280 com.valhalla.Logger.debug( "Bad emoticon theme file." ); 281 return box; 282 } 283 284 InputStreamReader in = new InputStreamReader( stream ); 285 BufferedReader reader = new BufferedReader( in ); 286 String line; 287 try { 288 while( ( line = reader.readLine() ) != null ) 289 { 290 if( !line.equals( current ) ) box.addItem( line ); 291 } 292 } 293 catch( IOException e ) { } 294 295 return box; 296 } 297 298 /** 299 * Gets the String representation of a font 300 * @return the string representation of a font 301 */ 302 private String getEncodedFontName( Font font ) 303 { 304 String fontString = font.getName() + "-"; 305 306 if( font.isPlain() ) fontString += "PLAIN"; 307 if( font.isBold() ) fontString += "BOLD"; 308 if( font.isItalic() ) fontString += "ITALIC"; 309 fontString += "-" + font.getSize(); 310 311 return fontString; 312 } 313 314 /** 315 * Gets temporary settings 316 * @return temporary settings 317 */ 318 public TempSettings getSettings() 319 { 320 TempSettings tempSettings = new TempSettings(); 321 322 if( lookAndFeel.getSelectedIndex() != current ) 323 { 324 Standard.noticeMessage( prefs, resources.getString( "themeLabel" ), 325 resources.getString( "themeSettingsApplied" ) ); 326 327 try { 328 Class c = PluginLoader.getInstance().loadClass( lfs[lookAndFeel.getSelectedIndex()].getClassName() ); 329 330 UIManager.setLookAndFeel( (LookAndFeel)c.newInstance() ); 331 tempSettings.setProperty( "lookAndFeel", lfs[lookAndFeel.getSelectedIndex()].getClassName() ); 332 SwingUtilities.updateComponentTreeUI( BuddyList.getInstance() ); 333 SwingUtilities.updateComponentTreeUI( BuddyList.getInstance().getBuddyListTree() ); 334 SwingUtilities.updateComponentTreeUI( prefs ); 335 if( BuddyList.getInstance().getTabFrame() != null ) SwingUtilities.updateComponentTreeUI( BuddyList.getInstance().getTabFrame() ); 336 337 Hashtable map = BuddyList.getInstance().getBuddyStatuses(); 338 java.util.List keys = new ArrayList( map.keySet() ); 339 Iterator iterator = keys.iterator(); 340 while( iterator.hasNext() ) 341 { 342 BuddyStatus buddy = (BuddyStatus)map.get( iterator.next() ); 343 if( buddy.getConversation() != null ) SwingUtilities.updateComponentTreeUI( buddy.getConversation() ); 344 } 345 346 current = lookAndFeel.getSelectedIndex(); 347 } 348 catch( Exception e ) 349 { 350 Standard.warningMessage( prefs, resources.getString( "themeLabel" ), resources.getString( "couldNotApplyTheme" ) + 351 "\n" + resources.getString( "errorMessage" ) + " " + e.getMessage() ); 352 com.valhalla.Logger.logException( e ); 353 } 354 } 355 356 tempSettings.setProperty( "messageWindowFont", getEncodedFontName( messageFontButton.getFont() ) ); 357 // update all open conversation areas 358 Hashtable buddyStatuses = BuddyList.getInstance().getBuddyStatuses(); 359 Iterator i = buddyStatuses.keySet().iterator(); 360 361 while( i.hasNext() ) 362 { 363 BuddyStatus buddy = BuddyList.getInstance().getBuddyStatus( (String)i.next() ); 364 if( buddy.getConversation() != null ) buddy.getConversation().updateStyle( messageFontButton.getFont() ); 365 } 366 367 if( BuddyList.getInstance().getTabFrame() != null ) BuddyList.getInstance().getTabFrame().updateStyles( messageFontButton.getFont() ); 368 369 tempSettings.setProperty( "applicationFont", getEncodedFontName( appFontButton.getFont() ) ); 370 updateApplicationFonts( appFontButton.getFont(), prefs ); 371 372 String selectedStatus = (String)statusTheme.getItemAt( statusTheme.getSelectedIndex() ); 373 tempSettings.setProperty( "statusTheme", selectedStatus ); 374 tempSettings.setProperty( "emoticonTheme", (String)emoticonTheme.getItemAt( emoticonTheme.getSelectedIndex() ) ); 375 376 BuddyList.getInstance().getBuddyListTree().repaint(); 377 if( BuddyList.getInstance().getTabFrame() != null ) 378 BuddyList.getInstance().getTabFrame().repaint(); 379 380 Emoticons.getInstance().switchTheme( tempSettings.getProperty( "emoticonTheme" ) ); 381 382 return tempSettings; 383 } 384 385 /** 386 * Updates all the fonts in the application 387 * @param font the font to update to 388 */ 389 public static void updateApplicationFonts( Font font, PreferencesDialog prefs ) 390 { 391 com.valhalla.jbother.JBotherLoader.setupFont( font ); 392 SwingUtilities.updateComponentTreeUI( BuddyList.getInstance() ); 393 if( prefs != null ) SwingUtilities.updateComponentTreeUI( prefs ); 394 if( BuddyList.getInstance().getTabFrame() != null ) SwingUtilities.updateComponentTreeUI( BuddyList.getInstance().getTabFrame() ); 395 396 Hashtable buddyStatuses = BuddyList.getInstance().getBuddyStatuses(); 397 if( buddyStatuses == null ) return; 398 Iterator i = buddyStatuses.keySet().iterator(); 399 400 while( i.hasNext() ) 401 { 402 String id = (String)i.next(); 403 BuddyStatus buddy = (BuddyStatus)buddyStatuses.get( id ); 404 if( buddy.getConversation() != null ) 405 SwingUtilities.updateComponentTreeUI( buddy.getConversation() ); 406 } 407 } 408 }