فهرست منبع

Make level dialog so that you do not need to learn all spells before you are able to prepare spells.
Instead, "<none>"s will be added for every empty slot and the system will automatically update the list when you edit the Known group.

Sam Jaffe 8 سال پیش
والد
کامیت
6d508af897

+ 2 - 1
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/LearnSpellPicker.java

@@ -6,6 +6,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.observer.Observable;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
@@ -14,7 +15,7 @@ import lombok.experimental.FieldDefaults;
 
 @AllArgsConstructor
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
-public class LearnSpellPicker implements SpellPicker {
+public class LearnSpellPicker extends Observable.Instance implements SpellPicker {
 	@Getter ChooseSpellTuple info;
 	
 	@Override

+ 2 - 1
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/PrepareSpellPicker.java

@@ -5,6 +5,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.observer.Observable;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
@@ -13,7 +14,7 @@ import lombok.experimental.FieldDefaults;
 
 @AllArgsConstructor
 @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
-public class PrepareSpellPicker implements SpellPicker {
+public class PrepareSpellPicker extends Observable.Instance implements SpellPicker {
 	@Getter ChooseSpellTuple info;
 	
 	@Override

+ 2 - 1
src/main/lombok/org/leumasjaffe/charsheet/controller/magic/SpellPicker.java

@@ -4,8 +4,9 @@ import java.util.Collection;
 import java.util.List;
 
 import org.leumasjaffe.charsheet.model.magic.DDSpell;
+import org.leumasjaffe.observer.Observable;
 
-public interface SpellPicker {
+public interface SpellPicker extends Observable {
 	ChooseSpellTuple getInfo();
 	default boolean allowsDuplicates() { return true; }
 	public List<Integer> getSpellCounts(int level);

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

@@ -58,7 +58,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 	
 	BoolGate readyCount = new BoolGate(5);
 	ObservableListener<Consumer<Boolean>, BoolGate> listener;
-	@NonFinal ObservableListener<UpdateClassWithLevelPanel, BoolGate> learnAndPrepareListener = null;
+	@NonFinal ObservableListener<SpellPicker, SpellPicker> learnAndPrepareListener = null;
 
 	LU_FeaturesPanel featurePanel;
 
@@ -144,27 +144,16 @@ class UpdateClassWithLevelPanel extends JPanel {
 	}
 
 	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)));
+		prepSpells = Optional.of(new LevelUpSpellPanel(new PrepareSpellPicker(info), info, readyCount.handle(PREPARE_SPELL_INDEX)));
 		tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
 	}
 
 	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)));
+		SpellPicker pick = new LearnSpellPicker(info);
+		learnSpells = Optional.of(new LevelUpSpellPanel(pick, info, readyCount.handle(LEARN_SPELL_INDEX)));
 		tabbedPane.addTab("Learn Spells", null, learnSpells.get(), null);
 		if (info.spellBook.preparesSpells()) {
-			learnAndPrepareListener = new ObservableListener<>(this, (c, v) -> {
-				if (v.get(LEARN_SPELL_INDEX)) {
-					if (!prepSpells.isPresent()) c.createPrepareLearnedSpellPanel(learnSpells.get(), info);
-				} else {
-					prepSpells.ifPresent(c.tabbedPane::remove);
-					c.prepSpells = Optional.empty();
-				}
-			});
-			learnAndPrepareListener.setObserved(readyCount);
+			createPrepareLearnedSpellPanel(learnSpells.get(), info, pick);
 		}
 	}
 	
@@ -175,7 +164,7 @@ class UpdateClassWithLevelPanel extends JPanel {
 		tabbedPane.addTab("Bonus Spells", null, prepBonusSpells.get(), null);
 	}
 
