فهرست منبع

Move updating features to own panel definition.
This panel will contain:
- Hit Dice
- Current+New Features (partial)
- Ability Score (complete)
- Feats

Sam Jaffe 8 سال پیش
والد
کامیت
2620fb4c7e

+ 185 - 0
src/main/lombok/org/leumasjaffe/charsheet/view/level/LU_AbilityPanel.java

@@ -0,0 +1,185 @@
+package org.leumasjaffe.charsheet.view.level;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.SwingConstants;
+import javax.swing.border.LineBorder;
+
+import org.leumasjaffe.charsheet.model.Ability;
+import org.leumasjaffe.charsheet.model.observable.BoolGate;
+import org.leumasjaffe.charsheet.model.observable.IntValue;
+import org.leumasjaffe.charsheet.view.summary.AbilityBox;
+import org.leumasjaffe.observer.ObserverDispatch;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+import lombok.AccessLevel;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import lombok.experimental.NonFinal;
+
+@SuppressWarnings("serial")
+public class LU_AbilityPanel extends JPanel {
+	private static final String[] abils = new String[] { "STR", "DEX", "CON", "INT", "WIS", "CHA" };
+	private static final List<Function<Ability, Ability.Scores>> funcs = Arrays.asList( 
+		Ability::getStr, Ability::getDex, Ability::getCon,
+		Ability::getInt, Ability::getWis, Ability::getCha
+		);
+	static ObjectMapper mapper = new ObjectMapper();
+	static {
+		mapper.registerModule(new Jdk8Module());
+	}
+	Ability ability;
+	BoolGate.Handle gate;
+	boolean canGainAbility;
+	@NonFinal @Setter(AccessLevel.PRIVATE) int currentSelection = -1;
+	JPanel abilityGrowth;
+
+	public LU_AbilityPanel(LevelUpClassInfo info, BoolGate.Handle gate) {
+		this.ability = clone(info.ddCharacter.getAbilities());
+		this.gate = gate;
+		this.canGainAbility = info.ddCharacter.getLevel() % 4 == 3;
+		this.gate.set(null, !canGainAbility);
+		ButtonGroup group = new ButtonGroup();
+
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0};
+		gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JLabel lblAbilityScores = new JLabel("Ability Scores");
+		lblAbilityScores.setToolTipText("When your total character level (Hit Dice) is a multiple of four, " +
+				"you can increase one ability score by one point.");
+		GridBagConstraints gbc_lblAbilityScores = new GridBagConstraints();
+		gbc_lblAbilityScores.insets = new Insets(0, 0, 5, 0);
+		gbc_lblAbilityScores.gridx = 0;
+		gbc_lblAbilityScores.gridy = 0;
+		add(lblAbilityScores, gbc_lblAbilityScores);
+		
+		abilityGrowth = new JPanel();
+		GridBagConstraints gbc_abilGrowth = new GridBagConstraints();
+		gbc_abilGrowth.insets = new Insets(0, 0, 5, 0);
+		gbc_abilGrowth.fill = GridBagConstraints.BOTH;
+		gbc_abilGrowth.gridx = 0;
+		gbc_abilGrowth.gridy = 1;
+		add(abilityGrowth, gbc_abilGrowth);
+		GridBagLayout gbl_abilGrowth = new GridBagLayout();
+		gbl_abilGrowth.columnWidths = new int[]{0, 0, 0, 0};
+		gbl_abilGrowth.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0};
+		gbl_abilGrowth.columnWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE};
+		gbl_abilGrowth.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
+		abilityGrowth.setLayout(gbl_abilGrowth);
+		
+		JPanel panel_2 = new JPanel();
+		GridBagConstraints gbc_panel_2 = new GridBagConstraints();
+		gbc_panel_2.insets = new Insets(0, 0, 5, 0);
+		gbc_panel_2.fill = GridBagConstraints.BOTH;
+		gbc_panel_2.gridx = 0;
+		gbc_panel_2.gridy = 2;
+		add(panel_2, gbc_panel_2);
+		GridBagLayout gbl_panel_2 = new GridBagLayout();
+		gbl_panel_2.columnWidths = new int[]{0, 0, 0};
+		gbl_panel_2.rowHeights = new int[]{0, 0};
+		gbl_panel_2.columnWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
+		gbl_panel_2.rowWeights = new double[]{0.0, Double.MIN_VALUE};
+		panel_2.setLayout(gbl_panel_2);
+		
+		JButton btnClear = new JButton("Clear");
+		GridBagConstraints gbc_btnClear = new GridBagConstraints();
+		gbc_btnClear.gridx = 1;
+		gbc_btnClear.gridy = 0;
+		panel_2.add(btnClear, gbc_btnClear);
+		btnClear.setEnabled(canGainAbility);
+		btnClear.addActionListener(e -> {
+			gate.set(null, false);
+			group.clearSelection();
+			resetAbility();
+		});
+		
+		for (int i = 0; i < 6; ++i) {
+			createAbilityLine(i, group);
+		}
+	}
+
+	private void createAbilityLine(int y, ButtonGroup group) {
+		JLabel label = new JLabel(abils[y].toUpperCase());
+		label.setPreferredSize(new Dimension(50, 25));
+		label.setOpaque(true);
+		label.setMinimumSize(new Dimension(50, 25));
+		label.setMaximumSize(new Dimension(50, 25));
+		label.setHorizontalAlignment(SwingConstants.CENTER);
+		label.setForeground(Color.WHITE);
+		label.setFont(new Font("Tahoma", Font.BOLD, 18));
+		label.setBorder(new LineBorder(Color.WHITE));
+		label.setBackground(Color.BLACK);
+		GridBagConstraints gbc_label = new GridBagConstraints();
+		gbc_label.gridx = 0;
+		gbc_label.gridy = y;
+		abilityGrowth.add(label, gbc_label);
+		
+		AbilityBox abilityBox = new AbilityBox(abils[y], "Ability");
+		GridBagConstraints gbc_abilityBox = new GridBagConstraints();
+		gbc_abilityBox.fill = GridBagConstraints.BOTH;
+		gbc_abilityBox.gridx = 1;
+		gbc_abilityBox.gridy = y;
+		abilityGrowth.add(abilityBox, gbc_abilityBox);
+		
+		abilityBox.setModel(funcs.get(y).apply(this.ability).getBase());
+		
+		JRadioButton radioButton = new JRadioButton("");
+		GridBagConstraints gbc_radioButton = new GridBagConstraints();
+		gbc_radioButton.gridx = 2;
+		gbc_radioButton.gridy = y;
+		abilityGrowth.add(radioButton, gbc_radioButton);
+		group.add(radioButton);
+		radioButton.addActionListener(e -> {
+			resetAbility();
+			setCurrentSelection(y);
+			updateAbility(this.ability, true);
+			gate.set(null, true);
+		});
+		radioButton.setEnabled(canGainAbility);
+	}
+
+	private void resetAbility() {
+		updateAbility(this.ability, false);
+	}
+	
+	public void commitChange(Ability ability) {
+		updateAbility(ability, true);
+		this.currentSelection = -1;
+	}
+
+	private void updateAbility(Ability ability, boolean increase) {
+		if (currentSelection != -1) {
+			IntValue val = funcs.get(currentSelection).apply(ability).getBase();
+			val.value(val.value() + (increase ? 1 : -1));
+			ObserverDispatch.notifySubscribers(val);
+		}
+	}
+
+	@SneakyThrows({JsonParseException.class, JsonMappingException.class, JsonProcessingException.class, IOException.class})
+	private Ability clone(Ability abilities) {
+		return mapper.readValue(mapper.writeValueAsBytes(abilities), Ability.class);
+	}
+}

