diff --git a/doc/DeveloperGuide.md b/doc/DeveloperGuide.md
index c82c3afb9..53d3e880d 100644
--- a/doc/DeveloperGuide.md
+++ b/doc/DeveloperGuide.md
@@ -74,6 +74,22 @@ Use case ends.
> 3a1. AddressBook shows an error message
Use case resumes at step 2
+#### Use case: Change theme
+
+ **MSS**
+
+ 1. User requests to change to a new theme
+ 2. AddressBook changes the theme
+ Use case ends.
+
+ **Extensions**
+
+ 1a. The theme to be renamed does not exist
+
+ > 1a1. AddressBook shows an error message
+ Use case ends
+
+
## Appendix C : Non Functional Requirements
1. Should work on any [mainstream OS](#mainstream-os) as long as it has Java 8 or higher installed.
diff --git a/doc/UserGuide.md b/doc/UserGuide.md
index 3e4baae95..073ca0e1a 100644
--- a/doc/UserGuide.md
+++ b/doc/UserGuide.md
@@ -99,6 +99,17 @@ Examples:
Clears all entries from the address book.
Format: `clear`
+## Changing a theme : `theme`
+ Changes the theme of the app. Irreversible.
+ Format: `theme NEW_THEME`
+
+ > Changes the theme of the app.
+
+ Examples:
+ * `theme Light`
+ Changes the theme of the app to Light theme.
+
+
## Exiting the program : `exit`
Exits the program.
Format: `exit`
diff --git a/src/seedu/addressbook/commands/AddCommand.java b/src/seedu/addressbook/commands/AddCommand.java
index b0f202d42..8b9f57fa0 100644
--- a/src/seedu/addressbook/commands/AddCommand.java
+++ b/src/seedu/addressbook/commands/AddCommand.java
@@ -58,7 +58,7 @@ public ReadOnlyPerson getPerson() {
}
@Override
- public CommandResult execute() {
+ public CommandResult execute() throws Exception {
try {
addressBook.addPerson(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
@@ -66,5 +66,9 @@ public CommandResult execute() {
return new CommandResult(MESSAGE_DUPLICATE_PERSON);
}
}
-
+
+ @Override
+ public boolean isMutating() {
+ return true;
+ }
}
diff --git a/src/seedu/addressbook/commands/ChangeThemeCommand.java b/src/seedu/addressbook/commands/ChangeThemeCommand.java
new file mode 100644
index 000000000..6a5c5f966
--- /dev/null
+++ b/src/seedu/addressbook/commands/ChangeThemeCommand.java
@@ -0,0 +1,34 @@
+package seedu.addressbook.commands;
+
+import seedu.addressbook.data.AddressBook;
+import seedu.addressbook.ui.Gui;
+
+public class ChangeThemeCommand extends Command {
+
+ public static final String COMMAND_WORD = "theme";
+
+ public static String MESSAGE_USAGE = String.format(COMMAND_WORD + ":\n"
+ + "Changes theme of the application.\n\t"
+ + "Parameters: NEW_THEME\n\t"
+ + "Themes available: %1$s\n\t"
+ + "Example: " + COMMAND_WORD + " Light", AddressBook.allThemesString());
+
+ public static final String MESSAGE_SUCCESS = "Theme changed successfully";
+ public static final String MESSAGE_FAILED_THEME_DOES_NOT_EXIST = "Theme %1$s does not exist.\n";
+
+ private final String newThemeName;
+
+ public ChangeThemeCommand(String newThemeName) {
+ this.newThemeName = newThemeName;
+ }
+
+ @Override
+ public CommandResult execute() {
+ if (!addressBook.containsTheme(newThemeName)) {
+ return new CommandResult(String.format(MESSAGE_FAILED_THEME_DOES_NOT_EXIST, newThemeName));
+ }
+ Gui.changeTheme(newThemeName);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+}
\ No newline at end of file
diff --git a/src/seedu/addressbook/commands/ClearCommand.java b/src/seedu/addressbook/commands/ClearCommand.java
index b09706013..bddbe4102 100644
--- a/src/seedu/addressbook/commands/ClearCommand.java
+++ b/src/seedu/addressbook/commands/ClearCommand.java
@@ -19,4 +19,9 @@ public CommandResult execute() {
addressBook.clear();
return new CommandResult(MESSAGE_SUCCESS);
}
+
+ @Override
+ public boolean isMutating() {
+ return true;
+ }
}
diff --git a/src/seedu/addressbook/commands/Command.java b/src/seedu/addressbook/commands/Command.java
index ccd4fcbf4..dd7aaf5d8 100644
--- a/src/seedu/addressbook/commands/Command.java
+++ b/src/seedu/addressbook/commands/Command.java
@@ -38,8 +38,9 @@ public static String getMessageForPersonListShownSummary(List extends ReadOnly
/**
* Executes the command and returns the result.
+ * @throws Exception
*/
- public abstract CommandResult execute();
+ public abstract CommandResult execute() throws Exception;
/**
* Supplies the data the command will operate on.
diff --git a/src/seedu/addressbook/commands/DeleteCommand.java b/src/seedu/addressbook/commands/DeleteCommand.java
index 1dd78f85e..47e8f2ab6 100644
--- a/src/seedu/addressbook/commands/DeleteCommand.java
+++ b/src/seedu/addressbook/commands/DeleteCommand.java
@@ -38,5 +38,10 @@ public CommandResult execute() {
return new CommandResult(Messages.MESSAGE_PERSON_NOT_IN_ADDRESSBOOK);
}
}
+
+ @Override
+ public boolean isMutating() {
+ return true;
+ }
}
diff --git a/src/seedu/addressbook/commands/ExitCommand.java b/src/seedu/addressbook/commands/ExitCommand.java
index 0585451f1..60643237c 100644
--- a/src/seedu/addressbook/commands/ExitCommand.java
+++ b/src/seedu/addressbook/commands/ExitCommand.java
@@ -15,5 +15,9 @@ public class ExitCommand extends Command {
public CommandResult execute() {
return new CommandResult(MESSAGE_EXIT_ACKNOWEDGEMENT);
}
-
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/FindCommand.java b/src/seedu/addressbook/commands/FindCommand.java
index c8e9a380f..dbee01bc5 100644
--- a/src/seedu/addressbook/commands/FindCommand.java
+++ b/src/seedu/addressbook/commands/FindCommand.java
@@ -52,5 +52,10 @@ private List getPersonsWithNameContainingAnyKeyword(Set
}
return matchedPersons;
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/HelpCommand.java b/src/seedu/addressbook/commands/HelpCommand.java
index 82530440c..6c18bfafc 100644
--- a/src/seedu/addressbook/commands/HelpCommand.java
+++ b/src/seedu/addressbook/commands/HelpCommand.java
@@ -19,7 +19,8 @@ public class HelpCommand extends Command {
+ "\n" + ViewCommand.MESSAGE_USAGE
+ "\n" + ViewAllCommand.MESSAGE_USAGE
+ "\n" + HelpCommand.MESSAGE_USAGE
- + "\n" + ExitCommand.MESSAGE_USAGE;
+ + "\n" + ExitCommand.MESSAGE_USAGE
+ + "\n" + ChangeThemeCommand.MESSAGE_USAGE;
public HelpCommand() {}
@@ -27,4 +28,9 @@ public HelpCommand() {}
public CommandResult execute() {
return new CommandResult(MESSAGE_ALL_USAGES);
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/IncorrectCommand.java b/src/seedu/addressbook/commands/IncorrectCommand.java
index 81abba7a1..331b30168 100644
--- a/src/seedu/addressbook/commands/IncorrectCommand.java
+++ b/src/seedu/addressbook/commands/IncorrectCommand.java
@@ -16,5 +16,10 @@ public IncorrectCommand(String feedbackToUser){
public CommandResult execute() {
return new CommandResult(feedbackToUser);
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/ListCommand.java b/src/seedu/addressbook/commands/ListCommand.java
index cb604a8e9..f302766e7 100644
--- a/src/seedu/addressbook/commands/ListCommand.java
+++ b/src/seedu/addressbook/commands/ListCommand.java
@@ -22,4 +22,9 @@ public CommandResult execute() {
List allPersons = addressBook.getAllPersons().immutableListView();
return new CommandResult(getMessageForPersonListShownSummary(allPersons), allPersons);
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/ViewAllCommand.java b/src/seedu/addressbook/commands/ViewAllCommand.java
index ed2c16e83..2ee64af44 100644
--- a/src/seedu/addressbook/commands/ViewAllCommand.java
+++ b/src/seedu/addressbook/commands/ViewAllCommand.java
@@ -37,4 +37,9 @@ public CommandResult execute() {
return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/commands/ViewCommand.java b/src/seedu/addressbook/commands/ViewCommand.java
index 1058c4b52..762aba8e7 100644
--- a/src/seedu/addressbook/commands/ViewCommand.java
+++ b/src/seedu/addressbook/commands/ViewCommand.java
@@ -37,5 +37,10 @@ public CommandResult execute() {
return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
}
}
+
+ @Override
+ public boolean isMutating() {
+ return false;
+ }
}
diff --git a/src/seedu/addressbook/data/AddressBook.java b/src/seedu/addressbook/data/AddressBook.java
index b3ab0dfeb..6bdb48340 100644
--- a/src/seedu/addressbook/data/AddressBook.java
+++ b/src/seedu/addressbook/data/AddressBook.java
@@ -19,7 +19,7 @@ public class AddressBook {
private final UniquePersonList allPersons;
private final UniqueTagList allTags; // can contain tags not attached to any person
-
+ private final static String[] allThemes = {"Dark", "Light", "Mocha", "Grape"};
public static AddressBook empty() {
return new AddressBook();
}
@@ -106,6 +106,27 @@ public boolean containsTag(Tag key) {
}
/**
+ * Checks if provided theme name exists
+ * */
+
+ public boolean containsTheme(String theme) {
+ for (String th : allThemes) {
+ if (th.equals(theme)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns all themes as a string, for use of help command.
+ * */
+ public static String allThemesString() {
+ return String.join(", ", allThemes);
+ }
+
+ /**
+
* Removes the equivalent person from the address book.
*
* @throws PersonNotFoundException if no such Person could be found.
diff --git a/src/seedu/addressbook/logic/Logic.java b/src/seedu/addressbook/logic/Logic.java
index 17afd61a0..976a1d533 100644
--- a/src/seedu/addressbook/logic/Logic.java
+++ b/src/seedu/addressbook/logic/Logic.java
@@ -85,7 +85,10 @@ public CommandResult execute(String userCommandText) throws Exception {
private CommandResult execute(Command command) throws Exception {
command.setData(addressBook, lastShownList);
CommandResult result = command.execute();
- storage.save(addressBook);
+ if (command.isMutating()) {
+ storage.save(addressBook);
+
+ }
return result;
}
diff --git a/src/seedu/addressbook/parser/Parser.java b/src/seedu/addressbook/parser/Parser.java
index 3a8305f28..fb4838abd 100644
--- a/src/seedu/addressbook/parser/Parser.java
+++ b/src/seedu/addressbook/parser/Parser.java
@@ -9,224 +9,258 @@
import static seedu.addressbook.common.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
/**
* Parses user input.
*/
public class Parser {
- public static final Pattern PERSON_INDEX_ARGS_FORMAT = Pattern.compile("(?.+)");
-
- public static final Pattern KEYWORDS_ARGS_FORMAT =
- Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one or more keywords separated by whitespace
-
- public static final Pattern PERSON_DATA_ARGS_FORMAT = // '/' forward slashes are reserved for delimiter prefixes
- Pattern.compile("(?[^/]+)"
- + " (?p?)p/(?[^/]+)"
- + " (?p?)e/(?[^/]+)"
- + " (?p?)a/(?[^/]+)"
- + "(?(?: t/[^/]+)*)"); // variable number of tags
-
-
- /**
- * Signals that the user input could not be parsed.
- */
- public static class ParseException extends Exception {
- ParseException(String message) {
- super(message);
- }
- }
-
- /**
- * Used for initial separation of command word and args.
- */
- public static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- public Parser() {}
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- */
- public Command parseCommand(String userInput) {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return prepareAdd(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return prepareDelete(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return prepareFind(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ViewCommand.COMMAND_WORD:
- return prepareView(arguments);
-
- case ViewAllCommand.COMMAND_WORD:
- return prepareViewAll(arguments);
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD: // Fallthrough
- default:
- return new HelpCommand();
- }
- }
-
- /**
- * Parses arguments in the context of the add person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareAdd(String args){
- final Matcher matcher = PERSON_DATA_ARGS_FORMAT.matcher(args.trim());
- // Validate arg string format
- if (!matcher.matches()) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
- }
- try {
- return new AddCommand(
- matcher.group("name"),
-
- matcher.group("phone"),
- isPrivatePrefixPresent(matcher.group("isPhonePrivate")),
-
- matcher.group("email"),
- isPrivatePrefixPresent(matcher.group("isEmailPrivate")),
-
- matcher.group("address"),
- isPrivatePrefixPresent(matcher.group("isAddressPrivate")),
-
- getTagsFromArgs(matcher.group("tagArguments"))
- );
- } catch (IllegalValueException ive) {
- return new IncorrectCommand(ive.getMessage());
- }
- }
-
- /**
- * Checks whether the private prefix of a contact detail in the add command's arguments string is present.
- */
- private static boolean isPrivatePrefixPresent(String matchedPrefix) {
- return matchedPrefix.equals("p");
- }
-
- /**
- * Extracts the new person's tags from the add command's tag arguments string.
- * Merges duplicate tag strings.
- */
- private static Set getTagsFromArgs(String tagArguments) throws IllegalValueException {
- // no tags
- if (tagArguments.isEmpty()) {
- return Collections.emptySet();
- }
- // replace first delimiter prefix, then split
- final Collection tagStrings = Arrays.asList(tagArguments.replaceFirst(" t/", "").split(" t/"));
- return new HashSet<>(tagStrings);
- }
-
-
- /**
- * Parses arguments in the context of the delete person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareDelete(String args) {
- try {
- final int targetIndex = parseArgsAsDisplayedIndex(args);
- return new DeleteCommand(targetIndex);
- } catch (ParseException | NumberFormatException e) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
- }
- }
-
- /**
- * Parses arguments in the context of the view command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareView(String args) {
-
- try {
- final int targetIndex = parseArgsAsDisplayedIndex(args);
- return new ViewCommand(targetIndex);
- } catch (ParseException | NumberFormatException e) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- ViewCommand.MESSAGE_USAGE));
- }
- }
-
- /**
- * Parses arguments in the context of the view all command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareViewAll(String args) {
-
- try {
- final int targetIndex = parseArgsAsDisplayedIndex(args);
- return new ViewAllCommand(targetIndex);
- } catch (ParseException | NumberFormatException e) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- ViewAllCommand.MESSAGE_USAGE));
- }
- }
-
- /**
- * Parses the given arguments string as a single index number.
- *
- * @param args arguments string to parse as index number
- * @return the parsed index number
- * @throws ParseException if no region of the args string could be found for the index
- * @throws NumberFormatException the args string region is not a valid number
- */
- private int parseArgsAsDisplayedIndex(String args) throws ParseException, NumberFormatException {
- final Matcher matcher = PERSON_INDEX_ARGS_FORMAT.matcher(args.trim());
- if (!matcher.matches()) {
- throw new ParseException("Could not find index number to parse");
- }
- return Integer.parseInt(matcher.group("targetIndex"));
- }
-
-
- /**
- * Parses arguments in the context of the find person command.
- *
- * @param args full command args string
- * @return the prepared command
- */
- private Command prepareFind(String args) {
- final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
- if (!matcher.matches()) {
- return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
- FindCommand.MESSAGE_USAGE));
- }
-
- // keywords delimited by whitespace
- final String[] keywords = matcher.group("keywords").split("\\s+");
- final Set keywordSet = new HashSet<>(Arrays.asList(keywords));
- return new FindCommand(keywordSet);
- }
-
+ public static final Pattern PERSON_INDEX_ARGS_FORMAT = Pattern.compile("(?.+)");
+
+ public static final Pattern KEYWORDS_ARGS_FORMAT = Pattern.compile("(?\\S+(?:\\s+\\S+)*)"); // one
+ // or
+ // more
+ public static final Pattern CHANGE_THEME_ARGS_FORMAT = Pattern.compile("(?.+)"); // keywords
+ // separated
+ // by // whitespace
+
+ public static final Pattern PERSON_DATA_ARGS_FORMAT = // '/' forward slashes
+ // are reserved for
+ // delimiter
+ // prefixes
+ Pattern.compile("(?[^/]+)" + " (?p?)p/(?[^/]+)"
+ + " (?p?)e/(?[^/]+)" + " (?p?)a/(?[^/]+)"
+ + "(?(?: t/[^/]+)*)"); // variable number of
+ // tags
+
+ /**
+ * Signals that the user input could not be parsed.
+ */
+ public static class ParseException extends Exception {
+ ParseException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ public static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ public Parser() {
+ }
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput
+ * full user input string
+ * @return the command based on the user input
+ */
+ public Command parseCommand(String userInput) {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+
+ final String commandWord = matcher.group("commandWord");
+ final String arguments = matcher.group("arguments");
+ switch (commandWord) {
+
+ case AddCommand.COMMAND_WORD:
+ return prepareAdd(arguments);
+
+ case DeleteCommand.COMMAND_WORD:
+ return prepareDelete(arguments);
+
+ case ClearCommand.COMMAND_WORD:
+ return new ClearCommand();
+
+ case FindCommand.COMMAND_WORD:
+ return prepareFind(arguments);
+
+ case ListCommand.COMMAND_WORD:
+ return new ListCommand();
+
+ case ViewCommand.COMMAND_WORD:
+ return prepareView(arguments);
+
+ case ViewAllCommand.COMMAND_WORD:
+ return prepareViewAll(arguments);
+
+ case ChangeThemeCommand.COMMAND_WORD:
+ return prepareChangeTheme(arguments);
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD: // Fallthrough
+ default:
+ return new HelpCommand();
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the add person command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareAdd(String args) {
+ final Matcher matcher = PERSON_DATA_ARGS_FORMAT.matcher(args.trim());
+ // Validate arg string format
+ if (!matcher.matches()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ }
+ try {
+ return new AddCommand(matcher.group("name"),
+
+ matcher.group("phone"), isPrivatePrefixPresent(matcher.group("isPhonePrivate")),
+
+ matcher.group("email"), isPrivatePrefixPresent(matcher.group("isEmailPrivate")),
+
+ matcher.group("address"), isPrivatePrefixPresent(matcher.group("isAddressPrivate")),
+
+ getTagsFromArgs(matcher.group("tagArguments")));
+ } catch (IllegalValueException ive) {
+ return new IncorrectCommand(ive.getMessage());
+ }
+ }
+
+ private Command changeTheme(String args) {
+ final Matcher matcher = CHANGE_THEME_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ChangeThemeCommand.MESSAGE_USAGE));
+ }
+ return new ChangeThemeCommand(matcher.group("newTheme"));
+ }
+
+ /**
+ *
+ * /** Checks whether the private prefix of a contact detail in the add
+ * command's arguments string is present.
+ */
+ private static boolean isPrivatePrefixPresent(String matchedPrefix) {
+ return matchedPrefix.equals("p");
+ }
+
+ /**
+ * Extracts the new person's tags from the add command's tag arguments
+ * string. Merges duplicate tag strings.
+ */
+ private static Set getTagsFromArgs(String tagArguments) throws IllegalValueException {
+ // no tags
+ if (tagArguments.isEmpty()) {
+ return Collections.emptySet();
+ }
+ // replace first delimiter prefix, then split
+ final Collection tagStrings = Arrays.asList(tagArguments.replaceFirst(" t/", "").split(" t/"));
+ return new HashSet<>(tagStrings);
+ }
+
+ /**
+ * Parses arguments in the context of the delete person command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareDelete(String args) {
+ try {
+ final int targetIndex = parseArgsAsDisplayedIndex(args);
+ return new DeleteCommand(targetIndex);
+ } catch (ParseException | NumberFormatException e) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE));
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the change theme command.
+ *
+ * @param args full command args string
+ * @return the prepared command
+ */
+ private Command prepareChangeTheme(String args) {
+ final Matcher matcher = CHANGE_THEME_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ChangeThemeCommand.MESSAGE_USAGE));
+ }
+ return new ChangeThemeCommand(matcher.group("newTheme"));
+ }
+
+ /**
+ * Parses arguments in the context of the view command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareView(String args) {
+
+ try {
+ final int targetIndex = parseArgsAsDisplayedIndex(args);
+ return new ViewCommand(targetIndex);
+ } catch (ParseException | NumberFormatException e) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE));
+ }
+ }
+
+ /**
+ * Parses arguments in the context of the view all command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareViewAll(String args) {
+
+ try {
+ final int targetIndex = parseArgsAsDisplayedIndex(args);
+ return new ViewAllCommand(targetIndex);
+ } catch (ParseException | NumberFormatException e) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewAllCommand.MESSAGE_USAGE));
+ }
+ }
+
+ /**
+ * Parses the given arguments string as a single index number.
+ *
+ * @param args
+ * arguments string to parse as index number
+ * @return the parsed index number
+ * @throws ParseException
+ * if no region of the args string could be found for the index
+ * @throws NumberFormatException
+ * the args string region is not a valid number
+ */
+ private int parseArgsAsDisplayedIndex(String args) throws ParseException, NumberFormatException {
+ final Matcher matcher = PERSON_INDEX_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ throw new ParseException("Could not find index number to parse");
+ }
+ return Integer.parseInt(matcher.group("targetIndex"));
+ }
+
+ /**
+ * Parses arguments in the context of the find person command.
+ *
+ * @param args
+ * full command args string
+ * @return the prepared command
+ */
+ private Command prepareFind(String args) {
+ final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
+ if (!matcher.matches()) {
+ return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
+ }
+
+ // keywords delimited by whitespace
+ final String[] keywords = matcher.group("keywords").split("\\s+");
+ final Set keywordSet = new HashSet<>(Arrays.asList(keywords));
+ return new FindCommand(keywordSet);
+ }
}
\ No newline at end of file
diff --git a/src/seedu/addressbook/ui/Grape.css b/src/seedu/addressbook/ui/Grape.css
new file mode 100644
index 000000000..46b8660df
--- /dev/null
+++ b/src/seedu/addressbook/ui/Grape.css
@@ -0,0 +1,15 @@
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Consolas";
+ -fx-font-weight: bold;
+ -fx-text-fill: #FFFFFF;
+ -fx-control-inner-background: derive(#8E1AB2,20%);
+}
+
+.text-area {
+ -fx-background-color: #8E1AB2;
+ -fx-control-inner-background: #8E1AB2;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 10pt;
+ -fx-padding: 5 5 5 5;
+}
\ No newline at end of file
diff --git a/src/seedu/addressbook/ui/Gui.java b/src/seedu/addressbook/ui/Gui.java
index 20a7833c1..278ec5d40 100644
--- a/src/seedu/addressbook/ui/Gui.java
+++ b/src/seedu/addressbook/ui/Gui.java
@@ -23,27 +23,36 @@ public class Gui {
private MainWindow mainWindow;
private String version;
-
+ private static Stage stage;
+
public Gui(Logic logic, String version) {
this.logic = logic;
this.version = version;
}
public void start(Stage stage, Stoppable mainApp) throws IOException {
- mainWindow = createMainWindow(stage, mainApp);
+ Gui.stage = stage;
+ mainWindow = createMainWindow(mainApp);
mainWindow.displayWelcomeMessage(version, logic.getStorageFilePath());
}
- private MainWindow createMainWindow(Stage stage, Stoppable mainApp) throws IOException{
+ private MainWindow createMainWindow(Stoppable mainApp) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("ui" + File.separator + "mainwindow.fxml"));
stage.setTitle(version);
stage.setScene(new Scene(loader.load(), INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT));
+ changeTheme("Dark");
stage.show();
MainWindow mainWindow = loader.getController();
mainWindow.setLogic(logic);
mainWindow.setMainApp(mainApp);
return mainWindow;
}
+
+ public static void changeTheme(String newThemeName) {
+ stage.getScene().getStylesheets().clear();
+ stage.getScene().getStylesheets()
+ .add(Main.class.getResource("ui/" + newThemeName + "Theme.css").toExternalForm());
+ }
}
diff --git a/src/seedu/addressbook/ui/LightTheme.css b/src/seedu/addressbook/ui/LightTheme.css
new file mode 100644
index 000000000..35fe562aa
--- /dev/null
+++ b/src/seedu/addressbook/ui/LightTheme.css
@@ -0,0 +1,15 @@
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Consolas";
+ -fx-font-weight: bold;
+ -fx-text-fill: grey;
+ -fx-control-inner-background: derive(#eeeeee,20%);
+}
+
+.text-area {
+ -fx-background-color: white;
+ -fx-control-inner-background: white;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 10pt;
+ -fx-padding: 5 5 5 5;
+}
\ No newline at end of file
diff --git a/src/seedu/addressbook/ui/MochaTheme.css b/src/seedu/addressbook/ui/MochaTheme.css
new file mode 100644
index 000000000..6bb241543
--- /dev/null
+++ b/src/seedu/addressbook/ui/MochaTheme.css
@@ -0,0 +1,15 @@
+.text-field {
+ -fx-font-size: 12pt;
+ -fx-font-family: "Consolas";
+ -fx-font-weight: bold;
+ -fx-text-fill: #A14200;
+ -fx-control-inner-background: derive(#46961F,20%);
+}
+
+.text-area {
+ -fx-background-color: #46961F;
+ -fx-control-inner-background: #46961F;
+ -fx-font-family: "Segoe UI Semibold";
+ -fx-font-size: 10pt;
+ -fx-padding: 5 5 5 5;
+}
\ No newline at end of file
diff --git a/src/seedu/addressbook/ui/mainwindow.fxml b/src/seedu/addressbook/ui/mainwindow.fxml
index dafeaf6a7..bfc35e955 100644
--- a/src/seedu/addressbook/ui/mainwindow.fxml
+++ b/src/seedu/addressbook/ui/mainwindow.fxml
@@ -4,7 +4,7 @@
-