Gridarta Editor
AttributesPaneBuilder.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.dialog.gameobjectattributes;
21 
22 import java.awt.Color;
23 import java.awt.Component;
24 import java.awt.Container;
25 import java.awt.GridBagConstraints;
26 import java.awt.GridBagLayout;
27 import java.awt.Insets;
28 import java.awt.event.FocusListener;
29 import java.io.File;
30 import java.text.DecimalFormat;
31 import java.text.NumberFormat;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.regex.Pattern;
36 import javax.swing.BorderFactory;
37 import javax.swing.Box;
38 import javax.swing.DefaultComboBoxModel;
39 import javax.swing.ImageIcon;
40 import javax.swing.JButton;
41 import javax.swing.JCheckBox;
42 import javax.swing.JComboBox;
43 import javax.swing.JComponent;
44 import javax.swing.JFormattedTextField;
45 import javax.swing.JLabel;
46 import javax.swing.JPanel;
47 import javax.swing.JScrollPane;
48 import javax.swing.JTabbedPane;
49 import javax.swing.JTextArea;
50 import javax.swing.JTextField;
51 import javax.swing.filechooser.FileFilter;
52 import javax.swing.text.DefaultFormatterFactory;
53 import javax.swing.text.NumberFormatter;
104 import org.jetbrains.annotations.NotNull;
105 import org.jetbrains.annotations.Nullable;
106 
112 public class AttributesPaneBuilder<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
113 
117  @NotNull
118  private static final Color FLOAT_COLOR = new Color(19, 134, 0);
119 
123  @NotNull
124  private static final Color INT_COLOR = new Color(74, 70, 156);
125 
129  @NotNull
130  private static final Pattern PARAGRAPH_DELIMITER = Pattern.compile("\n+");
131 
136  @NotNull
138 
142  @NotNull
143  private final Component parent;
144 
148  @NotNull
150 
155  @NotNull
157 
161  @NotNull
163 
168  @NotNull
170 
174  @NotNull
176 
180  @NotNull
181  private final FileFilter mapFileFilter;
182 
186  @NotNull
187  private final FileFilter scriptFileFilter;
188 
193  @NotNull
194  private final FaceObjects faceObjects;
195 
199  @NotNull
201 
205  @NotNull
207 
212  private final int undefinedSpellIndex;
213 
217  @NotNull
218  private final TreasureTree treasureTree;
219 
224  @NotNull
225  private final ImageIcon noFaceSquareIcon;
226 
231  @NotNull
232  private final ImageIcon unknownSquareIcon;
233 
237  @NotNull
239 
244  @NotNull
245  private final JTabbedPane tabbedPane = new JTabbedPane();
246 
247  @NotNull
248  private final FocusListener focusListener = new ScrollToVisibleFocusListener();
249 
253  @NotNull
254  private final Collection<DialogAttribute<G, A, R, ?>> dialogAttributes = new ArrayList<>();
255 
259  @Nullable
261 
266  @NotNull
268 
274  private void adjustTooltip(@Nullable final JComponent component, @NotNull final ArchetypeAttribute attribute) {
275  @NotNull final String desc = attribute.getDescription();
276  if (component != null && !desc.isEmpty()) {
277  final StringBuilder sb = new StringBuilder("<html>");
278  for (final String paragraph : PARAGRAPH_DELIMITER.split(desc)) {
279  sb.append("<p>").append(paragraph).append("</p>");
280  }
281  component.setToolTipText(sb.toString());
282  }
283  }
284 
285  @Override
286  public void visit(@NotNull final ArchetypeAttributeAnimationName archetypeAttribute) {
287  final String attributeName = archetypeAttribute.getArchetypeAttributeName();
288  final String defaultText = attributes.getAttributeString(attributeName);
289  final AnimationComponent input = new AnimationComponent(defaultText, animationObjects, faceObjectProviders, noFaceSquareIcon, unknownSquareIcon);
290  adjustTooltip(input, archetypeAttribute);
291  final JLabel cLabel = new JLabel(archetypeAttribute.getAttributeName() + ": ");
292  adjustTooltip(cLabel, archetypeAttribute);
293  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeAnimationName<G, A, R>(archetypeAttribute, input), cLabel, input);
294  }
295 
296  @Override
297  public void visit(@NotNull final ArchetypeAttributeBitmask archetypeAttribute) {
298  final JTextArea input = new JTextArea();
299  final DialogAttributeBitmask<G, A, R> tmpAttribute = new DialogAttributeBitmask<>(archetypeAttribute, input);
300  final AttributeBitmask bitmask = archetypeTypeSet.getBitmask(archetypeAttribute.getBitmaskName());
301  if (bitmask != null) {
302  tmpAttribute.setBitmask(bitmask);
303  final JButton label = new JButton(new MaskChangeAL<>(archetypeAttribute.getAttributeName() + ":", tmpAttribute));
304  adjustTooltip(label, archetypeAttribute);
305  input.setBackground(parent.getBackground());
306  input.setEditable(false);
307  input.setBorder(BorderFactory.createLineBorder(Color.gray));
308  input.setText(bitmask.getText(tmpAttribute.getValue()));
309  adjustTooltip(input, archetypeAttribute);
310  tmpAttribute.setEncodedValue(attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName()));
311  guiInfo = new GuiInfoTwoColumn<>(tmpAttribute, label, input);
312  } else {
313  final JLabel row = new JLabel("Error: Undefined Bitmask");
314  guiInfo = new GuiInfoRow<>(tmpAttribute, row);
315  }
316  }
317 
318  @Override
319  public void visit(@NotNull final ArchetypeAttributeBool archetypeAttribute) {
320  final JCheckBox input = new JCheckBox(archetypeAttribute.getAttributeName(), attributes.getAttributeInt(archetypeAttribute.getArchetypeAttributeName()) == 1);
321  adjustTooltip(input, archetypeAttribute);
322  guiInfo = new GuiInfoRow<>(new DialogAttributeBool<G, A, R>(archetypeAttribute, input), input);
323  }
324 
325  @Override
326  public void visit(@NotNull final ArchetypeAttributeBoolSpec archetypeAttribute) {
327  final String attributeString = attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName());
328  final boolean defaultValue;
329  if (archetypeAttribute.getTrueValue().equals("0")) {
330  defaultValue = attributeString.isEmpty() || attributeString.equals("0");
331  } else {
332  defaultValue = attributeString.equals(archetypeAttribute.getTrueValue());
333  }
334  final JCheckBox input = new JCheckBox(archetypeAttribute.getAttributeName(), defaultValue);
335  adjustTooltip(input, archetypeAttribute);
336  guiInfo = new GuiInfoRow<>(new DialogAttributeBoolSpec<G, A, R>(archetypeAttribute, input), input);
337  }
338 
339  @Override
340  public void visit(@NotNull final ArchetypeAttributeFaceName archetypeAttribute) {
341  final String attributeName = archetypeAttribute.getArchetypeAttributeName();
342  final String defaultText = attributes.getAttributeString(attributeName);
343  final FaceComponent input = new FaceComponent(defaultText, faceObjects, faceObjectProviders, noFaceSquareIcon, unknownSquareIcon, archetypeAttribute.getDescription());
344  adjustTooltip(input, archetypeAttribute);
345  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ":");
346  adjustTooltip(label, archetypeAttribute);
347  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeFaceName<G, A, R>(archetypeAttribute, input), label, input);
348  }
349 
350  @Override
351  public void visit(@NotNull final ArchetypeAttributeFixed archetypeAttribute) {
352  throw new AssertionError();
353  }
354 
355  @Override
356  public void visit(@NotNull final ArchetypeAttributeFloat archetypeAttribute) {
357  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
358  adjustTooltip(label, archetypeAttribute);
359  label.setForeground(FLOAT_COLOR);
360  final int fieldLength = archetypeAttribute.getInputLength() == 0 ? ArchetypeAttribute.TEXTFIELD_COLUMNS : archetypeAttribute.getInputLength();
361  final DecimalFormat format = new DecimalFormat("#0.0#");
362  format.setMaximumFractionDigits(10);
363  format.setGroupingUsed(false);
364  final NumberFormatter formatter = new NumberFormatter(format);
365  formatter.setValueClass(Double.class);
366  final DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
367  final Number value = attributes.getAttributeDouble(archetypeAttribute.getArchetypeAttributeName());
368  final JFormattedTextField input = new JFormattedTextField(factory, value);
369  input.setColumns(fieldLength);
370  adjustTooltip(input, archetypeAttribute);
371  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeFloat<G, A, R>(archetypeAttribute, input), label, input);
372  }
373 
374  @Override
375  public void visit(@NotNull final ArchetypeAttributeInt archetypeAttribute) {
376  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
377  adjustTooltip(label, archetypeAttribute);
378  label.setForeground(INT_COLOR);
379  final int fieldLength = archetypeAttribute.getInputLength() == 0 ? ArchetypeAttribute.TEXTFIELD_COLUMNS : archetypeAttribute.getInputLength();
380  final NumberFormat format = NumberFormat.getIntegerInstance();
381  format.setGroupingUsed(false);
382  final NumberFormatter formatter = new NumberFormatter(format);
383  final DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
384  final Number value = attributes.getAttributeInt(archetypeAttribute.getArchetypeAttributeName());
385  final JFormattedTextField input = new JFormattedTextField(factory, value);
386  input.setColumns(fieldLength);
387  adjustTooltip(input, archetypeAttribute);
388  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeInt<G, A, R>(archetypeAttribute, input), label, input);
389  }
390 
391  @Override
392  public void visit(@NotNull final ArchetypeAttributeInvSpell archetypeAttribute) {
393  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
394  adjustTooltip(label, archetypeAttribute);
395  label.setForeground(INT_COLOR);
396  final JComboBox<?> input = buildInvSpellBox(gameObjectSpells, attributes, archetypeAttribute.isOptionalSpell(), archetypeAttribute.getAttributeName());
397  adjustTooltip(input, archetypeAttribute);
398  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeInvSpell<>(archetypeAttribute.isOptionalSpell(), archetypeAttribute, input, gameObjectSpells), label, input);
399  }
400 
401  @Override
402  public void visit(@NotNull final ArchetypeAttributeList archetypeAttribute) {
403  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
404  adjustTooltip(label, archetypeAttribute);
405  label.setForeground(INT_COLOR);
406  final JComponent component;
407  final JComboBox<?> input;
408  final ArchetypeTypeList list = archetypeTypeSet.getList(archetypeAttribute.getListName());
409  if (list != null) {
410  input = buildArrayBox(list, attributes.getAttributeInt(archetypeAttribute.getArchetypeAttributeName()), archetypeAttribute.getAttributeName());
411  component = input;
412  } else {
413  // error: list data is missing or corrupt
414  input = new JComboBox<>();
415  component = new JLabel("Error: Undefined List");
416  }
417  adjustTooltip(input, archetypeAttribute);
418  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeList<G, A, R>(archetypeAttribute, input, archetypeTypeSet), label, component);
419  }
420 
421  @Override
422  public void visit(@NotNull final ArchetypeAttributeList2 archetypeAttribute) {
423  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
424  adjustTooltip(label, archetypeAttribute);
425  label.setForeground(INT_COLOR);
426  final int value = attributes.getAttributeInt(archetypeAttribute.getArchetypeAttributeName());
427 
428  final JComponent component1;
429  @Nullable final JComboBox<?> input1;
430  final ArchetypeTypeList list1 = archetypeTypeSet.getList(archetypeAttribute.getListName1());
431  if (list1 != null) {
432  input1 = buildArrayBox(list1, value & 0x0F, archetypeAttribute.getAttributeName());
433  component1 = input1;
434  } else {
435  // error: list data is missing or corrupt
436  input1 = new JComboBox<>();
437  component1 = new JLabel("Error: Undefined List");
438  }
439 
440  final JComponent component2;
441  @Nullable final JComboBox<?> input2;
442  final ArchetypeTypeList list2 = archetypeTypeSet.getList(archetypeAttribute.getListName2());
443  if (list2 != null) {
444  input2 = buildArrayBox(list2, value >> 4, archetypeAttribute.getAttributeName());
445  component2 = input2;
446  } else {
447  // error: list data is missing or corrupt
448  input2 = new JComboBox<>();
449  component2 = new JLabel("Error: Undefined List");
450  }
451 
452  adjustTooltip(input1, archetypeAttribute);
453  adjustTooltip(input2, archetypeAttribute);
454  final JComponent component = new JPanel(new GridBagLayout());
455  final GridBagConstraints gbc = new GridBagConstraints();
456  gbc.weightx = 1.0;
457  gbc.fill = GridBagConstraints.HORIZONTAL;
458  component.add(component1, gbc);
459  component.add(component2, gbc);
460  adjustTooltip(component, archetypeAttribute);
461  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeList2<G, A, R>(archetypeAttribute, input1, input2, archetypeTypeSet), label, component);
462  }
463 
464  @Override
465  public void visit(@NotNull final ArchetypeAttributeLong archetypeAttribute) {
466  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
467  adjustTooltip(label, archetypeAttribute);
468  label.setForeground(INT_COLOR);
469  final int fieldLength = archetypeAttribute.getInputLength() == 0 ? ArchetypeAttribute.TEXTFIELD_COLUMNS : archetypeAttribute.getInputLength();
470  final NumberFormat format = NumberFormat.getIntegerInstance();
471  format.setGroupingUsed(false);
472  final NumberFormatter formatter = new NumberFormatter(format);
473  final DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
474  final Number value = attributes.getAttributeLong(archetypeAttribute.getArchetypeAttributeName());
475  final JFormattedTextField input = new JFormattedTextField(factory, value);
476  input.setColumns(fieldLength);
477  adjustTooltip(input, archetypeAttribute);
478  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeLong<G, A, R>(archetypeAttribute, input), label, input);
479  }
480 
481  @Override
482  public void visit(@NotNull final ArchetypeAttributeMapPath archetypeAttribute) {
483  final MapSquare<?, ?, ?> mapSquare = attributes instanceof GameObject ? ((GameObject<?, ?, ?>) attributes).getMapSquare() : null;
484  final MapFile mapFile = mapSquare == null ? null : mapSquare.getMapModel().getMapFile();
485  final File relativeReference = mapFile == null ? new File(projectSettings.getMapsDirectory(), "dummy") : mapFile.getFile();
486  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
487  adjustTooltip(label, archetypeAttribute);
488  final TilePanel tilePanel = new TilePanel(mapFileFilter, attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName()), relativeReference, projectSettings.getMapsDirectory());
489  adjustTooltip(tilePanel, archetypeAttribute);
490  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeMapPath<G, A, R>(archetypeAttribute, tilePanel), label, tilePanel);
491  }
492 
493  @Override
494  public void visit(@NotNull final ArchetypeAttributeScriptFile archetypeAttribute) {
495  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
496  adjustTooltip(label, archetypeAttribute);
497  final File mapsDirectory = projectSettings.getMapsDirectory();
498  final TilePanel tilePanel = new TilePanel(scriptFileFilter, attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName()), new File(mapsDirectory, "dummy"), mapsDirectory);
499  adjustTooltip(tilePanel, archetypeAttribute);
500  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeScriptFile<G, A, R>(archetypeAttribute, tilePanel), label, tilePanel);
501  }
502 
503  @Override
504  public void visit(@NotNull final ArchetypeAttributeSpell archetypeAttribute) {
505  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
506  adjustTooltip(label, archetypeAttribute);
507  label.setForeground(INT_COLOR);
508  final JComboBox<?> input = buildSpellBox(attributes, numberSpells, undefinedSpellIndex, false, archetypeAttribute);
509  adjustTooltip(input, archetypeAttribute);
510  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeSpell<G, A, R>(archetypeAttribute, input, numberSpells), label, input);
511  }
512 
513  @Override
514  public void visit(@NotNull final ArchetypeAttributeString archetypeAttribute) {
515  final String defaultText = attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName());
516  final JTextField input = new JTextField(defaultText, ArchetypeAttribute.TEXTFIELD_COLUMNS);
517  adjustTooltip(input, archetypeAttribute);
518  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
519  adjustTooltip(label, archetypeAttribute);
520  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeString<G, A, R>(archetypeAttribute, input), label, input);
521  }
522 
523  @Override
524  public void visit(@NotNull final ArchetypeAttributeText archetypeAttribute) {
525  final String text;
526  if (archetypeAttribute.getArchetypeAttributeName().equals("msg") && attributes instanceof GameObject) {
527  final GameObject<?, ?, ?> tmp = (GameObject<?, ?, ?>) attributes;
528  final String archetypeMsgText = tmp.getArchetype().getMsgText();
529  final String gameObjectMsgText = tmp.getMsgText();
530  if (archetypeMsgText != null && !archetypeMsgText.isEmpty() && (gameObjectMsgText == null || gameObjectMsgText.isEmpty())) {
531  text = archetypeMsgText;
532  } else {
533  text = gameObjectMsgText;
534  }
535  } else {
536  text = "";
537  }
538  final SyntaxDocument document = new SyntaxDocument();
539  document.setTokenMarker(TokenMarkerFactory.createTokenMarker(archetypeAttribute.getFileExtension()));
540  final JEditTextArea input = new JEditTextArea(textAreaDefaults, document, false);
541  input.setText(text == null ? "" : text);
542  input.setCaretPosition(0);
543  input.setBorder(BorderFactory.createEmptyBorder(3, 7, 0, 0));
544  adjustTooltip(input, archetypeAttribute);
545  guiInfo = new GuiInfoGlue<>(new DialogAttributeText<G, A, R>(archetypeAttribute, input), input);
546  }
547 
548  @Override
549  public void visit(@NotNull final ArchetypeAttributeTreasure archetypeAttribute) {
550  String treasureName = attributes.getAttributeString(archetypeAttribute.getArchetypeAttributeName());
551  if (treasureName.trim().isEmpty() || treasureName.trim().equalsIgnoreCase("none")) {
552  treasureName = CFTreasureListTree.NONE_SYM;
553  }
554  final JTextField input = new JTextField(" " + treasureName, ArchetypeAttribute.TEXTFIELD_COLUMNS);
555  adjustTooltip(input, archetypeAttribute);
556  input.setEditable(false);
557  final DialogAttributeTreasure<G, A, R> tmpAttribute = new DialogAttributeTreasure<>(archetypeAttribute, input, treasureTree);
558  final JButton label = new JButton(new ViewTreasurelistAL(input, parent, treasureListTree));
559  adjustTooltip(label, archetypeAttribute);
560  guiInfo = new GuiInfoTwoColumn<>(tmpAttribute, label, input);
561  }
562 
563  @Override
564  public void visit(@NotNull final ArchetypeAttributeZSpell archetypeAttribute) {
565  final JLabel label = new JLabel(archetypeAttribute.getAttributeName() + ": ");
566  adjustTooltip(label, archetypeAttribute);
567  label.setForeground(INT_COLOR);
568  final JComboBox<?> input = buildSpellBox(attributes, numberSpells, undefinedSpellIndex, true, archetypeAttribute);
569  adjustTooltip(input, archetypeAttribute);
570  guiInfo = new GuiInfoTwoColumn<>(new DialogAttributeZSpell<G, A, R>(archetypeAttribute, input, numberSpells, undefinedSpellIndex), label, input);
571  }
572 
573  };
574 
597  public AttributesPaneBuilder(@NotNull final Attributes attributes, @NotNull final Component parent, @NotNull final ArchetypeTypeSet archetypeTypeSet, @NotNull final CFTreasureListTree treasureListTree, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects, @NotNull final ProjectSettings projectSettings, @NotNull final FileFilter mapFileFilter, @NotNull final FileFilter scriptFileFilter, @NotNull final FaceObjects faceObjects, @NotNull final Spells<GameObjectSpell<G, A, R>> gameObjectSpells, @NotNull final Spells<NumberSpell> numberSpells, final int undefinedSpellIndex, @NotNull final TreasureTree treasureTree, @NotNull final ImageIcon noFaceSquareIcon, @NotNull final ImageIcon unknownSquareIcon, @NotNull final TextAreaDefaults textAreaDefaults) {
598  this.attributes = attributes;
599  this.parent = parent;
600  this.archetypeTypeSet = archetypeTypeSet;
601  this.treasureListTree = treasureListTree;
602  this.faceObjectProviders = faceObjectProviders;
603  this.animationObjects = animationObjects;
604  this.projectSettings = projectSettings;
605  this.mapFileFilter = mapFileFilter;
606  this.scriptFileFilter = scriptFileFilter;
607  this.faceObjects = faceObjects;
608  this.gameObjectSpells = gameObjectSpells;
609  this.numberSpells = numberSpells;
610  this.undefinedSpellIndex = undefinedSpellIndex;
611  this.treasureTree = treasureTree;
612  this.noFaceSquareIcon = noFaceSquareIcon;
613  this.unknownSquareIcon = unknownSquareIcon;
614  this.textAreaDefaults = textAreaDefaults;
615  }
616 
621  @NotNull
622  public Component getTabbedPane() {
623  return tabbedPane;
624  }
625 
630  @NotNull
631  public Iterable<DialogAttribute<G, A, R, ?>> getDialogAttributes() {
632  return Collections.unmodifiableCollection(dialogAttributes);
633  }
634 
641  public void buildAttribute(@NotNull final Attributes attributes, @NotNull final Iterable<ArchetypeAttributeSection> archetypeType) {
642  this.attributes = attributes;
643  tabbedPane.removeAll();
644  int sectionId = 0;
645  for (final ArchetypeAttributeSection archetypeAttributeSection : archetypeType) {
646  final Component panel = makeAttributePanel(archetypeAttributeSection);
647  if (panel != null) {
648  final String sectionName = archetypeAttributeSection.getSectionName();
649  final String title;
650  if (sectionName.length() <= 1) {
651  title = sectionName;
652  } else {
653  title = sectionName.substring(0, 1).toUpperCase() + sectionName.substring(1);
654  }
655  tabbedPane.addTab(title, null, panel);
656  sectionId++;
657  }
658  }
659 
660  tabbedPane.setSelectedIndex(sectionId > 0 ? 0 : -1);
661  tabbedPane.validate();
662  }
663 
671  @Nullable
672  private Component makeAttributePanel(@NotNull final Iterable<ArchetypeAttribute> archetypeAttributeSection) {
673  int matchingAttributes = 0; // number of attributes in this section
674  boolean hasBitmask = false; // true if this section contains a bitmask attribute
675 
676  // first we check how many attributes this section has
677  for (final ArchetypeAttribute archetypeAttribute : archetypeAttributeSection) {
678  // count number of attributes
679  if (!(archetypeAttribute instanceof ArchetypeAttributeFixed)) {
680  matchingAttributes++;
681  }
682  // check for bitmask attributes
683  if (!hasBitmask && archetypeAttribute instanceof ArchetypeAttributeBitmask) {
684  hasBitmask = true;
685  }
686  }
687  if (matchingAttributes == 0) {
688  return null;
689  }
690 
691  // All attribute-"lines" go into this panel:
692  final JPanel panel = new JPanel(new GridBagLayout());
693  final Insets gbcInsets = new Insets(2, 2, 2, 2);
694 
695  final GridBagConstraints gbc = new GridBagConstraints();
696  gbc.insets = gbcInsets;
697  gbc.fill = GridBagConstraints.HORIZONTAL;
698  final Object labelGbc = gbc.clone();
699  gbc.weightx = 1.0;
700  gbc.gridwidth = GridBagConstraints.REMAINDER;
701  final Object compGbc = gbc.clone();
702  gbc.anchor = GridBagConstraints.WEST;
703  final Object rowGbc = gbc.clone();
704  gbc.fill = GridBagConstraints.BOTH;
705  gbc.gridwidth = 2;
706  gbc.weighty = 1.0;
707  final Object glueGbc = gbc.clone();
708 
709  boolean hasGlue = false;
710  // now add the entries, line by line
711  for (final ArchetypeAttribute archetypeAttribute : archetypeAttributeSection) {
712  if (!(archetypeAttribute instanceof ArchetypeAttributeFixed)) {
713  guiInfo = null;
714  archetypeAttribute.visit(archetypeAttributeVisitor);
715  final GuiInfo<G, A, R, ?> tmpGuiInfo = guiInfo;
716  assert tmpGuiInfo != null;
717 
718  dialogAttributes.add(tmpGuiInfo.getAttribute());
719  addElement(panel, tmpGuiInfo.getLabel(), labelGbc);
720  addElement(panel, tmpGuiInfo.getComponent(), compGbc);
721  addElement(panel, tmpGuiInfo.getRow(), rowGbc);
722  addElement(panel, tmpGuiInfo.getGlue(), glueGbc);
723  hasGlue |= tmpGuiInfo.getGlue() != null;
724  }
725  }
726 
727  if (!hasGlue) {
728  // if the component does not already have glue, put glue inside to align its contents to the top.
729  panel.add(Box.createGlue(), glueGbc);
730  }
731  final JScrollPane panelReturn = new JScrollPane(panel);
732  panelReturn.getVerticalScrollBar().setUnitIncrement(8);
733  return panelReturn;
734  }
735 
742  private void addElement(@NotNull final Container container, @Nullable final Component component, @NotNull final Object constraints) {
743  if (component != null) {
744  container.add(component, constraints);
745  component.addFocusListener(focusListener);
746  }
747  }
748 
757  @NotNull
758  private static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> JComboBox<?> buildInvSpellBox(@NotNull final Spells<GameObjectSpell<G, A, R>> gameObjectSpells, @NotNull final Attributes attributes, final boolean isOptionalSpell, @NotNull final String attributeName) {
759  if (!(attributes instanceof BaseObject)) {
760  throw new IllegalArgumentException();
761  }
762  final BaseObject<?, ?, ?, ?> baseObject = (BaseObject<?, ?, ?, ?>) attributes;
763  final int selectedIndex;
764  @Nullable final String title;
765  switch (baseObject.countInvObjects()) {
766  case 0:
767  selectedIndex = gameObjectSpells.size();
768  title = isOptionalSpell ? null : "<none>";
769  break;
770 
771  default:
772  selectedIndex = gameObjectSpells.size() + (isOptionalSpell ? 1 : 0);
773  title = "<multiple>";
774  break;
775 
776  case 1:
777  final GameObject<?, ?, ?> invObject = baseObject.iterator().next();
778  final String invObjectArchetypeName = invObject.getArchetype().getArchetypeName();
779  int index = 0;
780  @Nullable String tmpTitle = "<customized spell>";
781  for (final GameObjectSpell<?, ?, ?> spellObject : gameObjectSpells) {
782  if (invObjectArchetypeName.equals(spellObject.getArchetypeName())) {
783  tmpTitle = invObject.isDefaultGameObject() ? null : spellObject.getName() + " <customized>";
784  break;
785  }
786  index++;
787  }
788  selectedIndex = tmpTitle != null ? gameObjectSpells.size() + (isOptionalSpell ? 1 : 0) : index;
789  title = tmpTitle;
790  break;
791  }
792 
793  final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
794  for (final Spell spell : gameObjectSpells) {
795  model.addElement(spell.getName());
796  }
797  if (isOptionalSpell) {
798  model.addElement("<none>");
799  }
800  if (title != null) {
801  model.addElement(title);
802  }
803  final JComboBox<?> comboBox = new JComboBox<>(model);
804  comboBox.setSelectedIndex(selectedIndex);
805  comboBox.setMaximumRowCount(10);
806  comboBox.setKeySelectionManager(new StringKeyManager(comboBox));
807  comboBox.setName(attributeName);
808  return comboBox;
809  }
810 
818  @NotNull
819  private static JComboBox<?> buildArrayBox(@NotNull final ArchetypeTypeList listData, final int value, @NotNull final String attributeName) {
820  final String[] array = new String[listData.size()];
821  boolean hasSelection = false;
822  int selectedIndex = 0;
823  for (int i = 0; i < array.length; i++) {
824  array[i] = listData.get(i).getSecond();
825  if (!hasSelection && listData.get(i).getFirst() == value) {
826  hasSelection = true;
827  selectedIndex = i;
828  }
829  }
830  final JComboBox<?> comboBox = new JComboBox<>(array);
831  comboBox.setSelectedIndex(selectedIndex);
832  comboBox.setMaximumRowCount(10);
833  comboBox.setKeySelectionManager(new StringKeyManager(comboBox));
834  comboBox.setName(attributeName);
835  return comboBox;
836  }
837 
847  @NotNull
848  private static JComboBox<?> buildSpellBox(@NotNull final Attributes attributes, @NotNull final Spells<NumberSpell> numberSpells, final int undefinedSpellIndex, final boolean isZSpell, @NotNull final ArchetypeAttribute archetypeAttribute) {
849  int spellNumber = attributes.getAttributeInt(archetypeAttribute.getArchetypeAttributeName());
850 
851  if (spellNumber < 0 || spellNumber >= numberSpells.size()) {
852  spellNumber = undefinedSpellIndex;
853  }
854 
855  final int selectedIndex;
856  if (spellNumber == undefinedSpellIndex && isZSpell) {
857  selectedIndex = 0;
858  } else {
859  selectedIndex = 1 + AbstractArchetypeAttributeSpell.findSpellIndex(numberSpells, spellNumber);
860  }
861 
862  final DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
863  model.addElement("<none>");
864  for (final Spell spell : numberSpells) {
865  model.addElement(spell.getName());
866  }
867  final JComboBox<?> comboBox = new JComboBox<>(model);
868  comboBox.setSelectedIndex(selectedIndex);
869  comboBox.setMaximumRowCount(10);
870  comboBox.setKeySelectionManager(new StringKeyManager(comboBox));
871  comboBox.setName(archetypeAttribute.getAttributeName());
872  return comboBox;
873  }
874 
875 }
final Collection< DialogAttribute< G, A, R, ?> > dialogAttributes
All DialogAttributes in the dialog.
An ArchetypeAttribute for selecting long integer values.
final AnimationObjects animationObjects
The AnimationObjects instance for choosing animation names.
final ArchetypeTypeSet archetypeTypeSet
Reference to the ArchetypeTypeSet.
A document implementation that can be tokenized by the syntax highlighting system.
final ImageIcon unknownSquareIcon
The ImageIcon for undefined animations.
final Spells< GameObjectSpell< G, A, R > > gameObjectSpells
The game object spells to use.
Graphical User Interface of Gridarta.
A JPanel that allows the user to select an animation name.
A GuiInfo that fills one component horizontally.
Definition: GuiInfoRow.java:34
Settings that apply to a project.
MapModel< G, A, R > getMapModel()
Returns the MapModel this map square is part of.
Definition: MapSquare.java:99
Manages ArchetypeType instances, list, and bitmask definitions.
This Class contains the data of one archetype attribute.
int getAttributeInt(@NotNull String attributeName)
Returns an attribute value of this Archetype as int.
An ArchetypeAttribute for selecting an optional spell encoded as an integer attribute.
Component makeAttributePanel(@NotNull final Iterable< ArchetypeAttribute > archetypeAttributeSection)
This method creates an attribute panel for one section of attributes.
Gridarta can handle frame information of animations and allow the selection of an animation using a t...
A tile panel displays exactly one direction for map tiling.
Definition: TilePanel.java:52
static TokenMarker createTokenMarker(@Nullable final File file)
Creates a suitable TokenMarker for a given file.
long getAttributeLong(@NotNull String attributeName)
Returns an attribute value of this Archetype as long.
abstract Component getRow()
Returns the row component to display filled horizontally or.
A JPanel that allows the user to select a face name.
Component getTabbedPane()
Returns the JTabbedPane that contains all attribute tabs.
An ArchetypeAttribute displaying a fixed string.
An ArchetypeAttribute for selecting boolean values having specific "true" and "false" values...
Describes a numbered in-game spell.
static final Pattern PARAGRAPH_DELIMITER
A Pattern that matches one or more NL characters.
void setText(@NotNull final String text)
Sets the entire text of this text area.
AttributeBitmask getBitmask(@NotNull final String bitmaskName)
Returns a bitmask type by name.
final ArchetypeAttributeVisitor archetypeAttributeVisitor
The ArchetypeAttributeVisitor for creating GUI elements for ArchetypeAttributes.
An ArchetypeAttribute for selecting map path names.
final FaceObjectProviders faceObjectProviders
The FaceObjectProviders for looking up faces.
An ArchetypeAttribute for selecting string values.
void buildAttribute(@NotNull final Attributes attributes, @NotNull final Iterable< ArchetypeAttributeSection > archetypeType)
Constructs the central part of the attribute dialog, containing the object&#39;s attributes.
String getAttributeString(@NotNull String attributeName)
Returns the requested attribute value of this GameObject as String.
void setEncodedValue(@NotNull final String encodedValue)
Set the active bitmask value in external file representation.
GuiInfo< G, A, R, ?> guiInfo
The return value for archetypeAttributeVisitor.
abstract Component getGlue()
Returns the glue component to display filled both horizontally and vertically or. ...
final FileFilter mapFileFilter
The FileFilter to use for map files.
Base package of all Gridarta classes.
Common base class for spells and spell lists.
Definition: Spells.java:33
Reflects a game object (object on a map).
Definition: GameObject.java:36
A GuiInfo that fills one component both horizontally and vertically.
Iterable< DialogAttribute< G, A, R, ?> > getDialogAttributes()
Returns all DialogAttributes in the dialog.
final TextAreaDefaults textAreaDefaults
The TextAreaDefaults for text fields.
A factory for creatingTokenMarker instances for Files.
A GuiInfo that displays a label and another component in two columns.
static JComboBox<?> buildArrayBox(@NotNull final ArchetypeTypeList listData, final int value, @NotNull final String attributeName)
Constructs the combo box for arrays of "list data".
final FaceObjects faceObjects
The FaceObjects instance for choosing face names.
AnimationObjects is a container for AnimationObjects.
static final int TEXTFIELD_COLUMNS
The width (columns) for input fields like textfields or JChooseBoxes.
GameObjects are the objects based on Archetypes found on maps.
This class manages bitmask values which appear in Gridarta archetype attributes.
final FileFilter scriptFileFilter
The FileFilter to use for script files.
final CFTreasureListTree treasureListTree
The CFTreasureListTree to use.
DialogAttribute< G, A, R, T > getAttribute()
Returns the DialogAttribute this entry represents.
Definition: GuiInfo.java:55
The CFTreasureListTree class fully manages treasurelists.
KeySelectionManager to manage the select-per-keystroke in a JComboBox (The default KeySelectionManage...
final JTabbedPane tabbedPane
The central tabbed pane (the place where all the attribute tabs are).
abstract Component getLabel()
Returns the label to display in the first column or.
Describes a numbered in-game spell.
This package contains the other part of the script editor.
FaceObjects is a container for FaceObjects.
static final String NONE_SYM
The string displayed in attribute dialog for "none".
Base classes for rendering maps.
Describes an in-game spell.
Definition: Spell.java:28
An ArchetypeAttribute for selecting bitmask values.
int countInvObjects()
Counts the number of all inventory items (recursively).
static JComboBox<?> buildSpellBox(@NotNull final Attributes attributes, @NotNull final Spells< NumberSpell > numberSpells, final int undefinedSpellIndex, final boolean isZSpell, @NotNull final ArchetypeAttribute archetypeAttribute)
Constructs the combo box of the available spells.
An ArchetypeAttribute for selecting spells encoded as in integer attribute.
void addElement(@NotNull final Container container, @Nullable final Component component, @NotNull final Object constraints)
Adds a Component to a Container.
Stores all defined treasure lists.
An ArchetypeAttribute for selecting integer values.
Provider for faces of GameObjects and Archetypes.
The face is the appearance of an object.
MapFile getMapFile()
Returns the map file.
File getFile()
Returns a File for this map file.
Definition: MapFile.java:102
void setCaretPosition(final int caret)
Sets the caret position.
An ArchetypeAttribute for selecting a value from two lists.
An ArchetypeAttribute for selecting boolean values.
ActionListener for the change buttons of bitmasks.
File getMapsDirectory()
Returns the default maps directory.
ArchetypeTypeList getList(@NotNull final String listName)
Returns a list type definition.
An ArchetypeAttribute for selecting a value from a list.
An ArchetypeAttribute for selecting floating point values.
abstract Component getComponent()
Returns the component to display in the second column or.
An ArchetypeAttribute for selecting text fields.
final ProjectSettings projectSettings
The ProjectSettings instance.
An ArchetypeAttribute for selecting a spell encoded as an inventory game object.
static int findSpellIndex(@NotNull final Spells< NumberSpell > numberSpells, final int number)
Returns the spell index for a spell number.
Defines types of GameObjects with corresponding attributes.
double getAttributeDouble(@NotNull String attributeName)
Returns an attribute value of this Archetype as double.
The location of a map file with a map directory.
Definition: MapFile.java:31
void setTokenMarker(@Nullable final TokenMarker tokenMarker)
Sets the token marker that is to be used to split lines of this document up into tokens.
int size()
Return the number of existing spell objects.
Definition: Spells.java:64
AttributesPaneBuilder(@NotNull final Attributes attributes, @NotNull final Component parent, @NotNull final ArchetypeTypeSet archetypeTypeSet, @NotNull final CFTreasureListTree treasureListTree, @NotNull final FaceObjectProviders faceObjectProviders, @NotNull final AnimationObjects animationObjects, @NotNull final ProjectSettings projectSettings, @NotNull final FileFilter mapFileFilter, @NotNull final FileFilter scriptFileFilter, @NotNull final FaceObjects faceObjects, @NotNull final Spells< GameObjectSpell< G, A, R >> gameObjectSpells, @NotNull final Spells< NumberSpell > numberSpells, final int undefinedSpellIndex, @NotNull final TreasureTree treasureTree, @NotNull final ImageIcon noFaceSquareIcon, @NotNull final ImageIcon unknownSquareIcon, @NotNull final TextAreaDefaults textAreaDefaults)
Creates a new instance.
Encapsulates default settings for a text area.
MapSquare< G, A, R > getMapSquare()
Get the MapSquare of this GameObjectContainer.