+ 65 - 0
src/main/lombok/org/leumasjaffe/charsheet/view/level/LU_FeaturesPanel.java

@@ -0,0 +1,65 @@
+package org.leumasjaffe.charsheet.view.level;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.jdesktop.swingx.VerticalLayout;
+import org.leumasjaffe.charsheet.model.observable.BoolGate;
+import org.leumasjaffe.observer.ObservableListener;
+import org.leumasjaffe.observer.ObserverDispatch;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+
+@SuppressWarnings("serial")
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+class LU_FeaturesPanel extends JPanel {
+	static int HD_INDEX = 0, ABIL_INDEX = 1, FEAT_INDEX = 2;
+	ObservableListener<LU_FeaturesPanel, BoolGate> listener;
+	
+	public LU_FeaturesPanel(LevelUpClassInfo info, BoolGate.Handle ready) {		
+		BoolGate gate = new BoolGate(3);
+		gate.set(HD_INDEX, true);
+		gate.set(FEAT_INDEX, true); // TODO Feats
+
+		GridBagLayout gridBagLayout = new GridBagLayout();
+		gridBagLayout.columnWidths = new int[]{0, 0, 0};
+		gridBagLayout.rowHeights = new int[]{0, 0};
+		gridBagLayout.columnWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
+		gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE};
+		setLayout(gridBagLayout);
+		
+		JPanel features = new JPanel(new VerticalLayout(2));
+		GridBagConstraints gbc_panel = new GridBagConstraints();
+		gbc_panel.insets = new Insets(0, 0, 0, 5);
+		gbc_panel.fill = GridBagConstraints.BOTH;
+		gbc_panel.gridx = 0;
+		gbc_panel.gridy = 0;
+		add(features, gbc_panel);
+		info.ddClass.getProto().getFeatures(info.toLevel).forEach(prop -> {
+			features.add(new JLabel(prop.getName()));
+		});
+		
+		LU_AbilityPanel abilPanel = new LU_AbilityPanel(info, gate.handle(ABIL_INDEX));
+		GridBagConstraints gbc_abilPanel = new GridBagConstraints();
+		gbc_abilPanel.fill = GridBagConstraints.BOTH;
+		gbc_abilPanel.gridx = 1;
+		gbc_abilPanel.gridy = 0;
+		add(abilPanel, gbc_abilPanel);
+		
+		this.listener = new ObservableListener<>(this, (c, v) -> {
+			ready.set(null, v.all());
+		});
+		this.listener.setObserved(gate);
+	}
+	
+	@Override
+	public void removeNotify() {
+		super.removeNotify();
+		ObserverDispatch.unsubscribeAll(listener);
+	}
+}

