Gridarta Editor
FaceTab.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.gui.panel.gameobjectattributes;
21 
22 import java.awt.Component;
23 import java.awt.Container;
24 import java.awt.GridBagConstraints;
25 import java.awt.GridBagLayout;
26 import javax.swing.AbstractButton;
27 import javax.swing.ImageIcon;
28 import javax.swing.JCheckBox;
29 import javax.swing.JComponent;
30 import javax.swing.JPanel;
31 import javax.swing.JTextField;
32 import javax.swing.border.TitledBorder;
33 import javax.swing.text.JTextComponent;
49 import net.sf.japi.swing.action.ActionBuilder;
50 import net.sf.japi.swing.action.ActionBuilderFactory;
51 import org.jetbrains.annotations.NotNull;
52 import org.jetbrains.annotations.Nullable;
53 
59 public class FaceTab<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends AbstractGameObjectAttributesTab<G, A, R> {
60 
64  @NotNull
65  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta");
66 
70  @NotNull
72 
76  @NotNull
78 
82  @NotNull
84 
88  @NotNull
90 
94  @NotNull
95  private final AbstractButton animatedCheckBox = new JCheckBox(ActionBuilderUtils.getString(ACTION_BUILDER, "faceIsAnimated"));
96 
100  @NotNull
101  private final JTextComponent animSpeedTextField = new JTextField();
102 
106  @NotNull
107  private final JPanel panel = new JPanel();
108 
113  @NotNull
115 
119  private static final long serialVersionUID = 1L;
120 
121  @Override
122  protected void direction(@Nullable final Integer direction) {
123  final int dir = direction == null ? 0 : direction;
124  final GameObject<?, ?, ?> gameObject = getSelectedGameObject();
125  if (gameObject != null) {
126  final MapSquare<?, ?, ?> mapSquare = gameObject.getMapSquare();
127  if (mapSquare != null) {
128  final MapModel<?, ?, ?> mapModel = mapSquare.getMapModel();
129  mapModel.beginTransaction("Change object attributes");
130  try {
131  gameObject.setAttributeInt(BaseObject.DIRECTION, dir);
132  } finally {
133  mapModel.endTransaction();
134  }
135  }
136  }
137  }
138 
139  };
140 
144  @NotNull
145  private String defaultFaceComponentValue = "";
146 
150  @NotNull
151  private String defaultAnimComponentValue = "";
152 
157 
161  @NotNull
162  private String defaultAnimSpeedTextFieldValue = "";
163 
173  public FaceTab(@NotNull final GameObjectAttributesModel<G, A, R> gameObjectAttributesModel, @NotNull final FaceObjects faceObjects, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects, @NotNull final ImageIcon noFaceSquareIcon, @NotNull final ImageIcon unknownSquareIcon) {
174  super(gameObjectAttributesModel);
175  this.faceObjects = faceObjects;
176  this.animationObjects = animationObjects;
177  faceComponent = new FaceComponent("", faceObjects, faceObjectProviders, noFaceSquareIcon, unknownSquareIcon, "");
178  animationComponent = new AnimationComponent("", animationObjects, faceObjectProviders, noFaceSquareIcon, unknownSquareIcon);
179 
180  final GridBagLayout gridBagLayout = new GridBagLayout();
181  final GridBagConstraints gbc = new GridBagConstraints();
182 
183  panel.setLayout(gridBagLayout);
184  gbc.fill = GridBagConstraints.BOTH;
185  gbc.weightx = 1.0;
186  gbc.weighty = 1.0;
187  gbc.anchor = GridBagConstraints.NORTHWEST;
188 
189  gbc.gridx = 0;
190  gbc.gridy = 0;
191  gbc.gridwidth = 1;
192  gbc.gridheight = 1;
193  final Component facePanel = createFacePanel();
194  gridBagLayout.setConstraints(facePanel, gbc);
195  panel.add(facePanel);
196 
197  gbc.gridx = 1;
198  gbc.gridy = 0;
199  gbc.gridwidth = 1;
200  gbc.gridheight = 1;
201  final Component animationPanel = createAnimationPanel();
202  gridBagLayout.setConstraints(animationPanel, gbc);
203  panel.add(animationPanel);
204 
205  gbc.gridx = 2;
206  gbc.gridy = 0;
207  gbc.weightx = 0.0;
208  gbc.gridwidth = 1;
209  gbc.gridheight = 1;
210  final Component directionPanel = createDirectionPanel();
211  gridBagLayout.setConstraints(directionPanel, gbc);
212  panel.add(directionPanel);
213 
214  addAutoApply(faceComponent.getInputComponent());
215  addAutoApply(animationComponent.getInputComponent());
216  addAutoApply(animatedCheckBox);
217  addAutoApply(animSpeedTextField);
218  addAutoApply(directionComponent);
219  refresh(gameObjectAttributesModel.getSelectedGameObject());
220  }
221 
222  @Override
223  protected final void refresh(@Nullable final G gameObject) {
224  Severity severity = Severity.DEFAULT;
225 
226  final String faceName;
227  if (gameObject == null) {
228  faceName = "";
229  } else {
230  final String tmpFaceName = gameObject.getFaceName();
231  if (tmpFaceName != null) {
232  faceName = normalizeFace(tmpFaceName);
233  //noinspection ConstantConditions
234  if (severity == Severity.DEFAULT) {
235  severity = Severity.MODIFIED;
236  }
237  } else {
238  faceName = normalizeFace(gameObject.getArchetype().getFaceName());
239  }
240  if (!faceName.equals("NONE") && !faceObjects.containsKey(faceName)) {
241  severity = Severity.ERROR;
242  }
243  }
244 
245  final String animName;
246  if (gameObject == null) {
247  animName = "";
248  } else {
249  final String tmpAnimName = gameObject.getAnimName();
250  if (tmpAnimName != null) {
251  animName = normalizeFace(tmpAnimName);
252  if (severity == Severity.DEFAULT) {
253  severity = Severity.MODIFIED;
254  }
255  } else {
256  animName = normalizeFace(gameObject.getArchetype().getAnimName());
257  }
258  if (!animName.equals("NONE") && !animationObjects.containsKey(animName)) {
259  severity = Severity.ERROR;
260  }
261  }
262 
263  final boolean animated;
264  if (gameObject == null) {
265  animated = false;
266  } else {
267  animated = gameObject.getAttributeInt(BaseObject.IS_ANIMATED) != 0;
268  //noinspection UnnecessaryParentheses,DoubleNegation
269  if (severity == Severity.DEFAULT && animated != (gameObject.getArchetype().getAttributeInt(BaseObject.IS_ANIMATED) != 0)) {
270  severity = Severity.MODIFIED;
271  }
272  }
273 
274  final String animSpeed;
275  if (gameObject == null) {
276  animSpeed = "";
277  } else {
278  animSpeed = gameObject.getAttributeString(BaseObject.ANIM_SPEED);
279  if (severity == Severity.DEFAULT && !gameObject.getArchetype().getAttributeString(BaseObject.ANIM_SPEED).equals(animSpeed)) {
280  severity = Severity.MODIFIED;
281  }
282  }
283 
284  final int direction;
285  if (gameObject == null || !gameObject.getArchetype().usesDirection()) {
286  direction = 0;
287  } else {
288  direction = gameObject.getDirection();
289  if (severity == Severity.DEFAULT && direction != gameObject.getArchetype().getDirection()) {
290  severity = Severity.MODIFIED;
291  }
292  }
293 
294  setTabSeverity(severity);
295  faceComponent.setEnabled(gameObject != null);
296  faceComponent.setFaceName(faceName);
297  defaultFaceComponentValue = faceName;
298  animationComponent.setEnabled(gameObject != null);
299  animationComponent.setAnimName(animName);
300  defaultAnimComponentValue = animName;
301  animatedCheckBox.setEnabled(gameObject != null);
302  animatedCheckBox.setSelected(animated);
303  defaultAnimatedCheckBoxValue = animated;
304  animSpeedTextField.setEnabled(gameObject != null);
305  animSpeedTextField.setText(animSpeed);
306  defaultAnimSpeedTextFieldValue = animSpeed;
307  directionComponent.setEnabled(gameObject != null);
308  directionComponent.updateDirection(direction);
309  }
310 
311  @Override
312  public boolean canApply() {
313  return !faceComponent.getFaceName().equals(defaultFaceComponentValue) || !animationComponent.getAnimName().equals(defaultAnimComponentValue) || animatedCheckBox.isSelected() != defaultAnimatedCheckBoxValue || !animSpeedTextField.getText().equals(defaultAnimSpeedTextFieldValue);
314  }
315 
316  @Override
317  public void activate() {
318  faceComponent.requestFocusInWindow();
319  }
320 
321  @Override
322  protected void apply(@NotNull final G gameObject) {
323  final String faceName = normalizeFace(faceComponent.getFaceName());
324  final String faceName2;
325  if (faceName.equals("NONE")) {
326  final String archFaceName = gameObject.getArchetype().getFaceName();
327  faceName2 = archFaceName == null || archFaceName.isEmpty() ? "" : "NONE";
328  } else {
329  faceName2 = faceName;
330  }
331  gameObject.setAttributeString(BaseObject.FACE, faceName2);
332 
333  final String animName = normalizeFace(animationComponent.getAnimName());
334  final String animName2;
335  if (animName.equals("NONE")) {
336  final String archAnimName = gameObject.getArchetype().getAnimName();
337  animName2 = archAnimName == null || archAnimName.isEmpty() ? "" : "NONE";
338  } else {
339  animName2 = animName;
340  }
341  gameObject.setAttributeString(BaseObject.ANIMATION, animName2);
342 
343  final boolean isAnimated = animatedCheckBox.isSelected();
344  if (isAnimated == (gameObject.getArchetype().getAttributeInt(BaseObject.IS_ANIMATED) != 0)) {
345  gameObject.removeAttribute(BaseObject.IS_ANIMATED);
346  } else {
347  gameObject.setAttributeInt(BaseObject.IS_ANIMATED, isAnimated ? 1 : 0);
348  }
349 
350  final String animSpeed = animSpeedTextField.getText().trim();
351  final String animSpeedAttribute = gameObject.getArchetype().getAttributeString(BaseObject.ANIM_SPEED);
352  if (animSpeed.isEmpty() || (animSpeed.equals("0") ? "" : animSpeed).equals(animSpeedAttribute)) {
353  gameObject.removeAttribute(BaseObject.ANIM_SPEED);
354  } else {
355  gameObject.setAttributeString(BaseObject.ANIM_SPEED, animSpeed);
356  }
357  }
358 
359  @NotNull
360  @Override
361  public JPanel getPanel() {
362  return panel;
363  }
364 
369  @NotNull
370  private Component createFacePanel() {
371  final GridBagLayout gridBagLayout = new GridBagLayout();
372 
373  final JComponent facePanel = new JPanel();
374  facePanel.setLayout(gridBagLayout);
375  facePanel.setBorder(new TitledBorder(ActionBuilderUtils.getString(ACTION_BUILDER, "faceFaceTitle")));
376 
377  final GridBagConstraints gbc = new GridBagConstraints();
378 
379  gbc.fill = GridBagConstraints.HORIZONTAL;
380  gbc.weightx = 1.0;
381  gbc.anchor = GridBagConstraints.NORTHWEST;
382  gbc.gridx = 0;
383  gbc.gridy = 0;
384  gridBagLayout.setConstraints(faceComponent, gbc);
385  facePanel.add(faceComponent);
386 
387  addFiller(gridBagLayout, facePanel, 1, 1);
388  return facePanel;
389  }
390 
395  @NotNull
396  private Component createAnimationPanel() {
397  final GridBagLayout gridBagLayout = new GridBagLayout();
398  final JComponent animationPanel = new JPanel();
399  animationPanel.setLayout(gridBagLayout);
400  animationPanel.setBorder(new TitledBorder(ActionBuilderUtils.getString(ACTION_BUILDER, "faceAnimationTitle")));
401 
402  final GridBagConstraints gbc = new GridBagConstraints();
403 
404  gbc.fill = GridBagConstraints.HORIZONTAL;
405  gbc.weightx = 1.0;
406  gbc.anchor = GridBagConstraints.NORTHWEST;
407  gbc.gridx = 0;
408  gbc.gridy = 0;
409  gbc.gridwidth = 2;
410  gridBagLayout.setConstraints(animationComponent, gbc);
411  animationPanel.add(animationComponent);
412 
413  gbc.gridy = 1;
414  gridBagLayout.setConstraints(animatedCheckBox, gbc);
415  animationPanel.add(animatedCheckBox);
416 
417  gbc.fill = GridBagConstraints.NONE;
418  gbc.weightx = 0.0;
419  gbc.gridx = 0;
420  gbc.gridy = 2;
421  gbc.gridwidth = 1;
422  final Component speedLabel = ActionBuilderUtils.newLabel(ACTION_BUILDER, "faceAnimationSpeed");
423  gridBagLayout.setConstraints(speedLabel, gbc);
424  animationPanel.add(speedLabel);
425 
426  gbc.fill = GridBagConstraints.HORIZONTAL;
427  gbc.weightx = 1.0;
428  gbc.gridx = 1;
429  gridBagLayout.setConstraints(animSpeedTextField, gbc);
430  animationPanel.add(animSpeedTextField);
431 
432  addFiller(gridBagLayout, animationPanel, 2, 3);
433  return animationPanel;
434  }
435 
440  @NotNull
441  private Component createDirectionPanel() {
442  final GridBagLayout gridBagLayout = new GridBagLayout();
443 
444  final JComponent directionPanel = new JPanel();
445  directionPanel.setLayout(gridBagLayout);
446  directionPanel.setBorder(new TitledBorder(ActionBuilderUtils.getString(ACTION_BUILDER, "faceAnimationDirection")));
447 
448  final GridBagConstraints gbc = new GridBagConstraints();
449 
450  gbc.fill = GridBagConstraints.NONE;
451  gbc.weightx = 1.0;
452  gbc.gridx = 0;
453  gbc.gridy = 0;
454  gridBagLayout.setConstraints(directionComponent, gbc);
455  directionPanel.add(directionComponent);
456 
457  addFiller(gridBagLayout, directionPanel, 1, 1);
458  return directionPanel;
459  }
460 
468  private static void addFiller(@NotNull final GridBagLayout gridBagLayout, @NotNull final Container container, final int gridWidth, final int gridY) {
469  final GridBagConstraints gbc = new GridBagConstraints();
470  gbc.fill = GridBagConstraints.BOTH;
471  gbc.weighty = 1.0;
472  gbc.gridwidth = gridWidth;
473  gbc.gridy = gridY;
474  final Component filler = new JPanel();
475  gridBagLayout.setConstraints(filler, gbc);
476  container.add(filler);
477  }
478 
485  @NotNull
486  private static String normalizeFace(@Nullable final String value) {
487  return value == null || value.isEmpty() ? "NONE" : value;
488  }
489 
490 }
void addAutoApply( @NotNull final Component component)
Registers a component that auto-applies when the focus is lost.
void setAnimName(@NotNull final String animName)
Sets the current animation name.
Component getInputComponent()
Returns the input field component.
The data package contains classes for handling data that is organized in a tree.
final void updateDirection(@Nullable final Integer direction)
Sets the selected direction.
A MapModel reflects the data of a map.
Definition: MapModel.java:75
Graphical User Interface of Gridarta.
A JPanel that allows the user to select an animation name.
MapModel< G, A, R > getMapModel()
Returns the MapModel this map square is part of.
Definition: MapSquare.java:99
This class manages NamedObjects, managing their tree as well as providing a method for showing a dial...
String ANIM_SPEED
The name of the "anim_speed" attribute.
void endTransaction()
End a transaction.
Gridarta can handle frame information of animations and allow the selection of an animation using a t...
String ANIMATION
The attribute name of the object&#39;s animation.
Definition: BaseObject.java:42
String FACE
The attribute name of the object&#39;s face.
Definition: BaseObject.java:54
String getAnimName()
Returns the current animation name.
final NamedObjects<?> animationObjects
The AnimationObjects for looking up animations.
Definition: FaceTab.java:77
A JPanel that allows the user to select a face name.
String defaultFaceComponentValue
The default value of faceComponent.
Definition: FaceTab.java:145
boolean defaultAnimatedCheckBoxValue
The default value of animatedCheckBox.
Definition: FaceTab.java:156
final JTextComponent animSpeedTextField
The JTextField for selecting the animation speed.
Definition: FaceTab.java:101
final DirectionComponent directionComponent
The DirectionComponent for selecting the game object&#39;s direction.
Definition: FaceTab.java:114
FaceTab(@NotNull final GameObjectAttributesModel< G, A, R > gameObjectAttributesModel, @NotNull final FaceObjects faceObjects, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects, @NotNull final ImageIcon noFaceSquareIcon, @NotNull final ImageIcon unknownSquareIcon)
Creates a new instance.
Definition: FaceTab.java:173
MODIFIED
The tab contents are modified from defaults.
Definition: Severity.java:39
The "Face" tab in the archetype chooser.
Definition: FaceTab.java:59
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Returns the value of a key.
Base package of all Gridarta classes.
Reflects a game object (object on a map).
Definition: GameObject.java:36
void setEnabled(final boolean enabled)
static void addFiller(@NotNull final GridBagLayout gridBagLayout, @NotNull final Container container, final int gridWidth, final int gridY)
Adds a filler component that fills the remaining space.
Definition: FaceTab.java:468
String DIRECTION
The attribute name of the object&#39;s direction.
Definition: BaseObject.java:48
final FaceComponent faceComponent
The FaceComponent for selecting the game object&#39;s face.
Definition: FaceTab.java:83
A GUI component for selecting a direction.
AnimationObjects is a container for AnimationObjects.
GameObjects are the objects based on Archetypes found on maps.
Component getInputComponent()
Returns the input field component.
FaceObjects is a container for FaceObjects.
Component createDirectionPanel()
Creates the "Direction" panel.
Definition: FaceTab.java:441
String getFaceName()
Returns the current face name.
ERROR
The tab contents are invalid.
Definition: Severity.java:44
String defaultAnimComponentValue
The default value of animationComponent.
Definition: FaceTab.java:151
void apply(@NotNull final G gameObject)
Definition: FaceTab.java:322
Component createFacePanel()
Creates the "Face" panel.
Definition: FaceTab.java:370
Severity levels for colors of tabs.
Definition: Severity.java:29
Utility class for ActionBuilder related functions.
final AnimationComponent animationComponent
The FaceComponent for selecting the game object&#39;s animation.
Definition: FaceTab.java:89
Provider for faces of GameObjects and Archetypes.
The face is the appearance of an object.
String IS_ANIMATED
The attribute name of the "is_animated" flag.
Definition: BaseObject.java:78
final void refresh(@Nullable final G gameObject)
Definition: FaceTab.java:223
final AbstractButton animatedCheckBox
The JCheckBox for selecting whether the game object is animated.
Definition: FaceTab.java:95
static final ActionBuilder ACTION_BUILDER
The action builder.
Definition: FaceTab.java:65
boolean containsKey(@NotNull String name)
Check whether an object is defined.
void setFaceName(@NotNull final String faceName)
Sets the current face name.
DEFAULT
The tab contents are unchanged from defaults.
Definition: Severity.java:34
static String normalizeFace(@Nullable final String value)
Normalizes a face or animation name.
Definition: FaceTab.java:486
final NamedObjects<?> faceObjects
The FaceObjects for looking up faces.
Definition: FaceTab.java:71
static JLabel newLabel(@NotNull final ActionBuilder actionBuilder, @NotNull final String key)
Creates a new JLabel from a resource key.
void beginTransaction(@NotNull String name)
Starts a new transaction.
Component createAnimationPanel()
Creates the "Animation" panel.
Definition: FaceTab.java:396
String defaultAnimSpeedTextFieldValue
The default value of animSpeedTextField.
Definition: FaceTab.java:162