Jelajahi Sumber

Adding GUI elements for Skills
Loading of default skills into the prototype list occurs on program start

Sam Jaffe 9 tahun lalu
induk
melakukan
46cfa0e76d

+ 1 - 1
resources/Potato.json

@@ -59,7 +59,7 @@
     {"name":"Knowledege (Religion)","ability":"INT","isClassSkill":true,"requiresTraining":true,"ranks":5.0,"pointsSpent":5},
     {"name":"Knowledege (Nature)","ability":"INT","isClassSkill":true,"requiresTraining":true,"ranks":6.0,"pointsSpent":6},
     {"name":"Perform (Sing)","ability":"CHA","isClassSkill":true,"requiresTraining":true,"ranks":3.0,"pointsSpent":3}
-  ]
+  ],
   
   "inventory":{
     "items":[

+ 3 - 0
src/org/leumasjaffe/charsheet/model/DDCharacter.java

@@ -7,6 +7,7 @@ import java.util.Set;
 
 import org.leumasjaffe.charsheet.model.inventory.DDInventory;
 import org.leumasjaffe.charsheet.model.observable.ObjectValue;
+import org.leumasjaffe.charsheet.model.skill.DDSkills;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
@@ -46,6 +47,8 @@ public class DDCharacter {
 	
 	@NonNull Ability abilities = new Ability();
 	
+	@NonNull DDSkills skills = new DDSkills(Collections.emptyList());
+	
 	@NonNull DDInventory inventory = new DDInventory();
 
 	public String getClassAndLevelString() {

+ 23 - 5
src/org/leumasjaffe/charsheet/model/skill/DDSkillPrototype.java

@@ -1,9 +1,17 @@
 package org.leumasjaffe.charsheet.model.skill;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
@@ -22,19 +30,29 @@ public class DDSkillPrototype {
 	
 	static {
 		Map<String, DDSkillPrototype> tmp = new HashMap<>();
-		// TODO
+		final ObjectMapper mapper = new ObjectMapper();
+		mapper.registerModule(new Jdk8Module());
+		try {
+			final Collection<DDSkillPrototype> col = mapper.readValue(new File("resources/skills/skills.json"), 
+					mapper.getTypeFactory().constructCollectionType(Collection.class, DDSkillPrototype.class));
+			tmp = col.stream().collect(Collectors.toMap(t -> t.getName(), t -> t));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
 		prototypes = Collections.unmodifiableMap(tmp);
 	}
 	
 	public static Optional<DDSkillPrototype> getPrototype(String name) {
 		if (name.contains("(")) {
-			return Optional.ofNullable(getProtoTypeInternal(name.replaceFirst("(.*)", "(*)")));
+			DDSkillPrototype proto = prototypes.get(name.replaceFirst("(.*)", "(*)"));
+			if ( proto == null ) return Optional.empty();
+			return Optional.of(new DDSkillPrototype(name, proto.requiresTraining, proto.ability));
 		} else {
-			return Optional.ofNullable(getProtoTypeInternal(name));
+			return Optional.ofNullable(prototypes.get(name));
 		}
 	}
 
-	private static DDSkillPrototype getProtoTypeInternal(String name) {
-		return prototypes.get(name);
+	public static Stream<DDSkillPrototype> untrained() {
+		return prototypes.values().stream().filter(p -> !p.requiresTraining && !p.getName().contains("(*)"));
 	}
 }

+ 10 - 4
src/org/leumasjaffe/charsheet/model/skill/DDSkills.java

@@ -1,8 +1,9 @@
 package org.leumasjaffe.charsheet.model.skill;
 
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -13,15 +14,20 @@ import lombok.experimental.FieldDefaults;
 
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class DDSkills {
-	Map<String, DDSkill> skills = new HashMap<>();
+	Map<String, DDSkill> skills = new TreeMap<>();
 	
 	@JsonCreator
-	private DDSkills(Collection<DDSkill> in) {
-		in.stream().forEach( s -> skills.put(s.getName(), s) );
+	public DDSkills(Collection<DDSkill> in) {
+		skills.putAll(DDSkillPrototype.untrained().collect(Collectors.toMap(t -> t.getName(), t -> new DDSkill(t))));
+		skills.putAll(in.stream().collect(Collectors.toMap(t -> t.getName(), t -> t)));
 	}
 	
 	@JsonValue
 	private Collection<DDSkill> getSerial() {
 		return skills.values().stream().filter(s -> s.getPointsSpent() > 0).collect(Collectors.toList());
 	}
+
+	public Collection<DDSkill> getSkills() {
+		return Collections.unmodifiableCollection(skills.values());
+	}
 }

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

@@ -9,6 +9,10 @@ public class StringHelper {
 		else { return o.toString(); }
 	}
 	
+	public String toString(float f) {
+		return Float.toString(f);
+	}
+	
 	public String toString(int i) {
 		return Integer.toString(i);
 	}

+ 3 - 2
src/org/leumasjaffe/charsheet/view/D20Sheet.java

@@ -44,7 +44,7 @@ public class D20Sheet extends JFrame {
 	SummaryTab summaryTab;
 	List<ClassTab> classTabs = new ArrayList<>();
 	JPanel abilitiesTab;
-	JPanel skillTab;
+	SkillTab skillTab;
 	EquipmentTab equipmentTab;
 	
 	public D20Sheet() {
@@ -58,7 +58,7 @@ public class D20Sheet extends JFrame {
 		
 		summaryTab = new SummaryTab();
 		abilitiesTab = new JPanel();
-		skillTab = new JPanel();
+		skillTab = new SkillTab();
 		equipmentTab = new EquipmentTab();
 		
 		JMenuBar menuBar = new JMenuBar();
@@ -144,6 +144,7 @@ public class D20Sheet extends JFrame {
 		summaryTab.setModel(model);
 		model.getClasses().stream().forEach(cc -> classTabs.add(new ClassTab(cc)));
 		equipmentTab.setModel(model);
+		skillTab.setModel(model);
 		
 		reorderTabs();
 	}

+ 53 - 0
src/org/leumasjaffe/charsheet/view/SkillTab.java

@@ -0,0 +1,53 @@
+package org.leumasjaffe.charsheet.view;
+
+import javax.swing.JPanel;
+import java.awt.GridBagLayout;
+import javax.swing.JScrollPane;
+import java.awt.GridBagConstraints;
+import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.charsheet.model.DDCharacter;
+import org.leumasjaffe.charsheet.model.skill.DDSkills;
+import org.leumasjaffe.charsheet.view.skills.SkillLine;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import java.awt.Dimension;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class SkillTab extends JPanel {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	JPanel skillPanel;
+
+	public SkillTab() {
+		setPreferredSize(new Dimension(600, 300));
+		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);
+		
+		JScrollPane scrollPane = new JScrollPane();
+		GridBagConstraints gbc_scrollPane = new GridBagConstraints();
+		gbc_scrollPane.fill = GridBagConstraints.BOTH;
+		gbc_scrollPane.gridx = 0;
+		gbc_scrollPane.gridy = 0;
+		add(scrollPane, gbc_scrollPane);
+		
+		skillPanel = new JPanel();
+		scrollPane.setViewportView(skillPanel);
+		skillPanel.setLayout(new VerticalLayout());
+	}
+	
+	public void setModel(final DDCharacter model) {
+		skillPanel.removeAll();
+		final DDSkills skills = model.getSkills();
+		skills.getSkills().stream().forEach( skill -> {
+			skillPanel.add(new SkillLine(model, skill));
+		});
+	}
+	
+}

+ 177 - 0
src/org/leumasjaffe/charsheet/view/skills/SkillLine.java

@@ -0,0 +1,177 @@
+package org.leumasjaffe.charsheet.view.skills;
+
+import javax.swing.JPanel;
+
+import org.leumasjaffe.charsheet.model.Ability;
+import org.leumasjaffe.charsheet.model.DDCharacter;
+import org.leumasjaffe.charsheet.model.observable.IntValue;
+import org.leumasjaffe.charsheet.model.skill.DDSkill;
+import org.leumasjaffe.charsheet.util.StringHelper;
+import org.leumasjaffe.observer.IndirectObservableListener;
+import org.leumasjaffe.observer.ObservableListener;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+
+import java.awt.GridBagLayout;
+import javax.swing.JCheckBox;
+import java.awt.GridBagConstraints;
+import javax.swing.JLabel;
+import java.awt.Insets;
+import java.awt.Dimension;
+import javax.swing.JTextField;
+import java.awt.Color;
+import javax.swing.border.MatteBorder;
+import javax.swing.SwingConstants;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class SkillLine extends JPanel {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	ObservableListener<JTextField, IntValue> modifierListener;
+	IndirectObservableListener<JTextField, DDCharacter> totalListener;
+
+	public SkillLine(final DDCharacter chara, final DDSkill skill) {
+		setBorder(new MatteBorder(0, 0, 1, 0, (Color) new Color(0, 0, 0)));
+		setPreferredSize(new Dimension(550, 22));
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JCheckBox checkBoxIsClassSkill = new JCheckBox("");
+		checkBoxIsClassSkill.setToolTipText("Class Skill?");
+		checkBoxIsClassSkill.setSelected(skill.isClassSkill());
+		checkBoxIsClassSkill.setEnabled(false);
+		GridBagConstraints gbc_checkBoxIsClassSkill = new GridBagConstraints();
+		gbc_checkBoxIsClassSkill.insets = new Insets(1, 0, 0, 0);
+		gbc_checkBoxIsClassSkill.gridx = 0;
+		gbc_checkBoxIsClassSkill.gridy = 0;
+		add(checkBoxIsClassSkill, gbc_checkBoxIsClassSkill);
+		
+		JLabel lblName = new JLabel(skill.getName());
+		lblName.setMaximumSize(new Dimension(150, 14));
+		lblName.setMinimumSize(new Dimension(150, 14));
+		lblName.setPreferredSize(new Dimension(150, 14));
+		GridBagConstraints gbc_lblName = new GridBagConstraints();
+		gbc_lblName.fill = GridBagConstraints.HORIZONTAL;
+		gbc_lblName.insets = new Insets(1, 0, 0, 0);
+		gbc_lblName.gridx = 1;
+		gbc_lblName.gridy = 0;
+		add(lblName, gbc_lblName);
+		
+		JLabel lblAbil = new JLabel(skill.getAbility());
+		lblAbil.setMaximumSize(new Dimension(30, 14));
+		lblAbil.setMinimumSize(new Dimension(30, 14));
+		lblAbil.setPreferredSize(new Dimension(30, 14));
+		GridBagConstraints gbc_lblAbil = new GridBagConstraints();
+		gbc_lblAbil.insets = new Insets(1, 0, 0, 0);
+		gbc_lblAbil.anchor = GridBagConstraints.EAST;
+		gbc_lblAbil.gridx = 2;
+		gbc_lblAbil.gridy = 0;
+		add(lblAbil, gbc_lblAbil);
+		
+		JTextField total = new JTextField();
+		total.setToolTipText("Skill Modifier");
+		total.setHorizontalAlignment(SwingConstants.CENTER);
+		total.setEditable(false);
+		total.setMinimumSize(new Dimension(30, 20));
+		total.setMaximumSize(new Dimension(30, 20));
+		total.setPreferredSize(new Dimension(30, 20));
+		GridBagConstraints gbc_total = new GridBagConstraints();
+		gbc_total.insets = new Insets(1, 0, 0, 0);
+		gbc_total.fill = GridBagConstraints.HORIZONTAL;
+		gbc_total.gridx = 3;
+		gbc_total.gridy = 0;
+		add(total, gbc_total);
+		total.setColumns(10);
+		
+		JLabel label = new JLabel("=");
+		GridBagConstraints gbc_label = new GridBagConstraints();
+		gbc_label.anchor = GridBagConstraints.EAST;
+		gbc_label.insets = new Insets(1, 0, 0, 1);
+		gbc_label.gridx = 4;
+		gbc_label.gridy = 0;
+		add(label, gbc_label);
+		
+		JTextField modifier = new JTextField();
+		modifier.setToolTipText("Ability Modifier");
+		modifier.setHorizontalAlignment(SwingConstants.CENTER);
+		modifier.setEditable(false);
+		modifier.setMinimumSize(new Dimension(30, 20));
+		modifier.setMaximumSize(new Dimension(30, 20));
+		modifier.setPreferredSize(new Dimension(30, 20));
+		GridBagConstraints gbc_modifier = new GridBagConstraints();
+		gbc_modifier.insets = new Insets(1, 0, 0, 0);
+		gbc_modifier.fill = GridBagConstraints.HORIZONTAL;
+		gbc_modifier.gridx = 5;
+		gbc_modifier.gridy = 0;
+		add(modifier, gbc_modifier);
+		modifier.setColumns(10);
+		
+		JLabel label_1 = new JLabel("+");
+		GridBagConstraints gbc_label_1 = new GridBagConstraints();
+		gbc_label_1.anchor = GridBagConstraints.EAST;
+		gbc_label_1.insets = new Insets(1, 0, 0, 1);
+		gbc_label_1.gridx = 6;
+		gbc_label_1.gridy = 0;
+		add(label_1, gbc_label_1);
+		
+		JTextField ranks = new JTextField(StringHelper.toString(skill.getRanks()));
+		ranks.setToolTipText("Ranks");
+		ranks.setHorizontalAlignment(SwingConstants.CENTER);
+		ranks.setEditable(false);
+		ranks.setMinimumSize(new Dimension(30, 20));
+		ranks.setMaximumSize(new Dimension(30, 20));
+		ranks.setPreferredSize(new Dimension(30, 20));
+		GridBagConstraints gbc_ranks = new GridBagConstraints();
+		gbc_ranks.insets = new Insets(1, 0, 0, 0);
+		gbc_ranks.fill = GridBagConstraints.HORIZONTAL;
+		gbc_ranks.gridx = 7;
+		gbc_ranks.gridy = 0;
+		add(ranks, gbc_ranks);
+		ranks.setColumns(10);
+		
+		JLabel label_2 = new JLabel("+");
+		GridBagConstraints gbc_label_2 = new GridBagConstraints();
+		gbc_label_2.insets = new Insets(1, 0, 0, 1);
+		gbc_label_2.anchor = GridBagConstraints.EAST;
+		gbc_label_2.gridx = 8;
+		gbc_label_2.gridy = 0;
+		add(label_2, gbc_label_2);
+		
+		JTextField misc = new JTextField();
+		misc.setToolTipText("Miscellaneous Modifier");
+		misc.setHorizontalAlignment(SwingConstants.CENTER);
+		misc.setMinimumSize(new Dimension(30, 20));
+		misc.setMaximumSize(new Dimension(30, 20));
+		misc.setPreferredSize(new Dimension(30, 20));
+		GridBagConstraints gbc_misc = new GridBagConstraints();
+		gbc_misc.insets = new Insets(1, 0, 0, 0);
+		gbc_misc.fill = GridBagConstraints.HORIZONTAL;
+		gbc_misc.gridx = 9;
+		gbc_misc.gridy = 0;
+		add(misc, gbc_misc);
+		misc.setColumns(10);
+		
+		totalListener = new IndirectObservableListener<>(total,
+				(c, v) -> {
+					final float skillRanks = skill.getRanks();
+					final int mod = Ability.modifier(Ability.fields.get(skill.getAbility())
+							.apply(chara.getAbilities().getBase()).value());
+					c.setText(StringHelper.toString(skillRanks + mod));
+				});
+		modifierListener = new ObservableListener<>(modifier, 
+				( c, v ) -> c.setText(StringHelper.toString(Ability.modifier(v.value()))));
+		
+		final IntValue abilScore = Ability.fields.get(skill.getAbility())
+				.apply(chara.getAbilities().getBase());
+		totalListener.setObserved(chara, abilScore);
+		modifierListener.setObserved(abilScore);
+	}
+	
+}