/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.ui.widgets; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashSet; import java.util.Properties; import java.util.Set; import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.border.EmptyBorder; import net.miginfocom.swing.MigLayout; import org.jajuk.base.Album; import org.jajuk.base.File; import org.jajuk.events.JajukEvent; import org.jajuk.events.JajukEvents; import org.jajuk.events.ObservationManager; import org.jajuk.events.Observer; import org.jajuk.services.players.Player; import org.jajuk.services.players.QueueModel; import org.jajuk.services.webradio.WebRadio; import org.jajuk.ui.helpers.JajukTimer; import org.jajuk.util.Conf; import org.jajuk.util.Const; import org.jajuk.util.Messages; import org.jajuk.util.UtilFeatures; import org.jajuk.util.UtilGUI; import org.jajuk.util.UtilString; import org.jajuk.util.error.JajukException; import org.jajuk.util.log.Log; import org.jdesktop.swingx.JXPanel; /** * Status / information panel ( static view ). */ public final class InformationJPanel extends JXPanel implements Observer { /** Generated serialVersionUID. */ private static final long serialVersionUID = 1L; /** * . */ public static enum MessageType { INFORMATIVE, ERROR, WARNING } /** Self instance. */ private static InformationJPanel ijp = new InformationJPanel(); /** Swing Timer to refresh the component. */ private final Timer timer = new Timer(JajukTimer.DEFAULT_HEARTBEAT, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { update(new JajukEvent(JajukEvents.HEART_BEAT)); } catch (Exception ex) { Log.error(ex); } } }); /** * Singleton access. * * @return the instance */ public static InformationJPanel getInstance() { return ijp; } // widgets declaration public JLabel jlMessage; JLabel jlSelection; JLabel jlTotal; // attributes String sMessage; /** Current message type. */ MessageType type = MessageType.INFORMATIVE; String sSelection; String sTotalStatus; private final TrackPositionSliderToolbar trackPositionSliderToolbar; /** * Instantiates a new information j panel. */ private InformationJPanel() { super(); // message bar JToolBar jtbMessage = new JajukJToolbar(); // Set a zero minimum size to allow user to reduce window width jtbMessage.setMinimumSize(new Dimension(0, 0)); // We use toolbar to display vertical separator lines jlMessage = new JLabel(); setMessage(Messages.getString("JajukWindow.18"), MessageType.INFORMATIVE); jtbMessage.add(jlMessage); jtbMessage.add(Box.createHorizontalGlue()); jtbMessage.addSeparator(); trackPositionSliderToolbar = new TrackPositionSliderToolbar(); jlTotal = new JLabel(); // Make sure to get always 5 px at the left and right of the label jlTotal.setBorder(new EmptyBorder(0, 5, 0, 5)); jlTotal.setToolTipText(Messages.getString("InformationJPanel.5")); // selection bar jlSelection = new JLabel(Messages.getString("InformationJPanel.9")); // Make sure to get always 5 px at the left and right of the label jlSelection.setBorder(new EmptyBorder(0, 5, 0, 3)); // add widgets setLayout(new MigLayout("insets 2", "[40%,grow][40%,grow][10%,grow][10%,grow]")); add(jtbMessage, "grow,left"); add(trackPositionSliderToolbar, "grow"); add(jlTotal, "grow"); add(jlSelection, "grow,right"); // check if some errors occurred before the view has been displayed if (ObservationManager.containsEvent(JajukEvents.PLAY_ERROR)) { update(new JajukEvent(JajukEvents.PLAY_ERROR, ObservationManager.getDetailsLastOccurence(JajukEvents.PLAY_ERROR))); } // check if some track has been launched before the view has been // displayed UtilFeatures.updateStatus(this); // register for given events ObservationManager.register(this); // start timer timer.start(); } /* * (non-Javadoc) * * @see org.jajuk.events.Observer#getRegistrationKeys() */ @Override public Set<JajukEvents> getRegistrationKeys() { Set<JajukEvents> eventSubjectSet = new HashSet<JajukEvents>(); eventSubjectSet.add(JajukEvents.ZERO); eventSubjectSet.add(JajukEvents.FILE_LAUNCHED); eventSubjectSet.add(JajukEvents.PLAY_ERROR); eventSubjectSet.add(JajukEvents.WEBRADIO_LAUNCHED); eventSubjectSet.add(JajukEvents.WEBRADIO_INFO_UPDATED); eventSubjectSet.add(JajukEvents.PLAYER_STOP); eventSubjectSet.add(JajukEvents.THUMB_CREATED); eventSubjectSet.add(JajukEvents.FILE_COPIED); eventSubjectSet.add(JajukEvents.FILE_CONVERSION); return eventSubjectSet; } /** * Gets the message. * * @return the message */ public String getMessage() { return sMessage; } /** * Gets the selection. * * @return the selection */ public String getSelection() { return this.sSelection; } /** * Sets the message. * * @param sMessage * @param messageType */ public void setMessage(final String sMessage, final MessageType messageType) { this.sMessage = sMessage; this.type = messageType; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { InformationJPanel.this.sMessage = sMessage; jlMessage.setText(sMessage); jlMessage.setToolTipText(sMessage); //Use default look and feel color for informative if (messageType == MessageType.ERROR) { jlMessage.setForeground(Color.RED); } else if (messageType == MessageType.WARNING) { jlMessage.setForeground(Color.ORANGE); } else if (messageType == MessageType.INFORMATIVE) { jlMessage.setForeground(UtilGUI.getForegroundColor()); } } }); } /** * Sets the selection. * * @param sSelection */ public void setSelection(String sSelection) { this.sSelection = sSelection; jlSelection.setText(sSelection); jlSelection.setToolTipText(sSelection); } /** * Gets the total time message. * * @return the total time message */ public String getTotalTimeMessage() { return sTotalStatus; } /** * Sets the total time message. * * @param string */ public void setTotalTimeMessage(String string) { sTotalStatus = string; jlTotal.setText(string); } /* * (non-Javadoc) * * @see org.jajuk.ui.Observer#update(java.lang.String) */ @Override public void update(final JajukEvent event) { final JajukEvents subject = event.getSubject(); // do not insert this subject inside the invokeLater because we have to // leave the awt dispatcher called inside the setMessage and THEN, sleep // for 2 secs. if (JajukEvents.PLAY_ERROR.equals(subject)) { try { // we synchronize this code to make sure error message is // visible all 2 secs synchronized (this) { // set error message Object o = ObservationManager.getDetail(event, Const.DETAIL_CONTENT); // current item is a file // display associated error code is given Object detail = ObservationManager.getDetail(event, Const.DETAIL_REASON); int errorCode = 0; if (detail != null) { errorCode = Integer.parseInt((String) detail); } // Already playing a track if (o instanceof File) { File fCurrent = (File) o; if (detail != null) { setMessage(Messages.getErrorMessage(errorCode) + ": " + fCurrent.getAbsolutePath(), InformationJPanel.MessageType.ERROR); } else {// default message setMessage(Messages.getString("Error.007") + fCurrent.getName(), InformationJPanel.MessageType.ERROR); } } else if (o instanceof WebRadio) { WebRadio radio = (WebRadio) o; // display associated error code is given if (detail != null) { setMessage(Messages.getErrorMessage(errorCode) + ": " + radio.toString(), InformationJPanel.MessageType.ERROR); } else {// default message setMessage(Messages.getString("Error.007") + radio.toString(), InformationJPanel.MessageType.ERROR); } } } } catch (Exception e) { Log.error(e); } } else if (JajukEvents.THUMB_CREATED.equals(subject)) { Album album = (Album) event.getDetails().get(Const.DETAIL_CONTENT); setMessage(Messages.getString("CatalogView.5") + " " + album.getName2(), InformationJPanel.MessageType.INFORMATIVE); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (JajukEvents.HEART_BEAT.equals(subject) && !QueueModel.isStopped() && !Player.isPaused() && !QueueModel.isPlayingRadio()) { final long timeToPlay; if (QueueModel.containsRepeat()) { // if repeat mode, total // time has no sense timeToPlay = -1; } else { timeToPlay = JajukTimer.getInstance().getTotalTimeToPlay(); } String sCurrentTotalMessage = UtilString.formatTimeBySec(timeToPlay); setTotalTimeMessage(sCurrentTotalMessage + " [" + QueueModel.getCountTracksLeft() + "]"); } else if (JajukEvents.ZERO.equals(subject) || JajukEvents.PLAYER_STOP.equals(subject)) { setTotalTimeMessage("00:00:00"); setMessage(Messages.getString("JajukWindow.18"), InformationJPanel.MessageType.INFORMATIVE); } else if (JajukEvents.FILE_LAUNCHED.equals(subject)) { File file = QueueModel.getPlayingFile(); if (file != null) { String message = ""; String pattern = Conf.getString(Const.CONF_PATTERN_INFORMATION); try { message = UtilString.applyPattern(file, pattern, false, false); } catch (JajukException e) { Log.error(e); } setMessage(message, InformationJPanel.MessageType.INFORMATIVE); } } else if (JajukEvents.WEBRADIO_LAUNCHED.equals(subject)) { setTotalTimeMessage("00:00:00"); if (event.getDetails() == null) { return; } WebRadio radio = (WebRadio) event.getDetails().get(Const.DETAIL_CONTENT); if (radio != null) { String message = Messages.getString("FIFO.14") + " " + radio.getName(); setMessage(message, InformationJPanel.MessageType.INFORMATIVE); } } else if (JajukEvents.WEBRADIO_INFO_UPDATED.equals(subject)) { if (event.getDetails() == null) { return; } String webradioInfo = (String) event.getDetails().get(Const.CURRENT_RADIO_TRACK); if (webradioInfo != null) { String message = Messages.getString("FIFO.14") + " " + webradioInfo; setMessage(message, InformationJPanel.MessageType.INFORMATIVE); } } else if (JajukEvents.FILE_COPIED.equals(subject)) { Properties properties = event.getDetails(); if (properties == null) { // if no property, the party is done setMessage("", InformationJPanel.MessageType.INFORMATIVE); } else { String filename = properties.getProperty(Const.DETAIL_CONTENT); if (filename != null) { setMessage(Messages.getString("Device.45") + filename + "]", InformationJPanel.MessageType.INFORMATIVE); } } } else if (JajukEvents.FILE_CONVERSION.equals(subject)) { Properties properties = event.getDetails(); if (properties == null) { // if no property, the party is done setMessage("", InformationJPanel.MessageType.INFORMATIVE); } else { String filename = properties.getProperty(Const.DETAIL_CONTENT); String target = properties.getProperty(Const.DETAIL_NEW); if (filename != null) { setMessage( Messages.getString("Device.46") + filename + Messages.getString("Device.47") + target + "]", InformationJPanel.MessageType.INFORMATIVE); } } } } }); } } /** * toString() method. * * @return the string */ @Override public String toString() { return getClass().getName(); } /** * Gets the message type. * * @return the message type */ public MessageType getMessageType() { return type; } }