| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- package org.leumasjaffe.charsheet.view.magic;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.List;
- import javax.swing.JPanel;
- import javax.swing.JPopupMenu;
- import javax.swing.JTable;
- import javax.swing.ListSelectionModel;
- import org.leumasjaffe.charsheet.model.DDCharacter;
- import org.leumasjaffe.charsheet.model.DDCharacterClass;
- 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;
- import lombok.AccessLevel;
- import lombok.AllArgsConstructor;
- import lombok.Getter;
- import lombok.experimental.FieldDefaults;
- import java.awt.GridBagLayout;
- import java.awt.Dimension;
- import java.awt.GridBagConstraints;
- import java.awt.Insets;
- import javax.swing.border.BevelBorder;
- import javax.swing.border.SoftBevelBorder;
- import javax.swing.table.AbstractTableModel;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JScrollPane;
- @SuppressWarnings("serial")
- @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
- public class SelectSpellsPanel extends JPanel {
-
- private static final String NONE = "<none>";
- @AllArgsConstructor
- private static class SelectSpellModel extends AbstractTableModel {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- final Object[] data;
- @Override
- public int getRowCount() {
- return data == null ? 0 : data.length;
- }
- @Override
- public int getColumnCount() {
- return 1;
- }
- @Override
- public Object getValueAt(int rowIndex, int columnIndex) {
- if (columnIndex != 0) { throw new IllegalArgumentException("There is only 1 column"); }
- return data[rowIndex];
- }
-
- @Override
- public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
- if (columnIndex != 0) { throw new IllegalArgumentException("There is only 1 column"); }
- data[rowIndex] = aValue;
- }
- }
- @AllArgsConstructor
- @FieldDefaults(level=AccessLevel.PUBLIC, makeFinal=true)
- public static class Info {
- DDCharacter chara;
- DDCharacterClass dclass;
- }
-
- public static final String READY = "Is Filled Out";
-
- @Getter Collection<DDSpell> prepared;
- boolean allowsDuplicates;
- IntValue sharedValue;
- SelectSpellModel modelPrepared, modelKnown;
-
- public SelectSpellsPanel(Info info, BoolGate.Handle gate, int level, Collection<DDSpell> prepared, int toPrepare,
- Collection<DDSpell> avail, boolean allowsDuplicates, IntValue sharedValue) {
- this.allowsDuplicates = allowsDuplicates;
- this.sharedValue = sharedValue;
- final DDSpellbook spellBook = info.dclass.getSpellBook().get();
- this.prepared = new ArrayList<>(prepared);
- final List<DDSpell> known = new ArrayList<>(avail);
- this.modelPrepared = new SelectSpellModel(createPrepareModel(prepared, toPrepare));
- this.modelKnown = new SelectSpellModel(known.stream().map(DDSpell::getName).toArray());
- putClientProperty(READY, countNone() == 0);
- sharedValue.value(sharedValue.value() - this.modelPrepared.data.length + countNone());
-
- GridBagLayout gridBagLayout = new GridBagLayout();
- gridBagLayout.columnWidths = new int[]{0, 40, 0, 0};
- gridBagLayout.rowHeights = new int[]{20, 0, 0};
- gridBagLayout.columnWeights = new double[]{1.0, 0.0, 1.0, Double.MIN_VALUE};
- gridBagLayout.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
- setLayout(gridBagLayout);
-
- JPanel panel = new ChooseSpellsPerDayHeader(level, spellBook, AbilityHelper.get(info.chara, info.dclass));
- GridBagConstraints gbc_panel = new GridBagConstraints();
- gbc_panel.gridwidth = 3;
- gbc_panel.insets = new Insets(0, 0, 5, 5);
- gbc_panel.fill = GridBagConstraints.BOTH;
- gbc_panel.gridx = 0;
- gbc_panel.gridy = 0;
- add(panel, gbc_panel);
-
- JScrollPane scrollPane_1 = new JScrollPane();
- scrollPane_1.setPreferredSize(new Dimension(175, 200));
- scrollPane_1.setViewportBorder(new SoftBevelBorder(BevelBorder.LOWERED, null, null, null, null));
- GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
- gbc_scrollPane_1.insets = new Insets(0, 0, 0, 5);
- gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
- gbc_scrollPane_1.gridx = 0;
- gbc_scrollPane_1.gridy = 1;
- add(scrollPane_1, gbc_scrollPane_1);
-
- JTable tablePrepared = new JTable(modelPrepared);
- tablePrepared.setTableHeader(null);
- scrollPane_1.setViewportView(tablePrepared);
- tablePrepared.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
- JPanel panelDivider = new JPanel();
- GridBagConstraints gbc_panelDivider = new GridBagConstraints();
- gbc_panelDivider.insets = new Insets(0, 0, 0, 5);
- gbc_panelDivider.fill = GridBagConstraints.BOTH;
- gbc_panelDivider.gridx = 1;
- gbc_panelDivider.gridy = 1;
- add(panelDivider, gbc_panelDivider);
- GridBagLayout gbl_panelDivider = new GridBagLayout();
- gbl_panelDivider.columnWidths = new int[]{0, 0};
- gbl_panelDivider.rowHeights = new int[]{0, 0, 0, 0, 0};
- gbl_panelDivider.columnWeights = new double[]{0.0, Double.MIN_VALUE};
- gbl_panelDivider.rowWeights = new double[]{1.0, 0.0, 0.0, 1.0, Double.MIN_VALUE};
- panelDivider.setLayout(gbl_panelDivider);
-
- JScrollPane scrollPane = new JScrollPane();
- scrollPane.setPreferredSize(new Dimension(175, 200));
- scrollPane.setViewportBorder(new SoftBevelBorder(BevelBorder.LOWERED, null, null, null, null));
- GridBagConstraints gbc_scrollPane = new GridBagConstraints();
- gbc_scrollPane.insets = new Insets(0, 0, 0, 5);
- gbc_scrollPane.fill = GridBagConstraints.BOTH;
- gbc_scrollPane.gridx = 2;
- gbc_scrollPane.gridy = 1;
- add(scrollPane, gbc_scrollPane);
-
- JTable tableKnown = new JTable(modelKnown);
- tableKnown.setTableHeader(null);
- scrollPane.setViewportView(tableKnown);
- tableKnown.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-
- JPopupMenu popup = new JPopupMenu();
- popup.addPopupMenuListener(new SelectTableRowPopupMenuListener(popup, tableKnown));
- JMenuItem mntmInfo = new JMenuItem("Info");
- mntmInfo.addActionListener( e -> {
- DDSpell spell = known.get(tableKnown.getSelectedRow());
- JFrame frame = new JFrame(spell.getName() + " (" + info.dclass.getName() + " " + level + ")");
- frame.add(new SpellInfoPanel(info.chara, info.dclass, spell));
- frame.pack();
- frame.setVisible(true);
- });
- popup.add(mntmInfo);
- tableKnown.setComponentPopupMenu(popup);
-
- JButton button = new JButton(">>");
- button.setMargin(new Insets(2, 8, 2, 8));
- GridBagConstraints gbc_button = new GridBagConstraints();
- gbc_button.insets = new Insets(0, 0, 5, 0);
- 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();
- if ((Boolean) getClientProperty(READY)) {
- putClientProperty(READY, false);
- }
- });
-
- JButton button_1 = new JButton("<<");
- button_1.setMargin(new Insets(2, 8, 2, 8));
- GridBagConstraints gbc_button_1 = new GridBagConstraints();
- gbc_button_1.insets = new Insets(0, 0, 5, 0);
- gbc_button_1.gridx = 0;
- 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);
- }
- });
- }
- public SelectSpellsPanel(Info info, BoolGate.Handle gate, int level,
- Collection<DDSpell> prepared, Collection<DDSpell> avail) {
- this(info, gate, level, prepared, 0, avail, true, new IntValue(-1));
- }
- private boolean wouldHaveIllegalDuplicate(int row) {
- return !this.allowsDuplicates && Arrays.asList(modelPrepared.data).contains(modelKnown.data[row]);
- }
- private String[] createPrepareModel(Collection<DDSpell> prepared, int toPrepare) {
- if (toPrepare <= prepared.size()) {
- return prepared.stream().map(DDSpell::getName).toArray(String[]::new);
- } else {
- String[] data = new String[toPrepare];
- int i = 0;
- for (DDSpell sp : prepared) {
- data[i++] = sp.getName();
- }
- for (; i < toPrepare; ++i) {
- data[i] = NONE;
- }
- return data;
- }
- }
- private void replace(int[] rows) {
- for (int i = 0; i < rows.length; ++i) {
- if (wouldHaveIllegalDuplicate(i)) continue;
- for (int j = 0; j < modelPrepared.data.length; ++j) {
- if (!modelPrepared.data[j].equals(NONE)) continue;
- modelPrepared.data[j] = modelKnown.data[rows[i]];
- sharedValue.value(sharedValue.value() - 1);
- break;
- }
- }
- }
-
- private int countNone() {
- int cnt = 0;
- for (Object o : modelPrepared.data) {
- if (o.equals(NONE)) ++cnt;
- }
- return cnt;
- }
- }
|