001    /*
002      Copyright (C) 2002-2003 Renaud Pawlak <renaud@aopsys.com>, 
003                              Laurent Martelli <laurent@aopsys.com>
004      
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful, but
011      WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013      Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser General Public
016      License along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
018      USA */
019    
020    package org.objectweb.jac.aspects.gui;
021    
022    import java.lang.reflect.Array;
023    import java.lang.reflect.Modifier;
024    import java.util.Arrays;
025    import java.util.Collection;
026    import java.util.Hashtable;
027    import java.util.Iterator;
028    import java.util.Map;
029    import java.util.Vector;
030    import org.apache.log4j.Logger;
031    import org.objectweb.jac.core.Collaboration;
032    import org.objectweb.jac.core.Naming;
033    import org.objectweb.jac.core.ObjectRepository;
034    import org.objectweb.jac.core.Wrappee;
035    import org.objectweb.jac.core.rtti.AbstractMethodItem;
036    import org.objectweb.jac.core.rtti.ClassItem;
037    import org.objectweb.jac.core.rtti.ClassRepository;
038    import org.objectweb.jac.core.rtti.CollectionItem;
039    import org.objectweb.jac.core.rtti.FieldItem;
040    import org.objectweb.jac.core.rtti.MetaItem;
041    import org.objectweb.jac.core.rtti.MethodItem;
042    import org.objectweb.jac.core.rtti.MixinMethodItem;
043    import org.objectweb.jac.core.rtti.RttiAC;
044    import org.objectweb.jac.core.rtti.VirtualClassItem;
045    import org.objectweb.jac.util.Classes;
046    import org.objectweb.jac.util.Enum;
047    import org.objectweb.jac.util.ExtArrays;
048    import org.objectweb.jac.util.ExtBoolean;
049    import org.objectweb.jac.util.NotInCollectionPredicate;
050    import org.objectweb.jac.util.Predicate;
051    import org.objectweb.jac.util.Stack;
052    import org.objectweb.jac.util.Strings;
053    
054    /**
055     * This class implements static methods that generically create GUI
056     * items. Depending on the actual view factory, the created items are
057     * for SWING, WEB or other GUI. */
058    
059    public class GenericFactory {
060        static Logger logger = Logger.getLogger("gui.generic");
061        static Logger loggerAssoc = Logger.getLogger("associations");
062    
063        /**
064         * Creates a view on an object.
065         *
066         * @param factory the used factory
067         * @param context the display context (passed to ceated sub-item so
068         * that they know displays and customized)
069         * @param viewName name of the view to build
070         * @param substance the object to build a view of */
071    
072        public static View createObjectView(
073            ViewFactory factory,
074            DisplayContext context,
075            String viewName,
076            Object substance) 
077        {
078            logger.debug("createObjectView("
079                    + factory + "," + Strings.hex(substance) + "," + viewName + ")");
080    
081            if (substance == null) {
082                return factory.createView("null", "Empty", context);
083            }
084    
085            if (substance instanceof Number
086                || substance instanceof Boolean
087                || substance instanceof Character
088                || substance instanceof String) {
089                return factory.createView(
090                    substance.getClass().getName(),
091                    "Field",
092                    new Object[] { substance, null, null },
093                    context);
094            }
095    
096            Class substance_type = substance.getClass();
097            ClassItem cli = ClassRepository.get().getClass(substance_type);
098    
099            CompositeView view =
100                (CompositeView) factory.createCompositeView(
101                    cli.getName(),
102                    "ObjectView",
103                    context);
104    
105            fillObjectView(view, cli, viewName, substance);
106            Collection dependencies = GuiAC.getDependentFields(cli);
107            if (dependencies != null) {
108                Iterator it = dependencies.iterator();
109                while (it.hasNext()) {
110                    FieldItem field = (FieldItem) it.next();
111                    Utils.registerField(substance, field, EventHandler.get(), view);
112                }
113            }
114            return view;
115        }
116    
117        public static void fillObjectView(
118            CompositeView view,
119            ClassItem cli,
120            String viewName,
121            Object substance) 
122        {
123            ObjectView objectView = GuiAC.getView(cli, viewName);
124            ViewFactory factory = view.getFactory();
125            DisplayContext context = view.getContext();
126            String[] categories = (String[]) cli.getAttribute(GuiAC.CATEGORIES);
127            String[] icons = GuiAC.getCategoriesIcons(cli);
128            String[] labels = GuiAC.getCategoriesLabels(cli);
129            if (labels == null)
130                labels = categories;
131    
132            view.setStyle((String) cli.getAttribute(GuiAC.STYLE));
133            view.setDescription(GuiAC.getDescription(substance, "<b>", "</b>"));
134    
135            logger.debug("categories = "
136                    + (categories != null
137                        ? Arrays.asList(categories).toString()
138                        : "null"));
139    
140            if (categories == null) {
141                view.addView(
142                    createObjectView(
143                        factory,
144                        context,
145                        objectView,
146                        substance,
147                        null));
148            } else {
149                TabsView tabbedPane =
150                    (TabsView) factory.createCompositeView(
151                        cli.getName(),
152                        "Tabbed",
153                        context);
154                for (int i = 0; i < categories.length; i++) {
155                    logger.debug("add tab for category " + categories[i]);
156    
157                    String icon;
158                    if ((icons != null) && (Array.getLength(icons) > i))
159                        icon = icons[i];
160                    else
161                        icon = null;
162    
163                    CompositeView tab =
164                        createObjectView(
165                            factory,
166                            context,
167                            objectView,
168                            substance,
169                            categories[i]);
170                    if (!compositeViewIsEmpty(tab))
171                        tabbedPane.addTab(tab, labels[i], icon);
172                    else
173                        logger.debug("tab[" + categories[i] + "] is empty");
174                }
175                view.addView((CompositeView) tabbedPane);
176            }
177        }
178    
179        /**
180         * Creates a view of an object (containing no tabs).
181         * 
182         * @param factory the used factory
183         * @param context the display context (passed to ceated sub-item so
184         * that they know displays and customized)
185         * @param substance the viewed object */
186    
187        public static View createObjectViewNoTab(
188            ViewFactory factory,
189            DisplayContext context,
190            Object substance) 
191        {
192            logger.debug("createObjectViewNoTab("
193                    + factory
194                    + ","
195                    + Strings.hex(substance)
196                    + ")");
197    
198            if (substance == null) {
199                return factory.createView(
200                    substance.getClass().getName(),
201                    "Empty",
202                    context);
203            } else {
204                return createObjectView(
205                    factory,
206                    context,
207                    GuiAC.getView(
208                        ClassRepository.get().getClass(substance),
209                        "default"),
210                    substance,
211                    null);
212            }
213        }
214    
215        /**
216         * Returns true is the CompositeView contains a view other than
217         * CompositeView.
218         */
219        public static boolean compositeViewIsEmpty(CompositeView view) {
220            Iterator it = view.getViews().iterator();
221            while (it.hasNext()) {
222                View subView = (View) it.next();
223                if (!(subView instanceof CompositeView))
224                    return false;
225                else if (!compositeViewIsEmpty((CompositeView) subView))
226                    return false;
227            }
228            return true;
229        }
230    
231        /**
232         * Create a view of an object, including only the attributes of a
233         * category.
234         *
235         * @param factory the ViewFactory
236         * @param context the DisplayContext
237         * @param substance the object to build the view of
238         * @param category the category; if null, all fields are shown
239         * @return a CompositeView representing the object
240         */
241        protected static CompositeView createObjectView(
242            ViewFactory factory,
243            DisplayContext context,
244            ObjectView view,
245            Object substance,
246            String category) 
247        {
248            logger.debug("createObjectView("
249                    + factory + "," + Strings.hex(substance) + ","
250                    + category+ "," + view.getName() + ")");
251            CompositeView resultPane =
252                factory.createCompositeView(
253                    substance.getClass().getName() + "[" + category + "]",
254                    "Container",
255                    new Object[] { new Integer(Constants.VERTICAL)},
256                    context);
257    
258            Class substance_type = substance.getClass();
259            ClassItem cli = ClassRepository.get().getClass(substance_type);
260    
261            CompositeView fieldpane =
262                factory.createCompositeView(
263                    "fields",
264                    "ParameterContainer",
265                    new Object[] { Boolean.TRUE },
266                    context);
267            //      EditorContainer editorContainer = (EditorContainer)fieldpane;
268    
269            // primitive fields and references
270    
271            FieldItem[] fields = null;
272            fields = view.getAttributesOrder();
273            if (fields == null)
274                fields = cli.getFields();
275    
276            boolean embedded = view.getName().equals(GuiAC.AUTOCREATE_VIEW);
277            logger.debug("attributes_order = " + Arrays.asList(fields));
278            FieldItem[] groups = (FieldItem[]) cli.getAttribute(GuiAC.LINE_BREAKS);
279            int curgroup = 0;
280    
281            CompositeView subFieldPane = null;
282            FieldItem oppositeRole =
283                (FieldItem) Collaboration.get().getAttribute(GuiAC.OPPOSITE_ROLE);
284            loggerAssoc.debug("opposite role = " + oppositeRole);
285            boolean first = true;
286            for (int i = 0; i < fields.length; i++) {
287                if (groups != null
288                    && curgroup < groups.length
289                    && groups[curgroup] == fields[i]) {
290                    if (subFieldPane != null) {
291                        fieldpane.addView(subFieldPane);
292                    }
293                    subFieldPane =
294                        factory.createCompositeView(
295                            "subField[" + i + "]",
296                            "Container",
297                            new Object[] { new Integer(Constants.HORIZONTAL)},
298                            context);
299                    first = true;
300                    curgroup++;
301                }
302                FieldItem field = fields[i];
303                //if(field==null) continue;
304                if (GuiAC.isMemberInCategory(field, category)
305                    && GuiAC.isVisible(substance, field)
306                    && !field.isStatic()
307                    && !field.equals(oppositeRole)) {
308                    CompositeView pane =
309                        subFieldPane != null ? subFieldPane : fieldpane;
310                    try {
311                        if (!first && subFieldPane != null)
312                            subFieldPane.addHorizontalStrut(10);
313                        pane.addView(
314                            getFieldPane(
315                                factory,
316                                context,
317                                substance,
318                                view,
319                                field,
320                                embedded));
321                        first = false;
322                    } catch (Exception e) {
323                        logger.error(
324                            "Failed to build view for field \""+field+"\"", e);
325                    }
326                }
327            }
328            if (subFieldPane != null) {
329                fieldpane.addView(subFieldPane);
330            }
331    
332            resultPane.addView(fieldpane);
333    
334            logger.debug("getMethodsPane for " + cli);
335    
336            Collection meths = new Vector();
337            //if (Collaboration.get().getAttribute(GuiAC.AUTO_CREATION) == null) {
338            MethodItem[] ms = view.getMethodsOrder();
339            if (ms != null) {
340                meths = Arrays.asList(ms);
341            }
342            //}
343    
344            logger.debug("methods = " + meths);
345    
346            CompositeView methodsPane =
347                getMethodsPane(factory, context, substance, meths, category, view);
348            if (methodsPane != null) {
349                logger.debug("adding methodPane");
350                resultPane.addView(methodsPane);
351            }
352    
353            return resultPane;
354    
355        }
356    
357        public static View getFieldPane(
358            ViewFactory factory,
359            DisplayContext context,
360            Object substance,
361            ObjectView objectView,
362            FieldItem field,
363            boolean embedded) 
364        {
365            GuiAC.pushGraphicContext(field);
366            try {
367                MemberItemView memberView = GuiAC.getView(field, objectView.getName());
368                if (field.isReference()) {
369                    return getReferenceFieldPane(
370                        factory,
371                        context,
372                        substance,
373                        field,
374                        embedded,
375                        objectView,memberView);
376                } else if (field.isPrimitive()
377                        || factory.hasViewerFor(field.getTypeItem().getName())) {
378                    return getPrimitiveFieldPane(
379                        factory,
380                        context,
381                        substance,
382                        field,
383                        objectView,
384                        memberView,
385                        embedded);
386                } else if (field instanceof CollectionItem) {
387                    return getCollectionPane(
388                        factory,
389                        context,
390                        substance,
391                        objectView,
392                        (CollectionItemView) memberView,
393                        (CollectionItem) field);
394                }
395            } finally {
396                GuiAC.popGraphicContext();
397            }
398            return null;
399        }
400    
401        /**
402         * Instantiates a viewer for a value of a field and add it to a
403         * container.
404         */
405        protected static boolean getViewer(
406            Object substance,
407            FieldItem field,
408            Object value,
409            CompositeView container,
410            ViewFactory factory,
411            DisplayContext context) 
412        {
413            Stack types = new Stack();
414            types.push(ClassRepository.get().getClass(field.getType()));
415            if (value != null) {
416                ClassItem actualClass = ClassRepository.get().getClass(value);
417                if (types.safeTop()!=actualClass)
418                    types.push(actualClass);
419            }
420    
421            Enum enum = GuiAC.getEnum(field);
422            if (enum!=null) {
423                types.push(ClassRepository.get().getVirtualClass("Enum"));
424            }
425    
426            MetaItem type = RttiAC.getFieldType(field,substance);
427            if (type!=null && types.safeTop()!=type)
428                types.push(type);
429    
430            logger.debug("types = " + types);
431            boolean foundViewer = false;
432            while (!types.empty()) {
433                type = (MetaItem) types.pop();
434                if (factory.hasViewerFor(type.getName())) {
435                    container.addView(
436                        factory.createView(
437                            field.getName(),
438                            type.getName(),
439                            new Object[] { value, substance, field },
440                            context));
441                    foundViewer = true;
442                    break;
443                }
444            }
445            return foundViewer;
446        }
447    
448        /**
449         * Returns a view of a primitive field. It contains a label and the
450         * value of the field.
451         *
452         * @param factory the view factory
453         * @param context the display context
454         * @param substance the object the field is part of
455         * @param field the field item 
456         * @param view  the view to build the field for
457         * @param embedded use embbeded editors 
458         */
459        protected static View getPrimitiveFieldPane(
460            ViewFactory factory,
461            DisplayContext context,
462            Object substance,
463            FieldItem field,
464            ObjectView objectView,
465            MemberItemView memberView,
466            boolean embedded) 
467        {
468            logger.debug("primitive field : " + substance + "," + field.getName());
469    
470            /*
471            Boolean attrValue = (Boolean)field.getAttribute(GuiAC.BORDER);
472            boolean border = attrValue!=null && attrValue.booleanValue();
473            */
474    
475            CompositeView container =
476                factory.createCompositeView(
477                    "field[" + field.getName() + "]",
478                    "Container",
479                    new Object[] { new Integer(Constants.HORIZONTAL)},
480                    context);
481            Border border = GuiAC.getBorder(field);
482            if (border != null) {
483                border.setTitle(GuiAC.getLabel(field));
484                container.setViewBorder(border);
485            }
486            container.setStyle((String) field.getAttribute(GuiAC.STYLE));
487            Boolean displayLabel =
488                (Boolean) field.getAttribute(GuiAC.DISPLAY_LABEL);
489            boolean useEditor =
490                GuiAC.isEditable(substance, field)
491                && memberView.isEmbeddedEditor(embedded)
492                && !objectView.isReadOnly();
493            if ((border == null)
494                && (displayLabel == null
495                    || (displayLabel != null && displayLabel.booleanValue()))) {
496                container.addView(
497                    factory.createView(
498                        GuiAC.getLabel(field) + ": ",
499                        "Label",
500                        context));
501            }
502    
503            FieldEditor editor = null;
504            if (useEditor) {
505                MethodItem setter = field.getSetter();
506                if (setter != null) {
507                    try {
508                        editor =
509                            getEditorComponent(
510                                factory,
511                                context,
512                                field.getSubstance(substance),
513                                setter,
514                                0,
515                                true,
516                                null);
517                        context.addEditor(editor);
518                        container.addView(editor);
519                    } catch (Exception e) {
520                        // If the editor failed, we'll try a normal view
521                        logger.error("Failed to build editor component for "+
522                                     substance+"."+field.getName(),e);
523                    }
524                }
525            } 
526            if (editor==null) {
527                Object value = field.getThroughAccessor(substance);
528                if (!getViewer(substance,
529                               field,
530                               value,
531                               container,
532                               factory,
533                               context)) 
534                {
535                    Enum enum = GuiAC.getEnum(field);
536                    if (enum != null) {
537                        container.addView(
538                            factory.createView(
539                                field.getName(),
540                                "Enum",
541                                new Object[] { value, enum, substance, field },
542                                context));
543                    } else {
544                        container.addView(
545                            factory.createView(
546                                field.getName(),
547                                "Field",
548                                new Object[] { value, substance, field },
549                                context));
550                    }
551                }
552    
553                if (GuiAC.isEditable(substance, field) && !objectView.isReadOnly()) {
554                    container.addView(
555                        getEditButton(factory, substance, field, context));
556                }
557            }
558            return container;
559        }
560    
561        /**
562         * Build a view containing a label for the name of the field, and
563         * the view of the reference.
564         *
565         * @param factory the view factory
566         * @param context the display context
567         * @param substance the object the field is part of
568         * @param field the field item 
569         * @param embedded use embbeded editors
570         */
571        static protected View getReferenceFieldPane(
572            ViewFactory factory,
573            DisplayContext context,
574            Object substance,
575            FieldItem field,
576            boolean embedded,
577            ObjectView objectView, 
578            MemberItemView memberView) 
579        {
580            logger.debug("reference field : " + field.getName());
581            /*
582            Boolean attrValue = (Boolean)field.getAttribute(GuiAC.BORDER);
583            boolean border = attrValue!=null && attrValue.booleanValue();
584            */
585            CompositeView container =
586                factory.createCompositeView(
587                    "field[" + field.getName() + "]",
588                    "Container",
589                    new Object[] { new Integer(Constants.HORIZONTAL)},
590                    context);
591    
592            Border border = GuiAC.getBorder(field);
593            if (border != null) {
594                border.setTitle(GuiAC.getLabel(field));
595                container.setViewBorder(border);
596            }
597    
598            container.setStyle((String) field.getAttribute(GuiAC.STYLE));
599            Boolean displayLabel =
600                (Boolean) field.getAttribute(GuiAC.DISPLAY_LABEL);
601    
602            if ((border == null)
603                && (displayLabel == null
604                    || (displayLabel != null && displayLabel.booleanValue()))) {
605    
606                container.addView(
607                    factory.createView(
608                        GuiAC.getLabel(field) + ": ",
609                        "Label",
610                        context));
611            }
612    
613            if ((memberView != null && memberView.isEmbedded()) && !embedded) {
614                FieldItem oppositeRole =
615                    (FieldItem) field.getAttribute(RttiAC.OPPOSITE_ROLE);
616                if (oppositeRole instanceof CollectionItem) {
617                    loggerAssoc.debug("Ignoring collection oppositeRole " + oppositeRole);
618                    oppositeRole = null;
619                }
620                Collaboration.get().addAttribute(GuiAC.OPPOSITE_ROLE, oppositeRole);
621                try {
622                    logger.debug("embedded view for " + field);
623                    container.addView(
624                        factory.createObjectView(
625                            "embbeded " + field.getName(),
626                            field.getThroughAccessor(substance),
627                            substance,
628                            field,
629                            context));
630                } finally {
631                    Collaboration.get().addAttribute(GuiAC.OPPOSITE_ROLE, null);
632                }
633            } else {
634                if (memberView.isEmbeddedEditor(embedded)
635                    && GuiAC.isEditable(substance, field) 
636                    && !objectView.isReadOnly())
637                {
638                    MethodItem setter = field.getSetter();
639                    FieldEditor editor =
640                        getEditorComponent(
641                            factory,
642                            context,
643                            field.getSubstance(substance),
644                            setter,
645                            0,
646                            true,
647                            null);
648                    container.addView(editor);
649                    context.addEditor(editor);
650                } else {
651                    //Object value = field.getThroughAccessor(substance);
652                    //if (!getViewer(substance,field,value,container,factory,context)) {
653                    View refView = 
654                        factory.createView(
655                            field.getName(),
656                            "Reference",
657                            new Object[] {
658                                field.getThroughAccessor(substance),
659                                field.getSubstance(substance),
660                                field.getField()},
661                            context);
662                    if (refView instanceof LinkGenerator)
663                        ((LinkGenerator)refView).setEnableLinks(objectView.areLinksEnabled());
664                    container.addView(refView);
665    
666                    if (GuiAC.isEditable(field.getSubstance(substance),field.getField())
667                        && !objectView.isReadOnly()) {
668                        container.addView(
669                            getEditButton(
670                                factory,
671                                field.getSubstance(substance),
672                                field.getField(),
673                                context));
674                    }
675                    //}
676                }
677            }
678            return container;
679        }
680    
681        /**
682         * Adds choices within a container containing a combobox and sort
683         * them.
684         *
685         * @param choice combo box model to fill
686         * @param type type of objects to fill the model with
687         * @param field associated field item
688         * @param nullAllowed boolean telling wether the add null to themodel
689         * @param nullLabel if nullAllowed==true, the label to use for the null value (if not null)
690         * @param predicate if not null, only add objects which match this
691         * predicate 
692         */
693        static protected void addChoices(
694            ComboBoxModel choice,
695            ClassItem type,
696            Enum enum,
697            Object substance,
698            FieldItem field,
699            boolean nullAllowed,
700            String nullLabel,
701            Predicate predicate) 
702        {
703            // use JacObjects.getObjects(type) instead
704            Collection all_objects = null;
705            logger.debug("ObjectChooser.type = " + type
706                    + "; predicate=" + predicate
707                    + "; field=" + field
708                    + "; nullAllowed=" + nullAllowed);
709            if (field != null) {
710                Object fieldChoice = field.getAttribute(GuiAC.FIELD_CHOICE);
711                logger.debug("  fieldChoice = "+fieldChoice);            
712                if (fieldChoice instanceof MethodItem) {
713                    try {
714                        all_objects =
715                            (Collection) (((MethodItem) fieldChoice)
716                                .invoke(null, ExtArrays.emptyObjectArray));
717                    } catch (Exception e) {
718                        e.printStackTrace();
719                    }
720                } else if (fieldChoice instanceof CollectionItem) {
721                    all_objects = ((CollectionItem)fieldChoice).getActualCollectionThroughAccessor(substance);
722                }
723                choice.setType(type);
724            }
725    
726            if (enum!=null) {
727                Iterator it = enum.getValues().iterator();
728                while (it.hasNext()) {
729                    String str = (String) it.next();
730                    choice.addObject(new Integer(enum.string2int(str)), str);
731                }
732                choice.setType(type);
733                if (nullAllowed) {
734                    choice.setNullLabel(nullLabel);
735                    choice.addObject(null);
736                }
737            } else {
738    
739                if (all_objects == null) {
740                    all_objects = ObjectRepository.getObjects(type);
741                    choice.setType(type);
742                }
743                if (nullAllowed) {
744                    choice.setNullLabel(nullLabel);
745                    choice.addObject(null);
746                }
747                
748                Iterator i = all_objects.iterator();
749                while (i.hasNext()) {
750                    Object object = i.next();
751                    if (predicate == null || predicate.apply(object)) {
752                        choice.addObject(object);
753                    }
754                }
755                choice.sort();
756            }
757        }
758    
759        /**
760         * Constructs an edit button for reference views. 
761         */
762        static protected View getEditButton(
763            ViewFactory factory,
764            Object substance,
765            FieldItem field,
766            DisplayContext context)
767        {
768            MethodView methodView =
769                (MethodView) factory.createView(
770                    "edit " + field.getName(),
771                    "Method",
772                    new Object[] { substance, field.getSetter()},
773                    context);
774            methodView.setIcon(ResourceManager.getResource("edit_icon"));
775            methodView.setOnlyIcon(true);
776            return methodView;
777        }
778    
779        /**
780         * Builds a view that will display a given collection field of an
781         * object.
782         *
783         * @param factory the view factory to use to build other inner views
784         * @param context the display context
785         * @param substance the object that contains the collection
786         * @param collection the collection to show
787         * @return the associated view
788         * @see TableModel 
789         */
790        static public View getCollectionPane(
791            ViewFactory factory,
792            DisplayContext context,
793            Object substance,
794            ObjectView objectView,
795            CollectionItemView memberView,
796            CollectionItem collection) throws ViewFactory.UnhandledViewTypeException 
797        {
798            logger.debug("collection : " + collection.getName());
799            String label = "collection[" + collection.getName() + "]";
800            /*
801            View newPane;
802            if (collection.isMap() && collection.getAttribute("Gui.tableView")==null) {
803               newPane = new MapView(parent,this,substance,collection);
804            } else {
805               newPane = new CollectionView(parent,this,substance,collection);
806            }
807            newPane.setName( collection.getName() );
808            }
809            */
810    
811            CompositeView container =
812                factory.createCompositeView(
813                    label,
814                    "Container",
815                    new Object[] { new Integer(Constants.VERTICAL)},
816                    context);
817    
818            Boolean displayLabel =
819                (Boolean) collection.getAttribute(GuiAC.DISPLAY_LABEL);
820            Border border = GuiAC.getBorder(collection);
821            logger.debug("  border="+border);
822            if (displayLabel == null
823                || (displayLabel != null && displayLabel.booleanValue())) {
824    
825                if (border != null) {
826                    border.setTitle(GuiAC.getLabel(collection));
827                } else {
828                    if (GuiAC.isChoiceView(collection)) {
829                        border = new Border(null, Border.LEFT, Border.LINE);
830                    } else {
831                        border =
832                            new Border(
833                                GuiAC.getLabel(collection),
834                                Border.LEFT,
835                                Border.LINE);
836                    }
837                }
838                container.setViewBorder(border);
839            }
840    
841            container.setStyle((String) collection.getAttribute(GuiAC.STYLE));
842    
843            View view = null;
844            Collaboration.get().addAttribute(
845                GuiAC.OPPOSITE_ROLE,
846                collection.getAttribute(RttiAC.OPPOSITE_ROLE));
847            GuiAC.pushGraphicContext(collection);
848            try {
849    
850                if (memberView.getViewType() != null) {
851    
852                    view =
853                        factory.createView(
854                            label,
855                            memberView.getViewType(),
856                            new Object[] { collection, substance, memberView },
857                            context);
858                    container.addView(view);
859    
860                } else if (memberView != null && memberView.isEmbedded()) {
861                    Collection values =
862                        collection.getActualCollectionThroughAccessor(substance);
863                    Iterator it = values.iterator();
864                    while (it.hasNext()) {
865                        Object value = it.next();
866                        container.addView(
867                            factory.createView(
868                                "embbeded " + collection.getName(),
869                                "Object",
870                                new Object[] { value },
871                                context));
872                    }
873    
874                } else {
875                    if (GuiAC.isTableView(collection)) {
876    
877                        // TABLE
878                        logger.debug("  isTableView");
879                        ExtendedTableModel model =
880                            new TableModel(
881                                collection,
882                                substance,
883                                objectView != null
884                                    ? objectView.getName()
885                                    : GuiAC.DEFAULT_VIEW,
886                                factory);
887    
888                        Collection filteredColumns = 
889                            (Collection)collection.getAttribute(GuiAC.FILTERED_COLUMNS);
890                        if (filteredColumns!=null) {
891                            model = new TableFilter(model,filteredColumns);
892                        }
893    
894                        model = new TableSorter(model);
895    
896                        view =
897                            factory.createView(
898                                label,
899                                "Table",
900                                new Object[] {
901                                    collection,
902                                    substance,
903                                    model,
904                                    memberView },
905                                context);
906    
907                    } else if (GuiAC.isChoiceView(collection)) {
908    
909                        // CHOICE VIEW
910                        logger.debug("  isChoiView");
911                        ComboBoxModel model =
912                            new ComboBoxModel(collection, substance);
913                        view =
914                            factory.createView(
915                                label,
916                                "ChoiceCollection",
917                                new Object[] {
918                                    collection,
919                                    substance,
920                                    model,
921                                    memberView },
922                                context);
923    
924                    } else {
925    
926                        // LIST
927                        logger.debug("  isListView");
928                        ListModel model = new ListModel(collection, substance);
929                        view =
930                            factory.createView(
931                                label,
932                                "List",
933                                new Object[] {
934                                    collection,
935                                    substance,
936                                    model,
937                                    memberView },
938                                context);
939                    }
940    
941                    Integer height =
942                        (Integer) collection.getAttribute(GuiAC.VIEW_HEIGHT);
943                    Integer width =
944                        (Integer) collection.getAttribute(GuiAC.VIEW_WIDTH);
945                    if (height == null)
946                        height = new Integer(70);
947                    if (width == null)
948                        width = new Integer(500);
949                    view.setWidth(width.intValue());
950                    view.setHeight(height.intValue());
951                    container.addView(view);
952                }
953            } finally {
954                Collaboration.get().addAttribute(GuiAC.OPPOSITE_ROLE, null);
955                GuiAC.popGraphicContext();
956            }
957    
958            return container;
959        }
960    
961        /**
962         * Gets a composite panel containing a set of methods that are held
963         * by the substance object. */
964    
965        static protected CompositeView getMethodsPane(
966            ViewFactory factory,
967            DisplayContext context,
968            Object substance,
969            Collection methods,
970            String category,
971            ObjectView objectView) throws ViewFactory.UnhandledViewTypeException 
972        {
973            CompositeView methodpane =
974                factory.createCompositeView(
975                    "methods",
976                    "Container",
977                    new Object[] { new Integer(Constants.VERTICAL)},
978                    context);
979            methodpane.setStyle("methods");
980    
981            CompositeView subMP =
982                factory.createCompositeView(
983                    "methods0",
984                    "Container",
985                    new Object[] { new Integer(Constants.HORIZONTAL)},
986                    context);
987    
988            Iterator it = methods.iterator();
989            int i = 0;
990            int nbMethods = 0;
991    
992            while (it.hasNext()) {
993    
994                MethodItem curmeth = (MethodItem) it.next();
995                MemberItemView memberView =
996                    GuiAC.getView(curmeth, objectView.getName());
997    
998                logger.debug("handling method " + curmeth);
999    
1000                if (i == 3) {
1001                    methodpane.addView(subMP);
1002                    subMP =
1003                        factory.createCompositeView(
1004                            "methods" + i,
1005                            "Container",
1006                            new Object[] { new Integer(Constants.HORIZONTAL)},
1007                            context);
1008                    i = 0;
1009                }
1010    
1011                if (curmeth == null)
1012                    continue;
1013    
1014                if (!GuiAC.isMemberInCategory(curmeth, category)) {
1015                    logger.debug("category, skipping " + curmeth);
1016                    continue;
1017                }
1018    
1019                if (!GuiAC.isVisible(substance, curmeth)) {
1020                    logger.debug("invisible, skipping " + curmeth);
1021                    continue;
1022                }
1023    
1024                subMP.addView(
1025                    getMethodView(
1026                        curmeth,
1027                        substance,
1028                        context,
1029                        factory,
1030                        memberView));
1031                i++;
1032                nbMethods++;
1033            }
1034    
1035            if (nbMethods > 0) {
1036                methodpane.addView(subMP);
1037                return methodpane;
1038            } else {
1039                return null;
1040            }
1041        }
1042    
1043        /**
1044         * Build view for a method
1045         * @param method the method item to build a view for
1046         * @param substance the object the method shall be invoked on
1047         * @param context display context
1048         * @param factory a view factory
1049         * @return a MethodView
1050         */
1051        public static MethodView getMethodView(
1052            AbstractMethodItem method,
1053            Object substance,
1054            DisplayContext context,
1055            ViewFactory factory,
1056            MemberItemView memberView) 
1057        {
1058            String text = GuiAC.getLabel(method);
1059            if (method.getParameterTypes().length > 0) {
1060                text += "...";
1061            }
1062            MethodView methodView = null;
1063            if (memberView != null && memberView.isEmbedded()) {
1064                EditorContainer inputView =
1065                    (EditorContainer) factory.createView(
1066                        "parameters[" + method.getName() + "]",
1067                        "InputParameters",
1068                        new Object[] { method, substance, null },
1069                        context);
1070                methodView =
1071                    (MethodView) factory.createView(
1072                        text,
1073                        "EmbeddedMethod",
1074                        new Object[] { substance, method, inputView },
1075                        context);
1076            } else {
1077                methodView =
1078                    (MethodView) factory.createView(
1079                        text,
1080                        "Method",
1081                        new Object[] { substance, method },
1082                        context);
1083            }
1084            methodView.setIcon(GuiAC.getIcon(method));
1085            return methodView;
1086        }
1087    
1088        /**
1089         * <p>Create a view containing editor components for the parameters of
1090         * a method.</p>
1091         *
1092         * <p>Parameters of type
1093         * <code>org.objectweb.jac.aspects.gui.DisplayContext</code> are
1094         * not displayed.</p>
1095         *
1096         * <p>If method is a MixinMethodItem, the first parameter is at
1097         * index 1 of the parameters array.</p>
1098         *
1099         * @param factory the ViewFactory
1100         * @param context the DisplayContext
1101         * @param method the method whose parameters you the view of
1102         * @param substance the object on which the method will be
1103         * called. It used to get a default value if the method is a
1104         * setter.  
1105         * @param parameters 
1106         * @return a CompositeView containing an editor component for each
1107         * parameter of the method. The returned View implements the
1108         * EditorContainer interface 
1109         */
1110        static public View createParameters(
1111            ViewFactory factory,
1112            DisplayContext context,
1113            final AbstractMethodItem method,
1114            Object substance,
1115            Object[] parameters) 
1116        {
1117            logger.debug("createParameters(" + method.getLongName() + ")");
1118    
1119            CompositeView panel =
1120                factory.createCompositeView(
1121                    method.toString(),
1122                    "ParameterContainer",
1123                    new Object[] { Boolean.FALSE },
1124                    context);
1125    
1126            Class[] paramTypes = method.getParameterTypes();
1127            String[] paramNames = GuiAC.getParameterNames(method);
1128    
1129            for (int i=0; i<paramTypes.length; i++) 
1130            {
1131    
1132                if (paramTypes[i]==DisplayContext.class) 
1133                    continue;
1134    
1135                String paramName = null;
1136                if (paramNames != null && paramNames.length>i && paramNames[i] != null) {
1137                    paramName = paramNames[i];
1138                } else {
1139                    paramName = "arg" + i + " (" + paramTypes[i] + ")";
1140                }
1141    
1142                CompositeView container =
1143                    factory.createCompositeView(
1144                        method.toString(),
1145                        "Container",
1146                        new Object[] { new Integer(Constants.HORIZONTAL)},
1147                        context);
1148                container.addView(
1149                    factory.createView(
1150                        paramName + " : ",
1151                        "Label",
1152                        ExtArrays.emptyObjectArray,
1153                        context));
1154                //         ((Component)ve).setName( "arg" + i );
1155    
1156                try {
1157                    FieldEditor editor =
1158                        getEditorComponent(
1159                            factory,
1160                            context,
1161                            substance,
1162                            method,
1163                            i,
1164                            false,
1165                            parameters != null ? method.getParameter(parameters,i) : null);
1166                    ((EditorContainer) panel).addEditor(editor);
1167                    container.addView(editor);
1168                } catch (Exception e) {
1169                    logger.error(
1170                        "Failed to build editor component for "
1171                            + method + "[" + i + "]",e);
1172                }
1173    
1174                panel.addView(container);
1175            }
1176            return panel;
1177        }
1178    
1179        /**
1180         * Returns a ValueEditor suitable for editing the i-th parameter of
1181         * a method.
1182         *
1183         * @param factory the view factory
1184         * @param substance the substance object
1185         * @param method the method that contains the parameter
1186         * @param i the parameter index 
1187         * @param embedded wether the editor is an embedded field
1188         * editor. If true, the component will commit changes when it
1189         * looses the focus (only works for swing).
1190         * @param value the initial edited value. Used only if non null. 
1191         */
1192        public static FieldEditor getEditorComponent(
1193            ViewFactory factory,
1194            DisplayContext context,
1195            Object substance,
1196            AbstractMethodItem method,
1197            int i,
1198            boolean embedded,
1199            Object value) 
1200        {
1201            logger.debug("getEditorComponent " + method + "[" + i + "]");
1202            Class[] paramTypes = method.getParameterTypes();
1203            ClassRepository cr = ClassRepository.get();
1204            ClassItem paramType = cr.getClass(paramTypes[i]);
1205            String[] passwordParams =
1206                (String[]) method.getAttribute(GuiAC.PASSWORD_PARAMETERS);
1207            Object[] defaultValues =
1208                (Object[]) method.getAttribute(GuiAC.DEFAULT_VALUES);
1209            FieldItem[] parameterFields =
1210                (FieldItem[]) method.getAttribute(RttiAC.PARAMETERS_FIELDS);
1211            Object[] parameterChoices =
1212                (Object[]) method.getAttribute(GuiAC.PARAMETER_CHOICES);
1213            boolean[] editableChoices =
1214                (boolean[]) method.getAttribute(GuiAC.EDITABLE_CHOICES);
1215            MetaItem[] parametersType =
1216                (MetaItem[]) method.getAttribute(RttiAC.PARAMETER_TYPES);
1217            Enum[] enums = (Enum[]) method.getAttribute(GuiAC.PARAMETER_ENUMS);
1218            CollectionItem[] linkedColls =
1219                (CollectionItem[]) method.getAttribute(GuiAC.LINKED_PARAMETERS);
1220    
1221            FieldItem editedField = null;
1222            FieldItem parameterField = null;
1223    
1224            Object defaultValue = null;
1225            boolean defaultValueSet = false;
1226            if (defaultValues != null) {
1227                defaultValue = defaultValues[i];
1228                defaultValueSet = true;
1229            }
1230            if (value != null) {
1231                defaultValue = value;
1232                defaultValueSet = true;
1233            }
1234            Object choiceObject = null;
1235            Object[] choice = null;
1236            Enum enum = null;
1237            boolean editableChoice = false;
1238            // the most specific type of the edited value
1239            MetaItem type = null;
1240            // a stack of type of the edited value (most specific on top)
1241            Stack types = new Stack();
1242    
1243            if (parameterFields != null) {
1244                parameterField = parameterFields[i];
1245            }
1246            // if it's a set-method, get the default value from the field
1247            // as well as the editableChoice attribute
1248            editedField = ((MethodItem) method).getSetField();
1249            if (editedField != null) {
1250                editedField = cr.getActualField(substance,editedField);
1251                logger.debug("edited field = " + editedField);
1252                if (substance != null) {
1253                    defaultValue = editedField.getThroughAccessor(substance);
1254                    defaultValueSet = true;
1255                }
1256    
1257                Object[] def_value =
1258                    ((Object[]) editedField.getAttribute(GuiAC.DYN_DEFAULT_VALUE));
1259                if ((!RttiAC.isNullAllowed(editedField))
1260                    && (defaultValue == null)
1261                    && (def_value != null))
1262                    defaultValue =
1263                        ((MethodItem) def_value[0]).invokeStatic(
1264                            new Object[] { editedField, def_value[1] });
1265    
1266                choiceObject = editedField.getAttribute(GuiAC.FIELD_CHOICE);
1267                editableChoice = GuiAC.isEditableChoice(editedField);
1268                enum = (Enum) editedField.getAttribute(GuiAC.FIELD_ENUM);
1269                logger.debug(
1270                    "choiceObject = "+ choiceObject
1271                    + (editableChoice ? " editable" : ""));
1272                type = RttiAC.getFieldType(editedField,substance);
1273                if (type != null) {
1274                    logger.debug("adding rtti type = " + type);
1275                    if (!types.contains(type))
1276                        types.add(0, type);
1277                }
1278                if (type == null)
1279                    type = editedField.getTypeItem();
1280                if (editedField.getTypeItem() != null) {
1281                    logger.debug("adding type item = " + editedField.getTypeItem());
1282                    if (!types.contains(editedField.getTypeItem()))
1283                        types.add(0, editedField.getTypeItem());
1284                }
1285            }
1286    
1287            if (parameterField != null) {
1288                logger.debug("parameter field = " + parameterField);
1289    
1290                Object[] def_value =
1291                    ((Object[]) parameterField
1292                        .getAttribute(GuiAC.DYN_DEFAULT_VALUE));
1293                if ((!RttiAC.isNullAllowed(parameterField))
1294                    && (defaultValue == null)
1295                    && (def_value != null))
1296                    defaultValue =
1297                        ((MethodItem) def_value[0]).invokeStatic(
1298                            new Object[] { parameterField, def_value[1] });
1299    
1300                choiceObject = parameterField.getAttribute(GuiAC.FIELD_CHOICE);
1301                editableChoice = GuiAC.isEditableChoice(parameterField);
1302                enum = (Enum) parameterField.getAttribute(GuiAC.FIELD_ENUM);
1303                logger.debug("choiceObject = "
1304                        + choiceObject
1305                        + (editableChoice ? " editable" : ""));
1306                type = RttiAC.getFieldType(parameterField,substance);
1307                if (type != null) {
1308                    logger.debug("adding rtti type = " + type);
1309                    if (!types.contains(type))
1310                        types.add(0, type);
1311                }
1312                if (type == null)
1313                    type = parameterField.getTypeItem();
1314                if (parameterField.getTypeItem() != null) {
1315                    logger.debug("adding type item = " + parameterField.getTypeItem());
1316                    if (!types.contains(parameterField.getTypeItem()))
1317                        types.add(0, parameterField.getTypeItem());
1318                }
1319            }
1320    
1321            if (defaultValueSet && defaultValue != null) {
1322                if (type == null)
1323                    type = cr.getClass(defaultValue);
1324                if (!types.contains(cr.getClass(defaultValue)))
1325                    types.add(0, cr.getClass(defaultValue));
1326                logger.debug("adding default value type = "
1327                        + cr.getClass(defaultValue));
1328            }
1329            if (parametersType != null) {
1330                if (type == null && parametersType[i] instanceof ClassItem)
1331                    type = (ClassItem) parametersType[i];
1332                if (!types.contains(parametersType[i]))
1333                    types.add(0, parametersType[i]);
1334                logger.debug("adding rtti parameter type = " + parametersType[i]);
1335            }
1336            if (type == null)
1337                type = paramType;
1338            if (!types.contains(paramType))
1339                types.add(0, paramType);
1340            logger.debug("adding parameter type = "
1341                         + paramType);
1342    
1343            if (parameterField != null) {
1344                choiceObject = parameterField.getAttribute(GuiAC.FIELD_CHOICE);
1345            }
1346    
1347            if (enum == null && enums != null)
1348                enum = enums[i];
1349    
1350            logger.debug("types: " + types);
1351            logger.debug("type=" + type);
1352    
1353            if (parameterChoices != null) {
1354                choiceObject = parameterChoices[i];
1355            }
1356    
1357            boolean classChoice = false;
1358            if (choiceObject==null) {
1359                choiceObject = type.getAttribute(GuiAC.CLASS_CHOICES);
1360                logger.debug("classChoices="+choiceObject);
1361                classChoice = choiceObject!=null;
1362            }
1363    
1364            if (choiceObject != null) {
1365                if (choiceObject instanceof MethodItem) {
1366                    MethodItem choiceMethod = (MethodItem) choiceObject;
1367                    logger.debug("choiceMethod="+choiceMethod);
1368                    try {
1369                        if (classChoice) {
1370                            choiceObject = 
1371                                choiceMethod.invokeStatic(new Object[] {type});
1372                        } else {
1373                            if (choiceMethod.isStatic()) {
1374                                choiceObject =
1375                                    choiceMethod.invokeStatic(
1376                                        new Object[] { substance });
1377                            } else {
1378                                choiceObject =
1379                                    choiceMethod.invoke(
1380                                        substance, 
1381                                        ExtArrays.emptyObjectArray);
1382                            }
1383                        }
1384                        logger.debug("choiceMethod returned "+choiceObject);
1385                    } catch (Exception e) {
1386                        logger.error(
1387                            "Invocation of choice "+choiceMethod+" method failed",e);
1388                    }
1389                }
1390                if (choiceObject instanceof Object[]) {
1391                    choice = (Object[]) choiceObject;
1392                } else if (
1393                    choiceObject.getClass().isArray()
1394                        && choiceObject.getClass().getComponentType().isPrimitive()) {
1395                    choice = Classes.convertPrimitiveArray(choiceObject);
1396                } else if (choiceObject instanceof Collection) {
1397                    choice = ((Collection) choiceObject).toArray();
1398                }
1399            }
1400    
1401            FieldEditor editor = null;
1402            String editorName =
1403                "editor " + Naming.getName(substance) + "." + 
1404                method.getName() + "[" + i + "]";
1405    
1406            boolean nullAllowed = false;
1407            if (editedField == null) {
1408                nullAllowed = RttiAC.isNullAllowedParameter(method, i);
1409            } else {
1410                nullAllowed = RttiAC.isNullAllowed(editedField);
1411            }
1412    
1413            if (linkedColls != null && linkedColls[i] != null) {
1414    
1415                ComboBoxModel model = new ComboBoxModel(linkedColls[i], substance);
1416    
1417                editor =
1418                    factory.createEditor(
1419                        editorName,
1420                        "ObjectChooser",
1421                        new Object[] {
1422                            substance,
1423                            editedField,
1424                            model,
1425                            Boolean.FALSE },
1426                        context);
1427    
1428            } else if (choice != null) {
1429                if (editableChoices != null) {
1430                    editableChoice = editableChoices[i];
1431                }
1432                ComboBoxModel model = new ComboBoxModel();
1433                for (int j = 0; j < choice.length; j++) {
1434                    if (enum != null)
1435                        model.addObject(
1436                            choice[j],
1437                            enum.int2string(((Integer) choice[j]).intValue()));
1438                    else
1439                        model.addObject(choice[j]);
1440                }
1441                if (nullAllowed)
1442                    model.addObject(null);
1443                if (type instanceof ClassItem)
1444                    model.setType((ClassItem) type);
1445                model.sort();
1446    
1447                editor =
1448                    factory.createEditor(
1449                        editorName,
1450                        "ObjectChooser",
1451                        new Object[] {
1452                            substance,
1453                            editedField,
1454                            model,
1455                            ExtBoolean.valueOf(editableChoice)},
1456                        context);
1457            } else if (enum != null) {
1458                ComboBoxModel model = new ComboBoxModel();
1459                Iterator it = enum.getValues().iterator();
1460                while (it.hasNext()) {
1461                    String str = (String) it.next();
1462                    model.addObject(new Integer(enum.string2int(str)), str);
1463                }
1464    
1465                editor =
1466                    factory.createEditor(
1467                        editorName,
1468                        "ObjectChooser",
1469                        new Object[] {
1470                            substance,
1471                            editedField,
1472                            model,
1473                            Boolean.FALSE },
1474                        context);
1475    
1476            } else if (
1477                !factory.hasViewerFor(
1478                    "editor:" + ((MetaItem) types.peek()).getName())
1479                    && (Wrappee.class.isAssignableFrom(paramTypes[i])
1480                        || paramTypes[i] == Object.class)) {
1481                // jac objects
1482                ClassItem collectionType = null;
1483                if (types.size() > 0)
1484                    collectionType = (ClassItem) types.peek();
1485                else
1486                    collectionType = paramType;
1487                Predicate predicate = null;
1488                if (method instanceof MethodItem) {
1489                    CollectionItem[] collections =
1490                        ((MethodItem) method).getAddedCollections();
1491                    if (collections != null && collections.length > 0) {
1492                        predicate =
1493                            new NotInCollectionPredicate(
1494                                (Collection) collections[0].getThroughAccessor(
1495                                    substance));
1496                    }
1497                }
1498                editor =
1499                    createReferenceEditor(
1500                        factory,
1501                        context,
1502                        substance,
1503                        editedField,
1504                        editorName,
1505                        collectionType,
1506                        predicate,
1507                        nullAllowed,null,
1508                        GuiAC.isCreationAllowedParameter(method, i));
1509                /*
1510            } else if (paramTypes[i].isArray()
1511                       || Collection.class.isAssignableFrom(paramTypes[i])) {
1512                */
1513                // array and collections
1514                //         editor = new ArrayEditor(paramTypes[i]);
1515            } else {
1516    
1517                boolean isPassword =
1518                    passwordParams != null && passwordParams[i].equals("true");
1519    
1520                Vector tried_types = new Vector();
1521                Stack viewerTypes = new Stack();
1522                while (!types.empty() && editor == null) {
1523                    String typeName = ((MetaItem)types.pop()).getName();
1524                    viewerTypes.add(0, typeName);
1525                    typeName = "editor:" + typeName;
1526                    tried_types.add(typeName);
1527                    logger.debug("Trying " + typeName);
1528                    if (factory.hasViewerFor(typeName) && !isPassword) {
1529                        logger.debug("Factory has viewer for " + typeName);
1530                        editor =
1531                            (FieldEditor) factory.createView(
1532                                editorName,
1533                                typeName,
1534                                new Object[] { substance, editedField },
1535                                context);
1536                    }
1537                }
1538                if (editor == null) {
1539                    if (!isPassword)
1540                        logger.error(
1541                            "Could not find an editor component for any of the type "
1542                            + tried_types);
1543                    editor =
1544                        factory.createEditor(
1545                            editorName,
1546                            "PrimitiveTypeEditor",
1547                            new Object[] {
1548                                substance,
1549                                editedField,
1550                                ExtBoolean.valueOf(isPassword)},
1551                            context);
1552                }
1553            }
1554    
1555            //if( fieldEditor != null && ve!=null ) {
1556            //   System.out.println("added focus listener for "+ve);
1557            //   System.out.println("--- Listener is: "+fieldEditor);
1558            //   ve.getValueComponent().addFocusListener(fieldEditor);
1559            //((Component)ve).addFocusListener(fieldEditor);
1560            //   }
1561    
1562            if (defaultValueSet) {
1563                logger.debug("setting default value for "
1564                        + method.getName() + " : " + defaultValue);
1565                editor.setValue(defaultValue);
1566            }
1567    
1568            editor.setEmbedded(embedded);
1569    
1570            logger.debug("type = " + type);
1571            logger.debug("types = " + types);
1572            int width = GuiAC.getEditorColumns(type);
1573            if (width != 0)
1574                editor.setWidth(width);
1575            if (parameterField == null) {
1576                parameterField = editedField;
1577            }
1578            if (parameterField != null) {
1579                width = GuiAC.getEditorCols(parameterField);
1580                if (width != 0)
1581                    editor.setWidth(width);
1582            } else {
1583                editor.setWidth(15);
1584            }
1585    
1586            int height = GuiAC.getEditorRows(type);
1587            if (height != 0)
1588                editor.setHeight(height);
1589            if (parameterField != null) {
1590                height = GuiAC.getEditorRows(parameterField);
1591                if (height != 0)
1592                    editor.setHeight(height);
1593            } else {
1594                editor.setHeight(10);
1595            }
1596    
1597            int[] cols = GuiAC.getMethodParametersCols(method);
1598            if (cols != null) {
1599                editor.setWidth(cols[i]);
1600            }
1601            int[] rows = GuiAC.getMethodParametersRows(method);
1602            if (rows != null) {
1603                editor.setHeight(rows[i]);
1604            }
1605    
1606            logger.debug("editedType = "+type);
1607            if (type instanceof ClassItem) {
1608                editor.setEditedType((ClassItem)type);
1609            } else if (type instanceof VirtualClassItem) {
1610                if (editedField!=null) 
1611                    editor.setEditedType(editedField.getTypeItem());
1612                else
1613                    editor.setEditedType(paramType);
1614            }
1615            return editor;
1616    
1617        }
1618    
1619        /**
1620         * Initialize the panels of a customized gui.
1621         *
1622         * @param factory the view factory
1623         * @param context the display context
1624         * @param internalView the CompositeView which holds the panels
1625         * @param customized the CustomizedGUI
1626         * @param panels if not null, overrides the content of panels
1627         * (panelID -> PanelContent)
1628         */
1629        public static void initCustomized(
1630            ViewFactory factory,
1631            DisplayContext context,
1632            CompositeView internalView,
1633            CustomizedGUI customized,
1634            Map panels) 
1635        {
1636            logger.debug("initCustomized...");
1637            // open the views on the objects in the right subpanes
1638            if (panels == null)
1639                panels = customized.getPaneContents();
1640            for (Iterator it = panels.keySet().iterator(); it.hasNext();) {
1641                String paneId = (String) it.next();
1642                PanelContent panel = (PanelContent) panels.get(paneId);
1643                logger.debug("init pane " + paneId + " -> " + panel);
1644                try {
1645                    View view =
1646                        factory.createView(
1647                            paneId,
1648                            panel.getType(),
1649                            panel.getArgs(),
1650                            context);
1651                    internalView.addView(view, paneId);
1652                } catch (Exception e) {
1653                    logger.error(
1654                        "Failed to build content for pane \""
1655                            + paneId + "\"",e);
1656                }
1657                logger.debug("init pane " + paneId + " DONE");
1658            }
1659            logger.debug("initCustomized DONE");
1660        }
1661    
1662        /**
1663         * Sets a status bar to a customized view.
1664         *
1665         * @param factory the used factory
1666         * @param context the passed context
1667         * @param view the customized that will hold the status bar
1668         * @param statusBar the method item that defines the text to print within the status bar
1669         * @param position the position
1670         * (<code>Constants.TOP||Constants.BOTTOM</code>) */
1671    
1672        public static void setStatusBar(
1673            ViewFactory factory,
1674            DisplayContext context,
1675            CustomizedView view,
1676            MethodItem statusBar,
1677            String position) 
1678        {
1679            logger.debug("setStatusbar(" + statusBar + ")");
1680            StatusView statusView =
1681                (StatusView) factory.createView(
1682                    "StatusBar",
1683                    "StatusBar",
1684                    new Object[] { statusBar },
1685                    context);
1686            view.setStatusBar(statusView, position);
1687        }
1688    
1689        /**
1690         * Build the menu bar of a customized gui.
1691         *
1692         * @param factory the view factory
1693         * @param context the display context
1694         * @param view the CustomizedView where to put the menu bar
1695         * @param menuBars the menuBars
1696         */
1697        public static void setMenuBars(
1698            ViewFactory factory,
1699            DisplayContext context,
1700            CustomizedView view,
1701            Hashtable menuBars) 
1702        {
1703            logger.debug("setMenuBars(" + menuBars + ")");
1704            Menu menus;
1705            Iterator it = menuBars.values().iterator();
1706            while (it.hasNext()) {
1707                menus = (Menu) it.next();
1708                MenuView menuBar =
1709                    (MenuView) factory.createView("MenuBar", "MenuBar", context);
1710                menuBar.setPosition(menus.getPosition());
1711                Iterator i = menus.getKeys().iterator();
1712                while (i.hasNext()) {
1713                    String key = (String) i.next();
1714                    logger.debug("createMenu " + key);
1715                    Object item = menus.get(key);
1716                    if (item instanceof Menu) {
1717                        Menu subMenu = (Menu) item;
1718                        menuBar.addSubMenu(
1719                            key,
1720                            subMenu.getIcon(),
1721                            createMenu(factory, context, key, subMenu));
1722                    } else {
1723                        if (key == null) {
1724                            menuBar.addSeparator();
1725                        } else {
1726                            Callback callback = (Callback) item;
1727                            if (GuiAC.isVisible(callback.getMethod())) {
1728                                menuBar.addAction(
1729                                    key,
1730                                    callback.getMethod() != null
1731                                        ? GuiAC.getIcon(callback.getMethod())
1732                                        : null,
1733                                    callback);
1734                            }
1735                        }
1736                    }
1737                }
1738                view.setMenuBar(menuBar, menus.getPosition());
1739            }
1740        }
1741    
1742        /**
1743         * Creates a menu in a a customized gui.
1744         *
1745         * @param factory the view factory
1746         * @param context the display context
1747         * @param content the content of the menu view
1748         */
1749    
1750        public static MenuView createMenu(
1751            ViewFactory factory,
1752            DisplayContext context,
1753            String label,
1754            Menu content) 
1755        {
1756            MenuView menu = (MenuView) factory.createView(label, "Menu", context);
1757            Iterator i = content.getKeys().iterator();
1758            while (i.hasNext()) {
1759                String key = (String) i.next();
1760                if (key == null) {
1761                    menu.addSeparator();
1762                } else {
1763                    Object value = content.get(key);
1764                    if (value instanceof Menu) {
1765                        // submenu
1766                        MenuView subMenu =
1767                            createMenu(factory, context, key, (Menu)value);
1768                        menu.addSubMenu(key, ((Menu) value).getIcon(), subMenu);
1769                    } else {
1770                        // action or separator
1771                        logger.debug("menu action: " + key + "->" + value);
1772                        if (key == null) {
1773                            menu.addSeparator();
1774                        } else {
1775                            Callback callback = (Callback) value;
1776                            if (callback.getMethod() == null
1777                                || GuiAC.isVisible(callback.getMethod())) 
1778                            {
1779                                menu.addAction(
1780                                    key, 
1781                                    GuiAC.getIcon(callback), 
1782                                    callback);
1783                            }
1784                        }
1785                    }
1786                }
1787            }
1788            return menu;
1789        }
1790    
1791        /**
1792         * Build the toolbar of a customized gui.
1793         *
1794         * @param factory the view factory
1795         * @param context the display context
1796         * @param view the CustomizedView where to put the menu bar
1797         * @param toolbar the toolbar definition
1798         */
1799        public static void setToolBar(
1800            ViewFactory factory,
1801            DisplayContext context,
1802            CustomizedView view,
1803            Collection toolbar) 
1804        {
1805            logger.debug("setToolbar(" + toolbar + ")");
1806            MenuView toolbarView =
1807                (MenuView) factory.createView("ToolBar", "ToolBar", context);
1808            Iterator i = toolbar.iterator();
1809            while (i.hasNext()) {
1810                Callback callback = (Callback) i.next();
1811                logger.debug("createButton " + callback);
1812                if (callback != null) {
1813                    toolbarView.addAction(
1814                        GuiAC.getLabel(callback.method),
1815                        GuiAC.getIcon(callback.method),
1816                        callback);
1817                } else {
1818                    toolbarView.addSeparator();
1819                }
1820            }
1821            view.setToolBar(toolbarView);
1822        }
1823    
1824        /**
1825         * Builds a dialog box to enter the parameters of method
1826         *
1827         * @param substance object the method will be invoked on
1828         * @param method the method
1829         * @param parameters an array where to store the value enteres by the user
1830         * @param context a display context
1831         *
1832         * @see #createParameters(ViewFactory,DisplayContext,AbstractMethodItem,Object,Object[])
1833         */
1834        public static DialogView createInputDialog(
1835            Object substance,
1836            AbstractMethodItem method,
1837            Object[] parameters,
1838            DisplayContext context) 
1839        {
1840            ViewFactory factory = context.getDisplay().getFactory();
1841            EditorContainer inputView =
1842                (EditorContainer) factory.createView(
1843                    "parameters",
1844                    "InputParameters",
1845                    new Object[] { method, substance, parameters },
1846                    context);
1847            String description = (String) method.getAttribute(GuiAC.DESCRIPTION);
1848            String title = GuiAC.getLabel(method);
1849            DialogView dialog =
1850                (DialogView) factory.createView(
1851                    method.getName(),
1852                    "Dialog",
1853                    new Object[] { inputView, null, title, description },
1854                    context);
1855            dialog.setLabel(GuiAC.getLabel(method));
1856            return dialog;
1857        }
1858    
1859        /**
1860         * A generic view builder for a reference editor. Returns a combox
1861         * box or a text input depending on the field's configuration
1862         *
1863         * @param factory
1864         * @param context
1865         * @param substance the object holding the field
1866         * @param field the field to build an editor for (may be null)
1867         * @param editorName the name of the editor to build
1868         * @param type the type of the objects to choose from
1869         * @param predicate a predicate used to filter proposed objects in
1870         * the case of a combobox.
1871         * @param nullAllowed wether the user is authorised to select the null value
1872         * @param isCreationAllowed wether the user is authorised to create
1873         * new instances of type
1874         *
1875         * @see org.objectweb.jac.aspects.gui.ClassAppearenceGuiConf#selectWithIndexedField(ClassItem,CollectionItem,String) 
1876         */
1877        public static FieldEditor createReferenceEditor(
1878            ViewFactory factory,
1879            DisplayContext context,
1880            Object substance,
1881            FieldItem field,
1882            String editorName,
1883            ClassItem type,
1884            Predicate predicate,
1885            boolean nullAllowed,
1886            String nullLabel,
1887            boolean isCreationAllowed) 
1888        {
1889            logger.debug("createReferenceEditor isCreationAllowed="+isCreationAllowed);
1890            CollectionItem index =
1891                (CollectionItem) type.getAttribute(GuiAC.INDEXED_FIELD_SELECTOR);
1892            if (index != null) {
1893                return factory.createEditor(
1894                    editorName,
1895                    "IndexSelector",
1896                    new Object[] {
1897                        substance,
1898                        field,
1899                        index,
1900                        GuiAC.getRepository(type),
1901                        ExtBoolean.valueOf(isCreationAllowed),
1902                        type.getAttribute(GuiAC.INDEX_NOT_FOUND_HANDLER)},
1903                    context);
1904            } else {
1905                ComboBoxModel model = new ComboBoxModel();
1906                addChoices(model, type, null, substance, field, 
1907                           nullAllowed, nullLabel, predicate);
1908                return factory.createEditor(
1909                    editorName,
1910                    "ObjectChooser",
1911                    new Object[] {
1912                        substance,
1913                        field,
1914                        model,
1915                        ExtBoolean.valueOf(isCreationAllowed)},
1916                    context);
1917            }
1918        }
1919    
1920        public static FieldEditor createEnumEditor(
1921            ViewFactory factory,
1922            DisplayContext context,
1923            Object substance,
1924            FieldItem field,
1925            String editorName,
1926            Enum enum,
1927            boolean nullAllowed,
1928            String nullLabel) 
1929        {
1930            ComboBoxModel model = new ComboBoxModel();
1931            ClassItem type = ClassRepository.get().getClass("java.lang.Integer");
1932            addChoices(model, type, enum, substance, field, 
1933                       nullAllowed, nullLabel, null);
1934            return factory.createEditor(
1935                editorName,
1936                "ObjectChooser",
1937                new Object[] {
1938                    substance,
1939                    field,
1940                    model,
1941                    Boolean.FALSE},
1942                context);
1943        }
1944    }