Browse Source

Start work on making Domain spells pickable on level

Sam Jaffe 8 years ago
parent
commit
42eac869b5

+ 23 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/ChooseSpellTuple.java

@@ -0,0 +1,23 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import org.leumasjaffe.charsheet.model.Ability;
+import org.leumasjaffe.charsheet.model.DDCharacter;
+import org.leumasjaffe.charsheet.model.DDCharacterClass;
+import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
+import org.leumasjaffe.charsheet.util.AbilityHelper;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.experimental.FieldDefaults;
+
+@AllArgsConstructor
+@FieldDefaults(level=AccessLevel.PUBLIC, makeFinal=true)
+public class ChooseSpellTuple {
+	DDCharacter chara;
+	DDCharacterClass dclass;
+	DDSpellbook spellBook;
+	
+	public Ability.Scores ability() {
+		return AbilityHelper.get(chara, dclass);
+	}
+}

+ 37 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/LearnSpellPicker.java

@@ -0,0 +1,37 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.experimental.FieldDefaults;
+
+@AllArgsConstructor
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class LearnSpellPicker implements SpellPicker {
+	@Getter ChooseSpellTuple info;
+	
+	@Override
+	public boolean allowsDuplicates() {
+		return false;
+	}
+	
+	@Override
+	public List<Integer> getSpellCounts(int level) {
+		if (level <= 0) return Collections.emptyList();
+		return info.dclass.getProto().getSpells().get().getKnown().get(level-1);
+	}
+	
+	@Override
+	public Collection<DDSpell> getAvailableSpells(int i) {
+		Collection<DDSpell> spells = new ArrayList<>(info.dclass.getProto().getSpellList(i));
+		spells.removeAll(info.spellBook.spellsKnownAtLevel(i));
+		return spells;
+	}
+}

+ 25 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/PrepareDomainSpellPicker.java

@@ -0,0 +1,25 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class PrepareDomainSpellPicker extends PrepareSpellPicker {	
+	
+	public PrepareDomainSpellPicker(ChooseSpellTuple info) {
+		super(info);
+	}
+
+	@Override
+	public List<Integer> getSpellCounts(int level) {
+		// FIXME: This only works if there's only ever 1 bonus spell per circle
+		// FIXME: This doesn't handle the fact that domains don't have a bonus 0-th level
+		// FIXME: Secondary Spellbooks are based on feature activation...
+		// TODO: Select Cleric Domains
+		// TODO: Select Wizard Schools
+		return super.getSpellCounts(level).stream().map(i -> i != 0 ? 1 : 0).collect(Collectors.toList());
+	}
+}

+ 29 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/PrepareNewlyLearnedSpellPicker.java

@@ -0,0 +1,29 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.function.IntFunction;
+
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class PrepareNewlyLearnedSpellPicker extends PrepareSpellPicker {	
+	IntFunction<Collection<DDSpell>> getNewSpells;
+	
+	public PrepareNewlyLearnedSpellPicker(ChooseSpellTuple info, IntFunction<Collection<DDSpell>> func) {
+		super(info);
+		this.getNewSpells = func;
+	}
+
+	@Override
+	public Collection<DDSpell> getAvailableSpells(int level) {
+		final Collection<DDSpell> start = new ArrayList<>(super.getAvailableSpells(level));
+		if (getNewSpells.apply(level) != null) {
+			start.addAll(getNewSpells.apply(level));
+		}
+		return start;
+	}
+}

+ 30 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/PrepareSpellPicker.java

@@ -0,0 +1,30 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.experimental.FieldDefaults;
+
+@AllArgsConstructor
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class PrepareSpellPicker implements SpellPicker {
+	@Getter ChooseSpellTuple info;
+	
+	@Override
+	public List<Integer> getSpellCounts(int level) {
+		// TODO: Bonus spells for high ability scores
+		if (level <= 0) return Collections.emptyList();
+		return info.dclass.getProto().getSpells().get().getPerDay().get(level-1);
+	}
+	
+	@Override
+	public Collection<DDSpell> getAvailableSpells(int level) {
+		return info.spellBook.spellsKnownAtLevel(level);
+	}
+}

+ 13 - 0
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/SpellPicker.java

