|
|
@@ -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);
|
|
|
+ }
|
|
|
+}
|