diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties index 4d973527b09..3cd8a60d0ff 100644 --- a/MekHQ/resources/mekhq/resources/GUI.properties +++ b/MekHQ/resources/mekhq/resources/GUI.properties @@ -1378,7 +1378,7 @@ btnNewCampaign.text=New Campaign btnLoadCampaign.text=Load Campaign btnLoadLastCampaign.text=Load Last Save btnLoadStoryArc.text=Story Arcs - +btnStoryArcEditor.text=Story Arc Editor ##### Panes #### RankSystemsPane Class diff --git a/MekHQ/resources/mekhq/resources/StoryArcEditorGUI.properties b/MekHQ/resources/mekhq/resources/StoryArcEditorGUI.properties new file mode 100644 index 00000000000..bfd469492b5 --- /dev/null +++ b/MekHQ/resources/mekhq/resources/StoryArcEditorGUI.properties @@ -0,0 +1,4 @@ +fileMenu.text=File +miNewArc.text=New Story Arc... +miLoadArc.text=Load Story Arc... +miSaveArc.text=Save Story Arc \ No newline at end of file diff --git a/MekHQ/src/mekhq/MekHQ.java b/MekHQ/src/mekhq/MekHQ.java index a489a9ac386..5f0276cca22 100644 --- a/MekHQ/src/mekhq/MekHQ.java +++ b/MekHQ/src/mekhq/MekHQ.java @@ -56,11 +56,17 @@ import mekhq.campaign.handler.XPHandler; import mekhq.campaign.mission.AtBScenario; import mekhq.campaign.mission.Scenario; +import mekhq.campaign.stratcon.StratconRulesManager; +import mekhq.campaign.unit.Unit; +import mekhq.gui.CampaignGUI; import mekhq.campaign.personnel.Person; import mekhq.campaign.stratcon.StratconRulesManager; import mekhq.campaign.unit.Unit; import mekhq.gui.CampaignGUI; import mekhq.gui.dialog.ChooseMulFilesDialog; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.gui.StoryArcEditorGUI; + import mekhq.gui.dialog.ResolveScenarioWizardDialog; import mekhq.gui.panels.StartupScreenPanel; import mekhq.gui.preferences.StringPreference; @@ -117,6 +123,7 @@ public class MekHQ implements GameListener { // the actual campaign - this is where the good stuff is private CampaignController campaignController; private CampaignGUI campaignGUI; + private StoryArcEditorGUI storyArcEditorGUI; private final IconPackage iconPackage = new IconPackage(); @@ -274,6 +281,10 @@ public void showNewView() { campaignGUI = new CampaignGUI(this); } + public void showNewStoryArcEditor(StoryArc arc) { + storyArcEditorGUI = new StoryArcEditorGUI(this, arc); + } + /** * Main method launching the application. */ diff --git a/MekHQ/src/mekhq/campaign/storyarc/StoryArc.java b/MekHQ/src/mekhq/campaign/storyarc/StoryArc.java index 24eda21b65b..9dd7b8d96ed 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/StoryArc.java +++ b/MekHQ/src/mekhq/campaign/storyarc/StoryArc.java @@ -198,6 +198,10 @@ private UUID getStartingPointId() { return startingPointId; } + public List getStoryPoints() { + return new ArrayList(storyPoints.values()); + } + public void setInitCampaignPath(String s) { this.initCampaignPath = s; } @@ -289,6 +293,15 @@ public String toString() { return getTitle(); } + public boolean isDuplicateName(String name) { + for(StoryPoint sp : getStoryPoints()) { + if(sp.getName().equals(name)) { + return true; + } + } + return false; + } + // region EventHandlers @Subscribe public void handleScenarioResolved(ScenarioResolvedEvent ev) { @@ -575,7 +588,7 @@ private static void updateReplacementTokens(Campaign c) { /** * This method will replace tokens in narrative text - * + * * @param text String containing the original text with tokens. * @return String containing the text with tokens replaced. */ diff --git a/MekHQ/src/mekhq/campaign/storyarc/StoryOutcome.java b/MekHQ/src/mekhq/campaign/storyarc/StoryOutcome.java index f6bf1ffdb44..488dc2dde89 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/StoryOutcome.java +++ b/MekHQ/src/mekhq/campaign/storyarc/StoryOutcome.java @@ -52,7 +52,7 @@ public class StoryOutcome { /** A list of StoryTriggers to replace the defaults on this outcome */ List storyTriggers; - StoryOutcome() { + public StoryOutcome() { storyTriggers = new ArrayList<>(); } @@ -60,17 +60,29 @@ public String getResult() { return result; } + public void setResult(String r) { + this.result = r; + } + public UUID getNextStoryPointId() { return nextStoryPointId; } + public void setNextStoryPointId(UUID id) { + this.nextStoryPointId = id; + } + public List getStoryTriggers() { return storyTriggers; } + public void setStoryTriggers(List triggers) { + this.storyTriggers = triggers; + } + /** * Set the StoryArc on all StoryTriggers here - * + * * @param a a {@link StoryArc StoryArc} */ public void setStoryArc(StoryArc a) { diff --git a/MekHQ/src/mekhq/campaign/storyarc/StoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/StoryPoint.java index b2e9855f8a3..269f3080274 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/StoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/StoryPoint.java @@ -20,6 +20,11 @@ */ package mekhq.campaign.storyarc; +import megamek.Version; +import mekhq.gui.StoryPointHyperLinkListener; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import org.apache.logging.log4j.LogManager; import java.io.PrintWriter; import java.text.ParseException; import java.util.ArrayList; @@ -86,6 +91,8 @@ public abstract class StoryPoint { private static final MMLogger logger = MMLogger.create(StoryPoint.class); + public final static String DEFAULT_OUTCOME = "DEFAULT"; + /** The story arc that this story point is a part of **/ private StoryArc storyArc; @@ -132,7 +139,7 @@ public void setStoryArc(StoryArc a) { } } - protected StoryArc getStoryArc() { + public StoryArc getStoryArc() { return storyArc; } @@ -140,7 +147,7 @@ public void setId(UUID id) { this.id = id; } - protected UUID getId() { + public UUID getId() { return id; } @@ -154,6 +161,30 @@ public String getName() { return name; } + public void setName(String s) { + name = s; + } + + public UUID getNextStoryPointId() { + return nextStoryPointId; + } + + public void setNextStoryPointId(UUID nextStoryPointId) { + this.nextStoryPointId = nextStoryPointId; + } + + public List getStoryOutcomes() { + return new ArrayList(storyOutcomes.values()); + } + + public List getStoryTriggers() { + return storyTriggers; + } + + public void setStoryTriggers(List storyTriggers) { + this.storyTriggers = storyTriggers; + } + /** * Do whatever needs to be done to start this story point. Specific story point * types may need to override this @@ -246,6 +277,53 @@ public Campaign getCampaign() { return getStoryArc().getCampaign(); } + public List getAllPossibleResults() { + ArrayList results = new ArrayList<>(); + results.add(DEFAULT_OUTCOME); + return results; + } + + public List getLinkingStoryPoints() { + List previous = new ArrayList(); + UUID nextId; + for (StoryPoint otherStoryPoint : storyArc.getStoryPoints()) { + nextId = otherStoryPoint.getNextStoryPointId(); + if ((nextId != null) && (nextId.equals(getId()))) { + previous.add(otherStoryPoint); + continue; + } + for( StoryOutcome outcome : otherStoryPoint.getStoryOutcomes()) { + nextId = outcome.getNextStoryPointId(); + if ((nextId != null) && (nextId.equals(getId()))) { + previous.add(otherStoryPoint); + continue; + } + } + } + return previous; + } + + public String getHyperlinkedName() { + return String.format("%s", StoryPointHyperLinkListener.STORYPOINT, getId(), getName()); + } + + public StoryOutcome getStoryOutcome(String result) { + return storyOutcomes.get(result); + } + + public void addStoryOutcome(String result, StoryOutcome outcome) { + storyOutcomes.put(result, outcome); + } + + public void removeStoryOutcome(String result) { + storyOutcomes.remove(result); + } + + public void removeDefaultOutcome() { + nextStoryPointId = null; + storyTriggers = new ArrayList<>(); + } + // region I/O public abstract void writeToXml(PrintWriter pw1, int indent); @@ -335,5 +413,4 @@ public static StoryPoint generateInstanceFromXML(Node wn, Campaign c, Version ve return retVal; } - } diff --git a/MekHQ/src/mekhq/campaign/storyarc/StoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/StoryTrigger.java index 47db1cd78a7..b2b92a0a9c0 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/StoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/StoryTrigger.java @@ -20,6 +20,15 @@ */ package mekhq.campaign.storyarc; +import megamek.Version; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; @@ -52,7 +61,7 @@ public void setStoryArc(StoryArc a) { this.arc = a; } - protected StoryArc getStoryArc() { + public StoryArc getStoryArc() { return arc; } @@ -65,6 +74,10 @@ protected Campaign getCampaign() { */ protected abstract void execute(); + public abstract String getDescription(); + + public abstract StoryTriggerPanel getPanel(JFrame frame); + // region I/O public abstract void writeToXml(PrintWriter pw1, int indent); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckMoreScenariosStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckMoreScenariosStoryPoint.java index b40125d9fbb..dafef70a243 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckMoreScenariosStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckMoreScenariosStoryPoint.java @@ -18,8 +18,20 @@ */ package mekhq.campaign.storyarc.storypoint; +import megamek.Version; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.mission.Mission; +import mekhq.campaign.storyarc.StoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import java.io.PrintWriter; import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import org.w3c.dom.Node; @@ -65,6 +77,15 @@ protected String getResult() { return "true"; } + @Override + public List getAllPossibleResults() { + ArrayList results = new ArrayList<>(); + results.add("true"); + results.add("false"); + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public void start() { super.start(); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckPersonStatusStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckPersonStatusStoryPoint.java index 02325ecc5a5..2e16fccac6c 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckPersonStatusStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckPersonStatusStoryPoint.java @@ -20,8 +20,21 @@ */ package mekhq.campaign.storyarc.storypoint; +import megamek.Version; +import mekhq.campaign.personnel.enums.PersonnelStatus; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.personnel.Person; +import mekhq.campaign.storyarc.StoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import java.io.PrintWriter; import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import org.w3c.dom.Node; @@ -65,6 +78,16 @@ protected String getResult() { } } + @Override + public List getAllPossibleResults() { + ArrayList results = new ArrayList<>(); + for(PersonnelStatus status : PersonnelStatus.getImplementedStatuses()) { + results.add(status.name()); + } + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public void start() { super.start(); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckStringVariableStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckStringVariableStoryPoint.java index 2284d69cff9..e881b69148f 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckStringVariableStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CheckStringVariableStoryPoint.java @@ -20,8 +20,21 @@ */ package mekhq.campaign.storyarc.storypoint; +import megamek.Version; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.ChangeStringVariableStoryTrigger; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import java.io.PrintWriter; import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -60,6 +73,33 @@ protected String getResult() { return getStoryArc().getCustomStringVariable(key); } + @Override + public List getAllPossibleResults() { + // this one is complicated, but we can find all the triggers where this has been changed and collect + // all possibilities + List results = new ArrayList<>(); + for(StoryPoint sp : getStoryArc().getStoryPoints()) { + for(StoryTrigger trigger : sp.getStoryTriggers()) { + if(trigger instanceof ChangeStringVariableStoryTrigger) { + if(!((ChangeStringVariableStoryTrigger)trigger).getKey().equals(key)) { + continue; + } + String value = ((ChangeStringVariableStoryTrigger)trigger).getValue(); + if(!results.contains(value)) { + results.add(value); + } + } + } + } + // finally, check the current value of this variable and add it if not already there + String value = getStoryArc().getCustomStringVariable(key); + if(!results.contains(value)) { + results.add(value); + } + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public void start() { super.start(); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/ChoiceStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/ChoiceStoryPoint.java index 22e4e36e997..df5ee653a48 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/ChoiceStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/ChoiceStoryPoint.java @@ -20,9 +20,21 @@ */ package mekhq.campaign.storyarc.storypoint; +import megamek.Version; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.gui.dialog.StoryChoiceDialog; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import java.io.PrintWriter; import java.text.ParseException; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -68,6 +80,13 @@ public Map getChoices() { return choices; } + @Override + public List getAllPossibleResults() { + List results = new ArrayList(choices.keySet()); + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public void start() { super.start(); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/MissionStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/MissionStoryPoint.java index f6a791fbd15..df5e51d4174 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/MissionStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/MissionStoryPoint.java @@ -30,6 +30,8 @@ import org.w3c.dom.NodeList; import megamek.Version; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; import mekhq.campaign.mission.Mission; @@ -149,6 +151,15 @@ public String getObjective() { return "Complete " + mission.getName() + " mission"; } + @Override + public List getAllPossibleResults() { + ArrayList results = new ArrayList<>(); + results.add(MissionStatus.FAILED.name()); + results.add(MissionStatus.SUCCESS.name()); + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/RollDiceStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/RollDiceStoryPoint.java index 6027d576e00..0f99234fc04 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/RollDiceStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/RollDiceStoryPoint.java @@ -18,8 +18,20 @@ */ package mekhq.campaign.storyarc.storypoint; +import megamek.Version; +import megamek.common.Compute; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import java.io.PrintWriter; import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -54,6 +66,7 @@ public String getTitle() { @Override public void start() { super.start(); + //index zero should contain the summed result value = Compute.individualDice(ndice, sides).get(0); complete(); } @@ -63,6 +76,16 @@ protected String getResult() { return Integer.toString(value); } + public List getAllPossibleResults() { + int min = ndice; + int max = ndice * sides; + List results = new ArrayList<>(); + for(int i = min; i <= max; i++) { + results.add(Integer.toString(i)); + } + results.add(DEFAULT_OUTCOME); + return results; + } @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/ScenarioStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/ScenarioStoryPoint.java index bf7d6b11f64..11ff11ff251 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/ScenarioStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/ScenarioStoryPoint.java @@ -28,6 +28,8 @@ import org.w3c.dom.NodeList; import megamek.Version; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.utilities.MHQXMLUtility; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; import mekhq.campaign.force.Force; @@ -36,6 +38,15 @@ import mekhq.campaign.mission.enums.ScenarioStatus; import mekhq.campaign.storyarc.StoryPoint; import mekhq.campaign.unit.Unit; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintWriter; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mekhq.utilities.MHQXMLUtility; /** @@ -146,6 +157,19 @@ protected String getResult() { return ""; } + @Override + public List getAllPossibleResults() { + ArrayList results = new ArrayList<>(); + for(ScenarioStatus nextStatus : ScenarioStatus.values()) { + if(nextStatus.isCurrent()) { + continue; + } + results.add(nextStatus.name()); + } + results.add(DEFAULT_OUTCOME); + return results; + } + @Override public String getObjective() { return "Complete " + scenario.getName() + " scenario"; diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddPersonStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddPersonStoryTrigger.java index 4d64f48c090..8b32c913ec1 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddPersonStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddPersonStoryTrigger.java @@ -20,6 +20,19 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.campaign.Campaign; +import mekhq.campaign.personnel.Person; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; +import java.io.PrintWriter; +import java.text.ParseException; import java.io.PrintWriter; import java.text.ParseException; @@ -48,6 +61,16 @@ protected void execute() { } + @Override + public String getDescription() { + return "Add person (" + person.getFullName() + ")"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new FakeStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java index 72fb12a1105..ef0d105d3ca 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AddUnitStoryTrigger.java @@ -20,6 +20,20 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import megamek.common.Entity; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; +import java.io.PrintWriter; +import java.text.ParseException; import java.io.PrintWriter; import java.text.ParseException; @@ -73,6 +87,16 @@ protected void execute() { getCampaign().addNewUnit(en, false, 0, quality); } + @Override + public String getDescription() { + return "Add unit(s)"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new FakeStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AdvanceTimeStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AdvanceTimeStoryTrigger.java index 43326eb2fa7..77496b0a36b 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AdvanceTimeStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/AdvanceTimeStoryTrigger.java @@ -20,6 +20,20 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.panels.storytriggerpanels.AdvanceTimeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; +import java.io.PrintWriter; +import java.text.ParseException; import java.io.PrintWriter; import java.text.ParseException; @@ -38,7 +52,7 @@ public class AdvanceTimeStoryTrigger extends StoryTrigger { private static final MMLogger logger = MMLogger.create(AdvanceTimeStoryTrigger.class); - int days; + int days = 1; @Override protected void execute() { @@ -49,6 +63,24 @@ protected void execute() { } } + public int getDays() { + return days; + } + + public void setDays(int days) { + this.days = days; + } + + @Override + public String getDescription() { + return "Advance time (" + days + " days)"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new AdvanceTimeStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangePersonStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangePersonStoryTrigger.java index 9708edc0f08..4f462164cb4 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangePersonStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangePersonStoryTrigger.java @@ -28,12 +28,23 @@ import org.w3c.dom.NodeList; import megamek.Version; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; import megamek.logging.MMLogger; import mekhq.campaign.Campaign; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.PersonnelStatus; import mekhq.campaign.storyarc.StoryTrigger; import mekhq.campaign.unit.Unit; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; +import java.io.PrintWriter; +import java.text.ParseException; +import java.util.UUID; import mekhq.utilities.MHQXMLUtility; /** @@ -132,6 +143,16 @@ protected void execute() { } } + @Override + public String getDescription() { + return "Change person"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new FakeStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangeStringVariableStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangeStringVariableStoryTrigger.java index 304375044bd..d2246bbdde9 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangeStringVariableStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/ChangeStringVariableStoryTrigger.java @@ -20,6 +20,20 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.gui.panels.storytriggerpanels.ChangeStringVariableStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryTrigger; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; +import java.io.PrintWriter; +import java.text.ParseException; import java.io.PrintWriter; import java.text.ParseException; @@ -46,6 +60,32 @@ protected void execute() { getStoryArc().addCustomStringVariable(key, value); } + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String getDescription() { + return "Change value of " + key + " to " + value; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new ChangeStringVariableStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/CompleteMissionStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/CompleteMissionStoryTrigger.java index 79e729af99d..e059153ca19 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/CompleteMissionStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/CompleteMissionStoryTrigger.java @@ -20,6 +20,22 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.gui.StoryPointHyperLinkListener; +import mekhq.gui.panels.storytriggerpanels.CompleteMissionStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.mission.enums.MissionStatus; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.storypoint.MissionStoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; import java.util.UUID; @@ -47,6 +63,22 @@ public class CompleteMissionStoryTrigger extends StoryTrigger { UUID missionStoryPointId; MissionStatus missionStatus; + public UUID getMissionStoryPointId() { + return missionStoryPointId; + } + + public void setMissionStoryPointId(UUID missionStoryPointId) { + this.missionStoryPointId = missionStoryPointId; + } + + public MissionStatus getMissionStatus() { + return missionStatus; + } + + public void setMissionStatus(MissionStatus missionStatus) { + this.missionStatus = missionStatus; + } + @Override protected void execute() { StoryPoint storyPoint = getStoryArc().getStoryPoint(missionStoryPointId); @@ -58,6 +90,29 @@ protected void execute() { } } + @Override + public String getDescription() { + StoryPoint storyPoint = getStoryArc().getStoryPoint(missionStoryPointId); + StringBuilder sb = new StringBuilder(); + sb.append("Complete "); + if(storyPoint == null) { + sb.append("mission (MISSING)"); + } else { + sb.append(storyPoint.getHyperlinkedName()); + } + if(missionStatus != null) { + sb.append(" ("); + sb.append(missionStatus.name()); + sb.append(")"); + } + return sb.toString(); + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new CompleteMissionStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/EndArcStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/EndArcStoryTrigger.java index 2e363a00511..2cf193b677e 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/EndArcStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/EndArcStoryTrigger.java @@ -23,8 +23,11 @@ import megamek.Version; import mekhq.campaign.Campaign; import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.panels.storytriggerpanels.EndArcStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; import org.w3c.dom.Node; +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; @@ -39,6 +42,16 @@ protected void execute() { getCampaign().unloadStoryArc(); } + @Override + public String getDescription() { + return "Complete story arc"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new EndArcStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/GameOverStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/GameOverStoryTrigger.java index aad92cef399..aab2c65ad21 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/GameOverStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/GameOverStoryTrigger.java @@ -24,8 +24,12 @@ import mekhq.MekHQ; import mekhq.campaign.Campaign; import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.GameOverStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; import org.w3c.dom.Node; +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; @@ -41,6 +45,16 @@ protected void execute() { getCampaign().getApp().restart(); } + @Override + public String getDescription() { + return "Game Over"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new GameOverStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/RemoveUnitStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/RemoveUnitStoryTrigger.java index d4c073ef691..52be93afd3f 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/RemoveUnitStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/RemoveUnitStoryTrigger.java @@ -20,6 +20,18 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.unit.Unit; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; import java.util.ArrayList; @@ -61,6 +73,16 @@ protected void execute() { } } + @Override + public String getDescription() { + return "Remove unit(s)"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new FakeStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SetDateStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SetDateStoryTrigger.java index ddd1866e049..b6640af90d5 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SetDateStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SetDateStoryTrigger.java @@ -18,6 +18,22 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.MekHQ; +import mekhq.gui.StoryPointHyperLinkListener; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.SetDateStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storypoint.CheckDateReachedStoryPoint; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; import java.time.LocalDate; @@ -68,6 +84,31 @@ public SetDateStoryTrigger() { } // endregion Constructors + + public UUID getStoryPointId() { + return storyPointId; + } + + public void setStoryPointId(UUID storyPointId) { + this.storyPointId = storyPointId; + } + + public int getFutureDays() { + return futureDays; + } + + public void setFutureDays(int futureDays) { + this.futureDays = futureDays; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + @Override protected void execute() { StoryPoint storyPoint = getStoryArc().getStoryPoint(storyPointId); @@ -81,6 +122,31 @@ protected void execute() { } } + @Override + public String getDescription() { + StoryPoint storyPoint = getStoryArc().getStoryPoint(storyPointId); + StringBuilder sb = new StringBuilder(); + sb.append("Set date"); + if(storyPoint != null) { + sb.append(" in "); + sb.append(storyPoint.getHyperlinkedName()); + if(date == null) { + sb.append(" ahead by "); + sb.append(futureDays); + sb.append(" days"); + } else { + sb.append(" to "); + sb.append(MekHQ.getMHQOptions().getDisplayFormattedDate(date)); + } + } + return sb.toString(); + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new SetDateStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SwitchTabStoryTrigger.java b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SwitchTabStoryTrigger.java index 5c74c979ddd..1ab019ff0e2 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SwitchTabStoryTrigger.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storytrigger/SwitchTabStoryTrigger.java @@ -20,6 +20,19 @@ */ package mekhq.campaign.storyarc.storytrigger; +import megamek.Version; +import mekhq.gui.panels.storytriggerpanels.FakeStoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.gui.panels.storytriggerpanels.SwitchTabStoryTriggerPanel; +import mekhq.utilities.MHQXMLUtility; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.enums.MHQTabType; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.swing.*; import java.io.PrintWriter; import java.text.ParseException; @@ -43,11 +56,29 @@ public class SwitchTabStoryTrigger extends StoryTrigger { MHQTabType tab; + public MHQTabType getTab() { + return tab; + } + + public void setTab(MHQTabType tab) { + this.tab = tab; + } + @Override protected void execute() { getCampaign().getApp().getCampaigngui().setSelectedTab(tab); } + @Override + public String getDescription() { + return "Switch to " + tab.toString() + " tab"; + } + + @Override + public StoryTriggerPanel getPanel(JFrame frame) { + return new SwitchTabStoryTriggerPanel(frame, "StoryTriggerPanel", this); + } + @Override public void writeToXml(PrintWriter pw1, int indent) { writeToXmlBegin(pw1, indent++); diff --git a/MekHQ/src/mekhq/gui/StoryArcEditorGUI.java b/MekHQ/src/mekhq/gui/StoryArcEditorGUI.java new file mode 100644 index 00000000000..df86ddd6c45 --- /dev/null +++ b/MekHQ/src/mekhq/gui/StoryArcEditorGUI.java @@ -0,0 +1,229 @@ +package mekhq.gui; + +import mekhq.MekHQ; +import mekhq.campaign.Campaign; +import mekhq.campaign.storyarc.StoryArc; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.*; +import mekhq.gui.model.StoryPointTableModel; +import mekhq.gui.panels.StoryPointEditorPanel; +import org.apache.logging.log4j.LogManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.ResourceBundle; +import java.util.UUID; + +public class StoryArcEditorGUI extends JPanel { + + //region Variable Declarations + public static final int MAX_START_WIDTH = 1400; + public static final int MAX_START_HEIGHT = 900; + + public static HashMap availableTriggers; + private JFrame frame; + private MekHQ app; + private StoryPointHyperLinkListener storyPointHLL; + + /* Menu Bar */ + private JMenuBar menuBar; + + /* Story Point Table */ + private JTable storyPointTable; + private StoryPointTableModel storyPointTableModel; + private JScrollPane scrollStoryPointEditor; + + + private StoryArc storyArc; + private static final ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.StoryArcEditorGUI", + MekHQ.getMHQOptions().getLocale()); + //endregion Variable Declarations + + //region Constructors + public StoryArcEditorGUI(MekHQ app, StoryArc arc) { + this.app = app; + this.storyArc = arc; + storyPointHLL = new StoryPointHyperLinkListener(storyArc, this); + initializeAvailableTriggers(); + initComponents(); + } + //endregion Constructors + + //region Getters/Setters + public JFrame getFrame() { + return frame; + } + + protected MekHQ getApplication() { + return app; + } + + public StoryPointHyperLinkListener getStoryPointHLL() { + return storyPointHLL; + } + + protected Campaign getCampaign() { + return getApplication().getCampaign(); + } + + protected ResourceBundle getResourceMap() { + return null;//resourceMap; + } + //endregion Getters/Setters + + //region Initialization + private void initComponents() { + frame = new JFrame("Story Arc Editor"); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + setLayout(new BorderLayout()); + + storyPointTableModel = new StoryPointTableModel(); + storyPointTable = new JTable(storyPointTableModel); + storyPointTable.setRowHeight(60); + storyPointTable.getColumnModel().getColumn(0).setCellRenderer(storyPointTableModel.getRenderer()); + storyPointTable.setOpaque(false); + JScrollPane scrollStoryPoints = new JScrollPane(storyPointTable); + storyPointTable.getSelectionModel().addListSelectionListener(ev -> refreshStoryPointEditor()); + refreshStoryPoints(); + + add(scrollStoryPoints, BorderLayout.WEST); + + scrollStoryPointEditor = new JScrollPane(); + scrollStoryPointEditor.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollStoryPointEditor.setViewportView(null); + + add(scrollStoryPointEditor, BorderLayout.CENTER); + + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + + frame.setSize(Math.min(MAX_START_WIDTH, dim.width), + Math.min(MAX_START_HEIGHT, dim.height)); + + // Determine the new location of the window + int w = frame.getSize().width; + int h = frame.getSize().height; + int x = (dim.width - w) / 2; + int y = (dim.height - h) / 2; + + // Move the window + frame.setLocation(x, y); + + initMenu(); + frame.setJMenuBar(menuBar); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(this, BorderLayout.CENTER); + frame.validate(); + + if (isMacOSX()) { + enableFullScreenMode(frame); + } + + frame.setVisible(true); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + getApplication().exit(false); + } + }); + + } + + private void initMenu() { + menuBar = new JMenuBar(); + + JMenu menuFile = new JMenu(resourceMap.getString("fileMenu.text")); + menuFile.setMnemonic(KeyEvent.VK_F); + JMenuItem miNewArc = new JMenuItem(resourceMap.getString("miNewArc.text")); + miNewArc.setMnemonic(KeyEvent.VK_N); + menuFile.add(miNewArc); + JMenuItem miLoadArc = new JMenuItem(resourceMap.getString("miLoadArc.text")); + + miLoadArc.setMnemonic(KeyEvent.VK_L); + menuFile.add(miLoadArc); + JMenuItem miSaveArc = new JMenuItem(resourceMap.getString("miSaveArc.text")); + miSaveArc.setMnemonic(KeyEvent.VK_S); + menuFile.add(miSaveArc); + + menuBar.add(menuFile); + } + //endregion Initialization + + private static boolean isMacOSX() { + return System.getProperty("os.name").contains("Mac OS X"); + } + + private static void enableFullScreenMode(Window window) { + String className = "com.apple.eawt.FullScreenUtilities"; + String methodName = "setWindowCanFullScreen"; + + try { + Class clazz = Class.forName(className); + Method method = clazz.getMethod(methodName, Window.class, boolean.class); + method.invoke(null, window, true); + } catch (Throwable t) { + LogManager.getLogger().error("Full screen mode is not supported", t); + } + } + + public void refreshStoryPoints() { + final int selected = storyPointTable.getSelectedRow(); + final List storyPoints = storyArc.getStoryPoints(); + //storyPoints.sort(new PersonTitleSorter().reversed()); + storyPointTableModel.setData(storyPoints); + if ((selected > -1) && (selected < storyPoints.size())) { + storyPointTable.setRowSelectionInterval(selected, selected); + } + } + + public void focusOnStoryPoint(UUID id) { + int row = -1; + for (int i = 0; i < storyPointTable.getRowCount(); i++) { + if (storyPointTableModel.getStoryPointAt(i).getId().equals(id)) { + row = i; + break; + } + } + if (row != -1) { + storyPointTable.setRowSelectionInterval(row, row); + storyPointTable.scrollRectToVisible(storyPointTable.getCellRect(row, 0, true)); + } + } + + public void refreshStoryPointEditor() { + int row = storyPointTable.getSelectedRow(); + if (row < 0) { + scrollStoryPointEditor.setViewportView(null); + return; + } + StoryPoint selectedStoryPoint = storyPointTableModel.getStoryPointAt(storyPointTable.convertRowIndexToModel(row)); + scrollStoryPointEditor.setViewportView(new StoryPointEditorPanel(frame, "story point editor", selectedStoryPoint, this)); + SwingUtilities.invokeLater(() -> scrollStoryPointEditor.getVerticalScrollBar().setValue(0)); + } + + private void initializeAvailableTriggers() { + availableTriggers = new HashMap<>(); + StoryTrigger trigger; + trigger = new AdvanceTimeStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new ChangeStringVariableStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new CompleteMissionStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new EndArcStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new GameOverStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new SetDateStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + trigger = new SwitchTabStoryTrigger(); + availableTriggers.put(trigger.getClass().getSimpleName(), trigger.getClass().getName()); + } +} diff --git a/MekHQ/src/mekhq/gui/StoryPointHyperLinkListener.java b/MekHQ/src/mekhq/gui/StoryPointHyperLinkListener.java new file mode 100644 index 00000000000..795582d4c39 --- /dev/null +++ b/MekHQ/src/mekhq/gui/StoryPointHyperLinkListener.java @@ -0,0 +1,36 @@ +package mekhq.gui; + +import mekhq.campaign.storyarc.StoryArc; +import mekhq.gui.StoryArcEditorGUI; +import org.apache.logging.log4j.LogManager; + +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.util.UUID; + +public class StoryPointHyperLinkListener implements HyperlinkListener { + + private StoryArc storyArc; + private StoryArcEditorGUI editorGUI; + + public static final String STORYPOINT = "STORYPOINT"; + + public StoryPointHyperLinkListener(final StoryArc arc, final StoryArcEditorGUI gui) { + this.storyArc = arc; + this.editorGUI = gui; + } + + @Override + public void hyperlinkUpdate(HyperlinkEvent evt) { + if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + if (evt.getDescription().startsWith(STORYPOINT)) { + try { + final UUID id = UUID.fromString(evt.getDescription().split(":")[1]); + editorGUI.focusOnStoryPoint(id); + } catch (Exception e) { + LogManager.getLogger().error("", e); + } + } + } + } +} diff --git a/MekHQ/src/mekhq/gui/dialog/CustomizeStoryOutcomeDialog.java b/MekHQ/src/mekhq/gui/dialog/CustomizeStoryOutcomeDialog.java new file mode 100644 index 00000000000..414798f8acb --- /dev/null +++ b/MekHQ/src/mekhq/gui/dialog/CustomizeStoryOutcomeDialog.java @@ -0,0 +1,220 @@ +package mekhq.gui.dialog; + +import mekhq.campaign.storyarc.StoryOutcome; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.GameOverStoryTrigger; +import mekhq.gui.StoryArcEditorGUI; +import mekhq.gui.panels.storytriggerpanels.StoryTriggerPanel; +import mekhq.gui.utilities.JSuggestField; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionListener; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Vector; + +public class CustomizeStoryOutcomeDialog extends JDialog { + + JFrame frame; + private StoryOutcome outcome; + private StoryPoint storyPoint; + private String result; + boolean isNewOutcome; + private JSuggestField suggestNext; + + JComboBox choiceAddTrigger; + + private ArrayList triggerPanels; + private JPanel panTriggers; + private JScrollPane scrTriggers; + + public CustomizeStoryOutcomeDialog(JFrame parent, boolean modal, String result, StoryPoint sp, boolean isNew) { + super(parent, modal); + this.frame = parent; + this.storyPoint = sp; + this.isNewOutcome = isNew; + this.result = result; + if (this.result.equals(StoryPoint.DEFAULT_OUTCOME)) { + outcome = new StoryOutcome(); + outcome.setNextStoryPointId(storyPoint.getNextStoryPointId()); + outcome.setStoryTriggers(storyPoint.getStoryTriggers()); + } else if (isNewOutcome) { + outcome = new StoryOutcome(); + } else { + outcome = storyPoint.getStoryOutcome(this.result); + } + initialize(); + setLocationRelativeTo(parent); + pack(); + } + + private void initialize() { + setTitle("Customize Story Outcome"); + getContentPane().setLayout(new BorderLayout()); + JPanel panMain = new JPanel(new GridBagLayout()); + JPanel panButtons = new JPanel(new GridLayout(0, 2)); + getContentPane().add(panMain, BorderLayout.CENTER); + getContentPane().add(panButtons, BorderLayout.PAGE_END); + + JButton btnOk = new JButton("OK"); + btnOk.addActionListener(this::done); + panButtons.add(btnOk); + JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener(this::cancel); + panButtons.add(btnCancel); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + gbc.insets = new Insets(5, 5, 5, 5); + panMain.add(new JLabel("Result:"), gbc); + gbc.gridy++; + panMain.add(new JLabel("Next Story Point:"), gbc); + + gbc.gridx = 1; + gbc.gridy = 0; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + panMain.add(new JLabel(result), gbc); + + Vector otherPoints = new Vector(); + for (StoryPoint sp : storyPoint.getStoryArc().getStoryPoints()) { + if (sp.getId().equals(storyPoint.getId())) { + continue; + } + otherPoints.add(sp.getName()); + } + suggestNext = new JSuggestField(this, otherPoints); + + if (outcome.getNextStoryPointId() != null) { + suggestNext.setText(storyPoint.getStoryArc().getStoryPoint(outcome.getNextStoryPointId()).getName()); + } + gbc.gridy++; + panMain.add(suggestNext, gbc); + + choiceAddTrigger = new JComboBox<>(); + for(String s : StoryArcEditorGUI.availableTriggers.keySet()) { + choiceAddTrigger.addItem(s); + } + JButton btnAddTrigger = new JButton("Add Story Trigger"); + btnAddTrigger.addActionListener(evt -> addTrigger()); + JPanel panAddTrigger = new JPanel(new BorderLayout()); + panAddTrigger.add(choiceAddTrigger, BorderLayout.CENTER); + panAddTrigger.add(btnAddTrigger, BorderLayout.LINE_END); + gbc.gridy++; + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.HORIZONTAL; + panMain.add(panAddTrigger, gbc); + + panTriggers = new JPanel(); + panTriggers.setLayout(new BoxLayout(panTriggers, BoxLayout.Y_AXIS)); + + triggerPanels = new ArrayList<>(); + for(StoryTrigger trigger : outcome.getStoryTriggers()) { + StoryTriggerPanel panTrigger = trigger.getPanel(frame); + panTrigger.getDeleteButton().addActionListener(evt -> removePanel(panTrigger)); + panTriggers.add(panTrigger); + triggerPanels.add(panTrigger); + } + + scrTriggers = new JScrollPane(panTriggers); + scrTriggers.setMinimumSize(new Dimension(400, 200)); + //scrTriggers.setPreferredSize(new Dimension(400, 200)); + gbc.gridy++; + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.BOTH; + panMain.add(scrTriggers, gbc); + } + + private void removePanel(StoryTriggerPanel panel) { + triggerPanels.remove(panel); + refreshTriggerPanels(); + } + + private void refreshTriggerPanels() { + panTriggers = new JPanel(); + panTriggers.setLayout(new BoxLayout(panTriggers, BoxLayout.Y_AXIS)); + for(StoryTriggerPanel panel : triggerPanels) { + panTriggers.add(panel); + } + scrTriggers.setViewportView(panTriggers); + } + + private void done(ActionEvent evt) { + //set no next story point as default and then look for it + outcome.setNextStoryPointId(null); + // need to find by name which might not be unique + for (StoryPoint sp : storyPoint.getStoryArc().getStoryPoints()) { + if (suggestNext.getText().equals(sp.getName())) { + outcome.setNextStoryPointId(sp.getId()); + break; + } + } + ArrayList triggers = new ArrayList<>(); + for(StoryTriggerPanel panel : triggerPanels) { + panel.updateStoryStrigger(); + triggers.add(panel.getStoryTrigger()); + } + outcome.setStoryTriggers(triggers); + // if this is the default or new, we need to do some additional stuff + if (result.equals(StoryPoint.DEFAULT_OUTCOME)) { + // if the default, we apply directly to the story point + storyPoint.setNextStoryPointId(outcome.getNextStoryPointId()); + storyPoint.setStoryTriggers(outcome.getStoryTriggers()); + } else if(isNewOutcome) { + // add a new outcome + outcome.setResult(result); + storyPoint.addStoryOutcome(result, outcome); + } + setVisible(false); + } + + private void cancel(ActionEvent evt) { + setVisible(false); + } + + private JFrame getFrame() { + return frame; + } + + private void addTrigger() { + String triggerName = (String) choiceAddTrigger.getSelectedItem(); + String className = StoryArcEditorGUI.availableTriggers.get(triggerName); + StoryTrigger trigger = null; + if(className != null) { + try { + trigger = (StoryTrigger) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + if(trigger != null) { + trigger.setStoryArc(storyPoint.getStoryArc()); + StoryTriggerPanel panTrigger = trigger.getPanel(getFrame()); + panTrigger.getDeleteButton().addActionListener(evt -> removePanel(panTrigger)); + triggerPanels.add(panTrigger); + refreshTriggerPanels(); + } + } +} diff --git a/MekHQ/src/mekhq/gui/dialog/DataLoadingDialog.java b/MekHQ/src/mekhq/gui/dialog/DataLoadingDialog.java index c907b99c003..e59a85902ad 100644 --- a/MekHQ/src/mekhq/gui/dialog/DataLoadingDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/DataLoadingDialog.java @@ -84,6 +84,7 @@ public class DataLoadingDialog extends AbstractMHQDialogBasic implements Propert private JLabel splash; private JProgressBar progressBar; private StoryArcStub storyArcStub; + private boolean storyArcEditor; private boolean isInAppNewCampaign; private final LocalDate DEFAULT_START_DATE = LocalDate.of(3051, 1, 1); @@ -93,15 +94,22 @@ public class DataLoadingDialog extends AbstractMHQDialogBasic implements Propert // region Constructors public DataLoadingDialog(final JFrame frame, final MekHQ application, final @Nullable File campaignFile) { - this(frame, application, campaignFile, null, false); + this(frame, application, campaignFile, null, false, false); } public DataLoadingDialog(final JFrame frame, final MekHQ application, - final @Nullable File campaignFile, StoryArcStub stub, final boolean isInAppNewCampaign) { + final @Nullable File campaignFile, StoryArcStub stub, final boolean isInAppNewCampaign) { + this(frame, application, campaignFile, stub, isInAppNewCampaign, false); + } + + public DataLoadingDialog(final JFrame frame, final MekHQ application, + final @Nullable File campaignFile, StoryArcStub stub, final boolean isInAppNewCampaign, + boolean storyArcEditor) { super(frame, "DataLoadingDialog", "DataLoadingDialog.title"); this.application = application; this.campaignFile = campaignFile; this.storyArcStub = stub; + this.storyArcEditor = storyArcEditor; this.isInAppNewCampaign = isInAppNewCampaign; this.task = new Task(this); getTask().addPropertyChangeListener(this); @@ -510,9 +518,13 @@ public void done() { if (campaign != null) { getApplication().setCampaign(campaign); getApplication().getCampaignController().setHost(campaign.getId()); - getApplication().showNewView(); + if(storyArcEditor) { + getApplication().showNewStoryArcEditor(storyArcStub.loadStoryArc(campaign)); + } else { + getApplication().showNewView(); + } getFrame().dispose(); - if (null != storyArcStub) { + if (null != storyArcStub && !storyArcEditor) { StoryArc storyArc = storyArcStub.loadStoryArc(campaign); if (null != storyArc) { campaign.useStoryArc(storyArc, true); diff --git a/MekHQ/src/mekhq/gui/model/StoryPointTableModel.java b/MekHQ/src/mekhq/gui/model/StoryPointTableModel.java new file mode 100644 index 00000000000..5a451997865 --- /dev/null +++ b/MekHQ/src/mekhq/gui/model/StoryPointTableModel.java @@ -0,0 +1,60 @@ +package mekhq.gui.model; + +import mekhq.campaign.Campaign; +import mekhq.campaign.personnel.Person; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.gui.BasicInfo; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import java.awt.*; +import java.util.ArrayList; + +public class StoryPointTableModel extends DataTableModel { + + public StoryPointTableModel() { + columnNames = new String[] { "Story Points" }; + data = new ArrayList(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return getStoryPointDesc((StoryPoint) data.get(rowIndex)); + } + + private String getStoryPointDesc(StoryPoint storyPoint) { + StringBuilder toReturn = new StringBuilder(128); + toReturn.append("").append(storyPoint.getName()).append("
"); + toReturn.append(storyPoint.getClass().getSimpleName()); + toReturn.append(""); + return toReturn.toString(); + } + + public StoryPoint getStoryPointAt(int row) { + return (StoryPoint) data.get(row); + } + + public StoryPointTableModel.Renderer getRenderer() { + return new StoryPointTableModel.Renderer(); + } + + public class Renderer extends BasicInfo implements TableCellRenderer { + public Renderer() { + super(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + setHtmlText(getValueAt(row, column).toString()); + if (isSelected) { + highlightBorder(); + } else { + unhighlightBorder(); + } + setBackground(table.getBackground()); + setForeground(table.getForeground()); + return this; + } + } +} diff --git a/MekHQ/src/mekhq/gui/panels/StartupScreenPanel.java b/MekHQ/src/mekhq/gui/panels/StartupScreenPanel.java index a09a4e95e73..f4ab386323c 100644 --- a/MekHQ/src/mekhq/gui/panels/StartupScreenPanel.java +++ b/MekHQ/src/mekhq/gui/panels/StartupScreenPanel.java @@ -169,6 +169,17 @@ protected void initialize() { } }); }); + + MegaMekButton btnStoryArcEditor = new MegaMekButton(resources.getString("btnStoryArcEditor.text"), + UIComponents.MainMenuButton.getComp(), true); + btnStoryArcEditor.addActionListener(evt -> { + // FIXME: for starters we will only load existing arcs, but later need an option to start a new arc + StoryArcStub storyArcStub = selectStoryArc(); + if ((null != storyArcStub) && (null != storyArcStub.getInitCampaignFile())) { + startStoryArcEditor(storyArcStub); + } + }); + MegaMekButton btnQuit = new MegaMekButton(resources.getString("Quit.text"), UIComponents.MainMenuButton.getComp(), true); btnQuit.addActionListener(evt -> System.exit(0)); @@ -200,6 +211,8 @@ protected void initialize() { btnLoadLastCampaign.setPreferredSize(minButtonDim); btnLoadStoryArc.setMinimumSize(minButtonDim); btnLoadStoryArc.setPreferredSize(minButtonDim); + btnStoryArcEditor.setMinimumSize(minButtonDim); + btnStoryArcEditor.setPreferredSize(minButtonDim); btnQuit.setMinimumSize(minButtonDim); btnQuit.setPreferredSize(minButtonDim); @@ -239,6 +252,8 @@ protected void initialize() { c.gridy++; add(btnLoadStoryArc, c); c.gridy++; + add(btnStoryArcEditor, c); + c.gridy++; add(btnQuit, c); getFrame().setResizable(false); @@ -267,6 +282,10 @@ private void startCampaign(final @Nullable File file, @Nullable StoryArcStub sto new DataLoadingDialog(getFrame(), app, file, storyArcStub, false).setVisible(true); } + private void startStoryArcEditor(@Nullable StoryArcStub storyArcStub) { + new DataLoadingDialog(getFrame(), app, storyArcStub.getInitCampaignFile(), storyArcStub, true, true).setVisible(true); + } + private @Nullable File selectCampaignFile() { return FileDialogs.openCampaign(getFrame()).orElse(null); } diff --git a/MekHQ/src/mekhq/gui/panels/StoryPointEditorPanel.java b/MekHQ/src/mekhq/gui/panels/StoryPointEditorPanel.java new file mode 100644 index 00000000000..eaff042eed2 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/StoryPointEditorPanel.java @@ -0,0 +1,302 @@ +package mekhq.gui.panels; + +import mekhq.campaign.storyarc.StoryOutcome; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.StoryArcEditorGUI; +import mekhq.gui.baseComponents.AbstractMHQScrollablePanel; +import mekhq.gui.dialog.CustomizeStoryOutcomeDialog; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; + +public class StoryPointEditorPanel extends AbstractMHQScrollablePanel { + + private StoryArcEditorGUI editorGUI; + private StoryPoint storyPoint; + + private JTextField txtName; + private JButton btnSaveName; + private JButton btnCancelName; + private JPanel pnlOutcomes; + + private JTable storyOutcomeTable; + + public StoryPointEditorPanel(JFrame frame, String name, StoryPoint sp, StoryArcEditorGUI gui) { + super(frame, name); + storyPoint = sp; + this.editorGUI = gui; + initialize(); + } + + @Override + protected void initialize() { + setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.gridwidth = 4; + gbc.insets = new Insets(5, 5, 5, 5); + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.fill = GridBagConstraints.NONE; + add(new JLabel("

