/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ /* * The org.opensourcephysics.media.core package defines the Open Source Physics * media framework for working with video and other media. * * Copyright (c) 2014 Douglas Brown and Wolfgang Christian. * * This 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 * (at your option) any later version. * * This software 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * For additional information and documentation on Open Source Physics, * please see <http://www.opensourcephysics.org/>. */ package org.opensourcephysics.display; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.event.SwingPropertyChangeSupport; import org.opensourcephysics.controls.XML; import org.opensourcephysics.controls.XMLControl; /** * This defines a subset of data elements called steps. The steps are the elements * with array index that meets the conditions: * 1. index >= startIndex * 2. index <= startIndex + (clipLength-1)*stride * 3. (index-startIndex) % stride = 0. * * @author Douglas Brown * @version 1.0 */ public class DataClip { private int dataLength = 2; private int startIndex = 0; private int clipLength = 0; private int stride = 1; private PropertyChangeSupport support; private boolean isAdjusting = false; /** * Constructs a DataClip. * * @param dataLength the number of data elements in the Data object */ public DataClip() { support = new SwingPropertyChangeSupport(this); } /** * Sets the data length (number of data elements in the Data object). * * @param length the data length */ public void setDataLength(int length) { length = Math.max(length, 1); dataLength = length; } /** * Gets the data length (number of data elements in the Data object). * * @return the data length */ public int getDataLength() { return dataLength; } /** * Sets the clip length (number of video frames on which the data * is displayed). If the clip length is set to zero or less then * it is reported as equal to the entire data length. * * @param clipLength the desired clip length * @return the resulting clip length */ public int setClipLength(int length) { int prev = getClipLength(); // check limits length = Math.min(length, dataLength); // if full length, set to zero if (length==dataLength) { length = 0; } clipLength = length; support.firePropertyChange("clip_length", prev, getClipLength()); //$NON-NLS-1$ return getClipLength(); } /** * Gets the clip length (number of video frames on which the data * is displayed unless limited by the video clip or stride). * * @return the clip length */ public int getClipLength() { if (clipLength<=0) return dataLength; return clipLength; } /** * Sets the start index. * * @param start the desired start index * @return the resulting start index */ public int setStartIndex(int start) { int prev = getStartIndex(); // check limits start = Math.max(start, 0); start = Math.min(start, dataLength-1); startIndex = start; support.firePropertyChange("start_index", prev, start); //$NON-NLS-1$ return getStartIndex(); } /** * Gets the start index. * * @return the start index */ public int getStartIndex() { return startIndex; } /** * Sets the stride (number of data elements per step). * * @param stride the desired stride * @return the resulting stride */ public int setStride(int stride) { int prev = getStride(); // check limits stride = Math.min(stride, dataLength-1); stride = Math.max(stride, 1); this.stride = stride; support.firePropertyChange("stride", prev, stride); //$NON-NLS-1$ return getStride(); } /** * Gets the stride (number of data elements per step). * * @return the stride */ public int getStride() { return stride; } /** * Gets the available clip length (step count). A step is available if it's index * is less than the data length. Available clip length <= clip length * * @return the index */ public int getAvailableClipLength() { int stepCount = getClipLength(); for (int i = stepCount-1; i>0; i--) { // look for first step with index less than data length if (stepToIndex(i)<dataLength) { return i+1; } } return 1; } /** * Converts step number to data index. * * @param stepNumber the step number * @return the data index */ public int stepToIndex(int stepNumber) { return startIndex+stepNumber*stride; } /** * Converts data index to step number. An index that falls * between two steps maps to the previous step. * * @param index the data index * @return the step number */ public int indexToStep(int index) { return (index-startIndex)/stride; } /** * Determines whether the specified index is a step index. * * @param n the index number * @return <code>true</code> if the index is a step index */ public boolean includesIndex(int n) { int stepCount = getClipLength(); for(int i = 0; i<stepCount; i++) { if(stepToIndex(i)==n) { return true; } } return false; } /** * Sets the adjusting flag. * * @param adjusting true if adjusting */ public void setAdjusting(boolean adjusting) { if (isAdjusting==adjusting) return; isAdjusting = adjusting; support.firePropertyChange("adjusting", null, adjusting); //$NON-NLS-1$ } /** * Gets the adjusting flag. * * @return true if adjusting */ public boolean isAdjusting() { return isAdjusting; } /** * Adds a PropertyChangeListener to this video clip. * * @param listener the object requesting property change notification */ public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } /** * Adds a PropertyChangeListener to this video clip. * * @param property the name of the property of interest to the listener * @param listener the object requesting property change notification */ public void addPropertyChangeListener(String property, PropertyChangeListener listener) { support.addPropertyChangeListener(property, listener); } /** * Removes a PropertyChangeListener from this video clip. * * @param listener the listener requesting removal */ public void removePropertyChangeListener(PropertyChangeListener listener) { support.removePropertyChangeListener(listener); } /** * Removes a PropertyChangeListener for a specified property. * * @param property the name of the property * @param listener the listener to remove */ public void removePropertyChangeListener(String property, PropertyChangeListener listener) { support.removePropertyChangeListener(property, listener); } /** * Returns an XML.ObjectLoader to save and load data for this class. * * @return the object loader */ public static XML.ObjectLoader getLoader() { return new Loader(); } /** * A class to save and load data for this class. */ static class Loader implements XML.ObjectLoader { /** * Saves object data in an XMLControl. * * @param control the control to save to * @param obj the object to save */ public void saveObject(XMLControl control, Object obj) { DataClip clip = (DataClip) obj; control.setValue("start", clip.getStartIndex()); //$NON-NLS-1$ control.setValue("clip_length", clip.getClipLength()); //$NON-NLS-1$ control.setValue("stride", clip.getStride()); //$NON-NLS-1$ control.setValue("data_length", clip.getDataLength()); //$NON-NLS-1$ } /** * Creates a new object. * * @param control the XMLControl with the object data * @return the newly created object */ public Object createObject(XMLControl control) { return new DataClip(); } /** * Loads a VideoClip with data from an XMLControl. * * @param control the XMLControl * @param obj the object * @return the loaded object */ public Object loadObject(XMLControl control, Object obj) { DataClip clip = (DataClip) obj; clip.setDataLength(control.getInt("data_length")); //$NON-NLS-1$ clip.setStartIndex(control.getInt("start")); //$NON-NLS-1$ clip.setClipLength(control.getInt("clip_length")); //$NON-NLS-1$ clip.setStride(control.getInt("stride")); //$NON-NLS-1$ return obj; } } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */