SkillLevelUpLine.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. package org.leumasjaffe.charsheet.view.skills;
  2. import javax.swing.JPanel;
  3. import org.leumasjaffe.charsheet.model.Ability;
  4. import org.leumasjaffe.charsheet.model.DDCharacter;
  5. import org.leumasjaffe.charsheet.model.DDCharacterClass;
  6. import org.leumasjaffe.charsheet.model.observable.IntValue;
  7. import org.leumasjaffe.charsheet.model.skill.DDSkill;
  8. import org.leumasjaffe.charsheet.util.AbilityHelper;
  9. import org.leumasjaffe.format.StringHelper;
  10. import org.leumasjaffe.observer.IndirectObservableListener;
  11. import org.leumasjaffe.observer.ObserverDispatch;
  12. import lombok.AccessLevel;
  13. import lombok.Value;
  14. import lombok.experimental.FieldDefaults;
  15. import java.awt.GridBagLayout;
  16. import javax.swing.JCheckBox;
  17. import java.awt.GridBagConstraints;
  18. import javax.swing.JLabel;
  19. import java.awt.Insets;
  20. import java.util.Optional;
  21. import java.util.function.IntFunction;
  22. import java.awt.Dimension;
  23. import javax.swing.JTextField;
  24. import java.awt.Color;
  25. import javax.swing.border.MatteBorder;
  26. import javax.swing.SwingConstants;
  27. import java.awt.Component;
  28. import javax.swing.Box;
  29. import javax.swing.JButton;
  30. import java.awt.Font;
  31. @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
  32. class SkillLevelUpLine extends JPanel {
  33. /**
  34. *
  35. */
  36. private static final long serialVersionUID = 1L;
  37. boolean isClassSkill;
  38. DDSkill skill;
  39. IntValue current;
  40. IndirectObservableListener<JTextField, TotalPacket> totalListener;
  41. @Value
  42. private static final class TotalPacket {
  43. Optional<Ability.Scores> ability;
  44. DDSkill skill;
  45. IntValue points;
  46. }
  47. public SkillLevelUpLine(final DDCharacter chara, final DDCharacterClass cclass, final DDSkill skill, IntValue pointsAvaliable) {
  48. isClassSkill = cclass.isClassSkill(skill.getName());
  49. this.skill = skill;
  50. current = new IntValue(0);
  51. final int pointsPerRank = isClassSkill ? 1 : 2;
  52. final int maxPoints = (chara.getLevel() + 3) / pointsPerRank - skill.getRanks().value();
  53. setBorder(new MatteBorder(0, 0, 1, 0, (Color) new Color(0, 0, 0)));
  54. setPreferredSize(new Dimension(475, 22));
  55. GridBagLayout gridBagLayout = new GridBagLayout();
  56. gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  57. gridBagLayout.rowHeights = new int[]{0, 0};
  58. gridBagLayout.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
  59. gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
  60. setLayout(gridBagLayout);
  61. JCheckBox checkBoxIsClassSkill = new JCheckBox("");
  62. checkBoxIsClassSkill.setToolTipText("Class Skill?");
  63. checkBoxIsClassSkill.setSelected(cclass.isClassSkill(skill.getName()));
  64. checkBoxIsClassSkill.setEnabled(false);
  65. GridBagConstraints gbc_checkBoxIsClassSkill = new GridBagConstraints();
  66. gbc_checkBoxIsClassSkill.insets = new Insets(1, 0, 0, 5);
  67. gbc_checkBoxIsClassSkill.gridx = 0;
  68. gbc_checkBoxIsClassSkill.gridy = 0;
  69. add(checkBoxIsClassSkill, gbc_checkBoxIsClassSkill);
  70. JLabel lblName = new JLabel(skill.getName());
  71. lblName.setMaximumSize(new Dimension(150, 14));
  72. lblName.setMinimumSize(new Dimension(150, 14));
  73. lblName.setPreferredSize(new Dimension(150, 14));
  74. GridBagConstraints gbc_lblName = new GridBagConstraints();
  75. gbc_lblName.fill = GridBagConstraints.HORIZONTAL;
  76. gbc_lblName.insets = new Insets(1, 0, 0, 5);
  77. gbc_lblName.gridx = 1;
  78. gbc_lblName.gridy = 0;
  79. add(lblName, gbc_lblName);
  80. JLabel lblAbil = new JLabel(skill.getAbility());
  81. lblAbil.setMaximumSize(new Dimension(30, 14));
  82. lblAbil.setMinimumSize(new Dimension(30, 14));
  83. lblAbil.setPreferredSize(new Dimension(30, 14));
  84. GridBagConstraints gbc_lblAbil = new GridBagConstraints();
  85. gbc_lblAbil.insets = new Insets(1, 0, 0, 5);
  86. gbc_lblAbil.anchor = GridBagConstraints.EAST;
  87. gbc_lblAbil.gridx = 2;
  88. gbc_lblAbil.gridy = 0;
  89. add(lblAbil, gbc_lblAbil);
  90. JTextField total = new JTextField();
  91. total.setToolTipText("Skill Modifier");
  92. total.setHorizontalAlignment(SwingConstants.CENTER);
  93. total.setEditable(false);
  94. total.setMinimumSize(new Dimension(30, 20));
  95. total.setMaximumSize(new Dimension(30, 20));
  96. total.setPreferredSize(new Dimension(30, 20));
  97. GridBagConstraints gbc_total = new GridBagConstraints();
  98. gbc_total.insets = new Insets(1, 0, 0, 5);
  99. gbc_total.fill = GridBagConstraints.HORIZONTAL;
  100. gbc_total.gridx = 3;
  101. gbc_total.gridy = 0;
  102. add(total, gbc_total);
  103. total.setColumns(10);
  104. JLabel label = new JLabel("=");
  105. GridBagConstraints gbc_label = new GridBagConstraints();
  106. gbc_label.anchor = GridBagConstraints.EAST;
  107. gbc_label.insets = new Insets(1, 0, 0, 5);
  108. gbc_label.gridx = 4;
  109. gbc_label.gridy = 0;
  110. add(label, gbc_label);
  111. JTextField modifier = new JTextField();
  112. modifier.setToolTipText("Ability Modifier");
  113. modifier.setHorizontalAlignment(SwingConstants.CENTER);
  114. modifier.setEditable(false);
  115. modifier.setMinimumSize(new Dimension(30, 20));
  116. modifier.setMaximumSize(new Dimension(30, 20));
  117. modifier.setPreferredSize(new Dimension(30, 20));
  118. GridBagConstraints gbc_modifier = new GridBagConstraints();
  119. gbc_modifier.insets = new Insets(1, 0, 0, 5);
  120. gbc_modifier.fill = GridBagConstraints.HORIZONTAL;
  121. gbc_modifier.gridx = 5;
  122. gbc_modifier.gridy = 0;
  123. add(modifier, gbc_modifier);
  124. modifier.setColumns(10);
  125. JLabel label_1 = new JLabel("+");
  126. GridBagConstraints gbc_label_1 = new GridBagConstraints();
  127. gbc_label_1.anchor = GridBagConstraints.EAST;
  128. gbc_label_1.insets = new Insets(1, 0, 0, 5);
  129. gbc_label_1.gridx = 6;
  130. gbc_label_1.gridy = 0;
  131. add(label_1, gbc_label_1);
  132. JTextField ranks = new JTextField(StringHelper.toString(skill.getRanks()));
  133. ranks.setToolTipText("Ranks");
  134. ranks.setHorizontalAlignment(SwingConstants.CENTER);
  135. ranks.setEditable(false);
  136. ranks.setMinimumSize(new Dimension(30, 20));
  137. ranks.setMaximumSize(new Dimension(30, 20));
  138. ranks.setPreferredSize(new Dimension(30, 20));
  139. GridBagConstraints gbc_ranks = new GridBagConstraints();
  140. gbc_ranks.insets = new Insets(1, 0, 0, 5);
  141. gbc_ranks.fill = GridBagConstraints.HORIZONTAL;
  142. gbc_ranks.gridx = 7;
  143. gbc_ranks.gridy = 0;
  144. add(ranks, gbc_ranks);
  145. ranks.setColumns(10);
  146. Component horizontalStrut = Box.createHorizontalStrut(20);
  147. GridBagConstraints gbc_horizontalStrut = new GridBagConstraints();
  148. gbc_horizontalStrut.insets = new Insets(0, 0, 0, 5);
  149. gbc_horizontalStrut.gridx = 8;
  150. gbc_horizontalStrut.gridy = 0;
  151. add(horizontalStrut, gbc_horizontalStrut);
  152. JButton plus = new JButton("+");
  153. plus.setMargin(new Insets(2, 2, 2, 2));
  154. plus.setFont(new Font("Tahoma", Font.PLAIN, 8));
  155. plus.setPreferredSize(new Dimension(30, 19));
  156. plus.setMinimumSize(new Dimension(30, 19));
  157. GridBagConstraints gbc_plus = new GridBagConstraints();
  158. gbc_plus.insets = new Insets(0, 0, 1, 5);
  159. gbc_plus.gridx = 9;
  160. gbc_plus.gridy = 0;
  161. add(plus, gbc_plus);
  162. JButton minus = new JButton("-");
  163. minus.setMargin(new Insets(2, 2, 2, 2));
  164. minus.setFont(new Font("Tahoma", Font.PLAIN, 8));
  165. minus.setMinimumSize(new Dimension(30, 19));
  166. minus.setPreferredSize(new Dimension(30, 19));
  167. GridBagConstraints gbc_minus = new GridBagConstraints();
  168. gbc_minus.insets = new Insets(0, 0, 1, 5);
  169. gbc_minus.gridx = 10;
  170. gbc_minus.gridy = 0;
  171. add(minus, gbc_minus);
  172. JTextField points = new JTextField();
  173. points.setMinimumSize(new Dimension(30, 20));
  174. points.setText("0");
  175. points.setEditable(false);
  176. GridBagConstraints gbc_points = new GridBagConstraints();
  177. gbc_points.gridx = 11;
  178. gbc_points.gridy = 0;
  179. add(points, gbc_points);
  180. points.setColumns(10);
  181. IntFunction<Void> lambda = (value) -> {
  182. pointsAvaliable.value(pointsAvaliable.value() - (value * pointsPerRank));
  183. current.value(current.value() + value);
  184. points.setText(Integer.toString(current.value()));
  185. ObserverDispatch.notifySubscribers(pointsAvaliable, this);
  186. ObserverDispatch.notifySubscribers(current, this);
  187. return null;
  188. };
  189. plus.addActionListener((e) -> {
  190. if (pointsAvaliable.value() >= pointsPerRank && current.value() < maxPoints) { lambda.apply(1); }
  191. });
  192. minus.addActionListener((e) -> {
  193. if (current.value() > 0) { lambda.apply(-1); }
  194. });
  195. totalListener = new IndirectObservableListener<>(total,
  196. (c, p) -> {
  197. final int skillRanks = p.skill.getRanks().value();
  198. final int mod = p.ability.map(v -> v.baseModifier()).orElse(0);
  199. c.setText(StringHelper.toString(skillRanks + mod + p.points.value()));
  200. });
  201. final Optional<Ability.Scores> ability = getAbility(chara, skill);
  202. ability.ifPresent(v -> modifier.setText(StringHelper.toString(v.baseModifier())));
  203. totalListener.setObserved(new TotalPacket(ability, skill, current), current);
  204. }
  205. private Optional<Ability.Scores> getAbility(final DDCharacter chara, final DDSkill skill) {
  206. if (skill.getAbility().isEmpty()) { return Optional.empty(); }
  207. else { return Optional.of(AbilityHelper.get(chara, skill)); }
  208. }
  209. void applyChange() {
  210. skill.spendPoints(current.value(), !isClassSkill);
  211. ObserverDispatch.notifySubscribers(skill.getRanks(), this);
  212. }
  213. @Override
  214. public void removeNotify() {
  215. super.removeNotify();
  216. ObserverDispatch.unsubscribeAll(totalListener);
  217. }
  218. }