001    /*
002      Copyright (C) 2002 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, but
010      WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012      Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017      USA */
018    
019    package org.objectweb.jac.aspects.gui;
020    
021    import java.util.Collection;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Vector;
025    import javax.swing.AbstractListModel;
026    import org.apache.log4j.Logger;
027    import org.objectweb.jac.core.rtti.CollectionItem;
028    import org.objectweb.jac.util.Stack;
029    
030    /**
031     * Base class for ListModel and ComboBoxModel.
032     */
033    public abstract class LessAbstractListModel extends AbstractListModel 
034        implements ObjectUpdate, CollectionModel, CollectionUpdate
035    {
036        static Logger logger = Logger.getLogger("gui.model");
037    
038        CollectionItem collection=null;
039        Object substance;
040    
041        List rows = new Vector();
042        List objects = new Vector();
043    
044        Stack context = new Stack();
045    
046        /**
047         * Construct a new abstract list model which is independent from
048         * any collection. */
049        public LessAbstractListModel() {
050            if (GuiAC.getGraphicContext()!=null)
051                context.addAll(GuiAC.getGraphicContext());      
052        }
053    
054        /**
055         * Construct a new abstract list model in which the values depend
056         * on a collection's values.
057         *
058         * @param collection the substance collection
059         * @param substance the object that holds the collection's value */
060        public LessAbstractListModel(CollectionItem collection, Object substance) {
061            if (GuiAC.getGraphicContext()!=null)
062                context.addAll(GuiAC.getGraphicContext());      
063           
064            this.collection = collection;
065            this.substance = substance;
066    
067            buildData();
068            Utils.registerCollection(substance,collection,this);
069        }
070    
071        void buildData() {
072            Collection c = collection.getActualCollectionThroughAccessor(substance);
073            if (c!=null) {
074                logger.debug("buildData for "+substance+"."+collection.getName());
075                logger.debug("objects : " + new Vector(c));
076                Iterator i = c.iterator();
077                while (i.hasNext()) {
078                    Object obj = i.next();
079                    logger.debug("add "+obj);
080                    addObject(obj);
081                }
082            }
083        }
084    
085        public CollectionItem getCollection() {
086            return collection;
087        }
088    
089        String nullLabel;
090        /**
091         * Sets the default label to be used for a null reference.
092         * @param label label for null
093         */
094        public void setNullLabel(String label) {
095            this.nullLabel = label;
096        }
097    
098        /**
099         * Adds an object in the list. Uses GuiAC.toString() to get a string
100         * representation of the object.
101         * @param object the object to add 
102         * @see #addObject(Object,String)
103         * @see #setNullLabel(String)
104         */
105        public void addObject(Object object) {
106            addObject(object,
107                      object==null ? 
108                              (nullLabel!=null ? nullLabel : GuiAC.getLabelNone()) 
109                            : GuiAC.toString(object,context));
110        }
111    
112        /**
113         * Add an object in the list with a given label to be displayed. 
114         * @param object the object to add
115         * @param label the label to be displayed for the object
116         * @see #addObject(Object)
117         */
118        public void addObject(Object object, String label) {
119            objects.add(object);
120            rows.add(label);
121            fireIntervalAdded(this,objects.size()-1,objects.size()-1);
122            Utils.registerObject(object,this);
123        }
124    
125        /**
126         * Gets the list element count. */
127        public int getRowCount() {
128            return rows.size();
129        }
130    
131        /**
132         * Returns the element at a given row. */
133        public Object getElementAt(int row) {
134            logger.debug("getElementAt("+row+") -> "+rows.get(row));
135            return rows.get(row);
136        }
137    
138        /**
139         * Gets the list size (same as <code>getRowCount</code>). */
140        public int getSize() {
141            return getRowCount();
142        }
143    
144        /**
145         * Gets the object at a given index. */
146        public Object getObject(int index) {
147            return objects.get(index);
148        }
149    
150        public int indexOf(Object object) {
151            return objects.indexOf(object);
152        }
153    
154        /**
155         * Tells if this cell is directly editable (always returns false
156         * for the moment). */
157    
158        public boolean isCellEditable(int row, int column) {
159            return false;
160        }
161    
162        // ObjectUpdate interface
163        public void objectUpdated(Object substance,Object param) {
164            int index = objects.indexOf(substance);
165            if (index!=-1) {
166                rows.set(index,GuiAC.toString(objects.get(index),context));
167                fireContentsChanged(this,index,index);
168            }
169        }
170    
171        private int getMin(String row, Object obj)
172        {
173            int min = 0;
174            for (int i = 1; i < rows.size(); i++)
175            {
176                if ((((String) (((Vector) rows).elementAt(i)))
177                     .compareToIgnoreCase((String) (((Vector) rows).elementAt(min))))
178                    < 0)
179                    min = i;
180            }
181            return min;
182        }
183    
184        /**
185         * sort the list alphabetically by label
186         */
187        public void sort()
188        {
189            Vector newRows = new Vector();
190            Vector newObjs = new Vector();
191          
192            Object obj = null;
193            String row = null;
194    
195            while (rows.size() > 0)
196            {
197                int min = getMin(row, obj);
198                row = (String) ((Vector) rows).elementAt(min);
199                obj = ((Vector) objects).elementAt(min);
200                newRows.add(row);
201                newObjs.add(obj);
202                rows.remove(row);
203                objects.remove(obj);
204            }
205            rows = newRows;
206            objects = newObjs;
207        }
208    
209    
210        /**
211         * Unregister ourself as a view on all objects of the collection
212         */
213        protected void unregisterViews() {
214            logger.debug("TableModel.unRegisterViews "+objects.size());
215            Iterator i = objects.iterator();
216            while (i.hasNext()) {
217                Object object = i.next();
218                Utils.unregisterObject(object,this);
219            }      
220        }
221    
222        public void close() {
223            unregisterViews();
224            if(collection!=null) {
225                Utils.unregisterCollection(substance,collection,this);
226            }
227        }
228    
229        // CollectionUpdate
230        public void onChange(Object substance, CollectionItem collection, 
231                             Object value, Object param) {
232            unregisterViews();
233            int size = objects.size();
234            objects.clear();
235            rows.clear();
236            if (size>0)
237                fireIntervalRemoved(this,0,size-1);
238            buildData();
239            if (!objects.isEmpty())
240                fireIntervalAdded(this, 0, objects.size()-1);
241        }
242    
243        public void onAdd(Object substance, CollectionItem collection, 
244                          Object value, Object added, Object param) {
245            onChange(substance,collection,value,param);
246        }
247    
248        public void onRemove(Object substance, CollectionItem collection, 
249                             Object value, Object removed, Object param) {
250            onChange(substance,collection,value,param);
251        }
252    
253    
254    }