/*----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is Fever Framework code. The Initial Developer of the Original Code is Romain Ecarnot. Portions created by Initial Developer are Copyright (C) 2006 the Initial Developer. All Rights Reserved. Contributor(s): Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -----------------------------------------------------------------------------*/ import org.aswing.ASWingUtils; import org.aswing.border.Border; import org.aswing.border.EmptyBorder; import org.aswing.border.TitledBorder; import org.aswing.BorderLayout; import org.aswing.Component; import org.aswing.geom.Point; import org.aswing.Insets; import org.aswing.JButton; import org.aswing.JComboBox; import org.aswing.JFrame; import org.aswing.JLabel; import org.aswing.JPanel; import org.aswing.SoftBoxLayout; import org.aswing.UIManager; import fever.app.theme.Theme; import fever.app.theme.ThemeLocator; import fever.display.ModalScreen; import fever.Fever; import fvaswing.components.FvBitmapIcon; import fvaswing.components.themechooser.FvThemeChooserResources; /** * Chooser dialog to customize application Look and Feel. * *
Dialog is open in modal mode to avoid user interactions during * customisation process. * *
Modifications can be process at runtime or at application restart
* Using a SharedLocal object saved object.
*
*
Use {@link #enabledRuntimeSwapping} property to define if runtime is enabled * or not. * *
Take a look at {@link fever.app.theme.Theme} class to know how * to register AsWing Look'nFeel. * *
Register some themes : * {@code * var at : ThemeLocator = ThemeLocator.getInstance(); * at.register( 'Office 2003', new Office2003LAF() ); * at.register( 'WinXP 2003', new WinXPLAF() ); * at.addEventListener( FvThemeLocator.onChangeEVENT, this, _onUIUpdate ); * at.load( 'WinXP 2003' ); * } * *
Opens chooser * {@code * FvThemeChooser.open(); * } * * @author Romain Ecarnot */ class fvaswing.components.FvThemeChooser { //------------------------------------------------------------------------- // Private properties //------------------------------------------------------------------------- private static var _instance : FvThemeChooser; private var _frame : JFrame; private var _list : JComboBox; private var _preview : JLabel; private var _okButton : JButton; private var _cancelButton : JButton; private var _applyButton : JButton; private var _restartLabel : JLabel; private var _modal : ModalScreen; private var _previewPanel : JPanel; private var _themePanel : JPanel; private var _current : Theme; private var _testedTheme : String; //------------------------------------------------------------------------- // Public Properties //------------------------------------------------------------------------- /** * Indicates if theme can be apply at runtime or only at application * restart. Default is {@code true}. */ public static var enabledRuntimeSwapping : Boolean = true; //------------------------------------------------------------------------- // Public API //------------------------------------------------------------------------- /** * Retreives singleton instance. */ public static function getInstance( ) : FvThemeChooser { if( !_instance ) _instance = new FvThemeChooser(); return _instance; } /** * Opens dialog. */ public function open() : Void { _openDialog(); } //------------------------------------------------------------------------- // Private implementation //------------------------------------------------------------------------- /** * Constructor. */ private function FvThemeChooser() { _configureUI(); } /** * Resets JList data and open dialog. */ private function _openDialog() : Void { _current = ThemeLocator.getInstance().getCurrentTheme(); if( !_current ) { _current = new Theme( 'default', UIManager.getLookAndFeel() ); ThemeLocator.getInstance().registerTheme( _current ); } _testedTheme = _current.getName(); _list.setListData( ThemeLocator.getInstance().getThemeList() ); _list.setSelectedItem( _current.getName() ); _list.revalidateIfNecessary(); _updateLocalisation(); _restartLabel.setVisible( !enabledRuntimeSwapping ); _layout(); _modal.show(); _frame.show(); } private function _updateLocalisation() : Void { _okButton.setText( FvThemeChooserResources.getInstance().okLabel ); _cancelButton.setText( FvThemeChooserResources.getInstance().cancelLabel ); _applyButton.setText( FvThemeChooserResources.getInstance().applyLabel ); _restartLabel.setText( FvThemeChooserResources.getInstance().restartMessage ); _frame.setTitle( FvThemeChooserResources.getInstance().title ); _themePanel.setBorder( _buildTiledBorder( FvThemeChooserResources.getInstance().lafTitle ) ); _previewPanel.setBorder( _buildTiledBorder( FvThemeChooserResources.getInstance().previewTitle ) ); } /** * Prepares dialog. */ private function _configureUI() : Void { _configureBasedFrame(); _themePanel = _buildTiledPanel( '' ); _themePanel.append( _getLafList(), BorderLayout.NORTH ); _previewPanel = _buildTiledPanel( '' ); _previewPanel.append( _getPreview(), BorderLayout.NORTH ); _restartLabel = new JLabel( '' ); var option : JPanel = new JPanel( new SoftBoxLayout( SoftBoxLayout.Y_AXIS, 5 ) ); option.append( _themePanel ); option.append( _previewPanel ); option.append( _restartLabel ); var framePanel : JPanel = new JPanel( new BorderLayout( 5, 5 ) ); framePanel.setBorder( new EmptyBorder( null, new Insets( 5, 5, 5, 5 ) ) ); framePanel.append( option, BorderLayout.NORTH ); framePanel.append( _getButtonPanel(), BorderLayout.SOUTH ); _frame.getContentPane().append ( framePanel, BorderLayout.CENTER ); } /** * Configures the based {@code JFrame} container. */ private function _configureBasedFrame() : Void { _modal = new ModalScreen(); _frame = new JFrame( _modal.getModalTarget(), '', false ); _frame.setResizable( false ); _frame.setClosable( false ); _frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); _frame.addEventListener( JFrame.ON_WINDOW_CLOSING, _handleClose, this ); } /** * Creates LAF Chooser list */ private function _getLafList() : JComboBox { _list = new JComboBox( ); _list.addActionListener( _handleListClick, this ); return _list; } /** * Creates container for laf preview image */ private function _getPreview() : Component { _preview = new JLabel( '', JLabel.CENTER ); _preview.setPreferredSize( 250, 150 ); return _preview; } private function _getButtonPanel() : JPanel { var w : Number = 100; _okButton = new JButton( '-' ); _okButton.setPreferredWidth( w ); _okButton.addActionListener( _handleOkButton, this ); _cancelButton = new JButton( '-' ); _cancelButton.setPreferredWidth( w ); _cancelButton.addActionListener( _handleCancelButton, this ); _applyButton = new JButton( '-' ); _applyButton.setPreferredWidth( w ); _applyButton.addActionListener( _handleApply, this ); var p : JPanel = new JPanel( new SoftBoxLayout( SoftBoxLayout.X_AXIS, 5, SoftBoxLayout.RIGHT ) ); p.append( _okButton ); p.append( _cancelButton ); p.append( _applyButton ); return p; } /** * Calculates a new frame position */ private function _layout() : Void { _frame.pack(); var location : Point = ASWingUtils.getScreenCenterPosition(); location.x = _frame.getWidth()/2; location.y = _frame.getHeight()/2; _frame.setLocation( location ); } /** * Creates a new JPanel with TiledBorder */ private function _buildTiledPanel( caption ) : JPanel { var p : JPanel = new JPanel( new BorderLayout( 5, 5 ) ); p.setBorder( _buildTiledBorder( caption ) ); return p; } /** * Creates a tiled border. */ private function _buildTiledBorder( caption : String ) : Border { return new TitledBorder( _buildInternalBorder(), caption, TitledBorder.TOP, TitledBorder.LEFT, 10 ); } /** * Creates internal border on component */ private function _buildInternalBorder() : Border { return new EmptyBorder( null, new Insets( 0,10,5,10 ) ); } /** * Trigerred when user click on a button ( or default close button ) */ private function _handleClose( button : JButton ) : Void { _modal.hide(); _frame.tryToClose(); } /** * Triggered when user click on list's item. */ private function _handleListClick( source : JComboBox ) : Void { var theme : Theme = ThemeLocator.getInstance().getTheme( source.getSelectedItem().toString() ); if( theme.hasPreview() ) { _preview.setText( ); _preview.setIcon( FvBitmapIcon.create( theme.getPreview(), Theme.PREVIEW_REPOSITORY ) ); } else { _preview.setIcon( null ); _preview.setText( FvThemeChooserResources.getInstance().noPreviewLabel ); } } private function _handleCancelButton() : Void { _applySelectedTheme( _current ); _handleClose(); } private function _handleOkButton() : Void { if( !enabledRuntimeSwapping ) { _saveCookie( _list.getSelectedItem().toString() ); } _handleClose(); } private function _handleApply() : Void { if( enabledRuntimeSwapping ) _applySelectedTheme( ThemeLocator.getInstance().getTheme( _list.getSelectedItem().toString() ) ); } private function _applySelectedTheme ( theme : Theme ) : Void { if( ( _testedTheme != theme.getName() ) ) { _testedTheme = theme.getName(); ThemeLocator.getInstance().load( theme.getName() ); } } private function _saveCookie( lafName : String ) : Void { Fever.application.config.save( ThemeLocator.CONFIG_ID, lafName ); } }