001 /** 002 * iFish - An iRiver iHP jukebox database creation tool 003 * 004 * Copyright (C) 2009 Richard "Shred" Körber 005 * http://ifish.shredzone.org 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020 package net.shredzone.ifish; 021 022 import java.awt.BorderLayout; 023 import java.awt.Component; 024 import java.awt.event.ActionEvent; 025 import java.awt.event.KeyEvent; 026 import java.util.HashMap; 027 import java.util.Map; 028 import java.util.prefs.Preferences; 029 030 import javax.swing.Action; 031 import javax.swing.Icon; 032 import javax.swing.JCheckBoxMenuItem; 033 import javax.swing.JOptionPane; 034 import javax.swing.JPanel; 035 import javax.swing.JTabbedPane; 036 import javax.swing.KeyStroke; 037 038 import net.shredzone.ifish.actions.AboutAction; 039 import net.shredzone.ifish.actions.DeleteDatabaseAction; 040 import net.shredzone.ifish.actions.ExportDatabaseAction; 041 import net.shredzone.ifish.actions.IFishAction; 042 import net.shredzone.ifish.actions.PlayerAction; 043 import net.shredzone.ifish.actions.PrefsAction; 044 import net.shredzone.ifish.actions.QuitAction; 045 import net.shredzone.ifish.actions.ReadDatabaseAction; 046 import net.shredzone.ifish.actions.SaveDatabaseAction; 047 import net.shredzone.ifish.actions.SyncDatabaseAction; 048 import net.shredzone.ifish.db.Entry; 049 import net.shredzone.ifish.db.PlaylistDb; 050 import net.shredzone.ifish.gui.DatabasePane; 051 import net.shredzone.ifish.gui.NaviDbTableModel; 052 import net.shredzone.ifish.gui.PlaylistPane; 053 import net.shredzone.ifish.gui.ScannerPane; 054 import net.shredzone.ifish.gui.StatusProgressBar; 055 import net.shredzone.ifish.i18n.L; 056 import net.shredzone.ifish.pool.ImgPool; 057 058 /** 059 * This is the IFish's main pane, with all the buttons and stuff. 060 * 061 * @author Richard Körber <dev@shredzone.de> 062 * @version $Id: IFishPane.java 291 2009-04-28 21:29:27Z shred $ 063 */ 064 public class IFishPane extends JPanel { 065 private static final long serialVersionUID = 3257850965439559731L; 066 067 public static final String ACTION_READDATABASE = "db.read"; 068 public static final String ACTION_SYNCDATABASE = "db.sync"; 069 public static final String ACTION_SAVEDATABASE = "db.save"; 070 public static final String ACTION_DELETEDATABASE = "db.delete"; 071 public static final String ACTION_EXPORTDATABASE = "db.export"; 072 public static final String ACTION_ABOUT = "about"; 073 public static final String ACTION_PREFS = "prefs"; 074 public static final String ACTION_QUIT = "quit"; 075 public static final String ACTION_TAB_SCANNER = "tab.scanner"; 076 public static final String ACTION_TAB_DB = "tab.db"; 077 public static final String ACTION_TAB_PLAYLIST = "tab.playlist"; 078 public static final String ACTION_PLAYER_PLAY = "player.play"; 079 public static final String ACTION_PLAYER_PAUSE = "player.pause"; 080 public static final String ACTION_PLAYER_STOP = "player.stop"; 081 082 private StatusProgressBar jprProgress; 083 private NaviDbTableModel model; 084 private PlaylistDb plmodel; 085 private DatabasePane database; 086 private PlaylistPane plpane; 087 private JTabbedPane tabpane; 088 private ScannerPane scanner; 089 private final String plBaseDir; 090 private PlaylistSource plsource = null; 091 private IFishPrefs prefs; 092 private Map<String, Action> mActions = new HashMap<String, Action>(); 093 private boolean hasChanges = false; 094 095 /** 096 * Create the IFish's main pane. 097 */ 098 public IFishPane() { 099 setLayout( new BorderLayout() ); 100 101 //--- Get preferences --- 102 prefs = IFishPrefs.instance(); 103 104 //--- Get basic settings --- 105 plBaseDir = prefs.getPLBaseDir(); 106 107 //--- Create all actions --- 108 mActions.put( ACTION_QUIT , new QuitAction( this ) ); 109 mActions.put( ACTION_ABOUT , new AboutAction( this ) ); 110 mActions.put( ACTION_PREFS , new PrefsAction( this ) ); 111 mActions.put( ACTION_READDATABASE , new ReadDatabaseAction( this ) ); 112 mActions.put( ACTION_SYNCDATABASE , new SyncDatabaseAction( this ) ); 113 mActions.put( ACTION_SAVEDATABASE , new SaveDatabaseAction( this ) ); 114 mActions.put( ACTION_DELETEDATABASE, new DeleteDatabaseAction( this ) ); 115 mActions.put( ACTION_EXPORTDATABASE, new ExportDatabaseAction( this ) ); 116 mActions.put( ACTION_PLAYER_PLAY , new PlayerAction( this, PlayerAction.PLAY ) ); 117 mActions.put( ACTION_PLAYER_PAUSE , new PlayerAction( this, PlayerAction.PAUSE ) ); 118 mActions.put( ACTION_PLAYER_STOP , new PlayerAction( this, PlayerAction.STOP ) ); 119 120 //--- Create the database table --- 121 database = new DatabasePane( this ); 122 model = new NaviDbTableModel(); 123 database.setModel( model ); 124 125 //--- Create the playlist --- 126 plpane = new PlaylistPane( this ); 127 128 //--- The Progress bar --- 129 jprProgress = new StatusProgressBar(); 130 add( jprProgress, BorderLayout.SOUTH ); 131 132 //--- Create the TabbedPane --- 133 scanner = new ScannerPane( this ); 134 tabpane = new JTabbedPane(); 135 136 addTab( 137 L.tr("main.tab.scanner"), 138 ImgPool.get("tab_sync.png"), 139 scanner, 140 L.tr("main.tab.scanner.tt"), 141 ACTION_TAB_SCANNER, 142 KeyStroke.getKeyStroke( KeyEvent.VK_1, ActionEvent.CTRL_MASK ) 143 ); 144 145 addTab( 146 L.tr("main.tab.database"), 147 ImgPool.get("tab_database.png"), 148 database, 149 L.tr("main.tab.database.tt"), 150 ACTION_TAB_DB, 151 KeyStroke.getKeyStroke( KeyEvent.VK_2, ActionEvent.CTRL_MASK ) 152 ); 153 154 addTab( 155 L.tr("main.tab.playlist"), 156 ImgPool.get("tab_playlist.png"), 157 plpane, 158 L.tr("main.tab.playlist.tt"), 159 ACTION_TAB_PLAYLIST, 160 KeyStroke.getKeyStroke( KeyEvent.VK_3, ActionEvent.CTRL_MASK ) 161 ); 162 163 add( tabpane, BorderLayout.CENTER ); 164 } 165 166 /** 167 * Get the Action named with the given key. 168 * 169 * @param key Action you are asking for 170 * @return The Action or null 171 */ 172 public IFishAction getAction( String key ) { 173 return (IFishAction) mActions.get( key ); 174 } 175 176 /** 177 * Get the Preferences 178 * 179 * @return Preferences 180 */ 181 public IFishPrefs getPrefs() { 182 return prefs; 183 } 184 185 /** 186 * Get the Playlist's base directory. 187 * 188 * @return Base directory, default is "ifish". 189 */ 190 public String getPLBase() { 191 return plBaseDir; 192 } 193 194 /** 195 * Set that there have been unsaved changes. 196 * This is a bound property with the name "unsaved". 197 * 198 * @param unsaved Unsaved changes 199 */ 200 public void setUnsaved( boolean unsaved ) { 201 boolean old = hasChanges; 202 hasChanges = unsaved; 203 if( old!=unsaved ) { 204 firePropertyChange( "unsaved", Boolean.valueOf(old), Boolean.valueOf(unsaved) ); 205 } 206 } 207 208 /** 209 * Check if there are unsaved changes. 210 * 211 * @return true if there are unsaved changes. 212 */ 213 public boolean isUnsaved() { 214 return hasChanges; 215 } 216 217 /** 218 * Confirm if the user really wants to lose all unsaved changes. 219 * 220 * @return true: there are no unsaved changes, or the user wants to lose 221 * them. false: there are unsaved changes and the user aborted the 222 * operation. 223 */ 224 public boolean confirmChanges() { 225 if(! isUnsaved() ) return true; 226 return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog( 227 this, 228 L.tr("lose.confirm"), 229 L.tr("lose.confirm.title"), 230 JOptionPane.YES_NO_OPTION, 231 JOptionPane.QUESTION_MESSAGE 232 ); 233 } 234 235 /** 236 * Get the StatusProgressBar that shows the status. 237 * 238 * @return StatusProgressBar 239 */ 240 public StatusProgressBar getStatusBar() { 241 return jprProgress; 242 } 243 244 /** 245 * Get the current NaviDb database 246 * 247 * @return Current Database 248 */ 249 public NaviDbTableModel getDatabase() { 250 return model; 251 } 252 253 /** 254 * Set a new database. 255 * This is a bound property with the name "database". 256 * 257 * @param model Database model to be shown 258 */ 259 public void setDatabase( NaviDbTableModel model ) { 260 NaviDbTableModel old = this.model; 261 this.model = model; 262 database.setModel( model ); 263 firePropertyChange( "database", old, model ); 264 } 265 266 /** 267 * Get the current PlaylistDb database 268 * 269 * @return Current Playlist database 270 */ 271 public PlaylistDb getPlaylist() { 272 return plmodel; 273 } 274 275 /** 276 * Set a new playlist database. 277 * This is a bound property with the name "playlist". 278 * 279 * @param playlist Playlist database 280 */ 281 public void setPlaylist( PlaylistDb playlist ) { 282 PlaylistDb old = this.plmodel; 283 this.plmodel = playlist; 284 plpane.setPlaylistDb( playlist ); 285 firePropertyChange( "playlist", old, playlist ); 286 } 287 288 /** 289 * Update the status panes with the data of the given model. This 290 * is not necessarily the current database. 291 * 292 * @param model Database model to be shown 293 */ 294 public void updateStatus( NaviDbTableModel model ) { 295 scanner.update( model ); 296 } 297 298 /** 299 * Set the playlist source which is to be used for playlist selection. 300 * This is a bound property with the name "playlistsource". 301 * 302 * @param source Playlist Source 303 */ 304 public void setPlaylistSource( PlaylistSource source ) { 305 PlaylistSource old = plsource; 306 plsource = source; 307 firePropertyChange( "playlistsource", old, source ); 308 } 309 310 /** 311 * Get the playlist source which is to be used for playlist selection. 312 * 313 * @return Playlist source or null if none was set yet. 314 */ 315 public PlaylistSource getPlaylistSource() { 316 return plsource; 317 } 318 319 /** 320 * Get the currently selected Entries in the database or the playlist. 321 * 322 * @return Array of Entry, might be empty but never null 323 */ 324 public Entry[] getSelectedEntries() { 325 if( plsource==null ) return new Entry[0]; 326 return plsource.getSelectedEntries(); 327 } 328 329 /** 330 * Get the entries currently selected in the database pane. 331 * 332 * @return Array of Entry, might be empty but never null 333 */ 334 public Entry[] getSelectedDatabaseEntries() { 335 return database.getSelectedEntries(); 336 } 337 338 /** 339 * Add a tab to the main tabbed pane and the tab menu. 340 * 341 * @param title Tab title 342 * @param icon Tab icon 343 * @param component Component shown in the tab 344 * @param tip Tooltip 345 * @param action Action name that will show this tab 346 */ 347 private void addTab( String title, Icon icon, Component component, String tip, String action, KeyStroke accel ) { 348 final int index = tabpane.getTabCount(); 349 tabpane.addTab( title, icon, component, tip ); 350 mActions.put( action, new IFishAction( this, title, icon, tip, accel ) { 351 private static final long serialVersionUID = 4050762710675110196L; 352 @Override 353 protected void action() { 354 tabpane.setSelectedIndex( index ); 355 } 356 }); 357 } 358 359 /** 360 * Store the GUI settings, like selected tabs. 361 * 362 * @param prefs Preferences context to store into. 363 */ 364 public void storeGUI( Preferences prefs ) { 365 prefs.putInt( "pane.tab.ix", tabpane.getSelectedIndex() ); 366 } 367 368 /** 369 * Recall previously stored GUI settings, or use reasonable defaults 370 * if there are none stored yet. 371 * 372 * @param prefs Preferences context to recall from. 373 */ 374 public void recallGUI( Preferences prefs ) { 375 tabpane.setSelectedIndex( prefs.getInt( "pane.tab.ix", 0) ); 376 } 377 378 } 379