View Javadoc

1   package com.melloware.jukes.gui.view;
2   
3   import java.awt.BorderLayout;
4   import java.awt.Dimension;
5   import java.awt.EventQueue;
6   import java.awt.FlowLayout;
7   import java.awt.event.ActionEvent;
8   import java.awt.event.ActionListener;
9   import java.beans.PropertyChangeEvent;
10  import java.beans.PropertyChangeListener;
11  import java.util.Map;
12  import java.util.prefs.Preferences;
13  
14  import javax.sound.sampled.SourceDataLine;
15  import javax.swing.BorderFactory;
16  import javax.swing.JComponent;
17  import javax.swing.JLabel;
18  import javax.swing.JPanel;
19  import javax.swing.JProgressBar;
20  import javax.swing.JSplitPane;
21  import javax.swing.JToolBar;
22  import javax.swing.Timer;
23  
24  import javazoom.jlgui.basicplayer.BasicController;
25  import javazoom.jlgui.basicplayer.BasicPlayer;
26  import javazoom.jlgui.basicplayer.BasicPlayerEvent;
27  import javazoom.jlgui.basicplayer.BasicPlayerListener;
28  
29  import org.apache.commons.lang.StringUtils;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.log4j.Level;
33  import org.apache.log4j.Logger;
34  
35  import com.jgoodies.looks.LookUtils;
36  import com.jgoodies.uif.action.ActionManager;
37  import com.jgoodies.uif.application.Application;
38  import com.jgoodies.uif.panel.SimpleInternalFrame;
39  import com.jgoodies.uif.util.ComponentTreeUtils;
40  import com.jgoodies.uifextras.util.ActionLabel;
41  import com.jgoodies.uifextras.util.UIFactory;
42  import com.melloware.jukes.db.HibernateUtil;
43  import com.melloware.jukes.db.orm.Track;
44  import com.melloware.jukes.file.Playlist;
45  import com.melloware.jukes.file.image.ImageFactory;
46  import com.melloware.jukes.gui.tool.Actions;
47  import com.melloware.jukes.gui.tool.MainModule;
48  import com.melloware.jukes.gui.tool.Resources;
49  import com.melloware.jukes.gui.tool.Settings;
50  import com.melloware.jukes.gui.view.component.SpectrumTimeAnalyzer;
51  import com.melloware.jukes.gui.view.editor.ArtistEditor;
52  import com.melloware.jukes.gui.view.editor.DiscEditor;
53  import com.melloware.jukes.gui.view.editor.EditorPanel;
54  import com.melloware.jukes.gui.view.editor.EmptyPanel;
55  import com.melloware.jukes.gui.view.editor.TrackEditor;
56  import com.melloware.jukes.gui.view.editor.WelcomePanel;
57  import com.melloware.jukes.util.TimeSpan;
58  
59  /**
60   * Builds the main page of the Jukes application:
61   * the tool bar, navigator, help navigation, all editors,
62   * the dynamic help viewer, and the status bar.
63   * <p>
64   * Copyright (c) 1999-2007 Melloware, Inc. <http://www.melloware.com>
65   * @author Emil A. Lefkof III <info@melloware.com>
66   * @version 4.0
67   */
68  public final class MainPageBuilder
69      implements BasicPlayerListener {
70  
71      private static final Log LOG = LogFactory.getLog(MainPageBuilder.class);
72      private static final Dimension PREFERRED_SIZE = LookUtils.IS_LOW_RESOLUTION ? new Dimension(800, 600)
73                                                                                  : new Dimension(1024, 768);
74      private static final String MAIN_DIVIDER_LOCATION_KEY = "mainDividerLocation";
75      private static final String VIEWER_DIVIDER_LOCATION_KEY = "viewerDividerLocation";
76      private static final String NAVIGATOR_DIVIDER_LOCATION_KEY = "navigatorDividerLocation";
77      private static final String NAVIGATOR_VISIBLE_KEY = "navigatorVisible";
78      private static final String PLAYLIST_VISIBLE_KEY = "playlistVisible";
79      private static final TimeSpan TIMESPAN = new TimeSpan(0);
80      private ActionLabel trackField;
81      private EditorPanel editorPanel;
82      private FilterPanel filterPanel;
83      private JLabel bitrateField;
84      private JLabel durationField;
85      private JPanel mainPage;
86      private JProgressBar elapsedBar;
87      private JSplitPane editorPlaylistSplitPane;
88      private JSplitPane mainSplitPane;
89      private JSplitPane navigatorSplitPane;
90      private long elapsedTime;
91      private final MainFrame mainframe;
92      private final MainModule mainModule;
93      private Map audioInfo;
94      private NavigationPanelBuilder navigationPanel;
95      private final Playlist playlist;
96      private PlaylistPanel playlistPanel;
97      private SimpleInternalFrame navigator;
98      private Timer timer;
99  
100     /**
101      * Constructs a MainPageBuilder for the given main module.
102      *
103      * @param mainModule   provides high-level models
104      */
105     MainPageBuilder(MainModule mainModule) {
106         this.mainModule = mainModule;
107         this.playlist = new Playlist();
108         this.mainModule.addPropertyChangeListener(this.playlist);
109         this.mainframe = (MainFrame)Application.getDefaultParentFrame();
110         MainModule.SETTINGS.addPropertyChangeListener(new PresentationSettingsChangeHandler());
111     }
112 
113     /**
114      * Gets the playlist.
115      * <p>
116      * @return Returns the playlist.
117      */
118     public Playlist getPlaylist() {
119         return this.playlist;
120     }
121 
122     /* (non-Javadoc)
123      * @see javazoom.jlgui.basicplayer.BasicPlayerListener#setController(javazoom.jlgui.basicplayer.BasicController)
124      */
125     public void setController(BasicController controller) {
126         if (LOG.isDebugEnabled()) {
127             LOG.debug("Controller " + controller);
128         }
129     }
130 
131     /**
132      * Sets the visiblity of the filter panel.
133      */
134     public void setFilterVisible(boolean b) {
135         if (isFilterVisible() == b) {
136             return;
137         }
138         if (b) {
139             navigatorSplitPane.setTopComponent(navigator);
140             navigatorSplitPane.setBottomComponent(filterPanel);
141             int navigatorDividerLocation = Application.getUserPreferences().getInt(NAVIGATOR_DIVIDER_LOCATION_KEY, -1);
142             if ((navigatorDividerLocation > 50) && (navigatorDividerLocation < (mainPage.getHeight() - 50))) {
143                 navigatorSplitPane.setDividerLocation(navigatorDividerLocation);
144             }
145         } else {
146             navigatorSplitPane.setTopComponent(navigator);
147             navigatorSplitPane.setBottomComponent(null);
148         }
149     }
150 
151     /**
152      * Sets the visiblity of the playlist panel.
153      * <p>
154      * @param visible whether or not the window is visible
155      */
156     public void setPlaylistVisible(boolean visible) {
157         if (isPlaylistVisible() == visible) {
158             return;
159         }
160         if (visible) {
161             editorPlaylistSplitPane.setTopComponent(editorPanel);
162             editorPlaylistSplitPane.setBottomComponent(playlistPanel);
163             int verticalDividerLocation = Application.getUserPreferences().getInt(VIEWER_DIVIDER_LOCATION_KEY, -1);
164             if ((verticalDividerLocation > 100) && (verticalDividerLocation < (mainPage.getHeight() - 50))) {
165                 editorPlaylistSplitPane.setDividerLocation(verticalDividerLocation);
166             }
167         } else {
168             editorPlaylistSplitPane.setTopComponent(editorPanel);
169             editorPlaylistSplitPane.setBottomComponent(null);
170         }
171     }
172 
173     /**
174      * Answers if the filter panel is visible.
175      */
176     public boolean isFilterVisible() {
177         return navigatorSplitPane.getBottomComponent() != null;
178     }
179 
180     /**
181      * Answers if the playlist panel is visible.
182      */
183     public boolean isPlaylistVisible() {
184         return editorPlaylistSplitPane.getBottomComponent() != null;
185     }
186 
187     /* (non-Javadoc)
188      * @see javazoom.jlgui.basicplayer.BasicPlayerListener#opened(java.lang.Object, java.util.Map)
189      */
190     public void opened(Object stream, Map properties) {
191         audioInfo = properties;
192 
193         /*
194          * mp3.frequency.hz='44100' title='We' mp3.length.bytes='6078464' comment='Test Comments !' mp3.channels='2'
195          * date='2003' mp3.version.layer='3' mp3.framesize.bytes='413' mp3.id3tag.track='3' mp3.version.mpeg='1'
196          * mp3.bitrate.nominal.bps='229000' mp3.vbr.scale='78' copyright='copy' mp3.length.frames='8122' mp3.crc='false'
197          * album='The Sta no Expe' mp3.vbr='true' mp3.copyright='false' mp3.framerate.fps='38.28125'
198          * mp3.id3tag.v2='java.io.ByteArrayInputStream@13caecd' mp3.id3tag.v2.version='3' mp3.version.encoding='MPEG1L3'
199          * mp3.header.pos='2150' mp3.id3tag.genre='(18)Techno' mp3.original='false' mp3.mode='1' mp3.padding='false'
200          * author='Scer' duration='212167000' vbr='true' bitrate='229000'
201          *
202          */
203         final Track track = playlist.getCurrentTrack();
204         final String title = track.getName();
205         final String disc = track.getDisc().getName();
206         final String artist = track.getDisc().getArtist().getName();
207         final Long duration = Long.valueOf(track.getDuration() * 1000);
208         final String bitrate = (track.getBitrate().intValue()) + " kbps";
209         final Runnable updateList = new Runnable() {
210            public void run() {
211               trackField.setText(artist + " - " + disc + " - " + title);
212               bitrateField.setText(bitrate);
213               final int ms = (int)(duration.longValue());
214               TIMESPAN.setTime(duration.longValue());
215               durationField.setText(TIMESPAN.getMusicDuration());
216               elapsedBar.setValue(0);
217               elapsedBar.setMaximum(ms);
218               
219               // set the tray icon tooltip
220               if (mainframe.getTrayIcon() != null) {
221                   mainframe.getTrayIcon().setToolTip(artist + " - " + title);
222               }
223               
224               // refresh the window
225               refreshUI();
226            }
227         };
228         EventQueue.invokeLater(updateList);
229 
230         
231     }
232 
233     /* (non-Javadoc)
234      * @see javazoom.jlgui.basicplayer.BasicPlayerListener#progress(int, long, byte[], java.util.Map)
235      */
236     public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties) {
237         mainframe.getAnalyzer().writeDSP(pcmdata);
238         this.setElapsedTime(microseconds);
239     }
240 
241     /**
242      * Repaints the screen after a track changes.
243      */
244     public void refreshUI() {
245         //mainPage.updateUI();
246        navigator.updateUI();
247        editorPanel.updateUI();
248     }
249 
250     /**
251      * Restores the frame's state from the user preferences.
252      */
253     public void restoreFrom(Preferences userPrefs) {
254         int mainDividerLocation = userPrefs.getInt(MAIN_DIVIDER_LOCATION_KEY, -1);
255         int verticalDividerLocation = userPrefs.getInt(VIEWER_DIVIDER_LOCATION_KEY, -1);
256         int navigatorDividerLocation = userPrefs.getInt(NAVIGATOR_DIVIDER_LOCATION_KEY, -1);
257         setPlaylistVisible(userPrefs.getBoolean(PLAYLIST_VISIBLE_KEY, true));
258         setFilterVisible(userPrefs.getBoolean(NAVIGATOR_VISIBLE_KEY, true));
259 
260         if ((mainDividerLocation > 100) && (mainDividerLocation < (mainPage.getWidth() - 50))) {
261             mainSplitPane.setDividerLocation(mainDividerLocation);
262         }
263         if ((verticalDividerLocation > 100) && (verticalDividerLocation < (mainPage.getHeight() - 50))) {
264             editorPlaylistSplitPane.setDividerLocation(verticalDividerLocation);
265         }
266         if ((navigatorDividerLocation > 50) && (navigatorDividerLocation < (mainPage.getHeight() - 50))) {
267             navigatorSplitPane.setDividerLocation(navigatorDividerLocation);
268         }
269     }
270 
271     /* (non-Javadoc)
272      * @see javazoom.jlgui.basicplayer.BasicPlayerListener#stateUpdated(javazoom.jlgui.basicplayer.BasicPlayerEvent)
273      */
274     public void stateUpdated(BasicPlayerEvent event) {
275         if (LOG.isDebugEnabled()) {
276            LOG.debug("stateUpdated : " + event.toString());
277         }
278         final SpectrumTimeAnalyzer analyzer = mainframe.getAnalyzer();
279         switch (event.getCode()) {
280             case BasicPlayerEvent.PLAYING: {
281                 break;
282             }
283             case BasicPlayerEvent.OPENED:
284             case BasicPlayerEvent.RESUMED: {
285                 mainframe.updateTrayIcon(ImageFactory.ICO_TRAYPLAY.getImage());
286                 if ((audioInfo.containsKey("basicplayer.sourcedataline")) && (analyzer != null)) {
287                    analyzer.setupDSP((SourceDataLine)audioInfo.get("basicplayer.sourcedataline"));
288                    analyzer.startDSP((SourceDataLine)audioInfo.get("basicplayer.sourcedataline"));
289                 }
290                 timer.start();
291                 break;
292             }
293             case BasicPlayerEvent.PAUSED: {
294                 timer.stop();
295                 mainframe.updateTrayIcon(ImageFactory.ICO_TRAYPAUSE.getImage());
296                 break;
297             }
298             case BasicPlayerEvent.STOPPED: {
299                 timer.stop();
300                 mainframe.updateTrayIcon(ImageFactory.ICO_TRAYSTOP.getImage());
301                 if (analyzer != null) {
302                    analyzer.stopDSP();
303                    analyzer.repaint();
304                 }
305                 final Runnable updateList = new Runnable() {
306                    public void run() {
307                       elapsedBar.setValue(0);
308                       TIMESPAN.setTime(0);
309                       elapsedBar.setString(TIMESPAN.getMusicDuration());
310                    }
311                 };
312                 EventQueue.invokeLater(updateList);
313                 break;
314             }
315             case BasicPlayerEvent.EOM: {
316                 timer.stop();
317                 final Track track = (Track)getPlaylist().getNext();
318                 if (track != null) {
319                     mainframe.getPlayer().play(track.getTrackUrl());
320                 }
321                 break;
322             }
323             default: {
324                 break;
325             }
326         }
327     }
328     
329     
330 
331     /**
332      * Stores the frame's state in the user preferences.
333      */
334     public void storeIn(Preferences userPrefs) {
335         if (isPlaylistVisible()) {
336             int verticalDividerLocation = editorPlaylistSplitPane.getDividerLocation();
337             userPrefs.putInt(VIEWER_DIVIDER_LOCATION_KEY, verticalDividerLocation);
338         }
339         if (isFilterVisible()) {
340             int navigatorDividerLocation = navigatorSplitPane.getDividerLocation();
341             userPrefs.putInt(NAVIGATOR_DIVIDER_LOCATION_KEY, navigatorDividerLocation);
342         }
343         int mainDividerLocation = mainSplitPane.getDividerLocation();
344         userPrefs.putInt(MAIN_DIVIDER_LOCATION_KEY, mainDividerLocation);
345         userPrefs.putBoolean(NAVIGATOR_VISIBLE_KEY, isFilterVisible());
346         userPrefs.putBoolean(PLAYLIST_VISIBLE_KEY, isPlaylistVisible());
347     }
348 
349     /**
350      * Builds this panel with the horizontal <code>JSplitPane</code> in the
351      * center and a status bar in the south.
352      */
353     JComponent build() {
354         initComponents();
355 
356         mainPage = new RefreshedPanel();
357         mainPage.setLayout(new BorderLayout());
358         mainPage.add(new MainToolBarBuilder().build(), BorderLayout.NORTH);
359         mainPage.add(buildMainSplitPane(), BorderLayout.CENTER);
360         mainPage.add(buildStatusBar(), BorderLayout.SOUTH);
361         mainPage.setPreferredSize(PREFERRED_SIZE);
362 
363         return mainPage;
364     }
365 
366     /**
367      * Builds the <code>EditorPanel</code>, the <code>PlaylistPanel</code>
368      * and answers them wrapped by a stripped <code>JSplitPane</code>.
369      */
370     private JComponent buildEditorHelpPanel() {
371         editorPlaylistSplitPane = UIFactory.createStrippedSplitPane(JSplitPane.VERTICAL_SPLIT, buildEditorPanel(),
372                                                                     playlistPanel, 0.667);
373         return editorPlaylistSplitPane;
374     }
375 
376     /**
377      * Builds and answers the <code>EditorPanel</code>.
378      */
379     private EditorPanel buildEditorPanel() {
380         WelcomePanel welcomePanel = new WelcomePanel();
381 
382         editorPanel.addEditor(welcomePanel);
383         editorPanel.addEditor(new EmptyPanel());
384         editorPanel.addEditor(new ArtistEditor());
385         editorPanel.addEditor(new DiscEditor());
386         editorPanel.addEditor(new TrackEditor());
387 
388         editorPanel.setActiveEditor(welcomePanel);
389         return editorPanel;
390     }
391 
392     /**
393      * Builds the <code>Navigator</code>, the <code>HelpNavigator</code>
394      * and answers them wrapped by a stripped <code>JSplitPane</code>.
395      */
396     private JComponent buildFilterPanel() {
397         return UIFactory.createStrippedSplitPane(JSplitPane.VERTICAL_SPLIT, navigator, filterPanel, 0.64);
398     }
399 
400     /**
401      * Builds and answers the main <code>JSplitPane</code> that contains
402      * the navigation elements on the left, and the view panels on the right.
403      */
404     private JComponent buildMainSplitPane() {
405         navigatorSplitPane = (JSplitPane)buildFilterPanel();
406         mainSplitPane = UIFactory.createStrippedSplitPane(JSplitPane.HORIZONTAL_SPLIT, navigatorSplitPane,
407                                                           buildEditorHelpPanel(), 0.25);
408         mainSplitPane.setBorder(BorderFactory.createEmptyBorder(6, 4, 0, 4));
409         return mainSplitPane;
410     }
411 
412     /**
413      * Builds and answers the status bar.
414      */
415     private JPanel buildStatusBar() {
416         final JPanel statusPanel = new JPanel(new BorderLayout());
417         final JPanel infoPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
418         final JToolBar toolbar = MainToolBarBuilder.buildPlayerToolBar();
419         toolbar.setBorder(BorderFactory.createEmptyBorder());
420         infoPanel.setBorder(BorderFactory.createEmptyBorder());
421         statusPanel.add(toolbar, BorderLayout.WEST);
422         statusPanel.add(infoPanel, BorderLayout.EAST);
423         statusPanel.setBorder(BorderFactory.createEmptyBorder());
424         infoPanel.add(trackField);
425         trackField.setBorder(BorderFactory.createEmptyBorder());
426         infoPanel.add(bitrateField);
427         bitrateField.setBorder(BorderFactory.createEmptyBorder());
428         infoPanel.add(durationField);
429         durationField.setBorder(BorderFactory.createEmptyBorder());
430         infoPanel.add(elapsedBar);
431         elapsedBar.setBorder(BorderFactory.createEmptyBorder());
432         return statusPanel;
433     }
434 
435     /**
436      * Creates, binds and configures the subpanels and components.
437      */
438     private void initComponents() {
439         navigator = new SimpleInternalFrame(Resources.getString("navigator.label"));
440         navigator.setFrameIcon(Resources.NAVIGATOR_ICON);
441         navigationPanel = new NavigationPanelBuilder(mainModule);
442         navigator.setContent(navigationPanel.build());
443         navigator.setSelected(true);
444         navigator.setMinimumSize(new Dimension(100, 100));
445         navigator.setPreferredSize(new Dimension(160, 200));
446         navigator.setFrameIcon(Resources.NAVIGATOR_ICON);
447 
448         filterPanel = new FilterPanel(MainModule.SETTINGS);
449         filterPanel.setSelected(true);
450         filterPanel.setMinimumSize(new Dimension(100, 45));
451         filterPanel.setPreferredSize(new Dimension(100, 45));
452 
453         editorPanel = new EditorPanel(mainModule);
454         editorPanel.setMinimumSize(new Dimension(200, 100));
455         editorPanel.setPreferredSize(new Dimension(400, 200));
456 
457         playlistPanel = new PlaylistPanel(this.playlist);
458         playlistPanel.setMinimumSize(new Dimension(300, 100));
459         playlistPanel.setPreferredSize(new Dimension(300, 100));
460 
461         trackField = new ActionLabel("");
462         trackField.addActionListener(new ActionListener() {
463 
464                 // select the track in the editor
465                 public void actionPerformed(ActionEvent event) {
466                     LOG.debug("Track clicked");
467                     if (playlist.getCurrentTrack() != null) {
468                         mainModule.selectNodeInTree(playlist.getCurrentTrack());
469                     }
470                 }
471             });
472         bitrateField = UIFactory.createPlainLabel("");
473         durationField = UIFactory.createPlainLabel("");
474         elapsedBar = new JProgressBar(0, 1);
475         elapsedBar.setIndeterminate(false);
476         elapsedBar.setStringPainted(true);
477         elapsedBar.setString("");
478 
479         timer = new Timer(950, new ActionListener() {
480 
481                 public void actionPerformed(ActionEvent aE) {
482                    final int elapsed = (int)(getElapsedTime() / 1000);
483                    TIMESPAN.setTime(elapsed);
484                    elapsedBar.setValue(elapsed);
485                    elapsedBar.setString(TIMESPAN.getMusicDuration());
486                 }
487             });
488     }
489     
490     /**
491      * Gets the elapsedTime.
492      * <p>
493      * @return Returns the elapsedTime.
494      */
495     protected synchronized long getElapsedTime() {
496        return this.elapsedTime;
497     }
498 
499     /**
500      * Sets the elapsedTime.
501      * <p>
502      * @param aElapsedTime The elapsedTime to set.
503      */
504     protected synchronized void setElapsedTime(long aElapsedTime) {
505        this.elapsedTime = aElapsedTime;
506     }
507 
508     // Updates the application if settings changed
509     private class PresentationSettingsChangeHandler
510         implements PropertyChangeListener {
511 
512         /**
513          * The presentation settings have changed.
514          *
515          * @param evt   describes the property change
516          */
517         public void propertyChange(PropertyChangeEvent evt) {
518             final String[] props = {
519                 Settings.PROPERTYNAME_AUDIT_INFO, Settings.PROPERTYNAME_COVER_SIZE_LARGE,
520                 Settings.PROPERTYNAME_COVER_SIZE_SMALL
521             };
522             final String[] refreshprops = {
523                 Settings.PROPERTYNAME_DISPLAY_FORMAT_DISC, Settings.PROPERTYNAME_DISPLAY_FORMAT_TRACK,
524                 Settings.PROPERTYNAME_NEW_FILE_IN_DAYS
525             };
526             final String[] connectProps = {
527                 Settings.PROPERTYNAME_REMOTE_DATABASE_URL, Settings.PROPERTYNAME_DIRECTORY_DB_LOCATION
528             };
529 
530             if (Settings.PROPERTYNAME_PLAYER_BUFFER_SIZE.equals(evt.getPropertyName())) {
531                 LOG.debug("Buffer size changed");
532                 BasicPlayer.EXTERNAL_BUFFER_SIZE = MainModule.SETTINGS.getPlayerBufferSize();
533             }
534             
535             if (Settings.PROPERTYNAME_LOG_LEVEL.equals(evt.getPropertyName())) {
536                 LOG.info("Log Level changed");
537                 Logger.getRootLogger().setLevel(Level.toLevel(MainModule.SETTINGS.getLogLevel()));
538                 Logger.getLogger("com.melloware").setLevel(Level.toLevel(MainModule.SETTINGS.getLogLevel()));
539                 Logger.getLogger("com.melloware.jukes.gui").setLevel(Level.toLevel(MainModule.SETTINGS.getLogLevel()));
540             }
541 
542             // if any of the editor settings changes reload
543             if (StringUtils.indexOfAny(evt.getPropertyName(), props) >= 0) {
544                 LOG.debug("Editor options changed");
545                 editorPanel.clearEditors();
546                 buildEditorPanel();
547             }
548 
549             // do we need to reconnect on prop change
550             if (StringUtils.indexOfAny(evt.getPropertyName(), connectProps) >= 0) {
551                 LOG.debug("DB Location changed, reconnecting to DB and refreshing tree.");
552                 HibernateUtil.shutdown();
553                 final String remoteURL = MainModule.SETTINGS.getRemoteDatabaseURL();
554                 if ((StringUtils.isNotBlank(remoteURL)) && (!Settings.DEFAULT_REMOTE_DATABASE_URL.equals(remoteURL))) {
555                     HibernateUtil.setRemoteUrl(remoteURL);
556                 } else {
557                     HibernateUtil.setRemoteUrl(null);
558                 }
559                 ActionManager.get(Actions.CONNECT_ID).actionPerformed(null);
560             }
561 
562             // do we need to refresh the tree on prop change
563             if (StringUtils.indexOfAny(evt.getPropertyName(), refreshprops) >= 0) {
564                 LOG.debug("Navigation options changed.");
565                 ActionManager.get(Actions.REFRESH_ID).actionPerformed(null);
566             }
567             
568             if (Settings.PROPERTYNAME_ANALYZER_MODE.equals(evt.getPropertyName())) {
569                 mainframe.getAnalyzer().setDisplayMode(MainModule.SETTINGS.getAnalyzerMode());
570             }
571         }
572     }
573 
574     private class RefreshedPanel
575         extends JPanel {
576 
577         /**
578          * In case some panels are invisible, we explicitly update their UIs.
579          */
580         public void updateUI() {
581             super.updateUI();
582             if (getComponentCount() == 0) {
583                 return;
584             }
585             if ((editorPlaylistSplitPane == null) || isPlaylistVisible()) {
586                 return;
587             }
588             ComponentTreeUtils.updateComponentTreeUI(editorPlaylistSplitPane);
589         }
590 
591     }
592 
593    
594 
595 }