001    /*
002     * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
003     * Copyright (C) 2000-2011 The Gridarta Developers.
004     *
005     * This program is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation; either version 2 of the License, or
008     * (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License along
016     * with this program; if not, write to the Free Software Foundation, Inc.,
017     * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
018     */
019    
020    package net.sf.gridarta.gui.dialog.gameobjectattributes;
021    
022    import java.awt.event.ItemEvent;
023    import java.awt.event.ItemListener;
024    import java.util.ArrayList;
025    import java.util.Collection;
026    import javax.swing.JComboBox;
027    import javax.swing.JOptionPane;
028    import net.sf.gridarta.model.archetype.Archetype;
029    import net.sf.gridarta.model.archetypetype.ArchetypeType;
030    import net.sf.gridarta.model.archetypetype.ArchetypeTypeSet;
031    import net.sf.gridarta.model.baseobject.BaseObject;
032    import net.sf.gridarta.model.gameobject.GameObject;
033    import net.sf.gridarta.model.maparchobject.MapArchObject;
034    import net.sf.gridarta.model.mapmodel.MapModel;
035    import org.jetbrains.annotations.NotNull;
036    import org.jetbrains.annotations.Nullable;
037    
038    /**
039     * ItemListener for the type-selection box on the attribute-dialog.
040     * @author <a href="mailto:cher@riedquat.de">Christian Hujer</a>
041     * @author Andreas Kirschbaum
042     */
043    public class TypesBoxItemListener<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements ItemListener {
044    
045        /**
046         * The attribute dialog main frame.
047         */
048        @NotNull
049        private final GameObjectAttributesDialog<G, A, R> gameObjectAttributesDialog;
050    
051        /**
052         * The game object which has the error to be added.
053         */
054        @NotNull
055        private final GameObject<G, A, R> gameObject;
056    
057        /**
058         * The {@link ArchetypeTypeSet} to display.
059         */
060        @NotNull
061        private final ArchetypeTypeSet archetypeTypeSet;
062    
063        /**
064         * The {@link DialogAttribute DialogAttributes} to update.
065         */
066        @NotNull
067        private final Collection<DialogAttribute<G, A, R, ?>> dialogAttributes;
068    
069        /**
070         * The selection box for the type.
071         */
072        @NotNull
073        private final JComboBox typeComboBox;
074    
075        /**
076         * Reference to the type data.
077         * @serial
078         */
079        @NotNull
080        private ArchetypeType archetypeType;
081    
082        /**
083         * The latest deselected item.
084         */
085        @Nullable
086        private String deselected;
087    
088        /**
089         * While <code>true</code>, this listener ignores all events.
090         */
091        private boolean ignoreEvent;
092    
093        /**
094         * The position of this type in the type list. This differs from the
095         * GameObject if the type is undefined.
096         * @serial
097         */
098        private int type;
099    
100        /**
101         * Creates a new instance.
102         * @param frameNew the attribute dialog main frame
103         * @param gameObject the game object which has the error to be added
104         * @param type the initially selected type
105         * @param archetypeTypeSet the archetype type set to display
106         * @param dialogAttributes the dialog attributes to update
107         * @param typeComboBox the selection box for the type
108         * @param archetypeType the references to the data type
109         */
110        public TypesBoxItemListener(@NotNull final GameObjectAttributesDialog<G, A, R> frameNew, @NotNull final GameObject<G, A, R> gameObject, final int type, @NotNull final ArchetypeTypeSet archetypeTypeSet, @NotNull final Collection<DialogAttribute<G, A, R, ?>> dialogAttributes, @NotNull final JComboBox typeComboBox, @NotNull final ArchetypeType archetypeType) {
111            gameObjectAttributesDialog = frameNew;
112            this.gameObject = gameObject;
113            this.type = type;
114            this.archetypeTypeSet = archetypeTypeSet;
115            this.dialogAttributes = new ArrayList<DialogAttribute<G, A, R, ?>>(dialogAttributes);
116            this.typeComboBox = typeComboBox;
117            this.archetypeType = archetypeType;
118            ignoreEvent = false;
119        }
120    
121        /**
122         * {@inheritDoc}
123         */
124        @Override
125        public void itemStateChanged(final ItemEvent e) {
126            if (ignoreEvent) {
127                return;
128            }
129    
130            if (e.getStateChange() == ItemEvent.DESELECTED) {
131                deselected = ((String) e.getItem()).trim();
132            } else if (e.getStateChange() == ItemEvent.SELECTED && !e.getItem().equals(deselected)) {
133                final ArchetypeType newType = archetypeTypeSet.getArchetypeTypeByName((String) e.getItem());
134    
135                typeComboBox.hidePopup();
136                gameObjectAttributesDialog.update(gameObjectAttributesDialog.getGraphics());
137    
138                if (deselected == null) {
139                    deselected = archetypeType.getTypeName();
140                }
141                if (JOptionPane.showConfirmDialog(gameObjectAttributesDialog, "Do you really want to change the type of this\n" + "object from \"" + deselected + "\" to \"" + newType.getTypeName() + "\"?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION) {
142                    archetypeType = newType;
143    
144                    final MapModel<G, A, R> mapModel = gameObject.getMapSquare().getMapModel();
145                    mapModel.beginTransaction("change type to " + newType.getTypeName());
146                    try {
147                        gameObject.setAttributeInt(BaseObject.TYPE, newType.getTypeNo());
148                    } finally {
149                        mapModel.endTransaction();
150                    }
151                    dialogAttributes.clear();
152    
153                    type = typeComboBox.getSelectedIndex();
154    
155                    gameObjectAttributesDialog.buildAttribute();
156                    gameObjectAttributesDialog.update(gameObjectAttributesDialog.getGraphics());
157                } else {
158                    ignoreEvent = true;
159                    typeComboBox.setSelectedIndex(type);
160                    ignoreEvent = false;
161                }
162            }
163        }
164    
165        /**
166         * Returns a reference to the type data.
167         * @return the reference
168         */
169        @NotNull
170        public ArchetypeType getArchetypeType() {
171            return archetypeType;
172        }
173    
174    }