@@ -0,0 +1,13 @@
+package org.leumasjaffe.charsheet.controller.magic;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.leumasjaffe.charsheet.model.magic.DDSpell;
+
+public interface SpellPicker {
+	ChooseSpellTuple getInfo();
+	default boolean allowsDuplicates() { return true; }
+	public List<Integer> getSpellCounts(int level);
+	public Collection<DDSpell> getAvailableSpells(int level);
+}

+ 8 - 42
src/main/lombok/org/leumasjaffe/charsheet/view/level/LevelUpSpellPanel.java

@@ -3,11 +3,12 @@ package org.leumasjaffe.charsheet.view.level;
 import javax.swing.JPanel;
 
 import org.jdesktop.swingx.VerticalLayout;
-import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.charsheet.controller.magic.ChooseSpellTuple;
+import org.leumasjaffe.charsheet.controller.magic.LearnSpellPicker;
+import org.leumasjaffe.charsheet.controller.magic.SpellPicker;
 import org.leumasjaffe.charsheet.model.observable.BoolGate;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
 import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel;
-import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel.Info;
 import org.leumasjaffe.observer.ObservableListener;
 import org.leumasjaffe.observer.ObserverDispatch;
 
@@ -18,8 +19,6 @@ import lombok.experimental.NonFinal;
 
 import java.awt.GridBagLayout;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -31,45 +30,15 @@ import java.awt.GridBagConstraints;
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PUBLIC, makeFinal=true)
 class LevelUpSpellPanel extends JPanel {
-	public static interface SpellPicker {
-		public List<List<Integer>> getSpellCounts(SelectSpellsPanel.Info info);
-		public Collection<DDSpell> getAvailableSpells(SelectSpellsPanel.Info info, int i);
-	}
-	public static enum SpellPickType implements SpellPicker {
-		LEARN {
-			@Override
-			public List<List<Integer>> getSpellCounts(SelectSpellsPanel.Info info) {
-				return info.dclass.getProto().getSpells().get().getKnown();
-			}
-			@Override
-			public Collection<DDSpell> getAvailableSpells(Info info, int i) {
-				Collection<DDSpell> spells = new ArrayList<>(info.dclass.getProto().getSpellList(i));
-				spells.removeAll(info.spellBook.spellsKnownAtLevel(i));
-				return spells;
-			}
-
-		}, PREPARE {
-			@Override
-			public List<List<Integer>> getSpellCounts(SelectSpellsPanel.Info info) {
-				// TODO: Bonus spells for high ability scores
-				return info.dclass.getProto().getSpells().get().getPerDay();
-			}
-			@Override
-			public Collection<DDSpell> getAvailableSpells(Info info, int i) {
-				return info.spellBook.spellsKnownAtLevel(i);
-			}
-		};		
-	}
-
 	int[] ready = {0};
 	@NonFinal int spellLevelsGrown = 0;
 	int oldHighestSpellLevel, newHighestSpellLevel, toLevel;
 	SpellPicker pick;
-	SelectSpellsPanel.Info info;
+	ChooseSpellTuple info;
 	@Getter List<SelectSpellsPanel> panels;
 	ObservableListener<Void, BoolGate.Meta> allReady;
 
-	public LevelUpSpellPanel(SpellPicker pick, SelectSpellsPanel.Info info, 
+	public LevelUpSpellPanel(SpellPicker pick, ChooseSpellTuple info, 
 			BoolGate.Handle readyCount) {
 		this.pick = pick;
 		this.info = info;
@@ -105,8 +74,7 @@ class LevelUpSpellPanel extends JPanel {
 			++spellLevelsGrown;
 			SelectSpellsPanel lvl = new SelectSpellsPanel(info, gate.handle(i), i,
 					new LinkedHashSet<>(), Math.max(spells.get(i), sharedSlots), 
-					pick.getAvailableSpells(info, i),
-					pick != SpellPickType.LEARN, val);
+					pick.getAvailableSpells(i), pick.allowsDuplicates(), val);
 			panels.add(lvl);
 			panel.add(lvl);
 		}
@@ -115,10 +83,8 @@ class LevelUpSpellPanel extends JPanel {
 	
 	private Map<Integer, Integer> getNewSpells(IntValue sharedSpellCountLimit) {
 		final Map<Integer, Integer> map = new TreeMap<>();
-		final List<List<Integer>> spellList = pick.getSpellCounts(info);
-		final List<Integer> spellsAtPreviousLevel = toLevel == 1 ? Collections.emptyList() :
-			spellList.get(toLevel-2);
-		final List<Integer> spellsAtCurrentLevel = spellList.get(toLevel-1);
+		final List<Integer> spellsAtPreviousLevel = pick.getSpellCounts(toLevel-1);
+		final List<Integer> spellsAtCurrentLevel = pick.getSpellCounts(toLevel);
 		for (int i = 0; i < newHighestSpellLevel; ++i) {
 			map.put(i, diff(spellsAtCurrentLevel, spellsAtPreviousLevel, i,
 					isNewSpellCircle(i)));

+ 71 - 51
src/main/lombok/org/leumasjaffe/charsheet/view/level/UpdateClassWithLevelPanel.java

@@ -1,9 +1,7 @@
 package org.leumasjaffe.charsheet.view.level;
 
-import static org.leumasjaffe.charsheet.view.level.LevelUpSpellPanel.SpellPickType.*;
-
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.SortedSet;
@@ -12,6 +10,12 @@ import java.util.function.Consumer;
 
 import javax.swing.JPanel;
 
+import org.leumasjaffe.charsheet.controller.magic.ChooseSpellTuple;
+import org.leumasjaffe.charsheet.controller.magic.LearnSpellPicker;
+import org.leumasjaffe.charsheet.controller.magic.PrepareDomainSpellPicker;
+import org.leumasjaffe.charsheet.controller.magic.PrepareNewlyLearnedSpellPicker;
+import org.leumasjaffe.charsheet.controller.magic.PrepareSpellPicker;
+import org.leumasjaffe.charsheet.controller.magic.SpellPicker;
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
 import org.leumasjaffe.charsheet.model.DDCharacterClass.DDSpellbookWrapper;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
@@ -19,7 +23,6 @@ import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
 import org.leumasjaffe.charsheet.model.observable.BoolGate;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
 import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel;
-import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel.Info;
 import org.leumasjaffe.charsheet.view.skills.SkillLevelUpPanel;
 import org.leumasjaffe.function.VoidVoidFunction;
 import org.leumasjaffe.observer.ObservableListener;
@@ -34,6 +37,7 @@ import javax.swing.JTabbedPane;
 
 import java.awt.GridBagConstraints;
 import java.awt.Insets;
+
 import java.awt.Component;
 import javax.swing.Box;
 import javax.swing.JButton;
@@ -41,7 +45,8 @@ import javax.swing.JButton;
 @SuppressWarnings("serial")
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
 class UpdateClassWithLevelPanel extends JPanel {
-	static int FEATURE_INDEX = 0, CHOOSE_SKILL_INDEX = 1, LEARN_SPELL_INDEX = 2, PREPARE_SPELL_INDEX = 3;
+	static int FEATURE_INDEX = 0, CHOOSE_SKILL_INDEX = 1, LEARN_SPELL_INDEX = 2, PREPARE_SPELL_INDEX = 3,
+			PREPARE_BONUS_SPELL_INDEX = 4;
 
 	LevelUpClassInfo levelUpInfo;
 	JTabbedPane tabbedPane;
@@ -49,15 +54,20 @@ class UpdateClassWithLevelPanel extends JPanel {
 	SkillLevelUpPanel skills;
 	@NonFinal Optional<LevelUpSpellPanel> learnSpells = Optional.empty();
 	@NonFinal Optional<LevelUpSpellPanel> prepSpells = Optional.empty();
+	@NonFinal Optional<LevelUpSpellPanel> prepBonusSpells = Optional.empty();
 	
-	BoolGate readyCount = new BoolGate(4);
+	BoolGate readyCount = new BoolGate(5);
 	ObservableListener<Consumer<Boolean>, BoolGate> listener;
 	@NonFinal ObservableListener<UpdateClassWithLevelPanel, BoolGate> learnAndPrepareListener = null;
 
 	LU_FeaturesPanel featurePanel;
+
 	
 	public UpdateClassWithLevelPanel(LevelUpClassInfo info, VoidVoidFunction back,
 			Consumer<Boolean> setReady) {
+		readyCount.set(LEARN_SPELL_INDEX, true);
+		readyCount.set(PREPARE_SPELL_INDEX, true);
+		readyCount.set(PREPARE_BONUS_SPELL_INDEX, true);
 		this.levelUpInfo = info;
 		info.ddClass.getLevel().value(info.toLevel);
 		GridBagLayout gridBagLayout = new GridBagLayout();
@@ -86,16 +96,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 		};
 		tabbedPane.addTab("Skills", null, skills, null);
 
-		// FIXME: Provide Work for secondary
-		info.ddClass.getSpellBook().map(DDSpellbookWrapper::getMain).ifPresent(sb -> {
-			readyCount.set(LEARN_SPELL_INDEX, !sb.learnsSpells());
-			readyCount.set(PREPARE_SPELL_INDEX, !sb.preparesSpells());
-			if (sb.learnsSpells()) {
-				createPanelsForLearnSpell(sb);
-			} else if (sb.preparesSpells()) {
-				createPanelForPrepareSpells(sb);
-			}
-		});
+		info.ddClass.getSpellBook().ifPresent(wrap -> initSpellTabs(info, wrap));
 
 		JPanel panel = new JPanel();
 		GridBagConstraints gbc_panel = new GridBagConstraints();
@@ -126,23 +127,38 @@ class UpdateClassWithLevelPanel extends JPanel {
 
 		listener = readyCount.makeListener(setReady);
 	}
+	
+	void initSpellTabs(LevelUpClassInfo info, DDSpellbookWrapper wrap) {
+		DDSpellbook sb = wrap.getMain();
+		readyCount.set(LEARN_SPELL_INDEX, !sb.learnsSpells());
+		readyCount.set(PREPARE_SPELL_INDEX, !sb.preparesSpells());
+		if (sb.learnsSpells()) {
+			createPanelsForLearnSpell(new ChooseSpellTuple(info.ddCharacter, info.ddClass, sb));
+		} else if (sb.preparesSpells()) {
+			createPanelForPrepareSpells(new ChooseSpellTuple(info.ddCharacter, info.ddClass, sb));
+		}
+		wrap.getSecondary().ifPresent(sec -> {
+			readyCount.set(PREPARE_BONUS_SPELL_INDEX, false);
+			createBonusSpellbookPreparePanel(new ChooseSpellTuple(info.ddCharacter, info.ddClass, sec));
+		});
+	}
 
-	private void createPanelForPrepareSpells(DDSpellbook sb) {
-		prepSpells = Optional.of(new LevelUpSpellPanel(PREPARE,
-				new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass, sb),
+	private void createPanelForPrepareSpells(ChooseSpellTuple info) {
+		prepSpells = Optional.of(new LevelUpSpellPanel(new PrepareSpellPicker(info),
+				new ChooseSpellTuple(levelUpInfo.ddCharacter, levelUpInfo.ddClass, info.spellBook),
 				readyCount.handle(PREPARE_SPELL_INDEX)));
 		tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
 	}
 
-	private void createPanelsForLearnSpell(DDSpellbook sb) {
-		learnSpells = Optional.of(new LevelUpSpellPanel(LEARN,
-				new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass, sb),
+	private void createPanelsForLearnSpell(ChooseSpellTuple info) {
+		learnSpells = Optional.of(new LevelUpSpellPanel(new LearnSpellPicker(info),
+				new ChooseSpellTuple(levelUpInfo.ddCharacter, levelUpInfo.ddClass, info.spellBook),
 				readyCount.handle(LEARN_SPELL_INDEX)));
 		tabbedPane.addTab("Learn Spells", null, learnSpells.get(), null);
-		if (sb.preparesSpells()) {
+		if (info.spellBook.preparesSpells()) {
 			learnAndPrepareListener = new ObservableListener<>(this, (c, v) -> {
 				if (v.get(LEARN_SPELL_INDEX)) {
-					if (!prepSpells.isPresent()) c.createPrepareLearnedSpellPanel(learnSpells.get(), sb);
+					if (!prepSpells.isPresent()) c.createPrepareLearnedSpellPanel(learnSpells.get(), info);
 				} else {
 					prepSpells.ifPresent(c.tabbedPane::remove);
 					c.prepSpells = Optional.empty();
@@ -151,26 +167,23 @@ class UpdateClassWithLevelPanel extends JPanel {
 			learnAndPrepareListener.setObserved(readyCount);
 		}
 	}
+	
+	private void createBonusSpellbookPreparePanel(ChooseSpellTuple info) {
+		prepBonusSpells = Optional.of(new LevelUpSpellPanel(new PrepareDomainSpellPicker(info),
+				new ChooseSpellTuple(levelUpInfo.ddCharacter, levelUpInfo.ddClass, info.spellBook),
+				readyCount.handle(PREPARE_BONUS_SPELL_INDEX)));
+		tabbedPane.addTab("Bonus Spells", null, prepBonusSpells.get(), null);
+	}
 
-	private void createPrepareLearnedSpellPanel(LevelUpSpellPanel spells, DDSpellbook sb) {
-		LevelUpSpellPanel.SpellPicker pick = new LevelUpSpellPanel.SpellPicker() {
-			@Override
-			public List<List<Integer>> getSpellCounts(Info info) {
-				return PREPARE.getSpellCounts(info);
-			}
-
-			@Override
-			public Collection<DDSpell> getAvailableSpells(Info info, int i) {
-				final Collection<DDSpell> start = new ArrayList<>(PREPARE.getAvailableSpells(info, i));
-				if (spells.getPanels().get(i) != null) {
-					start.addAll(spells.getPanels().get(i).getPrepared());
-				}
-				return start;
-			}
-		};
-
+	private void createPrepareLearnedSpellPanel(LevelUpSpellPanel spells, ChooseSpellTuple info) {
+		SpellPicker pick = new PrepareNewlyLearnedSpellPicker(info, level -> 
+			Optional.ofNullable(spells.getPanels().get(level))
+			.map(SelectSpellsPanel::getPrepared)
+			.orElse(Collections.emptyList())
+		);
+		
 		prepSpells = Optional.of(new LevelUpSpellPanel(pick,
-				new SelectSpellsPanel.Info(levelUpInfo.ddCharacter, levelUpInfo.ddClass, sb),
+				new ChooseSpellTuple(levelUpInfo.ddCharacter, levelUpInfo.ddClass, info.spellBook),
 				readyCount.handle(PREPARE_SPELL_INDEX)));
 		tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
 	}
@@ -183,23 +196,32 @@ class UpdateClassWithLevelPanel extends JPanel {
 	}
 
 	
-	private void commitSpellbook(DDSpellbook book) {
+	private void commitSpellbook(DDSpellbookWrapper wrap) {
 		learnSpells.ifPresent(pan -> {
 			final List<SelectSpellsPanel> selections = pan.getPanels();
 			for (int i = 0; i < selections.size(); ++i) {
 				if (selections.get(i) == null) continue;
-				List<DDSpell> known = new ArrayList<>(book.spellsKnownAtLevel(i));
+				List<DDSpell> known = new ArrayList<>(wrap.getMain().spellsKnownAtLevel(i));
 				known.addAll(selections.get(i).getPrepared());
-				book.learnSpells(i, known);
+				wrap.getMain().learnSpells(i, known);
 			}
 		});
 		prepSpells.ifPresent(pan -> {
 			final List<SelectSpellsPanel> selections = pan.getPanels();
 			for (int i = 0; i < selections.size(); ++i) {
 				if (selections.get(i) == null) continue;
-				List<DDSpell> known = new ArrayList<>(book.spellsPreparedAtLevel(i));
-				known.addAll(selections.get(i).getPrepared());
-				book.prepareSpells(i, known);
+				List<DDSpell> prep = new ArrayList<>(wrap.getMain().spellsPreparedAtLevel(i));
+				prep.addAll(selections.get(i).getPrepared());
+				wrap.getMain().prepareSpells(i, prep);
+			}
+		});
+		prepBonusSpells.ifPresent(pan -> {
+			final List<SelectSpellsPanel> selections = pan.getPanels();
+			for (int i = 0; i < selections.size(); ++i) {
+				if (selections.get(i) == null) continue;
+				List<DDSpell> prep = new ArrayList<>(wrap.getSecondary().get().spellsPreparedAtLevel(i));
+				prep.addAll(selections.get(i).getPrepared());
+				wrap.getSecondary().get().prepareSpells(i, prep);
 			}
 		});
 	}
@@ -207,9 +229,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 	public void commitAllChanges() {
 		final String className = levelUpInfo.ddClass.getName();
 		skills.commitAllChanges();
-		// FIXME: Secondary spellbook here too?
-		final Optional<DDSpellbook> maybeBook = levelUpInfo.ddClass.getSpellBook().map(DDSpellbookWrapper::getMain);
-		maybeBook.ifPresent(this::commitSpellbook);
+		levelUpInfo.ddClass.getSpellBook().ifPresent(this::commitSpellbook);
 		final SortedSet<DDCharacterClass> classes = new TreeSet<>(levelUpInfo.ddCharacter.getClasses());
 		classes.removeIf(cc -> cc.getName().equals(className));
 		classes.add(levelUpInfo.ddClass);

+ 2 - 1
src/main/lombok/org/leumasjaffe/charsheet/view/magic/SelectPreparedSpellsPanel.java

@@ -1,5 +1,6 @@
 package org.leumasjaffe.charsheet.view.magic;
 
+import org.leumasjaffe.charsheet.controller.magic.ChooseSpellTuple;
 import org.leumasjaffe.charsheet.model.DDCharacter;
 import org.leumasjaffe.charsheet.model.DDCharacterClass;
 import org.leumasjaffe.charsheet.model.magic.impl.Prepared;
@@ -14,7 +15,7 @@ class SelectPreparedSpellsPanel extends SelectSpellsPanel {
 	
 	public SelectPreparedSpellsPanel(DDCharacter chara, DDCharacterClass dclass, BoolGate.Handle gate, int level,
 			Prepared prep) {
-		super(new SelectSpellsPanel.Info(chara, dclass, prep), gate, level, 
+		super(new ChooseSpellTuple(chara, dclass, prep), gate, level, 
 				prep.getSpellsPreparedPreviouslyForLevel(level),
 				prep.spellsKnownAtLevel(level));
 	}

+ 4 - 19
src/main/lombok/org/leumasjaffe/charsheet/view/magic/SelectSpellsPanel.java

@@ -10,14 +10,10 @@ import javax.swing.JPopupMenu;
 import javax.swing.JTable;
 import javax.swing.ListSelectionModel;
 
-import org.leumasjaffe.charsheet.model.Ability;
-import org.leumasjaffe.charsheet.model.DDCharacter;
-import org.leumasjaffe.charsheet.model.DDCharacterClass;
+import org.leumasjaffe.charsheet.controller.magic.ChooseSpellTuple;
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
-import org.leumasjaffe.charsheet.model.magic.DDSpellbook;
 import org.leumasjaffe.charsheet.model.observable.BoolGate;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
-import org.leumasjaffe.charsheet.util.AbilityHelper;
 import org.leumasjaffe.event.SelectTableRowPopupMenuListener;
 import org.leumasjaffe.format.StringHelper;
 
@@ -77,18 +73,6 @@ public class SelectSpellsPanel extends JPanel {
 		}
 	}
 
-	@AllArgsConstructor
-	@FieldDefaults(level=AccessLevel.PUBLIC, makeFinal=true)
-	public static class Info {
-		DDCharacter chara;
-		DDCharacterClass dclass;
-		DDSpellbook spellBook;
-		
-		public Ability.Scores ability() {
-			return AbilityHelper.get(chara, dclass);
-		}
-	}
-	
 	public static final String READY = "Is Filled Out";
 	
 	@Getter Collection<DDSpell> prepared;
@@ -96,7 +80,8 @@ public class SelectSpellsPanel extends JPanel {
 	IntValue sharedValue;
 	SelectSpellModel modelPrepared, modelKnown;
 	
-	public SelectSpellsPanel(Info info, BoolGate.Handle gate, int level, Collection<DDSpell> prepared, int toPrepare,
+	public SelectSpellsPanel(ChooseSpellTuple info, BoolGate.Handle gate, int level, 
+			Collection<DDSpell> prepared, int toPrepare,
 			Collection<DDSpell> avail, boolean allowsDuplicates, IntValue sharedValue) {
 		this.allowsDuplicates = allowsDuplicates;
 		this.sharedValue = sharedValue;
@@ -240,7 +225,7 @@ public class SelectSpellsPanel extends JPanel {
 		});
 	}
 
-	public SelectSpellsPanel(Info info, BoolGate.Handle gate, int level,
+	public SelectSpellsPanel(ChooseSpellTuple info, BoolGate.Handle gate, int level,
 			Collection<DDSpell> prepared, Collection<DDSpell> avail) {
 		this(info, gate, level, prepared, 0, avail, true, new IntValue(-1));
 	}