+ 3 - 8
src/main/lombok/org/leumasjaffe/charsheet/view/level/UpdateClassWithLevelPanel.java

@@ -12,7 +12,6 @@ import java.util.function.Consumer;
 
 import javax.swing.JPanel;
 
-import org.jdesktop.swingx.VerticalLayout;
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
 import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
@@ -37,12 +36,11 @@ import java.awt.Insets;
 import java.awt.Component;
 import javax.swing.Box;
 import javax.swing.JButton;
-import javax.swing.JLabel;
 
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 class UpdateClassWithLevelPanel extends JPanel {
-	static int CHOOSE_SKILL_INDEX = 0, LEARN_SPELL_INDEX = 1, PREPARE_SPELL_INDEX = 2;
+	static int FEATURE_INDEX = 0, CHOOSE_SKILL_INDEX = 1, LEARN_SPELL_INDEX = 2, PREPARE_SPELL_INDEX = 3;
 
 	LevelUpClassInfo levelUpInfo;
 	JTabbedPane tabbedPane;
@@ -51,7 +49,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 	@NonFinal Optional<LevelUpSpellPanel> learnSpells = Optional.empty();
 	@NonFinal Optional<LevelUpSpellPanel> prepSpells = Optional.empty();
 	
-	BoolGate readyCount = new BoolGate(3);
+	BoolGate readyCount = new BoolGate(4);
 	ObservableListener<Consumer<Boolean>, BoolGate> listener;
 	@NonFinal ObservableListener<UpdateClassWithLevelPanel, BoolGate> learnAndPrepareListener = null;
 	
@@ -74,10 +72,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 		gbc_tabbedPane.gridy = 0;
 		add(tabbedPane, gbc_tabbedPane);
 
-		JPanel features = new JPanel(new VerticalLayout(2));
-		info.ddClass.getProto().getFeatures(info.toLevel).forEach(prop -> {
-			features.add(new JLabel(prop.getName()));
-		});
+		JPanel features = new LU_FeaturesPanel(info, readyCount.handle(FEATURE_INDEX));
 		tabbedPane.addTab("Features", null, features, null);
 
 		skills = new SkillLevelUpPanel(info.ddCharacter, info.ddClass) {

+ 1 - 4
src/main/lombok/org/leumasjaffe/charsheet/view/summary/AbilityBox.java

@@ -28,12 +28,9 @@ import lombok.experimental.FieldDefaults;
 
 import javax.swing.SwingConstants;
 
+@SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class AbilityBox extends JPanel {
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
 	ObservableListener<JTextField, IntValue> valueListener;
 	ObservableListener<JTextField, IntValue> modListener;
 	

+ 1 - 4
src/main/lombok/org/leumasjaffe/charsheet/view/summary/AbilityLine.java

@@ -17,12 +17,9 @@ import java.awt.GridBagConstraints;
 import java.awt.Dimension;
 import javax.swing.SwingConstants;
 
+@SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class AbilityLine extends JPanel {
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
 	Function<Ability, Ability.Scores> access;
 	AbilityBox ability;
 	AbilityBox temporary;

+ 1 - 4
src/main/lombok/org/leumasjaffe/charsheet/view/summary/AbilityPanel.java

@@ -15,12 +15,9 @@ import org.leumasjaffe.charsheet.model.Ability;
 import lombok.AccessLevel;
 import lombok.experimental.FieldDefaults;
 
+@SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 public class AbilityPanel extends JPanel {
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
 	private static final String[] abils = new String[] { "STR", "DEX", "CON", "INT", "WIS", "CHA" };
 	private static final List<Function<Ability, Ability.Scores>> funcs = Arrays.asList( 
 		Ability::getStr, Ability::getDex, Ability::getCon,