/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*
* (C) Copyright 2001-2007, by :
* Corporate:
* EADS Astrium
* Individual:
* Claude Cazenave
*
* $Id: PropertyEdit.java,v 1.5 2008/11/14 17:03:15 cazenave Exp $
*
* Changes
* -------
* 22 janv. 08 : Initial public release
*
*/
package jsynoptic.plugins.java3d.edit;
import java.util.ArrayList;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Node;
import javax.media.j3d.SceneGraphObject;
import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import jsynoptic.plugins.java3d.Animator;
import jsynoptic.plugins.java3d.AnimatorFactory;
import jsynoptic.plugins.java3d.AnimatorGroup;
import jsynoptic.plugins.java3d.AttachDetach;
import jsynoptic.plugins.java3d.SceneGraphObjectHolder;
/**
*
*/
public abstract class PropertyEdit <T extends SceneGraphObject,E> extends AbstractUndoableEdit {
protected final T _object;
protected final String _propertyName;
protected E _oldValue;
protected E _newValue;
protected boolean _changed;
protected ArrayList<UndoRedoListener> _listeners;
protected AttachDetach _ad;
protected SceneGraphObjectHolder _holder;
/**
*
*/
public PropertyEdit(T object, String name) {
_object=object;
_holder=null;
_propertyName=name;
_ad=null;
if(_object!=null){
_oldValue=getPropertyValue();
}
else{
_oldValue=null;
}
_newValue=null;
_listeners=null;
_changed=false;
}
public T getObject(){
return _object;
}
public SceneGraphObjectHolder getHolder(){
return _holder;
}
public void setHolder(SceneGraphObjectHolder h){
_holder=h;
}
public boolean isModified(){
return _changed;
}
public E getOldValue(){
return _oldValue;
}
public void setNewValue(E v){
_newValue=v;
compare();
if(_changed)setPropertyValue(_newValue);
}
@Override
public String getPresentationName() {
// TODO i18n
return _propertyName;
}
public AnimatorFactory.Parameters getAnimatorParameters(){
return null;
}
public SceneGraphObjectHolder addAnimator(Animator an, Object source){
// look for the first parent branch group
SceneGraphObjectHolder holder=getHolder().getParentHolder();
while(holder!=null && ! (holder.getSceneGraphObject() instanceof BranchGroup)){
holder=holder.getParentHolder();
}
if(holder==null){
throw new RuntimeException("Can not find a branch group to hold the new animator");
}
// look for one animator group node
ArrayList<SceneGraphObjectHolder> list=new ArrayList<SceneGraphObjectHolder>();
holder.getChildrenHolders(list);
SceneGraphObjectHolder ang=null;
for(SceneGraphObjectHolder h : list){
if(h.getSceneGraphObject() instanceof AnimatorGroup){
ang=h;
break;
}
}
CompoundEdit ce=new CompoundEdit();
if(ang==null){
// create one
AnimatorGroup ag=new AnimatorGroup();
holder.addSceneGraphObject(ag);
AddEdit ae=new AddEdit(holder,ag,null);
ce.addEdit(ae);
}
list.clear();
holder.getChildrenHolders(list);
for(SceneGraphObjectHolder h : list){
if(h.getSceneGraphObject() instanceof AnimatorGroup){
ang=h;
break;
}
}
if(ang==null){
throw new RuntimeException("Can not retrieve holder for animator group");
}
ang.addSceneGraphObject(an);
AddEdit ae=new AddEdit(ang,an,null);
ce.addEdit(ae);
holder.getUndoableEditListener().undoableEditHappened(
new UndoableEditEvent(source, ce));
ArrayList<SceneGraphObjectHolder> cl=new ArrayList<SceneGraphObjectHolder>();
ang.getChildrenHolders(cl);
holder=null;
for(SceneGraphObjectHolder h : cl){
if(h.getSceneGraphObject()==an){
holder=h;
break;
}
}
if(holder==null){
throw new RuntimeException("Can not retrieve holder for animator");
}
holder.addSceneGraphObject(getHolder().getSceneGraphObject());
return holder;
}
@Override
public void redo() throws CannotRedoException {
super.redo();
setPropertyValue(_newValue);
for(UndoRedoListener l : _listeners){
l.undoRedoPerfomed(false);
}
}
@Override
public void undo() throws CannotUndoException {
super.undo();
setPropertyValue(_oldValue);
for(UndoRedoListener l : _listeners){
l.undoRedoPerfomed(true);
}
}
@Override
public String toString() {
StringBuffer buff=new StringBuffer();
buff.append(_propertyName);
buff.append(" : ");
E v=_oldValue;
buff.append((v==null) ? "null" : (v.getClass().getName()+"="+v.toString()));
buff.append(" => ");
v=_newValue;
buff.append((v==null) ? "null" : (v.getClass().getName()+"="+v.toString()));
return buff.toString();
}
public void addListener(UndoRedoListener l){
if(_listeners==null) _listeners=new ArrayList<UndoRedoListener>();
_listeners.add(l);
}
public void removeListener(UndoRedoListener l){
_listeners.remove(l);
}
/**
* To overwrite for values when equals method is not valid
*/
protected void compare(){
if(_newValue != null){
_changed=!_newValue.equals(_oldValue);
}
else if(_oldValue !=null){
_changed=true;
}
else{
_changed=false;
}
}
protected SceneGraphObject getCapableObject(){
return _object;
}
public boolean forceCapability(int bit){
if(!getCapableObject().getCapability(bit)){
if(getCapableObject().isLive()){
Node n= null;
if(getCapableObject() instanceof Node){
n=(Node)getCapableObject();
}
else{
n=_holder.getSceneGraphNode();
}
if(_ad!=null){
throw new RuntimeException("Unexpected attach detach operation");
}
_ad=new AttachDetach(n);
_ad.detach();
}
getCapableObject().setCapability(bit);
return true;
}
return false;
}
public void restoreCapability(int bit){
getCapableObject().clearCapability(bit);
if(_ad!=null){
_ad.attach();
_ad=null;
}
}
public abstract String getDisplayClassName();
public abstract void setPropertyValue(E value);
public abstract E getPropertyValue();
public interface UndoRedoListener {
public void undoRedoPerfomed(boolean isUndo);
}
}