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.view.level.UpdateClassWithLevelPanel.BoolArray; import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel; import org.leumasjaffe.charsheet.view.magic.SelectSpellsPanel.Info; import org.leumasjaffe.observer.ObserverDispatch; import lombok.AccessLevel; import lombok.experimental.FieldDefaults; 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 javax.swing.JScrollPane; import java.awt.GridBagConstraints; @SuppressWarnings("serial") @FieldDefaults(level=AccessLevel.PUBLIC, makeFinal=true) class LevelUpSpellPanel extends JPanel { public static enum SpellPickType { LEARN { @Override public List> getSpellCounts(SelectSpellsPanel.Info info) { return info.dclass.getProto().getSpells().get().getKnown(); } @Override public Collection getAvailableSpells(Info info, int i) { Collection spells = new ArrayList<>(info.dclass.getBase().getSpellList(i)); spells.removeAll(info.dclass.getSpellBook().get().spellsKnownAtLevel(i)); return spells; } }, PREPARE { @Override public List> getSpellCounts(SelectSpellsPanel.Info info) { // TODO: Bonus spells for high ability scores return info.dclass.getProto().getSpells().get().getPerDay(); } @Override public Collection getAvailableSpells(Info info, int i) { return info.dclass.getSpellBook().get().spellsKnownAtLevel(i); } }; public abstract List> getSpellCounts(SelectSpellsPanel.Info info); public abstract Collection getAvailableSpells(SelectSpellsPanel.Info info, int i); } int[] ready = {0}; @NonFinal int spellLevelsGrown = 0; int oldHighestSpellLevel, newHighestSpellLevel; public LevelUpSpellPanel(SpellPickType pick, SelectSpellsPanel.Info info, int toLevel, BoolArray readyCount) { newHighestSpellLevel = info.dclass.getHighestSpellLevel(toLevel); oldHighestSpellLevel = info.dclass.getHighestSpellLevel(); GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[]{0, 0}; gridBagLayout.rowHeights = new int[]{0, 0}; gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE}; gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE}; setLayout(gridBagLayout); JScrollPane scrollPane = new JScrollPane(); GridBagConstraints gbc_scrollPane = new GridBagConstraints(); gbc_scrollPane.fill = GridBagConstraints.BOTH; gbc_scrollPane.gridx = 0; gbc_scrollPane.gridy = 0; add(scrollPane, gbc_scrollPane); JPanel panel = new JPanel(new VerticalLayout(5)); scrollPane.setViewportView(panel); final List panels = new ArrayList<>(); final List> spellList = pick.getSpellCounts(info); final List spellsAtPreviousLevel = toLevel == 1 ? Collections.emptyList() : spellList.get(toLevel-2); final List spellsAtCurrentLevel = spellList.get(toLevel-1); for (int i = 0; i < newHighestSpellLevel; ++i) { ++spellLevelsGrown; final int newSpells = diff(spellsAtCurrentLevel, spellsAtPreviousLevel, i, isNewSpellCircle(i)); SelectSpellsPanel lvl = new SelectSpellsPanel(info, i, new LinkedHashSet<>(), newSpells, pick.getAvailableSpells(info, i), pick != SpellPickType.LEARN); panels.add(lvl); lvl.addPropertyChangeListener(SelectSpellsPanel.READY, e -> { if ((Boolean) e.getNewValue()) ++ready[0]; else --ready[0]; readyCount.data[1] = (ready[0] == spellLevelsGrown); ObserverDispatch.notifySubscribers(readyCount, this); }); panel.add(lvl); } } private boolean isNewSpellCircle(int i) { return i == (newHighestSpellLevel - 1) && oldHighestSpellLevel != newHighestSpellLevel; } private int diff(List current, List previous, int level, boolean newSpellLevel) { return current.get(level) - (newSpellLevel || previous.size() <= level ? 0 : previous.get(level)); } }