/* * 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.media.core; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JDialog; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.event.SwingPropertyChangeSupport; import org.opensourcephysics.controls.OSPLog; /** * This is the abstract base class for all image filters. Note: subclasses * should always provide a no-argument constructor. * * @author Douglas Brown * @version 1.0 */ public abstract class Filter { // instance fields /** true if the filter inspector is visible */ public boolean inspectorVisible; /** the x-component of inspector position */ public int inspectorX = Integer.MIN_VALUE; /** the y-component of inspector position */ public int inspectorY; protected BufferedImage source, input, output; protected int w, h; protected Graphics2D gIn; private boolean enabled = true; private String name; protected boolean changed = false; protected String previousState; protected VideoPanel vidPanel; protected PropertyChangeSupport support; protected Action enabledAction; protected JCheckBoxMenuItem enabledItem; protected JMenuItem deleteItem; protected JMenuItem propertiesItem; protected boolean hasInspector; protected Frame frame; protected JButton closeButton; protected JButton ableButton; protected JButton clearButton; protected FilterStack stack; // set by stack when filter added /** * Constructs a Filter object. */ protected Filter() { support = new SwingPropertyChangeSupport(this); // get the name of this filter from the simple class name name = getClass().getSimpleName(); int i = name.indexOf("Filter"); //$NON-NLS-1$ if ((i>0)&&(i<name.length()-1)) { name = name.substring(0, i); } // set up menu items enabledAction = new AbstractAction(MediaRes.getString("Filter.MenuItem.Enabled")) { //$NON-NLS-1$ public void actionPerformed(ActionEvent e) { Filter.this.setEnabled(enabledItem.isSelected()); refresh(); } }; enabledItem = new JCheckBoxMenuItem(enabledAction); enabledItem.setSelected(isEnabled()); propertiesItem = new JMenuItem(MediaRes.getString("Filter.MenuItem.Properties")); //$NON-NLS-1$ propertiesItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JDialog inspector = getInspector(); if(inspector!=null) { inspector.setVisible(true); } } }); closeButton = new JButton(); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JDialog inspector = getInspector(); if(inspector!=null) { if (isChanged() && previousState!=null) { changed = false; support.firePropertyChange("filterChanged", previousState, Filter.this); //$NON-NLS-1$ previousState = null; } inspector.setVisible(false); } } }); ableButton = new JButton(); ableButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { enabledItem.setSelected(!enabledItem.isSelected()); enabledAction.actionPerformed(null); } }); clearButton = new JButton(); clearButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { clear(); } }); } /** * Applies the filter to a source image and returns the result. * If the filter is not enabled, the source image should be returned. * * @param sourceImage the source image * @return the filtered image */ public abstract BufferedImage getFilteredImage(BufferedImage sourceImage); /** * Returns a JDialog inspector for controlling filter properties. * * @return the inspector */ public abstract JDialog getInspector(); /** * Clears the filter. This default method does nothing. */ public void clear() { /** empty block */ } /** * Determines if the filter settings have changed. * * @return true if changed */ public boolean isChanged() { return changed; } /** * Sets the video panel. * * @param panel the video panel */ public void setVideoPanel(VideoPanel panel) { vidPanel = panel; frame = vidPanel==null? null: JOptionPane.getFrameForComponent(vidPanel); } /** * Refreshes this filter's GUI */ public void refresh() { enabledItem.setText(MediaRes.getString("Filter.MenuItem.Enabled")); //$NON-NLS-1$ propertiesItem.setText(MediaRes.getString("Filter.MenuItem.Properties")); //$NON-NLS-1$ closeButton.setText(MediaRes.getString("Filter.Button.Close")); //$NON-NLS-1$ ableButton.setText(isEnabled() ? MediaRes.getString("Filter.Button.Disable") : //$NON-NLS-1$ MediaRes.getString("Filter.Button.Enable")); //$NON-NLS-1$ clearButton.setText(MediaRes.getString("Filter.Button.Clear")); //$NON-NLS-1$ clearButton.setEnabled((isEnabled())); } @Override public void finalize() { OSPLog.finer(getClass().getSimpleName()+" resources released by garbage collector"); //$NON-NLS-1$ } /** * Sets whether this filter is enabled. * * @param enabled <code>true</code> if this is enabled. */ public void setEnabled(boolean enabled) { if(this.enabled==enabled) { return; } this.enabled = enabled; support.firePropertyChange("enabled", null, new Boolean(enabled)); //$NON-NLS-1$ } /** * Gets whether this filter is enabled. * * @return <code>true</code> if this is enabled. */ public boolean isEnabled() { return enabled; } /** * Disposes of this filter. */ public void dispose() { removePropertyChangeListener(stack); stack = null; JDialog inspector = getInspector(); if (inspector!=null) { inspector.setVisible(false); inspector.dispose(); } setVideoPanel(null); if (gIn!=null) gIn.dispose(); if (source!=null) source.flush(); if (input!=null) input.flush(); if (output!=null) output.flush(); } /** * Adds a PropertyChangeListener to this filter. * * @param listener the object requesting property change notification */ public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } /** * Adds a PropertyChangeListener to this filter. * * @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 filter. * * @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 a menu with items that control this filter. Subclasses should * override this method and add filter-specific menu items. * * @param video the video using the filter (may be null) * @return a menu */ public JMenu getMenu(Video video) { JMenu menu = new JMenu(MediaRes.getString("VideoFilter."+name)); //$NON-NLS-1$ if(hasInspector) { menu.add(propertiesItem); menu.addSeparator(); } menu.add(enabledItem); if(video!=null) { menu.addSeparator(); deleteItem = new JMenuItem(MediaRes.getString("Filter.MenuItem.Delete")); //$NON-NLS-1$ final FilterStack filterStack = video.getFilterStack(); deleteItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { filterStack.removeFilter(Filter.this); } }); menu.add(deleteItem); } return menu; } } /* * 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 */