" + storyPoint.getClass().getSimpleName() + "

"), gbc); + + gbc.gridy++; + gbc.gridwidth = 1; + add(new JLabel("Story Point Name:"), gbc); + + txtName = new JTextField(storyPoint.getName()); + txtName.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void changedUpdate(DocumentEvent e) { + checkName(); + } + @Override + public void removeUpdate(DocumentEvent e) { + checkName(); + } + @Override + public void insertUpdate(DocumentEvent e) { + checkName(); + } + }); + gbc.gridx++; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + add(txtName, gbc); + + gbc.gridx++; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; + btnSaveName = new JButton("Save"); + btnSaveName.addActionListener(this::saveName); + btnSaveName.setEnabled(false); + add(btnSaveName, gbc); + gbc.gridx++; + btnCancelName = new JButton("Cancel"); + btnCancelName.addActionListener(this::cancelName); + btnCancelName.setEnabled(false); + add(btnCancelName, gbc); + + gbc.gridx = 0; + gbc.gridy++; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; + add(new JLabel("Linking Story Points:"), gbc); + + StringBuilder sb = new StringBuilder(); + List linkedStoryPoints = storyPoint.getLinkingStoryPoints(); + String SEPARATOR = ""; + for (int i = 0; i < linkedStoryPoints.size(); i++) { + sb.append(SEPARATOR); + sb.append(linkedStoryPoints.get(i).getHyperlinkedName()); + SEPARATOR = ", "; + } + gbc.gridx++; + gbc.weightx = 1.0; + gbc.gridwidth = 3; + gbc.fill = GridBagConstraints.HORIZONTAL; + JTextPane txtLinking = new JTextPane(); + txtLinking.setContentType("text/html"); + txtLinking.setEditable(false); + txtLinking.setText(sb.toString()); + txtLinking.addHyperlinkListener(editorGUI.getStoryPointHLL()); + add(txtLinking, gbc); + + pnlOutcomes = new JPanel(new GridBagLayout()); + pnlOutcomes.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder("Story Outcomes and Triggers"), + BorderFactory.createEmptyBorder(5,5,5,5))); + gbc.gridx = 0; + gbc.gridy++; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.gridwidth = 4; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.fill = GridBagConstraints.BOTH; + add(pnlOutcomes, gbc); + refreshOutcomesPanel(); + } + + private void refreshOutcomesPanel() { + + pnlOutcomes.removeAll(); + // I would prefer to do this with a JTable, but I can't properly use a HyperLinkListener in a JTable + // so we need to create something else + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridx = 0; + gbc.gridy = 0; + pnlOutcomes.add(new JLabel("Result"), gbc); + gbc.gridx++; + pnlOutcomes.add(new JLabel("Next Story Point"), gbc); + gbc.gridx++; + pnlOutcomes.add(new JLabel("Story Triggers"), gbc); + + List currentOutcomes = new ArrayList<>(); + for(StoryOutcome outcome : storyPoint.getStoryOutcomes()) { + gbc.gridx = 0; + gbc.weightx = 1.0; + gbc.gridy++; + JTextPane txtResult = new JTextPane(); + txtResult.setContentType("text/html"); + txtResult.setEditable(false); + txtResult.setText(outcome.getResult()); + pnlOutcomes.add(txtResult, gbc); + gbc.gridx++; + String next = outcome.getNextStoryPointId() == null ? "-" : + storyPoint.getStoryArc().getStoryPoint(outcome.getNextStoryPointId()).getHyperlinkedName(); + JTextPane txtNext = new JTextPane(); + txtNext.setContentType("text/html"); + txtNext.setEditable(false); + txtNext.setText(next); + txtNext.addHyperlinkListener(editorGUI.getStoryPointHLL()); + pnlOutcomes.add(txtNext, gbc); + gbc.gridx++; + JTextPane txtTriggers = new JTextPane(); + txtTriggers.setContentType("text/html"); + txtTriggers.setEditable(false); + txtTriggers.setText(getStoryTriggerDescription(outcome.getStoryTriggers())); + txtTriggers.addHyperlinkListener(editorGUI.getStoryPointHLL()); + pnlOutcomes.add(txtTriggers, gbc); + gbc.gridx++; + gbc.weightx = 0.0; + JButton btnEdit = new JButton("Edit Outcome"); + btnEdit.addActionListener(evt -> editOutcome(outcome.getResult())); + pnlOutcomes.add(btnEdit, gbc); + gbc.gridx++; + JButton btnRemove = new JButton("Delete Outcome"); + btnRemove.addActionListener(evt -> removeOutcome(outcome.getResult())); + pnlOutcomes.add(btnRemove, gbc); + currentOutcomes.add(outcome.getResult()); + } + + // check for a default outcome or trigger + if (storyPoint.getNextStoryPointId() != null || storyPoint.getStoryTriggers().size() > 0) { + gbc.gridx = 0; + gbc.gridy++; + gbc.weightx = 1.0; + JTextPane txtResult = new JTextPane(); + txtResult.setContentType("text/html"); + txtResult.setEditable(false); + txtResult.setText("" + StoryPoint.DEFAULT_OUTCOME + ""); + pnlOutcomes.add(txtResult, gbc); + gbc.gridx++; + String next = storyPoint.getNextStoryPointId() == null ? "-" : + storyPoint.getStoryArc().getStoryPoint(storyPoint.getNextStoryPointId()).getHyperlinkedName(); + JTextPane txtNext = new JTextPane(); + txtNext.setContentType("text/html"); + txtNext.setEditable(false); + txtNext.setText(next); + txtNext.addHyperlinkListener(editorGUI.getStoryPointHLL()); + pnlOutcomes.add(txtNext, gbc); + gbc.gridx++; + JTextPane txtTriggers = new JTextPane(); + txtTriggers.setContentType("text/html"); + txtTriggers.setEditable(false); + txtTriggers.setText(getStoryTriggerDescription(storyPoint.getStoryTriggers())); + txtTriggers.addHyperlinkListener(editorGUI.getStoryPointHLL()); + pnlOutcomes.add(txtTriggers, gbc); + gbc.gridx++; + gbc.weightx = 0.0; + JButton btnEdit = new JButton("Edit Outcome"); + btnEdit.addActionListener(evt -> editOutcome(StoryPoint.DEFAULT_OUTCOME)); + pnlOutcomes.add(btnEdit, gbc); + gbc.gridx++; + JButton btnRemove = new JButton("Delete Outcome"); + btnRemove.addActionListener(evt -> removeOutcome(StoryPoint.DEFAULT_OUTCOME)); + pnlOutcomes.add(btnRemove, gbc); + currentOutcomes.add(StoryPoint.DEFAULT_OUTCOME); + } + + //check for other possible outcomes + List possibleResults = storyPoint.getAllPossibleResults(); + possibleResults.removeAll(currentOutcomes); + if(!possibleResults.isEmpty()) { + JPanel pnlAddOutcomes = new JPanel(new FlowLayout()); + JComboBox comboOutcomes = new JComboBox(); + for (String result : possibleResults) { + comboOutcomes.addItem(result); + } + JButton btnAdd = new JButton("Add Outcome"); + btnAdd.addActionListener(evt -> addOutcome((String) comboOutcomes.getSelectedItem())); + pnlAddOutcomes.add(btnAdd); + pnlAddOutcomes.add(comboOutcomes); + + gbc.gridx = 0; + gbc.gridy++; + gbc.gridwidth = 5; + gbc.fill = GridBagConstraints.NONE; + pnlOutcomes.add(pnlAddOutcomes, gbc); + } + } + + private String getStoryTriggerDescription(List triggers) { + if(triggers.isEmpty()) { + return "-"; + } + StringBuilder sb = new StringBuilder(); + for(StoryTrigger trigger : triggers) { + sb.append(trigger.getDescription()); + sb.append("
"); + } + return sb.toString(); + } + + public void removeOutcome(String result) { + if(result.equals(StoryPoint.DEFAULT_OUTCOME)) { + storyPoint.removeDefaultOutcome(); + } else { + storyPoint.removeStoryOutcome(result); + } + refreshOutcomesPanel(); + pnlOutcomes.revalidate(); + } + + public void checkName() { + btnSaveName.setEnabled(!txtName.getText().equals(storyPoint.getName())); + btnCancelName.setEnabled(!txtName.getText().equals(storyPoint.getName())); + } + + public void saveName(ActionEvent evt) { + if(storyPoint.getStoryArc().isDuplicateName(txtName.getText())) { + JOptionPane.showMessageDialog(getFrame(), "This name is already being used", "Dialog", + JOptionPane.ERROR_MESSAGE); + return; + } + storyPoint.setName(txtName.getText()); + btnSaveName.setEnabled(false); + btnCancelName.setEnabled(false); + editorGUI.refreshStoryPoints(); + } + + public void cancelName(ActionEvent evt) { + txtName.setText(storyPoint.getName()); + btnSaveName.setEnabled(false); + btnCancelName.setEnabled(false); + } + + public void editOutcome(String result) { + CustomizeStoryOutcomeDialog csod = new CustomizeStoryOutcomeDialog(getFrame(), true, result, storyPoint, false); + csod.setVisible(true); + refreshOutcomesPanel(); + pnlOutcomes.revalidate(); + } + + public void addOutcome(String result) { + CustomizeStoryOutcomeDialog csod = new CustomizeStoryOutcomeDialog(getFrame(), true, result, storyPoint, true); + csod.setVisible(true); + refreshOutcomesPanel(); + pnlOutcomes.revalidate(); + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/AdvanceTimeStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/AdvanceTimeStoryTriggerPanel.java new file mode 100644 index 00000000000..84f0f58eb6e --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/AdvanceTimeStoryTriggerPanel.java @@ -0,0 +1,41 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.AdvanceTimeStoryTrigger; + +import javax.swing.*; +import java.awt.*; + +public class AdvanceTimeStoryTriggerPanel extends StoryTriggerPanel { + + private JSpinner spinDays; + + public AdvanceTimeStoryTriggerPanel(JFrame frame, String name, AdvanceTimeStoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + getMainPanel().setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.insets = new Insets(5,5,5,5); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + getMainPanel().add(new JLabel("Number of days:"), gbc); + + gbc.gridx = 1; + gbc.weightx = 1.0; + spinDays = new JSpinner(new SpinnerNumberModel(((AdvanceTimeStoryTrigger) getStoryTrigger()).getDays(), + 1, null, 1)); + getMainPanel().add(spinDays, gbc); + } + + @Override + public void updateStoryStrigger() { + ((AdvanceTimeStoryTrigger) getStoryTrigger()).setDays((int) spinDays.getModel().getValue()); + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/ChangeStringVariableStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/ChangeStringVariableStoryTriggerPanel.java new file mode 100644 index 00000000000..8a5c66239fd --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/ChangeStringVariableStoryTriggerPanel.java @@ -0,0 +1,51 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryArc; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.ChangeStringVariableStoryTrigger; + +import javax.swing.*; +import java.awt.*; + +public class ChangeStringVariableStoryTriggerPanel extends StoryTriggerPanel { + + private JComboBox comboKey; + private JTextField txtValue; + + public ChangeStringVariableStoryTriggerPanel(JFrame frame, String name, ChangeStringVariableStoryTrigger trigger) { + super(frame, name, trigger); + } + + + @Override + protected void createMainPanel() { + getMainPanel().setLayout(new GridBagLayout()); + + comboKey = new JComboBox<>(); + for(String key : getStoryTrigger().getStoryArc().getCustomStringVariables().keySet()) { + comboKey.addItem(key); + } + comboKey.setSelectedItem(((ChangeStringVariableStoryTrigger) getStoryTrigger()).getKey()); + + txtValue = new JTextField(((ChangeStringVariableStoryTrigger) getStoryTrigger()).getValue()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.insets = new Insets(5,5,5,5); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + getMainPanel().add(comboKey, gbc); + gbc.gridx++; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + getMainPanel().add(txtValue, gbc); + } + + @Override + public void updateStoryStrigger() { + ((ChangeStringVariableStoryTrigger) getStoryTrigger()).setKey((String) comboKey.getSelectedItem()); + ((ChangeStringVariableStoryTrigger) getStoryTrigger()).setValue(txtValue.getText()); + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/CompleteMissionStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/CompleteMissionStoryTriggerPanel.java new file mode 100644 index 00000000000..12b1f1ba97f --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/CompleteMissionStoryTriggerPanel.java @@ -0,0 +1,69 @@ +package mekhq.gui.panels.storytriggerpanels; + +import megamek.client.ui.baseComponents.MMComboBox; +import mekhq.campaign.mission.enums.MissionStatus; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storypoint.MissionStoryPoint; +import mekhq.campaign.storyarc.storytrigger.CompleteMissionStoryTrigger; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class CompleteMissionStoryTriggerPanel extends StoryTriggerPanel { + + private List missions; + private JComboBox comboMission; + private MMComboBox comboStatus; + public CompleteMissionStoryTriggerPanel(JFrame frame, String name, CompleteMissionStoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + comboMission = new JComboBox<>(); + // need to track a list of UUIDs so we can get the right one + missions = new ArrayList<>(); + + for(StoryPoint storyPoint : getStoryTrigger().getStoryArc().getStoryPoints()) { + if(storyPoint instanceof MissionStoryPoint) { + comboMission.addItem(storyPoint.getName()); + missions.add(storyPoint.getId()); + } + } + UUID currentStoryPointId = ((CompleteMissionStoryTrigger) getStoryTrigger()).getMissionStoryPointId(); + StoryPoint currentMission = null; + if(currentStoryPointId != null) { + currentMission = getStoryTrigger().getStoryArc().getStoryPoint(currentStoryPointId); + } + if(currentMission != null) { + comboMission.setSelectedItem(currentMission.getName()); + } + + comboStatus = new MMComboBox<>("comboStatus", MissionStatus.values()); + comboStatus.setSelectedItem(((CompleteMissionStoryTrigger) getStoryTrigger()).getMissionStatus()); + + getMainPanel().setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 0.5; + gbc.weighty = 1.0; + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.insets = new Insets(5, 5, 5, 5); + getMainPanel().add(comboMission, gbc); + gbc.gridx = 1; + getMainPanel().add(comboStatus, gbc); + + } + + @Override + public void updateStoryStrigger() { + ((CompleteMissionStoryTrigger) getStoryTrigger()).setMissionStoryPointId(missions.get(comboMission.getSelectedIndex())); + ((CompleteMissionStoryTrigger) getStoryTrigger()).setMissionStatus(comboStatus.getSelectedItem()); + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/EndArcStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/EndArcStoryTriggerPanel.java new file mode 100644 index 00000000000..f8d99fb0499 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/EndArcStoryTriggerPanel.java @@ -0,0 +1,21 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryTrigger; + +import javax.swing.*; + +public class EndArcStoryTriggerPanel extends StoryTriggerPanel { + public EndArcStoryTriggerPanel(JFrame frame, String name, StoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + getMainPanel().add(new JLabel("This Story Trigger will finish the story arc.")); + } + + @Override + public void updateStoryStrigger() { + // nothing to update + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/FakeStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/FakeStoryTriggerPanel.java new file mode 100644 index 00000000000..2e520983163 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/FakeStoryTriggerPanel.java @@ -0,0 +1,23 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryTrigger; + +import javax.swing.*; + +public class FakeStoryTriggerPanel extends StoryTriggerPanel { + + public FakeStoryTriggerPanel(JFrame frame, String name, StoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + getMainPanel().add(new JLabel("Test!")); + } + + @Override + public void updateStoryStrigger() { + // nothing to update + } + +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/GameOverStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/GameOverStoryTriggerPanel.java new file mode 100644 index 00000000000..a5771d5eaaa --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/GameOverStoryTriggerPanel.java @@ -0,0 +1,22 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryTrigger; + +import javax.swing.*; + +public class GameOverStoryTriggerPanel extends StoryTriggerPanel { + + public GameOverStoryTriggerPanel(JFrame frame, String name, StoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + getMainPanel().add(new JLabel("This Story Trigger will quit the game.")); + } + + @Override + public void updateStoryStrigger() { + // nothing to update + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SetDateStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SetDateStoryTriggerPanel.java new file mode 100644 index 00000000000..08a9d1cfd56 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SetDateStoryTriggerPanel.java @@ -0,0 +1,132 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.MekHQ; +import mekhq.campaign.storyarc.StoryPoint; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storypoint.CheckDateReachedStoryPoint; +import mekhq.campaign.storyarc.storytrigger.SetDateStoryTrigger; +import mekhq.gui.dialog.DateChooser; + +import javax.swing.*; +import java.awt.*; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class SetDateStoryTriggerPanel extends StoryTriggerPanel { + + private LocalDate date; + private List checkDateStoryPoints; + private JComboBox comboStoryPoints; + private JSpinner spinDays; + private JButton btnDate; + private JCheckBox checkUseDate; + + public SetDateStoryTriggerPanel(JFrame frame, String name, SetDateStoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + comboStoryPoints = new JComboBox<>(); + checkDateStoryPoints = new ArrayList<>(); + for(StoryPoint storyPoint : getStoryTrigger().getStoryArc().getStoryPoints()) { + if(storyPoint instanceof CheckDateReachedStoryPoint) { + comboStoryPoints.addItem(storyPoint.getName()); + checkDateStoryPoints.add(storyPoint.getId()); + } + } + UUID currentStoryPointId = ((SetDateStoryTrigger) getStoryTrigger()).getStoryPointId(); + StoryPoint currentStoryPoint = null; + if(currentStoryPointId != null) { + currentStoryPoint = getStoryTrigger().getStoryArc().getStoryPoint(currentStoryPointId); + } + if(currentStoryPoint != null) { + comboStoryPoints.setSelectedItem(currentStoryPoint.getName()); + } + + date = ((SetDateStoryTrigger) getStoryTrigger()).getDate(); + btnDate = new JButton("None"); + btnDate.setEnabled(false); + if(date != null) { + btnDate.setText(MekHQ.getMHQOptions().getDisplayFormattedDate(date)); + btnDate.setEnabled(true); + } + btnDate.addActionListener(evt -> changeDate()); + + checkUseDate = new JCheckBox("Use Actual Date"); + checkUseDate.setSelected(date != null); + checkUseDate.addActionListener(evt -> checkUseDate()); + + spinDays = new JSpinner(new SpinnerNumberModel(((SetDateStoryTrigger) getStoryTrigger()).getFutureDays(), + 1, null, 1)); + spinDays.setEnabled(date == null); + + getMainPanel().setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.insets = new Insets(5,5,5,5); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + getMainPanel().add(new JLabel("CheckDateReachedStoryPoint:"), gbc); + gbc.gridy++; + gbc.gridwidth = 2; + getMainPanel().add(checkUseDate, gbc); + gbc.gridy++; + gbc.gridwidth = 1; + JLabel lblActualDate = new JLabel("Actual Date:"); + lblActualDate.setToolTipText("Set a specific date."); + getMainPanel().add(lblActualDate, gbc); + gbc.gridy++; + JLabel lblDays = new JLabel("Days in Future:"); + lblDays.setToolTipText("Set a date this many days in the future from when this trigger is executed."); + getMainPanel().add(lblDays, gbc); + + gbc.gridy = 0; + gbc.gridx++; + gbc.weightx = 1.0; + getMainPanel().add(comboStoryPoints, gbc); + gbc.gridy++; + gbc.gridy++; + getMainPanel().add(btnDate, gbc); + gbc.gridy++; + getMainPanel().add(spinDays, gbc); + } + + @Override + public void updateStoryStrigger() { + ((SetDateStoryTrigger) getStoryTrigger()).setStoryPointId(checkDateStoryPoints.get(comboStoryPoints.getSelectedIndex())); + if(checkUseDate.isSelected()) { + ((SetDateStoryTrigger) getStoryTrigger()).setDate(date); + } else { + ((SetDateStoryTrigger) getStoryTrigger()).setFutureDays((int) spinDays.getModel().getValue()); + } + } + + private void changeDate() { + // show the date chooser + DateChooser dc = new DateChooser(getFrame(), date); + // user can either choose a date or cancel by closing + if (dc.showDateChooser() == DateChooser.OK_OPTION) { + date = dc.getDate(); + btnDate.setText(MekHQ.getMHQOptions().getDisplayFormattedDate(date)); + } + } + + private void checkUseDate() { + if(checkUseDate.isSelected()) { + date = LocalDate.of(3025, 1, 1); + btnDate.setText(MekHQ.getMHQOptions().getDisplayFormattedDate(date)); + btnDate.setEnabled(true); + spinDays.setEnabled(false); + } else { + date = null; + btnDate.setText("None"); + btnDate.setEnabled(false); + spinDays.setEnabled(true); + } + } +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/StoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/StoryTriggerPanel.java new file mode 100644 index 00000000000..88ce8733ba1 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/StoryTriggerPanel.java @@ -0,0 +1,52 @@ +package mekhq.gui.panels.storytriggerpanels; + +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.gui.baseComponents.AbstractMHQScrollablePanel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionListener; + +public abstract class StoryTriggerPanel extends AbstractMHQScrollablePanel { + + private StoryTrigger storyTrigger; + protected JPanel panMain; + private JButton btnDelete; + + + public StoryTriggerPanel(JFrame frame, String name, StoryTrigger trigger) { + super(frame, name); + this.storyTrigger = trigger; + initialize(); + } + + public JButton getDeleteButton() { + return btnDelete; + } + public StoryTrigger getStoryTrigger() { + return storyTrigger; + } + + protected JPanel getMainPanel() { + return panMain; + } + + @Override + protected void initialize() { + setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder(storyTrigger.getClass().getSimpleName()), + BorderFactory.createEmptyBorder(5,5,5,5))); + setLayout(new BorderLayout()); + btnDelete = new JButton("Delete Trigger"); + JPanel panTop = new JPanel(new FlowLayout(FlowLayout.LEFT)); + panTop.add(btnDelete); + add(panTop, BorderLayout.PAGE_START); + panMain = new JPanel(); + createMainPanel(); + add(panMain, BorderLayout.CENTER); + } + + protected abstract void createMainPanel(); + + public abstract void updateStoryStrigger(); +} diff --git a/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SwitchTabStoryTriggerPanel.java b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SwitchTabStoryTriggerPanel.java new file mode 100644 index 00000000000..c258cd1d299 --- /dev/null +++ b/MekHQ/src/mekhq/gui/panels/storytriggerpanels/SwitchTabStoryTriggerPanel.java @@ -0,0 +1,43 @@ +package mekhq.gui.panels.storytriggerpanels; + +import megamek.client.ui.baseComponents.MMComboBox; +import mekhq.campaign.storyarc.StoryTrigger; +import mekhq.campaign.storyarc.storytrigger.SwitchTabStoryTrigger; +import mekhq.gui.enums.MHQTabType; + +import javax.swing.*; +import java.awt.*; + +public class SwitchTabStoryTriggerPanel extends StoryTriggerPanel { + + private MMComboBox comboTab; + + public SwitchTabStoryTriggerPanel(JFrame frame, String name, SwitchTabStoryTrigger trigger) { + super(frame, name, trigger); + } + + @Override + protected void createMainPanel() { + getMainPanel().setLayout(new GridBagLayout()); + comboTab = new MMComboBox<>("comboTab", MHQTabType.values()); + comboTab.setSelectedItem(((SwitchTabStoryTrigger) getStoryTrigger()).getTab()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.insets = new Insets(5,5,5,5); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + getMainPanel().add(new JLabel("Selected Tab:"), gbc); + gbc.gridx++; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + getMainPanel().add(comboTab, gbc); + } + + @Override + public void updateStoryStrigger() { + ((SwitchTabStoryTrigger) getStoryTrigger()).setTab(comboTab.getSelectedItem()); + } +}