001    /*
002      Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com>
003      
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.aspects.gui.swing;
019    
020    import java.awt.event.FocusEvent;
021    import java.awt.event.FocusListener;
022    import java.lang.IllegalAccessException;
023    import org.apache.log4j.Logger;
024    import org.objectweb.jac.aspects.gui.CommitException; 
025    import org.objectweb.jac.aspects.gui.FieldEditor; 
026    import org.objectweb.jac.aspects.gui.FieldUpdate; 
027    import org.objectweb.jac.aspects.gui.GuiAC;
028    import org.objectweb.jac.aspects.gui.Utils; 
029    import org.objectweb.jac.core.Collaboration;
030    import org.objectweb.jac.core.rtti.ClassItem;
031    import org.objectweb.jac.core.rtti.FieldItem;
032    import org.objectweb.jac.core.rtti.MethodItem;
033    
034    public abstract class AbstractFieldEditor extends AbstractView 
035        implements FocusListener, FieldEditor, FieldUpdate
036    {
037        static Logger logger = Logger.getLogger("gui.editor");
038        static Logger loggerFocus = Logger.getLogger("gui.focus");
039    
040        // substance and field are required so that we can register and
041        // unregister ourself from fieldUpdated events on close()
042        Object substance;
043        FieldItem field;
044        MethodItem setter;
045        Object value;
046        boolean isEmbedded;
047        ClassItem type;
048    
049        public AbstractFieldEditor(Object substance, FieldItem field) {
050            this.substance = substance;
051            setField(field);
052            addFocusListener(this);
053        }
054    
055        public void fieldUpdated(Object object, FieldItem field, 
056                                 Object value, Object param) {
057            setValue(value);
058        }
059    
060        public abstract Object getValue();
061    
062        public void setValue(Object value) {
063            this.value = value;
064        }
065    
066        public void setField(FieldItem field) {
067            Utils.unregisterField(substance,this.field,this);
068            this.field = field;
069            Utils.registerField(substance,this.field,this);
070            if (field!=null)
071                this.setter = field.getSetter();
072        }
073    
074        public FieldItem getField() {
075            return field;
076        }
077    
078        public void setSubstance(Object substance) {
079            logger.debug("setSubstance("+substance+")");
080            this.substance = substance;
081        }
082    
083        /**
084        * Returns the object that holds the field, if any
085        */
086        public Object getSubstance() {
087            return substance;
088        }
089    
090        public void setEditedType(ClassItem type) {
091            this.type = type;
092        }
093    
094        public void setEmbedded(boolean isEmbedded) {
095            this.isEmbedded = isEmbedded;
096            if (isEmbedded)
097                Utils.registerField(substance,field,this);
098            else
099                Utils.unregisterField(substance,field,this);
100        }
101    
102        public void setAutoUpdate(boolean autoUpdate) {
103            // TODO
104        }
105    
106        public void close(boolean validate) {
107            Utils.unregisterField(substance,field,this);
108            if (validate)
109                commit();
110            substance = null;
111            super.close(validate);
112        }
113    
114        public void onSetFocus(Object extraOption) {}
115    
116        /**
117        * Commit editing by calling the setter method.
118        */
119        public void commit() {
120            if (setter!=null && valueHasChanged()) {
121                logger.debug("value changed for "+substance+"."+field.getName());
122                try {
123                    field.setThroughWriter(substance,getValue());
124                } catch (IllegalAccessException e) {
125                    logger.error("Failed to commit value "+getValue()+
126                                 " for field "+substance+"."+field,e);
127                } catch (Exception e) {
128                    throw new CommitException(e,substance,field);
129                }
130                value = getValue();
131            }
132        }
133    
134        /**
135        * Tells wether the value in the editor was changed
136        */
137        boolean valueHasChanged() {
138            Object newValue = getValue();
139            boolean ret;
140            if (value == null &&  newValue != null) {
141                ret = true;
142            } else if (value == null) {
143                ret = false;
144            } else {
145                ret = ! value.equals(newValue);
146            }
147            logger.debug("valueHasChanged("+field.getName()+") "+
148                         value+" / "+newValue+" -> "+ret);
149            return ret;
150        }
151    
152        // FocusListener interface
153    
154        public void focusGained(FocusEvent e) {
155            /** do nothing */
156            loggerFocus.debug("focus gained on "+getClass().getName());
157        }
158    
159        public void focusLost(FocusEvent e) {
160            /** Update the object's field if needed. */
161            loggerFocus.debug("focus lost on "+getClass().getName());
162            // We must ignore the event if closed==true because susbtance
163            // is set to null
164            if (field!=null && isEmbedded && !closed) {
165                invokeInContext(this,"commit", new Object[]{});
166            } else {
167                loggerFocus.debug("ignoring focusLost event");
168            }
169        }
170    
171    }