/******************************************************************************** * * * (c) Copyright 2010 Verizon Communications USA and The Open University UK * * * * This software is freely distributed in accordance with * * the GNU Lesser General Public (LGPL) license, version 3 or later * * as published by the Free Software Foundation. * * For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html * * and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html * * * * This software is provided by the copyright holders and contributors "as is" * * and any express or implied warranties, including, but not limited to, the * * implied warranties of merchantability and fitness for a particular purpose * * are disclaimed. In no event shall the copyright owner or contributors be * * liable for any direct, indirect, incidental, special, exemplary, or * * consequential damages (including, but not limited to, procurement of * * substitute goods or services; loss of use, data, or profits; or business * * interruption) however caused and on any theory of liability, whether in * * contract, strict liability, or tort (including negligence or otherwise) * * arising in any way out of the use of this software, even if advised of the * * possibility of such damage. * * * ********************************************************************************/ package com.compendium.ui.movie; import java.awt.Adjustable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.util.concurrent.TimeUnit; import javax.media.Player; import javax.media.Time; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.compendium.LanguageProperties; import com.compendium.ProjectCompendium; import com.compendium.core.ICoreConstants; import com.compendium.core.datamodel.Movie; import com.compendium.core.datamodel.MovieMapView; import com.compendium.core.datamodel.MovieProperties; import com.compendium.core.datamodel.NodePositionTime; import com.compendium.core.datamodel.NodeSummary; import com.compendium.ui.IUIConstants; import com.compendium.ui.UIImageButton; import com.compendium.ui.UIImages; import com.compendium.ui.UILink; import com.compendium.ui.UINode; import com.compendium.ui.UIUtilities; import com.compendium.ui.UIViewPane; import com.compendium.ui.plaf.NodeUI; /** * This class loads all the time lines and header and bar and creates the master timer. * @author Michelle Bachler * */ public class UITimeLinesController extends JLayeredPane implements PropertyChangeListener, AdjustmentListener { /** * class's own logger */ final Logger log = LoggerFactory.getLogger(getClass()); /** The default length for a new node time span, in pixels */ public static final int DEFAULT_PIXEL_SPAN_LENGTH = 30; /** The left hand offset for each timelines internal layout .*/ public static final int TIMELINE_LEFT_OFFSET = 3; /** the default time, in hundreths of a second, that a pixel of timeline represents*/ public static final int DEFAULT_PIXEL_TIME_SCALE = 320; /** the height of a row of the timeline or timeline label panel*/ public static final int ROW_HEIGHT = 26; /** * */ private static final long serialVersionUID = 1L; /** The border colour for the timeline header area.*/ private static final Color HEADER_BORDER_COLOUR = Color.darkGray.darker(); /** The background colour for the Node timelines.*/ private static final Color NODE_TIMELINE_BACKGROUND_COLOUR = new Color(233, 234, 253); /** The border colour for the Node timelines.*/ private static final Color NODE_TIMELINE_BORDER_COLOUR = NODE_TIMELINE_BACKGROUND_COLOUR.darker(); /** The background colour when the node is selected**/ private static final Color NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR = new Color(255,255,192); //128 /** The background colour for the MovieTimelines.*/ private static final Color MOVIE_TIMELINE_BACKGROUND_COLOUR = new Color(193, 193, 193); /** The background colour when the movie is selected**/ private static final Color MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR = new Color(128,255,255); //192 /** The border colour for the Movie timelines.*/ private static final Color MOVIE_TIMELINE_BORDER_COLOUR = MOVIE_TIMELINE_BACKGROUND_COLOUR.darker(); /** A reference to the layer to hold timelines.*/ private static final Integer TIMELINE_LAYER = new Integer(100); /** A reference to the layer to hold timeline header bar.*/ private static final Integer HEADER_LAYER = new Integer(120); /** A reference to the layer holding the timeline bar.*/ private static final Integer BAR_LAYER = new Integer(130); /** A reference to the layer to hold timeline header bar.*/ private static final Integer LABEL_LAYER = new Integer(140); /** A reference to the layer to hold player toolbar*/ private static final Integer TOOLBAR_LAYER = new Integer(150); /** the position in the zoom options to start at - must match DEFAULT_PIXEL_TIME_SCALE position */ private static final int DEFAULT_PIXEL_TIME_SCALE_POSITION = 5; /** The amount in milliseconds to add and remove when buttons pushed.*/ private static final long EXTRA_TIME = 300000; //5 minutes? /** the time, in hundreths of a second, that a pixel of timeline represents*/ public int pixel_time_scale = DEFAULT_PIXEL_TIME_SCALE; /** the length of the timelines in pixels*/ public int timeline_length = 0; /** The main panel with all the timelines.*/ public JPanel oNodeTimeLinesPanel = null; /** The main panel with all the timeline labels.*/ public JPanel oNodeTimeLinesLabelPanel = null; /** The header panel*/ private JPanel oHeaderPanel = null; /** The left toolbar panel*/ private JPanel oToolBarPanel = null; /** the length of the current master timeline in milliseconds .*/ private long currentTimelineDuration = 0; /** the minimum length required to display know time elements.*/ private long requiredTimelineDuration = 0; /** The numbers represent number of millseconds of a second that a pixel represents.*/ private int zoomScales[] = {10,20,40,80,160,320,600,1200,2400,4800,9600,19200}; /** * The actual width required for the left Border to accomodate the top toolbar. * Also used (-1) to set the with of the left pane holding labels etc.. */ public int leftBorder = 101; /** This is the width of the right hand toobar. * It determines the right hand offset for each timelines internal layout . */ public int rightBorder = 70; private int position = DEFAULT_PIXEL_TIME_SCALE_POSITION; /** The button to zoom in on the current view.*/ private JButton pbZoomIn = null; /** The button to zoom in on the current view.*/ private JButton pbZoomOut = null; /** the button for taking off 5 minutes of time.*/ private UIImageButton lessButton = null; /** the button for adding 5 minutes of time.*/ private UIImageButton moreButton = null; /** The movie pane that this is the Controller for.*/ private UIMovieMapViewPane oMovieMapViewPane = null; /** The MovieMapView data object associated with this controller's map.*/ private MovieMapView oMovieMapView = null; /** Stores a list of all the UITimeLineForNode objects this controller is manageing.*/ private Hashtable<String, UITimeLineForNode> htNodeSliders = null; /** Stores a list of all the UITimeLineForMovie objects this controller is manageing.*/ private Hashtable<String, UITimeLineForMovie> htMovieSliders = null; /** Stores a list of the JPanels that hold the node timelines. * Used for changing background colour when a node selected.*/ private Hashtable<String, JPanel> htNodeTimeLinePanels = null; /** Stores a list of the JPanels that hold the node timeline labels. * Used for changing background colour when a node selected.*/ private Hashtable<String, JPanel> htNodeTimeLineLabelPanels = null; /** Stores a list of the JPanels that hold the movie timelines. * Used for changing background colour when a movie rolled over.*/ private Hashtable<String, JPanel> htMovieTimeLinePanels = null; /** Stores a list of the JPanels that hold the movie timeline labels. * Used for changing background colour when a movie rolled over.*/ private Hashtable<String, JPanel> htMovieTimeLineLabelPanels = null; /** Layout manager used by oNodeTimeLinesPanel.*/ private GridBagLayout layout = null; /** Layout constraints by used by the oNodeTimeLinesPanel layout manager.*/ private GridBagConstraints cons = null; /** Layout manager used by oNodeTimeLinesLabelPanel.*/ private GridBagLayout layoutLabel = null; /** Layout constraints by used by the oNodeTimeLinesLabelPanel layout manager.*/ private GridBagConstraints consLabel = null; /** The width of this panel **/ int width = 0; /** The height of this panel **/ int height = 0; private int rowCount = 0; /** The reference to the timeline header */ private UITimeLineHeader timelineHeader = null; /** The parent panel to this panel.*/ private UITimeLinesPanel parentPanel; /** The main master timeline grabber bar.*/ private UITimeLineBar bar = null; /** The time at which the movie was paused at.*/ private Time lastTime = new Time(0); /** The time at which the master time line needs to stop playing.*/ private long stopTime = 0; /** the master play/pause button.*/ private UIImageButton masterPlayButton = null; /** The master reset button to reset the master time line.*/ private UIImageButton masterResetButton = null; /** The master timer that runs all the time lines that this controller holds.*/ private MasterTimer controller = null; /** * Constructor creates/loads all the various timelines and panels that make up this controller area. * @param cp the parent panel to this panel. * @param oView The main pane that holds the movie map that this is the controller for. */ public UITimeLinesController(UITimeLinesPanel cp, UIMovieMapViewPane oView) { this.oMovieMapViewPane = oView; this.oMovieMapViewPane.addPropertyChangeListener(this); this.oMovieMapView = (MovieMapView)oView.getView(); this.oMovieMapView.addPropertyChangeListener(this); this.parentPanel = cp; cp.addScrollAdjustmentListener(this); htNodeSliders = new Hashtable<String, UITimeLineForNode>(); htNodeTimeLinePanels = new Hashtable<String, JPanel>(); htNodeTimeLineLabelPanels = new Hashtable<String, JPanel>(); htMovieSliders = new Hashtable<String, UITimeLineForMovie>(); htMovieTimeLinePanels = new Hashtable<String, JPanel>(); htMovieTimeLineLabelPanels = new Hashtable<String, JPanel>(); oNodeTimeLinesLabelPanel = new JPanel(); oNodeTimeLinesLabelPanel.setName("oNodeTimeLinesLabelPanel"); //$NON-NLS-1$ oNodeTimeLinesPanel = new JPanel(); oNodeTimeLinesPanel.setName("oNodeTimeLinesPanel"); //$NON-NLS-1$ /*oNodeTimeLinesPanel.addComponentListener(new ComponentAdapter() { public void componentResized ( ComponentEvent event ) { Thread thread = new Thread("UITimeLinesController.1") { public void run() { setPreferredSize(new Dimension(getWidth(), oNodeTimeLinesPanel.getHeight())); setSize(new Dimension(getWidth(), oNodeTimeLinesPanel.getHeight())); } }; thread.start(); } });*/ controller = new MasterTimer(); controller.prefetch(); refreshTimeLines(); oNodeTimeLinesPanel.setLocation(leftBorder, oHeaderPanel.getPreferredSize().height); add(oNodeTimeLinesPanel, TIMELINE_LAYER); oNodeTimeLinesPanel.setVisible(true); oNodeTimeLinesLabelPanel.setLocation(0, oHeaderPanel.getPreferredSize().height); add(oNodeTimeLinesLabelPanel, LABEL_LAYER); oNodeTimeLinesLabelPanel.setVisible(true); bar = new UITimeLineBar(this, controller); //bar.setBorder(new LineBorder(Color.red, 1)); bar.setLocation(leftBorder-1+TIMELINE_LEFT_OFFSET,0); bar.setSize(getPreferredSize().width-leftBorder-TIMELINE_LEFT_OFFSET-rightBorder, getPreferredSize().height); add(bar, BAR_LAYER); bar.setVisible(true); /*addComponentListener(new ComponentAdapter() { public void componentResized ( ComponentEvent event ) { if (bar != null) { bar.setPreferredSize(new Dimension(getPreferredSize().width-TIMELINES_START_OFFSET-TIMELINE_LEFT_OFFSET-TIMELINE_RIGHT_OFFSET, getPreferredSize().height)); bar.setSize(getPreferredSize().width-TIMELINES_START_OFFSET-TIMELINE_LEFT_OFFSET-TIMELINE_RIGHT_OFFSET, getPreferredSize().height); } parentPanel.resized(); revalidate(); repaint(); } });*/ Component [] array1 = oMovieMapViewPane.getComponentsInLayer((UIViewPane.LINK_LAYER).intValue()); for(int i=0;i<array1.length;i++) { JComponent object = (JComponent)array1[i]; UILink link = (UILink)object; UINode fromNode = link.getFromNode(); UINode toNode = link.getToNode(); if (!fromNode.isVisible() || !toNode.isVisible()) { link.setVisible(false); } } setVisible(true); } public void addSelectedItem() { } /** * Calculate the required timeline for all know time elements. * Sets the stopTime, the requiredTimelineDuration and the currentTimelineDuration. */ public synchronized void recalculateRequiredTimeline() { requiredTimelineDuration = calculateStopTime(); stopTime = TimeUnit.MILLISECONDS.toNanos(requiredTimelineDuration); if (controller != null) { controller.setStopTime(new Time(stopTime)); } if (requiredTimelineDuration >= currentTimelineDuration) { currentTimelineDuration = requiredTimelineDuration; } scaleWidth(); } /** * Take the current total timeline duration and apply the current scale and reset sizes accordingly. */ public synchronized void scaleWidth() { int pixelWidth = new Long(currentTimelineDuration/pixel_time_scale).intValue(); width=pixelWidth+leftBorder+TIMELINE_LEFT_OFFSET+rightBorder; // MAKE IT ALWAYS FILL THE AVAILABLE SCREEN SPACE AS A MINIMUM int parentWidth = parentPanel.getSize().width-(new JToolBar().getPreferredSize().width); if (parentWidth > width) { width = parentWidth; pixelWidth = width-leftBorder-TIMELINE_LEFT_OFFSET-rightBorder; } int requiredHundrethsLongest = new Long(requiredTimelineDuration).intValue(); int requiredPixelWidth = requiredHundrethsLongest/pixel_time_scale; int requiredWidth=requiredPixelWidth+leftBorder+TIMELINE_LEFT_OFFSET+rightBorder; if (width > requiredWidth && width > parentWidth) { lessButton.setEnabled(true); } else { lessButton.setEnabled(false); } timeline_length = pixelWidth+TIMELINE_LEFT_OFFSET+rightBorder; //int height = rowCount*ROW_HEIGHT; int height = layout.minimumLayoutSize(oNodeTimeLinesPanel).height; // reset all the sizes of the components and layout main panel again. oNodeTimeLinesPanel.setPreferredSize(new Dimension(width-TIMELINE_LEFT_OFFSET, height)); oNodeTimeLinesPanel.setSize(new Dimension(width-TIMELINE_LEFT_OFFSET, height)); oNodeTimeLinesLabelPanel.setPreferredSize(new Dimension(leftBorder, height)); oNodeTimeLinesLabelPanel.setSize(new Dimension(leftBorder, height)); oHeaderPanel.setPreferredSize(new Dimension(width-leftBorder, oHeaderPanel.getPreferredSize().height)); oHeaderPanel.setSize(new Dimension(width-leftBorder, oHeaderPanel.getPreferredSize().height)); oToolBarPanel.setPreferredSize(new Dimension(leftBorder, oHeaderPanel.getPreferredSize().height)); oToolBarPanel.setSize(new Dimension(leftBorder, oHeaderPanel.getPreferredSize().height)); layout.invalidateLayout(oNodeTimeLinesPanel); layout.layoutContainer(oNodeTimeLinesPanel); layoutLabel.invalidateLayout(oNodeTimeLinesLabelPanel); layoutLabel.layoutContainer(oNodeTimeLinesLabelPanel); height = height+oHeaderPanel.getPreferredSize().height; setSize(new Dimension(width, height)); setPreferredSize(new Dimension(width, height)); if (bar != null) { bar.setPreferredSize(new Dimension(width-leftBorder-TIMELINE_LEFT_OFFSET-rightBorder, height)); bar.setSize(width-leftBorder-TIMELINE_LEFT_OFFSET-rightBorder, height); bar.seek(controller.getMediaNanoseconds()); // otherwise it is not in the correct location relative to scale } revalidate(); repaint(); } /** * Look at the node time spans and the movies durations * and determine the last time requirement which determines the stop time or duration required.. * @return the largest time requirements either from a time span of a movie duration in milliseconds */ private synchronized long calculateStopTime() { long longest = 0; // Check node time spans Component[] array = oMovieMapViewPane.getComponentsInLayer((UIViewPane.NODE_LAYER).intValue()); for(int i=0;i<array.length;i++) { UINode uinode = (UINode)array[i]; Hashtable<String, NodePositionTime> times = oMovieMapView.getTimesForNode(uinode.getNode().getId()); for (Enumeration<NodePositionTime> ex = times.elements(); ex.hasMoreElements();) { NodePositionTime nextTime = (NodePositionTime)ex.nextElement(); long stoptime = nextTime.getTimeToHide(); if (stoptime > longest) { longest = stoptime; } } } // Check the movie duration and property times Vector<UIMoviePanel> movies = oMovieMapViewPane.getMovies(); int count = movies.size(); UIMoviePanel panel = null; long nextStart = 0; long nextDuration = 0; long nextDurationMillis = 0; Vector<MovieProperties> props = null; MovieProperties prop = null; for (int i=0; i<count; i++) { panel = (UIMoviePanel)movies.elementAt(i); nextDuration = panel.getDuration().getNanoseconds(); nextDurationMillis = TimeUnit.NANOSECONDS.toMillis(nextDuration); nextDurationMillis = nextDurationMillis+panel.getMovieData().getStartTime(); if (nextDurationMillis > longest) { longest = nextDurationMillis; } props = panel.getMovieData().getProperties(); int countj = props.size(); for (int j=0; j<countj; j++) { prop = props.elementAt(j); nextStart = prop.getTime(); if (nextStart > longest) { longest = nextStart; } } } return longest; } /** * Create all the time lines and header. */ private synchronized void refreshTimeLines() { this.htNodeTimeLinePanels.clear(); this.htNodeTimeLineLabelPanels.clear(); this.htMovieTimeLinePanels.clear(); this.htMovieTimeLineLabelPanels.clear(); this.htNodeSliders.clear(); // take this out if I fix why reuse of line was broken this.htMovieSliders.clear(); if (oHeaderPanel != null) { remove(oHeaderPanel); oHeaderPanel = null; } if (oToolBarPanel != null) { remove(oToolBarPanel); oToolBarPanel = null; } layout = new GridBagLayout(); cons = new GridBagConstraints(); cons.fill = GridBagConstraints.HORIZONTAL; cons.anchor = GridBagConstraints.NORTHWEST; cons.gridwidth = GridBagConstraints.REMAINDER; cons.weighty = 0; cons.weightx = 2; cons.ipady = 4; oNodeTimeLinesPanel.removeAll(); oNodeTimeLinesPanel.setLayout(layout); layoutLabel = new GridBagLayout(); consLabel = new GridBagConstraints(); consLabel.fill = GridBagConstraints.HORIZONTAL; consLabel.anchor = GridBagConstraints.NORTHWEST; consLabel.gridwidth = GridBagConstraints.REMAINDER; consLabel.weighty = 0; consLabel.weightx = 2; consLabel.ipady = 4; oNodeTimeLinesLabelPanel.removeAll(); oNodeTimeLinesLabelPanel.setLayout(layoutLabel); // ADD HEADER createTimeLineHeader(); oToolBarPanel.setLocation(0,0); add(oToolBarPanel, TOOLBAR_LAYER); oToolBarPanel.setVisible(true); oHeaderPanel.setLocation(leftBorder,0); add(oHeaderPanel, HEADER_LAYER); oHeaderPanel.setVisible(true); // GET NODES Component[] array = oMovieMapViewPane.getComponentsInLayer((UIViewPane.NODE_LAYER).intValue()); Vector<UINode> nodes = new Vector<UINode>(array.length); for(int i=0;i<array.length;i++) { nodes.addElement((UINode)array[i]); } nodes = UIUtilities.sortList(nodes); int count = nodes.size(); // ADD MOVIE TIME LINES - sort alphabetically by movie label Vector<UIMoviePanel> movies = oMovieMapViewPane.getMovies(); /*Object[] sa = new Object[movies.size()]; movies.copyInto(sa); List l = Arrays.asList(sa); Collections.sort(l, new Comparator() { public int compare(Object o1, Object o2) { UIMoviePanel data1 = (UIMoviePanel)o1; UIMoviePanel data2 = (UIMoviePanel)o2; String s1 = data1.getMovieData().getMovieName(); String s2 = data2.getMovieData().getMovieName(); return s1.compareTo(s2); } }); movies.removeAllElements(); movies.addAll(l);*/ int countj = movies.size(); Vector<UIMoviePanel> sortedmovies = new Vector<UIMoviePanel>(countj); for (int j=0; j<countj; j++) { sortedmovies.add(movies.elementAt(j)); } sortedmovies = UIMovieUtilities.sortList(sortedmovies); countj = sortedmovies.size(); rowCount = count+countj; for (int j=0; j<countj; j++) { UIMoviePanel panel = (UIMoviePanel)sortedmovies.elementAt(j); if (j == countj-1 && count == 0) { cons.weighty = 2; consLabel.weighty = 2; } else { cons.weighty = 0; consLabel.weighty = 2; } createMovieTimeLine(panel); } // ADD NODE TIME LINES for(int i=0;i<count;i++) { UINode uinode = (UINode)nodes.elementAt(i); if (i == count-1) { cons.weighty = 2; consLabel.weighty = 2; } else { cons.weighty = 0; consLabel.weighty = 0; } createNodeTimeLine(uinode); } recalculateRequiredTimeline(); } /** * Create the header bar with the times marked on. * @return the JPanel holding the header bar. */ private void createTimeLineHeader() { JPanel main = new JPanel(new BorderLayout()); main.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); oToolBarPanel = new JPanel(new BorderLayout()); JToolBar leftToolBar = new JToolBar(); oToolBarPanel.add(leftToolBar, BorderLayout.CENTER); leftToolBar.setFloatable(false); leftToolBar.setMargin(new Insets(5,5,5,5)); leftToolBar.setBorder(new LineBorder(HEADER_BORDER_COLOUR, 1)); timelineHeader = new UITimeLineHeader(this, pixel_time_scale); timelineHeader.setBorder(new LineBorder(HEADER_BORDER_COLOUR, 1)); masterPlayButton = new UIImageButton(new ImageIcon(UIImages.sPATH + "play.gif")); //$NON-NLS-1$ masterPlayButton.setActionCommand("Play"); //$NON-NLS-1$ masterPlayButton.setBorder(new EmptyBorder(0,0,0,5)); masterPlayButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.playButtonTip")); //$NON-NLS-1$ masterPlayButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (masterPlayButton.getActionCommand().equals("Play")) { //$NON-NLS-1$ start(); } else { stop(); } } }); masterResetButton = new UIImageButton(new ImageIcon(UIImages.sPATH + "restore-start.gif")); //$NON-NLS-1$ masterResetButton.setActionCommand("Reset"); //$NON-NLS-1$ masterResetButton.setBorder(null); masterResetButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.restButtonTip")); //$NON-NLS-1$ masterResetButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { lastTime = new Time(0); controller.setMediaTime(lastTime); setMovieTimes(0); } }); leftToolBar.add(masterPlayButton, BorderLayout.WEST); leftToolBar.add(masterResetButton, BorderLayout.EAST); // ZOOM IN AND OUT pbZoomIn = new UIImageButton(UIImages.get(IUIConstants.ZOOM_IN_ICON)); pbZoomIn.setBorder(new EmptyBorder(0,0,0,5)); pbZoomIn.setToolTipText(LanguageProperties.getString(LanguageProperties.TOOLBARS_BUNDLE, "UIToolBarZoom.zoomOut")); //$NON-NLS-1$ pbZoomIn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (position < zoomScales.length-1) { position++; } pixel_time_scale = zoomScales[position]; scaleWidth(); timelineHeader.setScale(pixel_time_scale); UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.setScale(pixel_time_scale); } UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); nodeSlider.setScale(pixel_time_scale); } } }); pbZoomIn.setEnabled(true); pbZoomOut = new UIImageButton(UIImages.get(IUIConstants.ZOOM_OUT_ICON)); pbZoomOut.setBorder(new EmptyBorder(0,0,0,5)); pbZoomOut.setToolTipText(LanguageProperties.getString(LanguageProperties.TOOLBARS_BUNDLE, "UIToolBarZoom.zoomIn")); //$NON-NLS-1$ pbZoomOut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (position > 0) { position--; } pixel_time_scale = zoomScales[position]; scaleWidth(); timelineHeader.setScale(pixel_time_scale); UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.setScale(pixel_time_scale); } UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); nodeSlider.setScale(pixel_time_scale); } } }); pbZoomOut.setEnabled(true); leftToolBar.addSeparator(); leftToolBar.add(pbZoomIn, BorderLayout.WEST); leftToolBar.add(pbZoomOut, BorderLayout.EAST); leftBorder = leftToolBar.getPreferredSize().width+1; //if (leftBorder < TIMELINES_START_OFFSET) { // leftBorder = TIMELINES_START_OFFSET; //} leftToolBar.setPreferredSize(new Dimension(leftBorder-1, leftToolBar.getPreferredSize().height)); leftToolBar.setSize(new Dimension(leftBorder-1, leftToolBar.getPreferredSize().height)); leftToolBar.setMaximumSize(new Dimension(leftBorder-1, leftToolBar.getPreferredSize().height)); leftToolBar.setMinimumSize(new Dimension(leftBorder-1, leftToolBar.getPreferredSize().height)); JPanel headerPanel = new JPanel(new BorderLayout()); headerPanel.add(timelineHeader, BorderLayout.CENTER); JToolBar rightToolBar = new JToolBar(); rightToolBar.setFloatable(false); rightToolBar.setMargin(new Insets(5,5,5,5)); rightToolBar.setBorder(new LineBorder(HEADER_BORDER_COLOUR, 1)); lessButton = new UIImageButton(new ImageIcon(UIImages.sPATH + "delete2.png")); //$NON-NLS-1$ lessButton.setBorder(new EmptyBorder(0,5,0,5)); lessButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.offTimeTip")); //$NON-NLS-1$ lessButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { currentTimelineDuration -= EXTRA_TIME; if (currentTimelineDuration <= requiredTimelineDuration) { currentTimelineDuration = requiredTimelineDuration; lessButton.setEnabled(false); } else { lessButton.setEnabled(true); } scaleWidth(); } }); if (currentTimelineDuration <= requiredTimelineDuration) { lessButton.setEnabled(false); } else { lessButton.setEnabled(true); } rightToolBar.add(lessButton); moreButton = new UIImageButton(new ImageIcon(UIImages.sPATH + "add-green.png")); //$NON-NLS-1$ moreButton.setBorder(new EmptyBorder(0,0,0,5)); moreButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.addTimeTip")); //$NON-NLS-1$ moreButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { currentTimelineDuration += EXTRA_TIME; scaleWidth(); if (currentTimelineDuration > requiredTimelineDuration) { lessButton.setEnabled(true); } } }); moreButton.setEnabled(true); rightToolBar.add(moreButton); rightBorder = rightToolBar.getPreferredSize().width; rightToolBar.setSize(rightToolBar.getPreferredSize().width, rightToolBar.getPreferredSize().height); rightToolBar.setPreferredSize(new Dimension(rightBorder, rightToolBar.getPreferredSize().height)); //main.add(leftToolBar, BorderLayout.WEST); main.add(headerPanel, BorderLayout.CENTER); main.add(rightToolBar, BorderLayout.EAST); oHeaderPanel = main; } /** * Return the timeline Header panel; */ public UITimeLineHeader getHeader() { return timelineHeader; } /** * Create a movie time line. * @param movie the Movie to create a timeline for. * @return a JPanel holding the movie time line. */ private void createMovieTimeLine(UIMoviePanel movie) { // Remove previously added one if there, else they pile up! movie.removePropertyChangeListener(this); movie.addPropertyChangeListener(this); //JPanel main = new JPanel(new BorderLayout()); //main.setBorder(new LineBorder(Color.black, 1)); //main.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); BorderLayout border = new BorderLayout(); border.setVgap(5); border.setHgap(5); final JPanel leftPanel = new JPanel(border); leftPanel.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); leftPanel.setBorder(new CompoundBorder(new LineBorder(MOVIE_TIMELINE_BORDER_COLOUR, 1), new EmptyBorder(3,3,3,3))); final JLabel movieicon = new JLabel(new ImageIcon(UIImages.sPATH + "movie.gif")); //$NON-NLS-1$ movieicon.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); movieicon.setAlignmentY(JLabel.CENTER_ALIGNMENT); movieicon.setAlignmentX(JLabel.WEST); /*movieicon.setToolTipText("Double-click to open: "+text); movieicon.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { boolean isLeftMouse = SwingUtilities.isLeftMouseButton(e); if (ProjectCompendium.isMac && (e.getButton() == 3 && e.isShiftDown())) { isLeftMouse = false; } int clickCount = e.getClickCount(); if (isLeftMouse && clickCount == 1) { oMovieMapViewPane.setSelectedNode(null,ICoreConstants.DESELECTALL); fuinode.setSelected(true); oMovieMapViewPane.setSelectedNode(fuinode,ICoreConstants.SINGLESELECT); } else if (isLeftMouse && clickCount == 2) { ((NodeUI)fuinode.getUI()).openNode(); } } });*/ leftPanel.add(movieicon, BorderLayout.WEST); final Movie fMovie = movie.getMovieData(); final String name = fMovie.getMovieName(); final JLabel flabel = new JLabel(name); final JTextField field = new JTextField(name); field.setEditable(true); field.setVisible(false); field.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { String newName = field.getText(); try { if (!fMovie.getMovieName().equals(newName)) { oMovieMapView.updateMovie(fMovie.getId(), fMovie.getLink(), newName, fMovie.getStartTime()); refreshTimeLines(); } else { field.setVisible(false); leftPanel.remove(field); leftPanel.add(flabel, BorderLayout.CENTER); flabel.setVisible(true); leftPanel.repaint(); } } catch(Exception ex) { log.info("Exception: "+ex.getLocalizedMessage()); //$NON-NLS-1$ } } }); field.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String newName = field.getText(); try { if (!fMovie.getMovieName().equals(newName)) { oMovieMapView.updateMovie(fMovie.getId(), fMovie.getLink(), newName, fMovie.getStartTime()); refreshTimeLines(); } else { field.setVisible(false); leftPanel.remove(field); leftPanel.add(flabel, BorderLayout.CENTER); flabel.setVisible(true); leftPanel.repaint(); } } catch(Exception ex) { log.info("Exception: "+ex.getLocalizedMessage()); //$NON-NLS-1$ } } }); flabel.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); flabel.setAlignmentY(JLabel.CENTER_ALIGNMENT); flabel.setAlignmentX(JLabel.WEST); flabel.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.editMovieTip")); //$NON-NLS-1$ flabel.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { boolean isRightMouse = SwingUtilities.isRightMouseButton(e); boolean isLeftMouse = SwingUtilities.isLeftMouseButton(e); if (ProjectCompendium.isMac && ( (e.getButton() == 3 && e.isShiftDown()) || (e.getButton() == 1 && e.isControlDown()) )) { isRightMouse = true; isLeftMouse = false; } int clickCount = e.getClickCount(); if (isRightMouse && clickCount == 1) { Rectangle bounds = flabel.getBounds(); field.setBounds(bounds); field.setText(name); leftPanel.remove(flabel); leftPanel.add(field, BorderLayout.CENTER); field.setVisible(true); field.requestFocus(); field.setCaretPosition(0); } else if (isLeftMouse && clickCount == 1) { flabel.requestFocus(); } } }); leftPanel.add(flabel, BorderLayout.CENTER); UITimeLineForMovie movieline = null; String sMovieID = movie.getMovieData().getId(); //NEED TO FIND OUT WHY REUSING OBJECTS WAS BROKEN //if (htMovieSliders.containsKey(sMovieID)) { // movieline = (UITimeLineForMovie)htMovieSliders.get(sMovieID); //} else { movieline = new UITimeLineForMovie(movie, oMovieMapViewPane ,oMovieMapView, this, controller); movieline.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); movieline.setScale(pixel_time_scale); htMovieSliders.put(sMovieID, movieline); //} movieline.setBorder(new LineBorder(MOVIE_TIMELINE_BORDER_COLOUR, 1)); JPanel moviePanel = new JPanel(new BorderLayout()); if (movie.isSelected()) { moviePanel.setBackground(MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { moviePanel.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); } moviePanel.add(movieline, BorderLayout.CENTER); //main.add(leftPanel, BorderLayout.WEST); //main.add(moviePanel, BorderLayout.CENTER); leftPanel.setPreferredSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setMaximumSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setMinimumSize(new Dimension(leftBorder-1, ROW_HEIGHT)); moviePanel.setPreferredSize(new Dimension(moviePanel.getPreferredSize().width, ROW_HEIGHT)); moviePanel.setSize(new Dimension(moviePanel.getPreferredSize().width, ROW_HEIGHT)); moviePanel.setMaximumSize(new Dimension(moviePanel.getPreferredSize().width, ROW_HEIGHT)); moviePanel.setMinimumSize(new Dimension(moviePanel.getPreferredSize().width, ROW_HEIGHT)); layoutLabel.setConstraints(leftPanel, consLabel); oNodeTimeLinesLabelPanel.add(leftPanel); layout.setConstraints(moviePanel, cons); oNodeTimeLinesPanel.add(moviePanel); htMovieTimeLinePanels.put(movie.getMovieData().getId(), moviePanel); htMovieTimeLineLabelPanels.put(movie.getMovieData().getId(), leftPanel); } /** * Create a Node timeline * @param uinode the node to create a timeline for. * @return a JPanel holding the node timeline. */ private void createNodeTimeLine(UINode uinode) { // Remove previously added one if there, else they pile up! uinode.removePropertyChangeListener(this); uinode.addPropertyChangeListener(this); final UINode fuinode = uinode; final String text = uinode.getText(); NodeSummary node = uinode.getNode(); //final JPanel main = new JPanel(new BorderLayout()); //main.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); ImageIcon icon = UINode.getNodeImageSmall(node.getType()); BorderLayout border = new BorderLayout(); border.setVgap(5); border.setHgap(5); JPanel leftPanel = new JPanel(border); leftPanel.setBorder(new CompoundBorder(new LineBorder(NODE_TIMELINE_BORDER_COLOUR, 1), new EmptyBorder(3,3,3,3))); leftPanel.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); final JLabel nodelabel = new JLabel(icon); nodelabel.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); nodelabel.setAlignmentY(JLabel.CENTER_ALIGNMENT); nodelabel.setAlignmentX(JLabel.WEST); nodelabel.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.openTip")+": "+text); //$NON-NLS-1$ nodelabel.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { boolean isLeftMouse = SwingUtilities.isLeftMouseButton(e); if (ProjectCompendium.isMac && (e.getButton() == 3 && e.isShiftDown())) { isLeftMouse = false; } int clickCount = e.getClickCount(); if (isLeftMouse && clickCount == 1) { oMovieMapViewPane.setSelectedNode(null,ICoreConstants.DESELECTALL); fuinode.setSelected(true); oMovieMapViewPane.setSelectedNode(fuinode,ICoreConstants.SINGLESELECT); } else if (isLeftMouse && clickCount == 2) { ((NodeUI)fuinode.getUI()).openNode(); } } }); leftPanel.add(nodelabel, BorderLayout.WEST); final JLabel flabel = new JLabel(text); flabel.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); flabel.setAlignmentY(JLabel.CENTER_ALIGNMENT); flabel.setAlignmentX(JLabel.WEST); flabel.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.openTip")+text); //$NON-NLS-1$ flabel.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { boolean isLeftMouse = SwingUtilities.isLeftMouseButton(e); if (ProjectCompendium.isMac && (e.getButton() == 3 && e.isShiftDown())) { isLeftMouse = false; } int clickCount = e.getClickCount(); if (isLeftMouse && clickCount == 1) { oMovieMapViewPane.setSelectedNode(null,ICoreConstants.DESELECTALL); fuinode.setSelected(true); oMovieMapViewPane.setSelectedNode(fuinode,ICoreConstants.SINGLESELECT); } else if (isLeftMouse && clickCount == 2) { ((NodeUI)fuinode.getUI()).openNode(); } } }); // If the node label has changed when the node looses focus // repaint the timelines so the order is correct. // TO DO: need to remove previous listener? or they will pile up uinode.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { String text = flabel.getText(); if (!text.equals(fuinode.getText())) { refreshTimeLines(); } } }); leftPanel.add(flabel, BorderLayout.CENTER); //main.add(leftPanel, BorderLayout.WEST); UITimeLineForNode progressSlider = null; //NEED TO FIND OUT WHY REUSING OBJECTS WAS BROKEN //if (htNodeSliders.containsKey(node.getId())) { // progressSlider = (UITimeLineForNode)htNodeSliders.get(node.getId()); //} else { progressSlider = new UITimeLineForNode(uinode, this.oMovieMapView, this, controller); progressSlider.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); progressSlider.setScale(pixel_time_scale); htNodeSliders.put(node.getId(), progressSlider); //} JPanel panelProgress = new JPanel ( new BorderLayout() ); panelProgress.setBorder(new LineBorder(NODE_TIMELINE_BORDER_COLOUR, 1)); if (uinode.isSelected()) { panelProgress.setBackground(NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { panelProgress.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); } panelProgress.add(progressSlider, BorderLayout.CENTER); //main.add(panelProgress, BorderLayout.CENTER); panelProgress.setPreferredSize(panelProgress.getPreferredSize()); leftPanel.setPreferredSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setMaximumSize(new Dimension(leftBorder-1, ROW_HEIGHT)); leftPanel.setMinimumSize(new Dimension(leftBorder-1, ROW_HEIGHT)); panelProgress.setPreferredSize(new Dimension(panelProgress.getPreferredSize().width, ROW_HEIGHT)); panelProgress.setSize(new Dimension(panelProgress.getPreferredSize().width, ROW_HEIGHT)); panelProgress.setMaximumSize(new Dimension(panelProgress.getPreferredSize().width, ROW_HEIGHT)); panelProgress.setMinimumSize(new Dimension(panelProgress.getPreferredSize().width, ROW_HEIGHT)); layoutLabel.setConstraints(leftPanel, consLabel); oNodeTimeLinesLabelPanel.add(leftPanel); layout.setConstraints(panelProgress, cons); oNodeTimeLinesPanel.add(panelProgress); htNodeTimeLinePanels.put(uinode.getNode().getId(), panelProgress); htNodeTimeLineLabelPanels.put(uinode.getNode().getId(), leftPanel); } /** * Update the movies current positions. * @param millis */ public void setMovieTimes(long millis) { for (Enumeration<UITimeLineForMovie> e = htMovieSliders.elements(); e.hasMoreElements();) { UITimeLineForMovie progressSlider = (UITimeLineForMovie)e.nextElement(); progressSlider.setMovieTime(millis); } } /** * Start the master timeline controller */ public void start() { if (controller.getState() == Player.Started) { return; } masterPlayButton.setActionCommand("Pause"); //$NON-NLS-1$ masterPlayButton.setIcon(new ImageIcon(UIImages.sPATH + "pause.gif")); //$NON-NLS-1$ masterPlayButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.pasueButtonTip")); //$NON-NLS-1$ controller.syncStart(lastTime); startMovies(); } /** * Stop the master timeline controller */ public void stop() { masterPlayButton.setActionCommand("Play"); //$NON-NLS-1$ masterPlayButton.setIcon(new ImageIcon(UIImages.sPATH + "play.gif")); //$NON-NLS-1$ masterPlayButton.setToolTipText(LanguageProperties.getString(LanguageProperties.MOVIE_BUNDLE, "UITimeLinesController.playButtonTip")); //$NON-NLS-1$ lastTime = controller.getMediaTime(); controller.stop(); stopMovies(); } /** * Return the current state of the player. */ public int getPlayerState() { return controller.getState(); } /** * Return the current time set in the controller in milliseconds. * @return the current time set in the controller in milliseconds */ public long getCurrentTime() { return TimeUnit.NANOSECONDS.toMillis(controller.getMediaNanoseconds()); } /** * Let the movie time lines know that the controller has been stopped. */ private void stopMovies() { UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.stopMovie(); } } /** * Let the movie time lines know that the controller has been started. */ private void startMovies() { UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.startMovie(TimeUnit.NANOSECONDS.toMillis(controller.getMediaNanoseconds())); } } /** * Clear all selected items */ public void clearSelection() { UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.clearSelection(); } UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); nodeSlider.clearSelection(); } } /** * Update all time lines that a move had occurred in order to update selected items */ public void dragMove(String fromID, long changeValue) { //check that all items can move first. boolean canMove = true; UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); if (!movieSlider.canAllMove(changeValue)) { canMove = false; break; } } if (canMove) { UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); if (!nodeSlider.canAllMove(changeValue)) { canMove = false; break; } } } if (canMove) { movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.dragMove(fromID, changeValue); } UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); nodeSlider.dragMove(fromID, changeValue); } } recalculateRequiredTimeline(); } /** * Save the change to all selected items */ public void dragComplete(String fromID) { UITimeLineForMovie movieSlider = null; for (Enumeration<UITimeLineForMovie> bars = htMovieSliders.elements(); bars.hasMoreElements();) { movieSlider = (UITimeLineForMovie)bars.nextElement(); movieSlider.dragComplete(fromID); } UITimeLineForNode nodeSlider = null; for (Enumeration<UITimeLineForNode> bars = htNodeSliders.elements(); bars.hasMoreElements();) { nodeSlider = (UITimeLineForNode)bars.nextElement(); nodeSlider.dragComplete(fromID); } recalculateRequiredTimeline(); } /** * If the vertical scrollbar moved, relocate screen elements as required. */ public void adjustmentValueChanged(AdjustmentEvent evt) { if (evt.getID() == AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED) { JScrollBar bar = (JScrollBar)evt.getSource(); if (bar.getOrientation() == Adjustable.HORIZONTAL) { if (oNodeTimeLinesLabelPanel != null) { Point currentLoc = oNodeTimeLinesLabelPanel.getLocation(); oNodeTimeLinesLabelPanel.setLocation(bar.getValue(), currentLoc.y); } if (oToolBarPanel != null) { Point currentLoc = oToolBarPanel.getLocation(); oToolBarPanel.setLocation(bar.getValue(), currentLoc.y); } } else { if (oHeaderPanel != null) { Point currentLoc = oHeaderPanel.getLocation(); oHeaderPanel.setLocation(currentLoc.x, bar.getValue()); } if (oToolBarPanel != null) { Point currentLoc = oToolBarPanel.getLocation(); oToolBarPanel.setLocation(currentLoc.x, bar.getValue()); } } parentPanel.validate(); } } /** * Handles property change events. * @param evt, the associated PropertyChangeEvent object. */ public void propertyChange(PropertyChangeEvent evt) { String prop = evt.getPropertyName(); Object source = evt.getSource(); Object oldvalue = evt.getOldValue(); Object newvalue = evt.getNewValue(); if (source instanceof UIMovieMapViewPane) { if (prop.equals(UIMovieMapViewPane.UINODE_ADDED)) { UINode uinode = (UINode)newvalue; addNode(uinode); } else if (prop.equals(UIMovieMapViewPane.UINODE_REMOVED)) { UINode uinode = (UINode)newvalue; uinode.removePropertyChangeListener(this); String sNodeID = uinode.getNode().getId(); if (htNodeSliders.containsKey(sNodeID)) { htNodeSliders.remove(sNodeID); } if (htNodeTimeLinePanels.containsKey(sNodeID)) { htNodeTimeLinePanels.remove(sNodeID); } if (htNodeTimeLineLabelPanels.containsKey(sNodeID)) { htNodeTimeLineLabelPanels.remove(sNodeID); } refreshTimeLines(); } else if (prop.equals(UIMovieMapViewPane.UIMOVIE_ADDED)) { refreshTimeLines(); } else if (prop.equals(UIMovieMapViewPane.UIMOVIE_REMOVED)) { UIMoviePanel uimovie = (UIMoviePanel)newvalue; String sMovieID = uimovie.getMovieData().getId(); if (htMovieSliders.containsKey(sMovieID)) { htMovieSliders.remove(sMovieID); } if (htMovieTimeLinePanels.containsKey(sMovieID)) { htMovieTimeLinePanels.remove(sMovieID); } if (htMovieTimeLineLabelPanels.containsKey(sMovieID)) { htMovieTimeLineLabelPanels.remove(sMovieID); } refreshTimeLines(); } } else if (source instanceof UINode) { if (prop.equals(UINode.SELECTED_PROPERTY)) { UINode node = (UINode)source; String sNodeID = node.getNode().getId(); if (htNodeTimeLineLabelPanels.containsKey(sNodeID)) { JPanel panel = (JPanel)htNodeTimeLineLabelPanels.get(sNodeID); if ((Boolean)newvalue) { panel.setBackground(NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { panel.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); } int countj = panel.getComponentCount(); for (int j=0; j<countj; j++) { Component innernext = panel.getComponent(j); if ((Boolean)newvalue) { innernext.setBackground(NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { innernext.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); } } } if (htNodeTimeLinePanels.containsKey(sNodeID)) { JPanel panel = (JPanel)htNodeTimeLinePanels.get(sNodeID); if ((Boolean)newvalue) { panel.setBackground(NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { panel.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); } int countj = panel.getComponentCount(); for (int j=0; j<countj; j++) { Component innernext = panel.getComponent(j); if ((Boolean)newvalue) { innernext.setBackground(NODE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { innernext.setBackground(NODE_TIMELINE_BACKGROUND_COLOUR); } } //works a bit. scrolls down, but not up? final JPanel fpanel = panel; SwingUtilities.invokeLater(new Runnable() { public void run() { fpanel.scrollRectToVisible(fpanel.getBounds()); } }); } if (htNodeSliders.containsKey(sNodeID)) { UITimeLineForNode line = (UITimeLineForNode)htNodeSliders.get(sNodeID); line.refreshNodeTimeDialog(); } } } else if (source instanceof MovieMapView) { if (prop.equals(MovieMapView.MOVIE_CHANGED_PROPERTY)) { Movie oldmovie = (Movie)oldvalue; Movie movie = (Movie)newvalue; if ((!oldmovie.getMovieName().equals(movie.getMovieName())) || (oldmovie.getStartTime() != movie.getStartTime())) { if (htMovieSliders.containsKey(movie.getId())) { UITimeLineForMovie panel = htMovieSliders.get(movie.getId()); panel.getMovie().setMovieData(movie); } refreshTimeLines(); } } } else if (source instanceof UIMoviePanel) { UIMoviePanel moviepanel = (UIMoviePanel)source; if (prop.equals(UIMoviePanel.SELECTED_PROPERTY)) { String sMovieID = moviepanel.getMovieData().getId(); if (htMovieTimeLineLabelPanels.containsKey(sMovieID)) { JPanel panel = (JPanel)htMovieTimeLineLabelPanels.get(sMovieID); if ((Boolean)newvalue) { panel.setBackground(MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { panel.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); } int countj = panel.getComponentCount(); for (int j=0; j<countj; j++) { Component innernext = panel.getComponent(j); if ((Boolean)newvalue) { innernext.setBackground(MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { innernext.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); } } } if (htMovieTimeLinePanels.containsKey(sMovieID)) { JPanel panel = (JPanel)htMovieTimeLinePanels.get(sMovieID); if ((Boolean)newvalue) { panel.setBackground(MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { panel.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); } int countj = panel.getComponentCount(); for (int j=0; j<countj; j++) { Component innernext = panel.getComponent(j); if ((Boolean)newvalue) { innernext.setBackground(MOVIE_TIMELINE_SELECTED_BACKGROUND_COLOUR); } else { innernext.setBackground(MOVIE_TIMELINE_BACKGROUND_COLOUR); } } //scroll to visible //parentPanel.scrollRectToVisible(new Rectangle(oNodeTimeLinesPanel.getX(), oNodeTimeLinesPanel.getY(), oNodeTimeLinesPanel.getWidth(), oNodeTimeLinesPanel.getHeight())); parentPanel.scrollToRectangle(oNodeTimeLinesPanel.getX(), oNodeTimeLinesPanel.getY(), oNodeTimeLinesPanel.getWidth(), oNodeTimeLinesPanel.getHeight()); } /*if (htMovieSliders.containsKey(sMovieID)) { UITimeLineForMovie line = (UITimeLineForMovie)htMovieSliders.get(sMovieID); //line.refreshNodeTimeDialog(); }*/ } } } /** * Jump to the time point when the node with the given id is first shown. * @param sNodeID the id of the node to jump to. */ public void jumpToNode(String sNodeID) { UITimeLineForNode nodeSlider = null; if (htNodeSliders.containsKey(sNodeID)) { nodeSlider = (UITimeLineForNode)htNodeSliders.get(sNodeID); nodeSlider.showFirstTime(); } } /** * Return the time length, in milliseconds, for a new time span. * @return */ public long getDefaultNodeTimeSpanLength() { return DEFAULT_PIXEL_SPAN_LENGTH*pixel_time_scale; } /** * There was a bug which meant many first spans where sometimes added. * This was an attempt to stop that. * @param uinode */ private synchronized void addNode(UINode uinode) { if (uinode != null) { // add a first span, if it does not have one. String sNodeID = uinode.getNode().getId(); Hashtable<String, NodePositionTime> times = oMovieMapView.getTimesForNode(sNodeID); if (times.size() == 0) { try { long currentTime = new Double(controller.getMediaTime().getNanoseconds()).longValue(); long milliCurrentTime = TimeUnit.NANOSECONDS.toMillis(currentTime); long milliDefaultSpan = getDefaultNodeTimeSpanLength(); oMovieMapView.addNodeTime(sNodeID, milliCurrentTime, milliCurrentTime+milliDefaultSpan, uinode.getLocation().x, uinode.getLocation().y); } catch(Exception ex) { log.error("Error...", ex); ProjectCompendium.APP.displayError(ex.getLocalizedMessage()); } } refreshTimeLines(); } } public void setCursor(Cursor cursor) { bar.setCursor(cursor); } }