Pārlūkot izejas kodu

Beginning work of spell panel information in class data.
Spells are stored in two tabs: prepared, and known.
Each tab is a hierarchy of level-tier info, and an arbitrary number of spells.

TODO:
- Confirm that the handling of spontaneous casters works as expected
- Enhance spell tabs with a SpellLine class, providing overview and tooltip info.

Sam Jaffe 8 gadi atpakaļ
vecāks
revīzija
7d8bc3b69a

+ 15 - 1
resources/Potato.json

@@ -4,7 +4,21 @@
   "classes":[
     {
       "level":3,
-      "name":"Cleric"
+      "name":"Cleric",
+      "spellBook":{
+        "@type":"Inspired",
+        "classRef":"Cleric",
+        "spellInfo":{
+          "0":{
+            "spellsPerDay":4,
+            "spellsPrepared":[
+              "Create Water",
+              "Create Water",
+              "Create Water"
+            ]
+          }
+        }
+      }
     },
     {
       "level":2,

+ 0 - 1
resources/classes/Bard.json

@@ -43,7 +43,6 @@
     "Use Magic Device"
   ],
   "spells":{
-    "@type":"Spontaneous",
     "group":"ARCANE",
     "ability":"CHA",
     "known":[

+ 0 - 1
resources/classes/Cleric.json

@@ -25,7 +25,6 @@
     "Spellcraft"
   ],
   "spells":{
-    "@type":"Inspired",
     "group":"DIVINE",
     "ability":"WIS",
     "known":[ ],

+ 1 - 0
resources/spells/default.json

@@ -1,5 +1,6 @@
 {
   "Create Water":{
+    "name":"Create Water",
     "school":"Conjuration",
     "subSchool":"Creation",
     "keywords":["Water"],

+ 1 - 1
src/org/leumasjaffe/charsheet/model/DDCharacterClass.java

@@ -43,7 +43,7 @@ public class DDCharacterClass {
 //	@NonNull List<Integer> healthRolls;
 	@Delegate @Getter(AccessLevel.NONE) Reference name;
 	
-	@Getter(AccessLevel.NONE) Optional<DDSpellbook> spellBook;
+	Optional<DDSpellbook> spellBook;
 	
 	public String toString() {
 		return getName() + " " + getLevel();

+ 5 - 2
src/org/leumasjaffe/charsheet/model/DDClass.java

@@ -2,6 +2,7 @@ package org.leumasjaffe.charsheet.model;
 
 import java.io.File;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -10,6 +11,7 @@ import java.util.Set;
 
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
 import org.leumasjaffe.charsheet.model.magic.DDSpellList;
+import org.leumasjaffe.charsheet.model.magic.DDSpellList.SpellList;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -38,7 +40,7 @@ public class DDClass {
 	
 	@NonNull Set<String> skills;
 	
-	@Getter(AccessLevel.PACKAGE) @NonNull Optional<DDSpellList> spells;
+	@NonNull Optional<DDSpellList> spells;
 	
 	static Map<String, DDClass> store = new HashMap<>();
 	
@@ -53,7 +55,8 @@ public class DDClass {
 	}
 	
 	public Collection<DDSpell> getSpellList( int level ) {
-		return spells.get().getSpellList().get( level ).getSpellList();
+		List<SpellList> list = spells.get().getSpellList();
+		return list.size() <= level ? Collections.emptySet() : list.get( level ).getSpellList();
 	}
 	
 	public boolean isClassSkill(final String skillName) {

+ 1 - 0
src/org/leumasjaffe/charsheet/model/magic/DDSpell.java

@@ -50,6 +50,7 @@ public class DDSpell {
 		}
 	}
 	
+	@NonNull String name;
 	@NonNull School school;
 	SubSchool subSchool;
 	@NonNull Set<String> keywords;

+ 18 - 2
src/org/leumasjaffe/charsheet/model/magic/impl/Inspired.java

@@ -3,11 +3,16 @@ package org.leumasjaffe.charsheet.model.magic.impl;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.leumasjaffe.charsheet.model.DDClass;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.charsheet.model.magic.DDSpellFactory;
 import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.NonNull;
@@ -17,11 +22,17 @@ import lombok.experimental.NonFinal;
 @AllArgsConstructor
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class Inspired implements DDSpellbook {
-	@AllArgsConstructor
 	@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 	private static class Level {
 		@NonNull List<DDSpell> spellsPrepared;
 		@NonFinal int spellsPerDay;
+		
+		@JsonCreator
+		Level(@JsonProperty("spellsPerDay") int spellsPerDay, 
+				@JsonProperty("spellsPrepared") List<String> spellsPrepared) {
+			this.spellsPerDay = spellsPerDay;
+			this.spellsPrepared = spellsPrepared.stream().map(s -> DDSpellFactory.loadSpell(s)).collect(Collectors.toList());
+		}
 	}
 	
 	private static class ClassReference {
@@ -44,10 +55,15 @@ public class Inspired implements DDSpellbook {
 	public Collection<DDSpell> spellsKnownAtLevel(int level) {
 		return classRef.ref.getSpellList( level );
 	}
+	
+	@Override
+	public int numSpellsKnownAtLevel( int level ) {
+		return -1;
+	}
 
 	@Override
 	public List<DDSpell> spellsPreparedAtLevel(int level) {
-		return spellInfo.get( level ).spellsPrepared;
+		return spellInfo.size() <= level ? null : spellInfo.get( level ).spellsPrepared;
 	}
 
 	@Override

+ 5 - 0
src/org/leumasjaffe/charsheet/util/StringHelper.java

@@ -17,6 +17,11 @@ public class StringHelper {
 		return Integer.toString(i);
 	}
 	
+	public String toString(int i, int ignore, String elseValue) {
+		if ( i == ignore ) { return elseValue; }
+		else { return Integer.toString(i); }
+	}
+
 	public String toString(int i, int ignore) {
 		if ( i == ignore ) { return ""; }
 		else { return Integer.toString(i); }

+ 74 - 14
src/org/leumasjaffe/charsheet/view/ClassTab.java

@@ -9,9 +9,14 @@ import javax.swing.JTextField;
 
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
 import org.leumasjaffe.charsheet.util.StringHelper;
+import org.leumasjaffe.charsheet.view.magic.SpellPanel;
 
 import java.awt.GridBagConstraints;
 import java.awt.Insets;
+import javax.swing.JLabel;
+import java.awt.Component;
+import javax.swing.Box;
+import java.awt.Font;
 
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class ClassTab extends JPanel {
@@ -26,33 +31,88 @@ public class ClassTab extends JPanel {
 		this.title = model.getName();
 		
 		GridBagLayout gridBagLayout = new GridBagLayout();
-		gridBagLayout.columnWidths = new int[]{0, 0, 0};
-		gridBagLayout.rowHeights = new int[]{0, 0};
-		gridBagLayout.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
-		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		gridBagLayout.columnWidths = new int[]{0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0};
+		gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, 1.0, 1.0, Double.MIN_VALUE};
 		setLayout(gridBagLayout);
 		
+		JPanel header = new JPanel();
+		GridBagConstraints gbc_header = new GridBagConstraints();
+		gbc_header.insets = new Insets(0, 0, 5, 0);
+		gbc_header.fill = GridBagConstraints.BOTH;
+		gbc_header.gridx = 0;
+		gbc_header.gridy = 0;
+		add(header, gbc_header);
+		GridBagLayout gbl_header = new GridBagLayout();
+		gbl_header.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0};
+		gbl_header.rowHeights = new int[]{0, 0};
+		gbl_header.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE};
+		gbl_header.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		header.setLayout(gbl_header);
+		
+		JLabel lblClass = new JLabel("Class:");
+		lblClass.setFont(new Font("Tahoma", Font.BOLD, 14));
+		GridBagConstraints gbc_lblClass = new GridBagConstraints();
+		gbc_lblClass.insets = new Insets(0, 0, 0, 5);
+		gbc_lblClass.anchor = GridBagConstraints.EAST;
+		gbc_lblClass.gridx = 0;
+		gbc_lblClass.gridy = 0;
+		header.add(lblClass, gbc_lblClass);
+		
 		JTextField nameField = new JTextField();
-		nameField.setEditable(false);
 		GridBagConstraints gbc_nameField = new GridBagConstraints();
 		gbc_nameField.insets = new Insets(0, 0, 0, 5);
-		gbc_nameField.fill = GridBagConstraints.HORIZONTAL;
-		gbc_nameField.gridx = 0;
+		gbc_nameField.gridx = 1;
 		gbc_nameField.gridy = 0;
-		add(nameField, gbc_nameField);
+		header.add(nameField, gbc_nameField);
+		nameField.setEditable(false);
 		nameField.setColumns(10);
 		
+		nameField.setText(model.getName());
+		
+		Component horizontalStrut = Box.createHorizontalStrut(20);
+		GridBagConstraints gbc_horizontalStrut = new GridBagConstraints();
+		gbc_horizontalStrut.insets = new Insets(0, 0, 0, 5);
+		gbc_horizontalStrut.gridx = 2;
+		gbc_horizontalStrut.gridy = 0;
+		header.add(horizontalStrut, gbc_horizontalStrut);
+		
+		JLabel lblLevel = new JLabel("Level:");
+		lblLevel.setFont(new Font("Tahoma", Font.BOLD, 14));
+		GridBagConstraints gbc_lblLevel = new GridBagConstraints();
+		gbc_lblLevel.insets = new Insets(0, 0, 0, 5);
+		gbc_lblLevel.anchor = GridBagConstraints.EAST;
+		gbc_lblLevel.gridx = 3;
+		gbc_lblLevel.gridy = 0;
+		header.add(lblLevel, gbc_lblLevel);
+		
 		JTextField levelField = new JTextField();
-		levelField.setEditable(false);
 		GridBagConstraints gbc_levelField = new GridBagConstraints();
-		gbc_levelField.fill = GridBagConstraints.HORIZONTAL;
-		gbc_levelField.gridx = 1;
+		gbc_levelField.insets = new Insets(0, 0, 0, 5);
+		gbc_levelField.gridx = 4;
 		gbc_levelField.gridy = 0;
-		add(levelField, gbc_levelField);
+		header.add(levelField, gbc_levelField);
+		levelField.setEditable(false);
 		levelField.setColumns(10);
-		
-		nameField.setText(model.getName());
 		levelField.setText(StringHelper.toString(model.getLevel()));
+		
+		JPanel levelBenefits = new JPanel();
+		GridBagConstraints gbc_levelBenefits = new GridBagConstraints();
+		gbc_levelBenefits.insets = new Insets(0, 0, 5, 0);
+		gbc_levelBenefits.fill = GridBagConstraints.BOTH;
+		gbc_levelBenefits.gridx = 0;
+		gbc_levelBenefits.gridy = 1;
+		add(levelBenefits, gbc_levelBenefits);
+		
+		if (model.getSpellBook().isPresent()) {
+			SpellPanel spells = new SpellPanel(model);
+			GridBagConstraints gbc_spells = new GridBagConstraints();
+			gbc_spells.fill = GridBagConstraints.BOTH;
+			gbc_spells.gridx = 0;
+			gbc_spells.gridy = 2;
+			add(spells, gbc_spells);
+		}
 	}
 	
 	@Override

+ 50 - 0
src/org/leumasjaffe/charsheet/view/magic/SpellLevelPanel.java

@@ -0,0 +1,50 @@
+package org.leumasjaffe.charsheet.view.magic;
+
+import javax.swing.JPanel;
+import java.awt.GridBagLayout;
+import java.awt.Component;
+import javax.swing.Box;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.util.Collection;
+
+import javax.swing.JLabel;
+
+import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+
+public class SpellLevelPanel extends JPanel {
+	public SpellLevelPanel(JPanel header, Collection<DDSpell> spells) {
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0};
+		gridBagLayout.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, 1.0, 0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		GridBagConstraints gbc_panel_1 = new GridBagConstraints();
+		gbc_panel_1.gridwidth = 2;
+		gbc_panel_1.insets = new Insets(0, 0, 5, 0);
+		gbc_panel_1.fill = GridBagConstraints.BOTH;
+		gbc_panel_1.gridx = 0;
+		gbc_panel_1.gridy = 0;
+		add(header, gbc_panel_1);
+		
+		JPanel panel = new JPanel(new VerticalLayout());
+		GridBagConstraints gbc_panel = new GridBagConstraints();
+		gbc_panel.insets = new Insets(0, 0, 5, 0);
+		gbc_panel.fill = GridBagConstraints.BOTH;
+		gbc_panel.gridx = 1;
+		gbc_panel.gridy = 1;
+		add(panel, gbc_panel);
+		spells.forEach(spell -> panel.add(new JLabel(spell.getName())));
+		
+		Component horizontalStrut = Box.createHorizontalStrut(20);
+		GridBagConstraints gbc_horizontalStrut = new GridBagConstraints();
+		gbc_horizontalStrut.insets = new Insets(0, 0, 0, 5);
+		gbc_horizontalStrut.gridx = 0;
+		gbc_horizontalStrut.gridy = 2;
+		add(horizontalStrut, gbc_horizontalStrut);
+	}
+
+}

+ 90 - 0
src/org/leumasjaffe/charsheet/view/magic/SpellPanel.java

@@ -0,0 +1,90 @@
+package org.leumasjaffe.charsheet.view.magic;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import java.awt.GridBagLayout;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import javax.swing.JTabbedPane;
+
+import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.charsheet.model.DDCharacterClass;
+import org.leumasjaffe.charsheet.model.DDClass;
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.charsheet.model.magic.DDSpellList;
+import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
+
+import java.awt.GridBagConstraints;
+
+public class SpellPanel extends JPanel {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private final int highestSpellLevel;
+
+	public SpellPanel(final DDCharacterClass cclass) {
+		highestSpellLevel = calcHighestSpellLevel(cclass);
+		final DDSpellbook model = cclass.getSpellBook().get();
+		
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JTabbedPane spellsPane = new JTabbedPane(JTabbedPane.TOP);
+		GridBagConstraints gbc_spells = new GridBagConstraints();
+		gbc_spells.fill = GridBagConstraints.BOTH;
+		gbc_spells.gridx = 0;
+		gbc_spells.gridy = 0;
+		add(spellsPane, gbc_spells);
+		
+		JScrollPane preparedPane = new JScrollPane();
+		spellsPane.addTab("Prepared", null, preparedPane, "Spells the character can use today");
+		generateSpellTree((l, e) -> new SpellsPerDayHeader(l, e, model.numSpellsPerDayAtLevel(l)),
+				i -> model.spellsPreparedAtLevel(i), preparedPane);
+
+		JScrollPane knownPane = new JScrollPane();
+		spellsPane.addTab("Known", null, knownPane, "Spells the player knows for this class");
+		generateSpellTree((l, e) -> new SpellsKnownHeader(l, model.numSpellsKnownAtLevel(l)), 
+				i -> model.spellsKnownAtLevel(i), knownPane);
+	}
+
+	private static int calcHighestSpellLevel(final DDCharacterClass cclass) {
+		int level = 0;
+		final DDSpellList spellList = DDClass.getFromResource(cclass.getName()).getSpells().get();
+		final int cLvl = cclass.getLevel();
+		if (spellList.getKnown().isEmpty()) {
+			List<Integer> list = spellList.getPerDay().get(cLvl);
+			level = list.size() - 1;
+			if (list.get(list.size()-1) == 0) {
+				--level;
+			}
+		} else {
+			level = spellList.getKnown().get(cLvl).size()-1;
+		}
+		return level;
+	}
+
+	private void generateSpellTree(final BiFunction<Integer, Integer, JPanel> getPanel,
+			final Function<Integer, Collection<DDSpell>> getSpells, final JScrollPane preparedPane) {
+		JPanel root = new JPanel();
+		root.setLayout(new VerticalLayout());
+		
+		int i = 0;
+		for (Collection<DDSpell> spells = getSpells.apply(i);
+				spells != null && i < highestSpellLevel; 
+				spells = getSpells.apply(++i)) {
+			root.add(new SpellLevelPanel(getPanel.apply(i, spells.size()), spells));
+		}
+		
+		preparedPane.setViewportView(root);
+	}
+
+}

+ 56 - 0
src/org/leumasjaffe/charsheet/view/magic/SpellsKnownHeader.java

@@ -0,0 +1,56 @@
+package org.leumasjaffe.charsheet.view.magic;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import org.leumasjaffe.charsheet.util.StringHelper;
+
+public class SpellsKnownHeader extends JPanel {
+	public SpellsKnownHeader(int level, int elems) {
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JLabel lblSpellLevel = new JLabel("Spell Level:");
+		GridBagConstraints gbc_lblSpellLevel = new GridBagConstraints();
+		gbc_lblSpellLevel.insets = new Insets(0, 0, 0, 5);
+		gbc_lblSpellLevel.anchor = GridBagConstraints.EAST;
+		gbc_lblSpellLevel.gridx = 0;
+		gbc_lblSpellLevel.gridy = 0;
+		add(lblSpellLevel, gbc_lblSpellLevel);
+		
+		JTextField textFieldLevel = new JTextField(Integer.toString(level));
+		textFieldLevel.setEditable(false);
+		GridBagConstraints gbc_textFieldLevel = new GridBagConstraints();
+		gbc_textFieldLevel.insets = new Insets(0, 0, 0, 5);
+		gbc_textFieldLevel.fill = GridBagConstraints.HORIZONTAL;
+		gbc_textFieldLevel.gridx = 1;
+		gbc_textFieldLevel.gridy = 0;
+		add(textFieldLevel, gbc_textFieldLevel);
+		textFieldLevel.setColumns(10);
+		
+		JLabel lblSpellsPerDay = new JLabel("Spells Known:");
+		GridBagConstraints gbc_lblSpellsPerDay = new GridBagConstraints();
+		gbc_lblSpellsPerDay.insets = new Insets(0, 0, 0, 5);
+		gbc_lblSpellsPerDay.gridx = 2;
+		gbc_lblSpellsPerDay.gridy = 0;
+		add(lblSpellsPerDay, gbc_lblSpellsPerDay);
+		
+		JTextField textFieldRemaining = new JTextField(StringHelper.toString(elems, -1, "--"));
+		GridBagConstraints gbc_textFieldRemaining = new GridBagConstraints();
+		gbc_textFieldRemaining.insets = new Insets(0, 0, 0, 5);
+		gbc_textFieldRemaining.gridx = 3;
+		gbc_textFieldRemaining.gridy = 0;
+		add(textFieldRemaining, gbc_textFieldRemaining);
+		textFieldRemaining.setEditable(false);
+		textFieldRemaining.setColumns(10);
+	}
+}

+ 69 - 0
src/org/leumasjaffe/charsheet/view/magic/SpellsPerDayHeader.java

@@ -0,0 +1,69 @@
+package org.leumasjaffe.charsheet.view.magic;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class SpellsPerDayHeader extends JPanel {
+	public SpellsPerDayHeader(int level, int elems, int perDay) {
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JLabel lblSpellLevel = new JLabel("Spell Level:");
+		GridBagConstraints gbc_lblSpellLevel = new GridBagConstraints();
+		gbc_lblSpellLevel.insets = new Insets(0, 0, 0, 5);
+		gbc_lblSpellLevel.anchor = GridBagConstraints.EAST;
+		gbc_lblSpellLevel.gridx = 0;
+		gbc_lblSpellLevel.gridy = 0;
+		add(lblSpellLevel, gbc_lblSpellLevel);
+		
+		JTextField textFieldLevel = new JTextField(Integer.toString(level));
+		textFieldLevel.setEditable(false);
+		GridBagConstraints gbc_textFieldLevel = new GridBagConstraints();
+		gbc_textFieldLevel.insets = new Insets(0, 0, 0, 5);
+		gbc_textFieldLevel.fill = GridBagConstraints.HORIZONTAL;
+		gbc_textFieldLevel.gridx = 1;
+		gbc_textFieldLevel.gridy = 0;
+		add(textFieldLevel, gbc_textFieldLevel);
+		textFieldLevel.setColumns(10);
+		
+		JLabel lblSpellsPerDay = new JLabel("Spells Per Day:");
+		GridBagConstraints gbc_lblSpellsPerDay = new GridBagConstraints();
+		gbc_lblSpellsPerDay.insets = new Insets(0, 0, 0, 5);
+		gbc_lblSpellsPerDay.gridx = 2;
+		gbc_lblSpellsPerDay.gridy = 0;
+		add(lblSpellsPerDay, gbc_lblSpellsPerDay);
+		
+		JTextField textFieldRemaining = new JTextField(Integer.toString(elems));
+		GridBagConstraints gbc_textFieldRemaining = new GridBagConstraints();
+		gbc_textFieldRemaining.insets = new Insets(0, 0, 0, 5);
+		gbc_textFieldRemaining.gridx = 3;
+		gbc_textFieldRemaining.gridy = 0;
+		add(textFieldRemaining, gbc_textFieldRemaining);
+		textFieldRemaining.setEditable(false);
+		textFieldRemaining.setColumns(10);
+		
+		JLabel label = new JLabel("/");
+		GridBagConstraints gbc_label = new GridBagConstraints();
+		gbc_label.insets = new Insets(0, 0, 0, 5);
+		gbc_label.gridx = 4;
+		gbc_label.gridy = 0;
+		add(label, gbc_label);
+		
+		JTextField textFieldOutOf = new JTextField(Integer.toString(perDay));
+		GridBagConstraints gbc_textFieldOutOf = new GridBagConstraints();
+		gbc_textFieldOutOf.gridx = 5;
+		gbc_textFieldOutOf.gridy = 0;
+		add(textFieldOutOf, gbc_textFieldOutOf);
+		textFieldOutOf.setEditable(false);
+		textFieldOutOf.setColumns(10);
+	}
+}