-	private void createPrepareLearnedSpellPanel(LevelUpSpellPanel spells, ChooseSpellTuple info) {
+	private void createPrepareLearnedSpellPanel(LevelUpSpellPanel spells, ChooseSpellTuple info, SpellPicker learn) {
 		SpellPicker pick = new PrepareNewlyLearnedSpellPicker(info, level -> 
 			Optional.ofNullable(spells.getPanels().get(level))
 			.map(SelectSpellsPanel::getPrepared)
@@ -186,6 +175,8 @@ class UpdateClassWithLevelPanel extends JPanel {
 				new ChooseSpellTuple(levelUpInfo.ddCharacter, levelUpInfo.ddClass, info.spellBook),
 				readyCount.handle(PREPARE_SPELL_INDEX)));
 		tabbedPane.addTab("Prepare Spells", null, prepSpells.get(), null);
+		
+		learnAndPrepareListener = ObservableListener.cascade(learn, pick);
 	}
 	
 	@Override

+ 75 - 51
src/main/lombok/org/leumasjaffe/charsheet/view/magic/SelectSpellsPanel.java

@@ -16,6 +16,8 @@ import org.leumasjaffe.charsheet.model.observable.BoolGate;
 import org.leumasjaffe.charsheet.model.observable.IntValue;
 import org.leumasjaffe.event.SelectTableRowPopupMenuListener;
 import org.leumasjaffe.format.StringHelper;
+import org.leumasjaffe.observer.ObservableListener;
+import org.leumasjaffe.observer.ObserverDispatch;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
@@ -42,13 +44,13 @@ public class SelectSpellsPanel extends JPanel {
 	static String NONE = "<none>";
 
 	@AllArgsConstructor
-	protected static class SelectSpellModel extends AbstractTableModel {
+	private static class SelectSpellModel extends AbstractTableModel {
 		/**
 		 * 
 		 */
 		private static final long serialVersionUID = 1L;
 		
-		final Object[] data;
+		Object[] data;
 
 		@Override
 		public int getRowCount() {
@@ -76,20 +78,26 @@ public class SelectSpellsPanel extends JPanel {
 	public static final String READY = "Is Filled Out";
 	
 	@Getter Collection<DDSpell> prepared;
-	boolean allowsDuplicates;
+	List<DDSpell> known = new ArrayList<>();
+	SpellPicker pick;
 	IntValue sharedValue;
 	SelectSpellModel modelPrepared, modelKnown;
+
+	BoolGate.Handle gate;
+	JTable tablePrepared, tableKnown;
+	
+	ObservableListener<JTable, SpellPicker> listener;
 	
 	public SelectSpellsPanel(SpellPicker pick, BoolGate.Handle gate, int level, 
 			Collection<DDSpell> prepared, IntValue sharedValue) {
-		this.allowsDuplicates = pick.allowsDuplicates();
+		this.pick = pick;
+		this.gate = gate;
 		this.sharedValue = sharedValue == null ? new IntValue(-1) : sharedValue;
 		this.prepared = new ArrayList<>(prepared);
-		final List<DDSpell> known = new ArrayList<>(pick.getAvailableSpells(level));
 		this.modelPrepared = new SelectSpellModel(createModel(prepared));
-		this.modelKnown = new SelectSpellModel(createModel(known));
+		this.modelKnown = new SelectSpellModel(null);
 		gate.set(countNone() == 0);
-		sharedValue.value(sharedValue.value() - this.modelPrepared.data.length + countNone());
+		this.sharedValue.value(this.sharedValue.value() - this.modelPrepared.data.length + countNone());
 		
 		GridBagLayout gridBagLayout = new GridBagLayout();
 		gridBagLayout.columnWidths = new int[]{0, 40, 0, 0};
@@ -117,7 +125,7 @@ public class SelectSpellsPanel extends JPanel {
 		gbc_scrollPane_1.gridy = 1;
 		add(scrollPane_1, gbc_scrollPane_1);
 		
-		JTable tablePrepared = new JTable(modelPrepared);
+		tablePrepared = new JTable(modelPrepared);
 		tablePrepared.setTableHeader(null);
 		scrollPane_1.setViewportView(tablePrepared);
 		tablePrepared.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@@ -146,7 +154,7 @@ public class SelectSpellsPanel extends JPanel {
 		gbc_scrollPane.gridy = 1;
 		add(scrollPane, gbc_scrollPane);
 		
-		JTable tableKnown = new JTable(modelKnown);
+		tableKnown = new JTable(modelKnown);
 		tableKnown.setTableHeader(null);
 		scrollPane.setViewportView(tableKnown);
 		tableKnown.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
@@ -171,16 +179,7 @@ public class SelectSpellsPanel extends JPanel {
 		gbc_button.gridx = 0;
 		gbc_button.gridy = 1;
 		panelDivider.add(button, gbc_button);
-		button.addActionListener(e -> {
-			final int row = tablePrepared.getSelectedRow();
-			if (row != -1 && !modelPrepared.data[row].equals(NONE)) {
-				sharedValue.value(sharedValue.value() + 1);
-				modelPrepared.setValueAt(NONE, row, 0);
-			}
-			tablePrepared.getSelectionModel().clearSelection();
-			tablePrepared.repaint();
-			gate.set(false);
-		});
+		button.addActionListener(e -> removeSpell());
 		
 		JButton button_1 = new JButton("<<");
 		button_1.setMargin(new Insets(2, 8, 2, 8));
@@ -190,42 +189,61 @@ public class SelectSpellsPanel extends JPanel {
 		gbc_button_1.gridy = 2;
 		panelDivider.add(button_1, gbc_button_1);
 		
-		button_1.addActionListener(e -> {
-			final int[] rows = tableKnown.getSelectedRows();
-			final int[] orows = tablePrepared.getSelectedRows();
-			if (sharedValue.value() == 0) {
-				JOptionPane.showMessageDialog(this, "You have exceeded the shared limit on new spells", 
-						"Error", JOptionPane.ERROR_MESSAGE);
-			} else if (orows.length >= rows.length) {
-				for (int i = 0; i < rows.length; ++i) {
-					if (wouldHaveIllegalDuplicate(rows[i])) continue;
-					modelPrepared.data[orows[i]] = modelKnown.data[rows[i]];
-					sharedValue.value(sharedValue.value() - 1);
-				}
-			} else if (orows.length == 0 && countNone() >= rows.length) {
-				replace(rows);
-			} else {
-				final String message = StringHelper.format(
-						"Unable to assign new spells, more spells were selected ({}) than were avaliable ({})", 
-						rows.length, orows.length == 0 ? countNone() : orows.length);
-				JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
-			}
-			tableKnown.getSelectionModel().clearSelection();
-			tablePrepared.getSelectionModel().clearSelection();
-			tablePrepared.repaint();
-			
-			if (!gate.get() && !Arrays.asList(modelPrepared.data).contains(NONE)) {
-				this.prepared.clear();
-				for (Object o : modelPrepared.data) {
-					this.prepared.add(DDSpell.fromString((String) o)); // TODO
-				}
-				gate.set(true);
-			}
+		button_1.addActionListener(e -> insertSpell());
+		
+		listener = new ObservableListener<>(tableKnown, (c, v) -> {
+			known.clear();
+			known.addAll(v.getAvailableSpells(level));
+			this.modelKnown.data = createModel(known);
 		});
+		listener.setObserved(pick);
+	}
+	
+	private void removeSpell() {
+		final int row = tablePrepared.getSelectedRow();
+		if (row != -1 && !modelPrepared.data[row].equals(NONE)) {
+			this.sharedValue.value(this.sharedValue.value() + 1);
+			modelPrepared.setValueAt(NONE, row, 0);
+		}
+		tablePrepared.getSelectionModel().clearSelection();
+		tablePrepared.repaint();
+		this.gate.set(false);
+	}
+
+	private void insertSpell() {
+		final int[] rows = tableKnown.getSelectedRows();
+		final int[] orows = tablePrepared.getSelectedRows();
+		if (this.sharedValue.value() == 0) {
+			JOptionPane.showMessageDialog(this, "You have exceeded the shared limit on new spells", 
+					"Error", JOptionPane.ERROR_MESSAGE);
+		} else if (orows.length >= rows.length) {
+			for (int i = 0; i < rows.length; ++i) {
+				if (wouldHaveIllegalDuplicate(rows[i])) continue;
+				modelPrepared.data[orows[i]] = modelKnown.data[rows[i]];
+				this.sharedValue.value(this.sharedValue.value() - 1);
+			}
+		} else if (orows.length == 0 && countNone() >= rows.length) {
+			replace(rows);
+		} else {
+			final String message = StringHelper.format(
+					"Unable to assign new spells, more spells were selected ({}) than were avaliable ({})", 
+					rows.length, orows.length == 0 ? countNone() : orows.length);
+			JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE);
+		}
+		tableKnown.getSelectionModel().clearSelection();
+		tablePrepared.getSelectionModel().clearSelection();
+		tablePrepared.repaint();
+		
+		this.prepared.clear();
+		for (Object o : modelPrepared.data) {
+			this.prepared.add(DDSpell.fromString((String) o)); // TODO
+		}
+		gate.set(countNone() == 0);
+		ObserverDispatch.notifySubscribers(pick);
 	}
 
 	private boolean wouldHaveIllegalDuplicate(int row) {
-		return !this.allowsDuplicates && Arrays.asList(modelPrepared.data).contains(modelKnown.data[row]);
+		return !pick.allowsDuplicates() && Arrays.asList(modelPrepared.data).contains(modelKnown.data[row]);
 	}
 
 	private String[] createModel(Collection<DDSpell> prepared) {
@@ -251,4 +269,10 @@ public class SelectSpellsPanel extends JPanel {
 		}
 		return cnt;
 	}
+	
+	@Override
+	public void removeNotify() {
+		super.removeNotify();
+		ObserverDispatch.unsubscribeAll(listener);
+	}
 }