diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java index 92cd8fa605a..5a11824ccc4 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/seedu/address/logic/Logic.java @@ -33,6 +33,9 @@ public interface Logic { /** Returns an unmodifiable view of the filtered list of persons */ ObservableList getFilteredPersonList(); + /** Returns an unmodifiable view of the pinned list of persons */ + ObservableList getPinnedPersonList(); + /** * Returns the user prefs' address book file path. */ diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java index 5aa3b91c7d0..8a15a15010b 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/seedu/address/logic/LogicManager.java @@ -71,6 +71,11 @@ public ObservableList getFilteredPersonList() { return model.getFilteredPersonList(); } + @Override + public ObservableList getPinnedPersonList() { + return model.getPinnedPersonList(); + } + @Override public Path getAddressBookFilePath() { return model.getAddressBookFilePath(); diff --git a/src/main/java/seedu/address/logic/commands/PinCommand.java b/src/main/java/seedu/address/logic/commands/PinCommand.java new file mode 100644 index 00000000000..716da16156a --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/PinCommand.java @@ -0,0 +1,73 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; + +/** + * Pins the person identified using it's displayed index from the address book. + */ +public class PinCommand extends Command { + + public static final String COMMAND_WORD = "pin"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Pins the person identified by the index number used in the displayed person list.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + public static final String MESSAGE_PIN_PERSON_SUCCESS = "Pinned Person: %1$s"; + + private final Index targetIndex; + + public PinCommand(Index targetIndex) { + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List lastShownList = model.getFilteredPersonList(); + + if (targetIndex.getZeroBased() >= lastShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToPin = lastShownList.get(targetIndex.getZeroBased()); + Person pinnedPerson = new Person(personToPin); + pinnedPerson.setPinned(true); + + model.setPerson(personToPin, pinnedPerson); + return new CommandResult(String.format(MESSAGE_PIN_PERSON_SUCCESS, Messages.format(personToPin))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PinCommand)) { + return false; + } + + PinCommand otherPinCommand = (PinCommand) other; + return targetIndex.equals(otherPinCommand.targetIndex); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("targetIndex", targetIndex) + .toString(); + } +} + diff --git a/src/main/java/seedu/address/logic/commands/UnpinCommand.java b/src/main/java/seedu/address/logic/commands/UnpinCommand.java new file mode 100644 index 00000000000..5e3e98619f4 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/UnpinCommand.java @@ -0,0 +1,73 @@ +package seedu.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import seedu.address.commons.core.index.Index; +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.logic.Messages; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Person; + +/** + * Unpins the person identified using it's displayed index from the address book. + */ +public class UnpinCommand extends Command { + + public static final String COMMAND_WORD = "unpin"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Unpins the person identified by the index number used in the displayed pinned list.\n" + + "Parameters: INDEX (must be a positive integer)\n" + + "Example: " + COMMAND_WORD + " 1"; + + public static final String MESSAGE_UNPIN_PERSON_SUCCESS = "Unpinned Person: %1$s"; + + private final Index targetIndex; + + public UnpinCommand(Index targetIndex) { + this.targetIndex = targetIndex; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List lastShownPinnedList = model.getPinnedPersonList(); + + if (targetIndex.getZeroBased() >= lastShownPinnedList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToUnpin = lastShownPinnedList.get(targetIndex.getZeroBased()); + Person unpinnedPerson = new Person(personToUnpin); + unpinnedPerson.setPinned(false); + + model.setPerson(personToUnpin, unpinnedPerson); + return new CommandResult(String.format(MESSAGE_UNPIN_PERSON_SUCCESS, Messages.format(personToUnpin))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof UnpinCommand)) { + return false; + } + + UnpinCommand otherUnpinCommand = (UnpinCommand) other; + return targetIndex.equals(otherUnpinCommand.targetIndex); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("targetIndex", targetIndex) + .toString(); + } +} + diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 3149ee07e0b..5d9e4020c88 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -17,6 +17,8 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.PinCommand; +import seedu.address.logic.commands.UnpinCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -62,6 +64,12 @@ public Command parseCommand(String userInput) throws ParseException { case DeleteCommand.COMMAND_WORD: return new DeleteCommandParser().parse(arguments); + case PinCommand.COMMAND_WORD: + return new PinCommandParser().parse(arguments); + + case UnpinCommand.COMMAND_WORD: + return new UnpinCommandParser().parse(arguments); + case ClearCommand.COMMAND_WORD: return new ClearCommand(); diff --git a/src/main/java/seedu/address/logic/parser/PinCommandParser.java b/src/main/java/seedu/address/logic/parser/PinCommandParser.java new file mode 100644 index 00000000000..8ed7846388a --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/PinCommandParser.java @@ -0,0 +1,29 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.PinCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new PinCommand object + */ +public class PinCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the PinCommand + * and returns a PinCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public PinCommand parse(String args) throws ParseException { + try { + Index index = ParserUtil.parseIndex(args); + return new PinCommand(index); + } catch (ParseException pe) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, PinCommand.MESSAGE_USAGE), pe); + } + } + +} diff --git a/src/main/java/seedu/address/logic/parser/UnpinCommandParser.java b/src/main/java/seedu/address/logic/parser/UnpinCommandParser.java new file mode 100644 index 00000000000..462f994f6f6 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/UnpinCommandParser.java @@ -0,0 +1,29 @@ +package seedu.address.logic.parser; + +import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.UnpinCommand; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Parses input arguments and creates a new UnpinCommand object + */ +public class UnpinCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the UnpinCommand + * and returns a UnpinCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public UnpinCommand parse(String args) throws ParseException { + try { + Index index = ParserUtil.parseIndex(args); + return new UnpinCommand(index); + } catch (ParseException pe) { + throw new ParseException( + String.format(MESSAGE_INVALID_COMMAND_FORMAT, UnpinCommand.MESSAGE_USAGE), pe); + } + } + +} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..4c386b0c85e 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -84,4 +84,7 @@ public interface Model { * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + /** Returns an unmodifiable view of the pinned person list */ + ObservableList getPinnedPersonList(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 57bc563fde6..d76ce954cfa 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -128,6 +128,13 @@ public void updateFilteredPersonList(Predicate predicate) { filteredPersons.setPredicate(predicate); } + @Override + public ObservableList getPinnedPersonList() { + FilteredList pinnedPersons = new FilteredList<>(this.addressBook.getPersonList()); + pinnedPersons.setPredicate(person -> person.isPinned()); + return pinnedPersons; + } + @Override public boolean equals(Object other) { if (other == this) { @@ -145,4 +152,6 @@ public boolean equals(Object other) { && filteredPersons.equals(otherModelManager.filteredPersons); } + + } diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index abe8c46b535..3fa84b6be07 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -24,6 +24,7 @@ public class Person { // Data fields private final Address address; private final Set tags = new HashSet<>(); + private boolean isPinned; /** * Every field must be present and not null. @@ -35,6 +36,16 @@ public Person(Name name, Phone phone, Email email, Address address, Set tag this.email = email; this.address = address; this.tags.addAll(tags); + this.isPinned = false; + } + + public Person(Person otherPerson) { + this.name = otherPerson.getName(); + this.phone = otherPerson.getPhone(); + this.email = otherPerson.getEmail(); + this.address = otherPerson.getAddress(); + this.isPinned = otherPerson.isPinned(); + this.tags.addAll(otherPerson.getTags()); } public Name getName() { @@ -53,6 +64,14 @@ public Address getAddress() { return address; } + public boolean isPinned() { + return isPinned; + } + + public void setPinned(boolean isPinned) { + this.isPinned = isPinned; + } + /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 4f235c9ee44..9ad728a3e3a 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -117,7 +117,7 @@ void fillInnerParts() { personListPanel = new PersonListPanel(logic.getFilteredPersonList()); personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); - pinnedPersonListPanel = new PinnedPersonListPanel(logic.getFilteredPersonList()); + pinnedPersonListPanel = new PinnedPersonListPanel(logic.getPinnedPersonList()); pinnedPersonListPanelPlaceholder.getChildren().add(pinnedPersonListPanel.getRoot()); resultDisplay = new ResultDisplay(); diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 90e8253f48e..812c4a99f59 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -157,6 +157,11 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public ObservableList getPinnedPersonList() { + throw new AssertionError("This method should not be called."); + } } /**