D20Sheet.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package org.leumasjaffe.charsheet.view;
  2. import javax.swing.JFileChooser;
  3. import javax.swing.JFrame;
  4. import javax.swing.JTabbedPane;
  5. import com.fasterxml.jackson.databind.ObjectMapper;
  6. import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
  7. import lombok.AccessLevel;
  8. import lombok.NonNull;
  9. import lombok.SneakyThrows;
  10. import lombok.experimental.FieldDefaults;
  11. import lombok.experimental.NonFinal;
  12. import java.awt.BorderLayout;
  13. import javax.swing.JPanel;
  14. import javax.swing.JMenuBar;
  15. import javax.swing.JMenu;
  16. import javax.swing.JMenuItem;
  17. import javax.swing.KeyStroke;
  18. import javax.swing.UIManager;
  19. import org.leumasjaffe.charsheet.model.DDCharacter;
  20. import org.leumasjaffe.charsheet.model.DDCharacterClass;
  21. import org.leumasjaffe.charsheet.view.builders.DialogBuilder;
  22. import org.leumasjaffe.charsheet.view.dev.DeveloperMenu;
  23. import java.awt.event.KeyEvent;
  24. import java.awt.event.WindowEvent;
  25. import java.io.File;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.awt.event.InputEvent;
  29. @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
  30. public class D20Sheet extends JFrame {
  31. /**
  32. *
  33. */
  34. private static final long serialVersionUID = 1L;
  35. ObjectMapper mapper = new ObjectMapper();
  36. @NonFinal File currentlyOpenFile = null;
  37. @NonFinal @NonNull DDCharacter model = new DDCharacter();
  38. JTabbedPane tabbedPane;
  39. SummaryTab summaryTab;
  40. List<ClassTab> classTabs = new ArrayList<>();
  41. JPanel abilitiesTab;
  42. SkillTab skillTab;
  43. EquipmentTab equipmentTab;
  44. private DeveloperMenu developerMenu;
  45. public D20Sheet() {
  46. UIManager.put("CheckBox.disabledText", UIManager.get("CheckBox.foreground"));
  47. // Set up local state variables
  48. final JFileChooser fc = new JFileChooser("resources");
  49. mapper.registerModule(new Jdk8Module());
  50. // Set up GUI Data (WindowBuilder)
  51. tabbedPane = new JTabbedPane(JTabbedPane.TOP);
  52. getContentPane().add(tabbedPane, BorderLayout.CENTER);
  53. summaryTab = new SummaryTab();
  54. abilitiesTab = new JPanel();
  55. skillTab = new SkillTab();
  56. equipmentTab = new EquipmentTab();
  57. JMenuBar menuBar = new JMenuBar();
  58. setJMenuBar(menuBar);
  59. JMenu mnFile = new JMenu("File");
  60. menuBar.add(mnFile);
  61. JMenuItem mntmNew = new JMenuItem("New");
  62. mntmNew.addActionListener(e -> { setModel(new DDCharacter()); });
  63. mntmNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
  64. mnFile.add(mntmNew);
  65. JMenuItem mntmOpen = new JMenuItem("Open");
  66. mntmOpen.addActionListener(e -> {
  67. int rv = fc.showOpenDialog(this);
  68. if ( rv == JFileChooser.APPROVE_OPTION ) {
  69. loadModelResource( fc.getSelectedFile() );
  70. tabbedPane.setSelectedIndex(0);
  71. }
  72. });
  73. mntmOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
  74. mnFile.add(mntmOpen);
  75. JMenuItem mntmSave = new JMenuItem("Save");
  76. mntmSave.addActionListener( e -> {
  77. if ( currentlyOpenFile == null ) { saveAs(fc); }
  78. else { saveModelResource(); }
  79. } );
  80. mntmSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
  81. mnFile.add(mntmSave);
  82. JMenuItem mntmSaveAs = new JMenuItem("Save As");
  83. mntmSaveAs.addActionListener( e -> saveAs(fc) );
  84. mntmSaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
  85. mnFile.add(mntmSaveAs);
  86. JMenuItem mntmExit = new JMenuItem("Exit");
  87. mntmExit.addActionListener( e -> { this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); } );
  88. mntmExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
  89. mnFile.add(mntmExit);
  90. JMenu mnSession = new JMenu("Session");
  91. menuBar.add(mnSession);
  92. JMenuItem mntmGainExperience = new JMenuItem("Gain Experience");
  93. mnSession.add(mntmGainExperience);
  94. JMenuItem mntmTakeRest = new JMenuItem("Take Rest");
  95. mntmTakeRest.addActionListener(e -> {
  96. // Step 0: Gather information about the rest
  97. // Step 0.1: Check if 8-hour or full day
  98. // Step 0.2: Check if Long-Term-Care
  99. // Step 1: Heal Character according to info
  100. // Step 1.1: Heal non-lethal damage
  101. // Step 1.2: Heal ability damage
  102. // Step 2: Regenerate spells prepared
  103. // Step 2.1: If Spontaneous, skip (2)
  104. for (DDCharacterClass dclass : model.getClasses()) {
  105. dclass.getSpellBook().ifPresent(sb -> {
  106. if (sb.preparesSpells()) {
  107. DialogBuilder.createPrepareSpellsDialog(this, model, dclass);
  108. } else {
  109. for (int i = 0; i < dclass.getHighestSpellLevel(); ++i) {
  110. sb.prepareSpells(i, null);
  111. }
  112. }
  113. });
  114. }
  115. // Step N: regenerate spellbooks
  116. reload();
  117. });
  118. mnSession.add(mntmTakeRest);
  119. developerMenu = new DeveloperMenu(this);
  120. menuBar.add(developerMenu);
  121. // Set up post-GUI dependencies
  122. setModel(model);
  123. }
  124. public D20Sheet(final String initialFile) {
  125. this();
  126. loadModelResource(new File(initialFile));
  127. }
  128. private void reorderTabs() {
  129. this.tabbedPane.removeAll();
  130. tabbedPane.addTab("Summary", null, summaryTab, null);
  131. classTabs.forEach( t -> tabbedPane.addTab(t.getName(), null, t, null) );
  132. tabbedPane.addTab("Abilities", null, abilitiesTab, "Racial and Class Abilities, Feats, etc.");
  133. tabbedPane.addTab("Skills", null, skillTab, null);
  134. tabbedPane.addTab("Gear & Items", null, equipmentTab, null);
  135. }
  136. private void saveAs(final JFileChooser fc) {
  137. int rv = fc.showSaveDialog(this);
  138. if ( rv == JFileChooser.APPROVE_OPTION ) {
  139. currentlyOpenFile = fc.getSelectedFile();
  140. saveModelResource();
  141. }
  142. }
  143. @SneakyThrows
  144. private void loadModelResource(File selectedFile) {
  145. currentlyOpenFile = selectedFile;
  146. setModel(mapper.readValue(selectedFile, DDCharacter.class));
  147. }
  148. @SneakyThrows
  149. private void saveModelResource() {
  150. if ( currentlyOpenFile != null ) {
  151. mapper.writeValue(currentlyOpenFile, model);
  152. }
  153. }
  154. public void reload() {
  155. setModel(this.model); // TODO: make this not awful
  156. }
  157. private void setModel(DDCharacter model) {
  158. classTabs.clear();
  159. this.model = model;
  160. summaryTab.setModel(model);
  161. model.getClasses().stream().forEach(cc -> classTabs.add(new ClassTab(model, cc)));
  162. equipmentTab.setModel(model);
  163. skillTab.setModel(model);
  164. developerMenu.setModel(model);
  165. reorderTabs();
  166. }
  167. }