UpdateClassWithLevelPanel.java 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package org.leumasjaffe.charsheet.view.level;
  2. import static org.leumasjaffe.charsheet.view.level.LevelUpSpellPanel.SpellPickType.*;
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import java.util.List;
  6. import java.util.Optional;
  7. import java.util.SortedSet;
  8. import java.util.TreeSet;
  9. import java.util.function.Consumer;
  10. import javax.swing.JPanel;
  11. import org.jdesktop.swingx.VerticalLayout;
  12. import org.leumasjaffe.charsheet.model.DDCharacterClass;
  13. import org.leumasjaffe.charsheet.model.magic.DDSpell;
  14. import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
  15. import org.leumasjaffe.charsheet.model.observable.BoolGate;
  16. import org.leumasjaffe.charsheet.model.observable.IntValue;
  17. import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel;
  18. import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel.Info;
  19. import org.leumasjaffe.charsheet.view.skills.SkillLevelUpPanel;
  20. import org.leumasjaffe.function.VoidVoidFunction;
  21. import org.leumasjaffe.observer.ObservableListener;
  22. import org.leumasjaffe.observer.ObserverDispatch;
  23. import lombok.AccessLevel;
  24. import lombok.experimental.FieldDefaults;
  25. import lombok.experimental.NonFinal;
  26. import java.awt.GridBagLayout;
  27. import javax.swing.JTabbedPane;
  28. import java.awt.GridBagConstraints;
  29. import java.awt.Insets;
  30. import java.awt.Component;
  31. import javax.swing.Box;
  32. import javax.swing.JButton;
  33. import javax.swing.JLabel;
  34. @SuppressWarnings("serial")
  35. @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
  36. class UpdateClassWithLevelPanel extends JPanel {
  37. static int CHOOSE_SKILL_INDEX = 0, LEARN_SPELL_INDEX = 1, PREPARE_SPELL_INDEX = 2;
  38. LevelUpClassInfo levelUpInfo;
  39. JTabbedPane tabbedPane;
  40. SkillLevelUpPanel skills;
  41. @NonFinal Optional<LevelUpSpellPanel> learnSpells = Optional.empty();
  42. @NonFinal Optional<LevelUpSpellPanel> prepSpells = Optional.empty();
  43. BoolGate readyCount = new BoolGate(3);
  44. ObservableListener<Consumer<Boolean>, BoolGate> listener;
  45. @NonFinal ObservableListener<UpdateClassWithLevelPanel, BoolGate> learnAndPrepareListener = null;
  46. public UpdateClassWithLevelPanel(LevelUpClassInfo info, VoidVoidFunction back,
  47. Consumer<Boolean> setReady) {
  48. this.levelUpInfo = info;
  49. info.ddClass.getLevel().value(info.toLevel);
  50. GridBagLayout gridBagLayout = new GridBagLayout();
  51. gridBagLayout.columnWidths = new int[]{0, 0};
  52. gridBagLayout.rowHeights = new int[]{0, 0, 0};
  53. gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
  54. gridBagLayout.rowWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
  55. setLayout(gridBagLayout);
  56. tabbedPane = new JTabbedPane(JTabbedPane.TOP);
  57. GridBagConstraints gbc_tabbedPane = new GridBagConstraints();
  58. gbc_tabbedPane.insets = new Insets(0, 0, 5, 0);
  59. gbc_tabbedPane.fill = GridBagConstraints.BOTH;
  60. gbc_tabbedPane.gridx = 0;
  61. gbc_tabbedPane.gridy = 0;
  62. add(tabbedPane, gbc_tabbedPane);
  63. JPanel features = new JPanel(new VerticalLayout(2));
  64. info.ddClass.getProto().getFeatures(info.toLevel).forEach(prop -> {
  65. features.add(new JLabel(prop.getName()));
  66. });
  67. tabbedPane.addTab("Features", null, features, null);
  68. skills = new SkillLevelUpPanel(info.ddCharacter, info.ddClass) {
  69. @Override public void setIsReady(boolean b) {
  70. readyCount.set(CHOOSE_SKILL_INDEX, b);
  71. ObserverDispatch.notifySubscribers(readyCount);
  72. }
  73. };
  74. tabbedPane.addTab("Skills", null, skills, null);
  75. info.ddClass.getSpellBook().ifPresent(sb -> {
  76. readyCount.set(LEARN_SPELL_INDEX, !sb.learnsSpells());
  77. readyCount.set(PREPARE_SPELL_INDEX, !sb.preparesSpells());
  78. if (sb.learnsSpells()) {
  79. createPanelsForLearnSpell(sb);
  80. } else if (sb.preparesSpells()) {
  81. createPanelForPrepareSpells();
  82. }
  83. });
  84. JPanel panel = new JPanel();
  85. GridBagConstraints gbc_panel = new GridBagConstraints();
  86. gbc_panel.fill = GridBagConstraints.BOTH;
  87. gbc_panel.gridx = 0;
  88. gbc_panel.gridy = 1;
  89. add(panel, gbc_panel);
  90. GridBagLayout gbl_panel = new GridBagLayout();
  91. gbl_panel.columnWidths = new int[]{0, 0, 0};
  92. gbl_panel.rowHeights = new int[]{0, 0};
  93. gbl_panel.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
  94. gbl_panel.rowWeights = new double[]{0.0, Double.MIN_VALUE};
  95. panel.setLayout(gbl_panel);
  96. JButton btnBack = new JButton("Back");
  97. GridBagConstraints gbc_btnBack = new GridBagConstraints();
  98. gbc_btnBack.insets = new Insets(0, 0, 0, 5);
  99. gbc_btnBack.gridx = 0;
  100. gbc_btnBack.gridy = 0;
  101. panel.add(btnBack, gbc_btnBack);
  102. btnBack.addActionListener(e -> back.apply());
  103. Component horizontalGlue = Box.createHorizontalGlue();
  104. GridBagConstraints gbc_horizontalGlue = new GridBagConstraints();
  105. gbc_horizontalGlue.gridx = 1;
  106. gbc_horizontalGlue.gridy = 0;
  107. panel.add(horizontalGlue, gbc_horizontalGlue);
  108. listener = new ObservableListener<>(setReady, (c, v) -> {
  109. c.accept(v.all());
  110. });
  111. listener.setObserved(readyCount);
  112. }
  113. private void createPanelForPrepareSpells() {
  114. prepSpells = Optional.of(new LevelUpSpellPanel(PREPARE,
  115. new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass),
  116. readyCount.handle(PREPARE_SPELL_INDEX)));
  117. tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
  118. }
  119. private void createPanelsForLearnSpell(DDSpellbook sb) {
  120. learnSpells = Optional.of(new LevelUpSpellPanel(LEARN,
  121. new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass),
  122. readyCount.handle(LEARN_SPELL_INDEX)));
  123. tabbedPane.addTab("Learn Spells", null, learnSpells.get(), null);
  124. if (sb.preparesSpells()) {
  125. learnAndPrepareListener = new ObservableListener<>(this, (c, v) -> {
  126. if (v.get(LEARN_SPELL_INDEX)) {
  127. if (!prepSpells.isPresent()) c.createPrepareLearnedSpellPanel(learnSpells.get());
  128. } else {
  129. prepSpells.ifPresent(c.tabbedPane::remove);
  130. c.prepSpells = Optional.empty();
  131. }
  132. });
  133. learnAndPrepareListener.setObserved(readyCount);
  134. }
  135. }
  136. private void createPrepareLearnedSpellPanel(LevelUpSpellPanel spells) {
  137. LevelUpSpellPanel.SpellPicker pick = new LevelUpSpellPanel.SpellPicker() {
  138. @Override
  139. public List<List<Integer>> getSpellCounts(Info info) {
  140. return PREPARE.getSpellCounts(info);
  141. }
  142. @Override
  143. public Collection<DDSpell> getAvailableSpells(Info info, int i) {
  144. final Collection<DDSpell> start = new ArrayList<>(PREPARE.getAvailableSpells(info, i));
  145. if (spells.getPanels().get(i) != null) {
  146. start.addAll(spells.getPanels().get(i).getPrepared());
  147. }
  148. return start;
  149. }
  150. };
  151. prepSpells = Optional.of(new LevelUpSpellPanel(pick,
  152. new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass),
  153. readyCount.handle(PREPARE_SPELL_INDEX)));
  154. tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
  155. }
  156. @Override
  157. public void removeNotify() {
  158. super.removeNotify();
  159. ObserverDispatch.unsubscribeAll(listener);
  160. ObserverDispatch.unsubscribeAll(learnAndPrepareListener);
  161. }
  162. private void commitSpellbook(DDSpellbook book) {
  163. learnSpells.ifPresent(pan -> {
  164. final List<SelectSpellsPanel> selections = pan.getPanels();
  165. for (int i = 0; i < selections.size(); ++i) {
  166. if (selections.get(i) == null) continue;
  167. List<DDSpell> known = new ArrayList<>(book.spellsKnownAtLevel(i));
  168. known.addAll(selections.get(i).getPrepared());
  169. book.learnSpells(i, known);
  170. }
  171. });
  172. prepSpells.ifPresent(pan -> {
  173. final List<SelectSpellsPanel> selections = pan.getPanels();
  174. for (int i = 0; i < selections.size(); ++i) {
  175. if (selections.get(i) == null) continue;
  176. List<DDSpell> known = new ArrayList<>(book.spellsPreparedAtLevel(i));
  177. known.addAll(selections.get(i).getPrepared());
  178. book.prepareSpells(i, known);
  179. }
  180. });
  181. }
  182. public void commitAllChanges() {
  183. final String className = levelUpInfo.ddClass.getName();
  184. skills.commitAllChanges();
  185. final Optional<DDSpellbook> maybeBook = levelUpInfo.ddClass.getSpellBook();
  186. maybeBook.ifPresent(this::commitSpellbook);
  187. final SortedSet<DDCharacterClass> classes = new TreeSet<>(levelUpInfo.ddCharacter.getClasses());
  188. classes.removeIf(cc -> cc.getName().equals(className));
  189. classes.add(levelUpInfo.ddClass);
  190. levelUpInfo.ddCharacter.setClasses(classes);
  191. // TODO: Acquire features
  192. final IntValue exp = levelUpInfo.ddCharacter.getExperience();
  193. final int neededExp = ExperienceDialog.experienceForLevel(levelUpInfo.ddCharacter.getLevel());
  194. if (exp.value() < neededExp) { exp.value(neededExp); }
  195. ObserverDispatch.notifySubscribers(exp);
  196. ObserverDispatch.notifySubscribers(levelUpInfo.ddCharacter);
  197. }
  198. }