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
020package net.sf.gridarta.gui.dialog.plugin.parameter;
021
022import java.awt.Color;
023import java.awt.Component;
024import java.awt.Container;
025import java.awt.Dimension;
026import java.awt.FlowLayout;
027import java.awt.GridBagConstraints;
028import java.awt.GridBagLayout;
029import java.awt.event.ActionEvent;
030import java.awt.event.ActionListener;
031import java.awt.event.MouseEvent;
032import java.awt.event.MouseListener;
033import javax.swing.AbstractButton;
034import javax.swing.ComboBoxEditor;
035import javax.swing.JButton;
036import javax.swing.JLabel;
037import javax.swing.JPanel;
038import javax.swing.JPopupMenu;
039import javax.swing.JTextField;
040import javax.swing.border.LineBorder;
041import javax.swing.event.DocumentEvent;
042import javax.swing.event.DocumentListener;
043import javax.swing.text.JTextComponent;
044import net.sf.gridarta.gui.panel.gameobjectattributes.GameObjectAttributesModel;
045import net.sf.gridarta.gui.panel.objectchooser.ObjectChooser;
046import net.sf.gridarta.model.archetype.Archetype;
047import net.sf.gridarta.model.baseobject.BaseObject;
048import net.sf.gridarta.model.face.FaceObjectProviders;
049import net.sf.gridarta.model.gameobject.GameObject;
050import net.sf.gridarta.model.maparchobject.MapArchObject;
051import net.sf.gridarta.utils.CommonConstants;
052import org.jetbrains.annotations.NotNull;
053import org.jetbrains.annotations.Nullable;
054
055public class ArchComboBoxEditor<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements ComboBoxEditor {
056
057    private final ArchComboBox<G, A, R> archComboBox;
058
059    private final ArchComboBoxModel<G, A, R> archComboBoxModel;
060
061    private final ObjectChooser<G, A, R> objectChooser;
062
063    private final GameObjectAttributesModel<G, A, R> gameObjectAttributesModel;
064
065    private Container editorPanel;
066
067    private JLabel icon;
068
069    private JTextComponent editor;
070
071    private JPopupMenu popup;
072
073    private volatile boolean locked;
074
075    /**
076     * The {@link FaceObjectProviders} for looking up faces.
077     */
078    @NotNull
079    private final FaceObjectProviders faceObjectProviders;
080
081    /**
082     * Creates a new instance.
083     * @param faceObjectProviders the face object providers for looking up
084     * faces
085     */
086    public ArchComboBoxEditor(final ArchComboBox<G, A, R> archComboBox, final ArchComboBoxModel<G, A, R> archComboBoxModel, final ObjectChooser<G, A, R> objectChooser, final GameObjectAttributesModel<G, A, R> gameObjectAttributesModel, @NotNull final FaceObjectProviders faceObjectProviders) {
087        this.archComboBox = archComboBox;
088        this.archComboBoxModel = archComboBoxModel;
089        this.objectChooser = objectChooser;
090        this.gameObjectAttributesModel = gameObjectAttributesModel;
091        this.faceObjectProviders = faceObjectProviders;
092    }
093
094    public void lockEditor() {
095        locked = true;
096    }
097
098    public void unlockEditor() {
099        locked = false;
100    }
101
102    private synchronized void buildPanel() {
103        if (editorPanel == null) {
104            editorPanel = new JPanel(new GridBagLayout());
105            final GridBagConstraints gbc = new GridBagConstraints();
106            gbc.gridx = 0;
107            gbc.gridy = 0;
108            gbc.weightx = 1.0;
109            gbc.gridwidth = 4;
110            gbc.fill = GridBagConstraints.HORIZONTAL;
111            editor = new JTextField();
112            editorPanel.add(editor, gbc);
113            gbc.gridy = 1;
114            gbc.gridwidth = 1;
115            gbc.weightx = 0.0;
116            gbc.gridx = 1;
117            final AbstractButton fromSelect = new JButton("From tile selection");
118            fromSelect.addActionListener(new ActionListener() {
119
120                @Override
121                public void actionPerformed(final ActionEvent e) {
122                    final BaseObject<G, A, R, ?> gameObject = objectChooser.getSelection();
123                    if (gameObject != null) {
124                        final Archetype<G, A, R> ao = archComboBoxModel.getNearestMatch(gameObject.getArchetype().getArchetypeName());
125                        archComboBox.setSelectedItem(ao);
126                        setItem(ao);
127                    }
128                }
129            });
130            editorPanel.add(fromSelect, gbc);
131            final AbstractButton fromActive = new JButton("From map selection");
132            fromActive.addActionListener(new ActionListener() {
133
134                @Override
135                public void actionPerformed(final ActionEvent e) {
136                    final BaseObject<G, A, R, ?> gameObject = gameObjectAttributesModel.getSelectedGameObject();
137                    if (gameObject != null) {
138                        final Archetype<G, A, R> ao = archComboBoxModel.getNearestMatch(gameObject.getArchetype().getArchetypeName());
139                        archComboBox.setSelectedItem(ao);
140                        setItem(ao);
141                    }
142                }
143            });
144            gbc.gridx = 2;
145            editorPanel.add(fromActive, gbc);
146            editor.addMouseListener(new MouseListener() {
147
148                @Override
149                public void mouseClicked(final MouseEvent e) {
150                }
151
152                @Override
153                public void mouseEntered(final MouseEvent e) {
154                    //popup.setLocation(p.x, p.y+archComboBoxEditor.getHeight()+5);
155                    popup.setPreferredSize(null);
156                    final Dimension d = popup.getPreferredSize();
157                    final Dimension p = editorPanel.getSize();
158                    if (d.width < p.width) {
159                        d.width = p.width;
160                    }
161                    if (d.height < p.height) {
162                        d.height = p.height;
163                    }
164                    popup.setPreferredSize(d);
165                    popup.show(editorPanel, 0, editorPanel.getHeight() + 5);
166                }
167
168                @Override
169                public void mouseExited(final MouseEvent e) {
170                    popup.setVisible(false);
171                }
172
173                @Override
174                public void mousePressed(final MouseEvent e) {
175                }
176
177                @Override
178                public void mouseReleased(final MouseEvent e) {
179                }
180            });
181            editor.setEditable(true);
182            editor.getDocument().addDocumentListener(new DocumentListener() {
183
184                @Override
185                public void changedUpdate(final DocumentEvent e) {
186                    archComboBox.editorEntryChange();
187                }
188
189                @Override
190                public void insertUpdate(final DocumentEvent e) {
191                    archComboBox.editorEntryChange();
192                }
193
194                @Override
195                public void removeUpdate(final DocumentEvent e) {
196                    archComboBox.editorEntryChange();
197                }
198            });
199            icon = new JLabel();
200            popup = new JPopupMenu();
201            popup.setLayout(new FlowLayout());
202            popup.setBackground(CommonConstants.BG_COLOR);
203            popup.setBorder(new LineBorder(Color.black));
204            popup.add(icon);
205            popup.setFocusable(false);
206            archComboBox.setBackground(CommonConstants.BG_COLOR);
207        }
208    }
209
210    @Override
211    public void selectAll() {
212        // TODO Auto-generated method stub
213
214    }
215
216    @Override
217    public Component getEditorComponent() {
218        if (editorPanel == null) {
219            buildPanel();
220        }
221        return editorPanel;
222    }
223
224    @Override
225    public void addActionListener(final ActionListener l) {
226        // TODO Auto-generated method stub
227
228    }
229
230    @Override
231    public void removeActionListener(final ActionListener l) {
232        // TODO Auto-generated method stub
233
234    }
235
236    @Nullable
237    @Override
238    public Object getItem() {
239        // TODO Auto-generated method stub
240        return null;
241    }
242
243    @Override
244    public void setItem(final Object anObject) {
245        final BaseObject<?, ?, ?, ?> arch = (BaseObject<?, ?, ?, ?>) anObject;
246        if (anObject == null) {
247            icon.setIcon(null);
248            icon.setText("No item selected");
249        } else {
250            icon.setIcon(faceObjectProviders.getFace(arch));
251        }
252
253        if (arch == null) {
254            icon.setText("");
255            if (!locked) {
256                editor.setText("");
257            }
258        } else {
259            if (!locked) {
260                editor.setText(arch.getArchetype().getArchetypeName());
261            }
262            icon.setText(arch.getArchetype().getArchetypeName());
263        }
264    }
265
266    public JTextComponent getEditor() {
267        return editor;
268    }
269
270}