From d0885d0ed4062d98e576e4117d7a6dd7a0dc78c0 Mon Sep 17 00:00:00 2001 From: Chua Wei Wen Date: Sat, 21 Oct 2017 22:46:50 +0800 Subject: [PATCH 01/13] Updated Developer Guide --- docs/DeveloperGuide.adoc | 525 ++++++++++----------------------------- 1 file changed, 133 insertions(+), 392 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 5cca645..568fc02 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -14,8 +14,14 @@ ifdef::env-github,env-browser[:outfilesuffix: .adoc] By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +== Introduction + +iContacts is an address book application for managing contacts. This guide is intended to get you to understand the internal designs of the application, so that you will be able to work with the application quickly. The guide explains the design, implementation of noteworthy features, and the testing methods used in iContacts. + == Setting up +This section will guide you on setting up the development environment. + === Prerequisites . *JDK `1.8.0_60`* or later @@ -34,41 +40,41 @@ Do not disable them. If you have disabled them, go to `File` > `Settings` > `Plu === Setting up the project in your computer -. Fork this repo, and clone the fork to your computer -. Open IntelliJ (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project dialog first) -. Set up the correct JDK version for Gradle -.. Click `Configure` > `Project Defaults` > `Project Structure` -.. Click `New...` and find the directory of the JDK -. Click `Import Project` -. Locate the `build.gradle` file and select it. Click `OK` -. Click `Open as Project` -. Click `OK` to accept the default settings +. Fork this repo, and clone the fork to your computer. +. Open IntelliJ (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project dialog first). +. Set up the correct JDK version for Gradle. +.. Click `Configure` > `Project Defaults` > `Project Structure`. +.. Click `New...` and find the directory of the JDK. +. Click `Import Project`. +. Locate the `build.gradle` file and select it. Click `OK`. +. Click `Open as Project`. +. Click `OK` to accept the default settings. . Open a console and run the command `gradlew processResources` (Mac/Linux: `./gradlew processResources`). It should finish with the `BUILD SUCCESSFUL` message. + -This will generate all resources required by the application and tests. +This will generate all the resources required by the application and tests. === Verifying the setup -. Run the `seedu.address.MainApp` and try a few commands +. Run the `seedu.address.MainApp` and try a few commands. . link:#testing[Run the tests] to ensure they all pass. === Configurations to do before writing code ==== Configuring the coding style -This project follows https://github.com/oss-generic/process/blob/master/docs/CodingStandards.md[oss-generic coding standards]. IntelliJ's default style is mostly compliant with ours but it uses a different import order from ours. To rectify, +This project follows https://github.com/oss-generic/process/blob/master/docs/CodingStandards.md[oss-generic coding standards]. IntelliJ's default style is mostly compliant with ours but it uses a different import order from ours. Here are the steps to rectify the order: . Go to `File` > `Settings...` (Windows/Linux), or `IntelliJ IDEA` > `Preferences...` (macOS) . Select `Editor` > `Code Style` > `Java` -. Click on the `Imports` tab to set the order +. Click on the `Imports` tab to set the order: -* For `Class count to use import with '\*'` and `Names count to use static import with '*'`: Set to `999` to prevent IntelliJ from contracting the import statements -* For `Import Layout`: The order is `import static all other imports`, `import java.\*`, `import javax.*`, `import org.\*`, `import com.*`, `import all other imports`. Add a `` between each `import` +* For `Class count to use import with '\*'` and `Names count to use static import with '*'`: Set to `999` to prevent IntelliJ from contracting the import statements. +* For `Import Layout`: The order is `import static all other imports`, `import java.\*`, `import javax.*`, `import org.\*`, `import com.*`, `import all other imports`. Add a `` between each `import`. Optionally, you can follow the <> document to configure Intellij to check style-compliance as you write code. ==== Updating documentation to match your fork -After forking the repo, links in the documentation will still point to the `se-edu/addressbook-level4` repo. If you plan to develop this as a separate product (i.e. instead of contributing to the `se-edu/addressbook-level4`) , you should replace the URL in the variable `repoURL` in `DeveloperGuide.adoc` and `UserGuide.adoc` with the URL of your fork. +After forking the repo, the links in the documentation will still point to the `se-edu/addressbook-level4` repo. If you plan to develop this as a separate product (i.e. instead of contributing to the `se-edu/addressbook-level4`) , you should replace the URL in the variable `repoURL` in `DeveloperGuide.adoc` and `UserGuide.adoc` with the URL of your fork. ==== Setting up CI @@ -81,24 +87,23 @@ Having both Travis and AppVeyor ensures your App works on both Unix-based platfo ==== Getting started with coding -When you are ready to start coding, - -1. Get some sense of the overall design by reading the link:#architecture[Architecture] section. -2. Take a look at the section link:#suggested-programming-tasks-to-get-started[Suggested Programming Tasks to Get Started]. +When you are ready to start coding, get some sense of the overall design by reading the link:#architecture[Architecture] section. == Design +This section will explain the design aspects of iContacts. + === Architecture image::Architecture.png[width="600"] -_Figure 2.1.1 : Architecture Diagram_ +_Figure 1 : Architecture Diagram_ -The *_Architecture Diagram_* given above explains the high-level design of the App. Given below is a quick overview of each component. +The *_Architecture Diagram_* given above explains the high-level design of the application. Below is a quick overview of each component: [TIP] The `.pptx` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. To update a diagram, modify the diagram in the pptx file, select the objects of the diagram, and choose `Save as picture`. -`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for, +`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`], where it does the following: * At app launch: Initializes the components in the correct sequence, and connects them up with each other. * At shut down: Shuts down the components and invokes cleanup method where necessary. @@ -108,7 +113,7 @@ link:#common-classes[*`Commons`*] represents a collection of classes used by mul * `EventsCenter` : This class (written using https://github.com/google/guava/wiki/EventBusExplained[Google's Event Bus library]) is used by components to communicate with other components using events (i.e. a form of _Event Driven_ design) * `LogsCenter` : Used by many classes to write log messages to the App's log file. -The rest of the App consists of four components. +The rest of the App consists of four components: * link:#ui-component[*`UI`*] : The UI of the App. * link:#logic-component[*`Logic`*] : The command executor. @@ -117,13 +122,13 @@ The rest of the App consists of four components. Each of the four components -* Defines its _API_ in an `interface` with the same name as the Component. -* Exposes its functionality using a `{Component Name}Manager` class. +* defines its _API_ in an `interface` with the same name as the Component. +* exposes its functionality using a `{Component Name}Manager` class. For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class. image::LogicClassDiagram.png[width="800"] -_Figure 2.1.2 : Class Diagram of the Logic Component_ +_Figure 2 : Class Diagram of the Logic Component_ [discrete] ==== Events-Driven nature of the design @@ -131,7 +136,7 @@ _Figure 2.1.2 : Class Diagram of the Logic Component_ The _Sequence Diagram_ below shows how the components interact for the scenario where the user issues the command `delete 1`. image::SDforDeletePerson.png[width="800"] -_Figure 2.1.3a : Component interactions for `delete 1` command (part 1)_ +_Figure 3 : Component interactions for `delete 1` command (part 1)_ [NOTE] Note how the `Model` simply raises a `AddressBookChangedEvent` when the Address Book data are changed, instead of asking the `Storage` to save the updates to the hard disk. @@ -139,73 +144,75 @@ Note how the `Model` simply raises a `AddressBookChangedEvent` when the Address The diagram below shows how the `EventsCenter` reacts to that event, which eventually results in the updates being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time. image::SDforDeletePersonEventHandling.png[width="800"] -_Figure 2.1.3b : Component interactions for `delete 1` command (part 2)_ +_Figure 4 : Component interactions for `delete 1` command (part 2)_ [NOTE] -Note how the event is propagated through the `EventsCenter` to the `Storage` and `UI` without `Model` having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components. +Note how the event is propagated through the `EventsCenter` to the `Storage` and `UI` without `Model` having to be coupled to either of them. This is an example of how this Event-Driven approach helps us reduce direct coupling between components. + +=== Components -The sections below give more details of each component. +This section explains the four components used in the App. -=== UI component +==== UI component image::UiClassDiagram.png[width="800"] -_Figure 2.2.1 : Structure of the UI Component_ +_Figure 5 : Structure of the UI component_ *API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`] -The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. +The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter`, `BrowserPanel` etc. All of these, including the `MainWindow`, inherit from the abstract `UiPart` class. -The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] +The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`]. -The `UI` component, +The `UI` component -* Executes user commands using the `Logic` component. -* Binds itself to some data in the `Model` so that the UI can auto-update when data in the `Model` change. -* Responds to events raised from various parts of the App and updates the UI accordingly. +* executes user commands using the `Logic` component. +* binds itself to some data in the `Model` so that the UI can auto-update when data in the `Model` change. +* responds to events raised from various parts of the App and updates the UI accordingly. -=== Logic component +==== Logic component image::LogicClassDiagram.png[width="800"] -_Figure 2.3.1 : Structure of the Logic Component_ +_Figure 6 : Structure of the Logic component_ image::LogicCommandClassDiagram.png[width="800"] -_Figure 2.3.2 : Structure of Commands in the Logic Component. This diagram shows finer details concerning `XYZCommand` and `Command` in Figure 2.3.1_ +_Figure 7 : Structure of Commands in the Logic component. This diagram shows finer details concerning `XYZCommand` and `Command` in Figure 6_ *API* : link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] -. `Logic` uses the `AddressBookParser` class to parse the user command. -. This results in a `Command` object which is executed by the `LogicManager`. -. The command execution can affect the `Model` (e.g. adding a person) and/or raise events. -. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`. +* `Logic` uses the `AddressBookParser` class to parse the user command. +* This results in a `Command` object which is executed by the `LogicManager`. +* The command execution can affect the `Model` (e.g. adding a person) and/or raise events. +* The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`. Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call. image::DeletePersonSdForLogic.png[width="800"] -_Figure 2.3.1 : Interactions Inside the Logic Component for the `delete 1` Command_ +_Figure 8 : Interactions inside the Logic component for the `delete 1` command_ -=== Model component +==== Model component image::ModelClassDiagram.png[width="800"] -_Figure 2.4.1 : Structure of the Model Component_ +_Figure 9 : Structure of the Model component_ *API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`] -The `Model`, +The `Model` * stores a `UserPref` object that represents the user's preferences. * stores the Address Book data. * exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. * does not depend on any of the other three components. -=== Storage component +==== Storage component image::StorageClassDiagram.png[width="800"] -_Figure 2.5.1 : Structure of the Storage Component_ +_Figure 10 : Structure of the Storage component_ *API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`] -The `Storage` component, +The `Storage` component * can save `UserPref` objects in json format and read it back. * can save the Address Book data in xml format and read it back. @@ -288,7 +295,7 @@ return nameFound && tagFound; // tag::export[] === Export mechanism -The `ExportCommand` uses `XmlAddressBookStorage` class to generate a xml file based on a given range and saves it to the path provided. It takes in two String values range and path. Below is the constructor for the class: +The `ExportCommand` uses `XmlAddressBookStorage` class to generate a xml file based on a given range and saves it to the path provided. It takes in two `String` values `range` and `path`. Below is the constructor for the class: [source,java] ---- @@ -302,7 +309,7 @@ The `ExportCommand` uses `XmlAddressBookStorage` class to generate a xml file ba } ---- -The method `getRangefromInput()` splits the String range using the regex "," and returns a String array for the different values in the String range. +The method `getRangefromInput()` splits the `String` range using the regex `","` and returns a `String` array for the different values in the `String` range. Below is an extract of the method `getRangefromInput()`. @@ -315,16 +322,16 @@ private String[] getRangeFromInput() { } ---- -To determine which contacts should be added to the exportBook we have to check the the user input, there are 3 cases: +To determine which contacts should be added to the `exportBook` we have to check the the user input, there are three cases: -* all (Priority) -** if the case *all* is present in the user input we will just export all the contacts in the last shown list -* specific index (1, 2, 3) -** if the user input contains a specific index we will add that index(One-based) to the exportBook. -* range of index (1-5,8-10) -** if the user input contains a range which is identified by *-* character we will add that range of index(One-based) to the exportBook. +* All (Priority) +** if the word `all` is present in the user input, we will just export all the contacts in the last shown list. +* Specific index (e.g. 1, 2, 3) +** if the user input contains a specific index we will add that index (one-based) to the `exportBook`. +* Range of indexes (e.g. 1-5,8-10) +** if the user input contains a range which is identified by `-` character, we will add that range of index (one-based) to the `exportBook`. -Below is the code snippet to identify the 3 cases in the user input +Below is the code snippet to identify the three cases in the user input: [source,java] ---- String[] multipleRange = getRangeFromInput(); @@ -343,9 +350,9 @@ String[] multipleRange = getRangeFromInput(); } ---- -Lastly is to create the xml file from the exportBook. +The final step is to create the xml file from the `exportBook`. -Below is the code snippet to export the data into an xml file using AddressBookStorage Class +Below is the code snippet to export the data into an xml file using `AddressBookStorage`. [source,java] ---- try { @@ -366,6 +373,7 @@ The undo/redo mechanism is facilitated by an `UndoRedoStack`, which resides insi `UndoRedoStack` only deals with `UndoableCommands`. Commands that cannot be undone will inherit from `Command` instead. The following diagram shows the inheritance diagram for commands: image::LogicCommandClassDiagram.png[width="800"] +_Figure 11 : Inheritance diagram for commands_ As you can see from the diagram, `UndoableCommand` adds an extra layer between the abstract `Command` class and concrete commands that can be undone, such as the `DeleteCommand`. Note that extra tasks need to be done when executing a command in an _undoable_ way, such as saving the state of the address book before execution. `UndoableCommand` contains the high-level algorithm for those extra tasks while the child classes implements the details of how to execute the specific command. Note that this technique of putting the high-level algorithm in the parent class and lower-level steps of the algorithm in child classes is also known as the https://www.tutorialspoint.com/design_pattern/template_pattern.htm[template pattern]. @@ -405,10 +413,12 @@ Suppose that the user has just launched the application. The `UndoRedoStack` wil The user executes a new `UndoableCommand`, `delete 5`, to delete the 5th person in the address book. The current state of the address book is saved before the `delete 5` command executes. The `delete 5` command will then be pushed onto the `undoStack` (the current state is saved together with the command). image::UndoRedoStartingStackDiagram.png[width="800"] +_Figure 12 : Stack diagram after executing Delete command_ As the user continues to use the program, more commands are added into the `undoStack`. For example, the user may execute `add n/David ...` to add a new person. image::UndoRedoNewCommand1StackDiagram.png[width="800"] +_Figure 13 : Stack diagram after executing Add command_ [NOTE] If a command fails its execution, it will not be pushed to the `UndoRedoStack` at all. @@ -418,6 +428,7 @@ The user now decides that adding the person was a mistake, and decides to undo t We will pop the most recent command out of the `undoStack` and push it back to the `redoStack`. We will restore the address book to the state before the `add` command executed. image::UndoRedoExecuteUndoStackDiagram.png[width="800"] +_Figure 14 : Stack diagram after executing Undo command_ [NOTE] If the `undoStack` is empty, then there are no other commands left to be undone, and an `Exception` will be thrown when popping the `undoStack`. @@ -425,6 +436,7 @@ If the `undoStack` is empty, then there are no other commands left to be undone, The following sequence diagram shows how the undo operation works: image::UndoRedoSequenceDiagram.png[width="800"] +_Figure 15 : Sequence diagram of the undo operation_ The redo does the exact opposite (pops from `redoStack`, push to `undoStack`, and restores the address book to the state after the command is executed). @@ -434,22 +446,25 @@ If the `redoStack` is empty, then there are no other commands left to be redone, The user now decides to execute a new command, `clear`. As before, `clear` will be pushed into the `undoStack`. This time the `redoStack` is no longer empty. It will be purged as it no longer make sense to redo the `add n/David` command (this is the behavior that most modern desktop applications follow). image::UndoRedoNewCommand2StackDiagram.png[width="800"] +_Figure 16 : Stack diagram after executing Clear command_ Commands that are not undoable are not added into the `undoStack`. For example, `list`, which inherits from `Command` rather than `UndoableCommand`, will not be added after execution: image::UndoRedoNewCommand3StackDiagram.png[width="800"] +_Figure 17 : Stack diagram remains unchanged after executing List command_ The following activity diagram summarize what happens inside the `UndoRedoStack` when a user executes a new command: image::UndoRedoActivityDiagram.png[width="200"] +_Figure 18 : Activity diagram for UndoRedoStack_ ==== Design Considerations **Aspect:** Implementation of `UndoableCommand` + -**Alternative 1 (current choice):** Add a new abstract method `executeUndoableCommand()` + +**Alternative 1 (current choice):** Add a new abstract method `executeUndoableCommand()`. + **Pros:** We will not lose any undone/redone functionality as it is now part of the default behaviour. Classes that deal with `Command` do not have to know that `executeUndoableCommand()` exist. + **Cons:** Hard for new developers to understand the template pattern. + -**Alternative 2:** Just override `execute()` + +**Alternative 2:** Just override `execute()`. + **Pros:** Does not involve the template pattern, easier for new developers to understand. + **Cons:** Classes that inherit from `UndoableCommand` must remember to call `super.execute()`, or lose the ability to undo/redo. @@ -499,15 +514,15 @@ The reading and writing of images is done using the `ImageIO` class. The sequence diagram for adding a display picture is shown below: + image::SDforDisplayPicture.PNG[width="800"] -_Figure 1: Sequence Diagram for Display Picture Command._ +_Figure 19 : Sequence Diagram for Display Picture Command._ The wireframe used to display the image for each person is shown below: image::WireFramePersonCard.PNG[width="800"] -_Figure 2: Wireframe for the UI._ +_Figure 20 : Wireframe for the UI._ -The binder for refreshing the image every time the picture is updated is implemented by the following function +The binder for refreshing the image every time the picture is updated is implemented by the following function: [source,java] ---- @@ -517,7 +532,7 @@ The binder for refreshing the image every time the picture is updated is impleme } ---- -The new image stored in directory is given a unique name which is formed using hashcode of the unique email address of each contact. +The new image stored in directory is given a unique name which is formed using hashcode of the unique email address of each contact: [source,java] ---- @@ -529,46 +544,47 @@ The new image stored in directory is given a unique name which is formed using h ==== Reason for this type of implementation -The command is implemented in this manner because of the following reasons +The command is implemented in this manner because of the following reasons: -* By specifying the index, there is no ambiguity as to who should be assigned the display picture -* The `PATHOFIMAGE` must be absolute path on the local device to make sure the image is referenced. -* The image is stored in directory with a unique name to avoid conflict. Hashcode of user's email address is used to maintain uniqueness -* The task is done using CLI and follows as NFR +* By specifying the index, there is no ambiguity as to who should be assigned the display picture. +* The `PATHOFIMAGE` must be an absolute path on the local device to make sure the image is referenced. +* The image is stored in directory with a unique name to avoid conflict. Hashcode of user's email address is used to maintain uniqueness. +* The task is done using CLI and follows as NFR. * The image is stored in jpg format to ensure maximum compatibility. ==== Design Considerations **Aspect:** At what stage should the image be read and stored + -**Alternative 1 (current choice):** Invoke 'ReadAndStoreImage' from Logic Component + -**Pros:** We will be able to get the contact's address for unique hash code + -**Cons:** Hard for new developers to understand the sequence diagram and flow. + -**Alternative 2:** Invoke 'ReadAndStoreImage' from Model Component + +**Alternative 1 (current choice):** Invoke 'ReadAndStoreImage' from Logic component. + +**Pros:** We will be able to get the contact's address for unique hash code. + +**Cons:** Difficult for new developers to understand the sequence diagram and flow. + +**Alternative 2:** Invoke 'ReadAndStoreImage' from Model component. + **Pros:** Easier for new developers to understand the sequence diagram and maintains event-driven nature. + -**Cons:** There might be clash in naming of two different images for large database of contacts +**Cons:** There might be clashes in naming of two different images for large database of contacts. --- **Aspect:** How should the image be taken from user + -**Alternative 1 (current choice):** User has to enter absolute path of image by checking his local device + +**Alternative 1 (current choice):** User has to enter the absolute path of image by checking his local device. + **Pros:** Complete CLI process + -**Cons:** Might be problematic for user to copy and paste and might result in error of path giving fail command + -**Alternative 2:** Pop up a `FileChooser` after command is entered + -**Pros:** Easier for users to mention the correct image at a quick pace + -**Cons:** Will no longer be a CLI process completely +**Cons:** Might be problematic for user to copy and paste and might result in error of path giving fail command. + +**Alternative 2:** Pop up a `FileChooser` after command is entered. + +**Pros:** Easier for users to mention the correct image quickly. + +**Cons:** Will no longer be a CLI process completely. === Toggling mechanism image::togglingMechanism1.png[width="790] -_Figure 1: Component interactions for the toggling mechanism._ +_Figure 21 : Component interactions for the toggling mechanism._ The toggling mechanism is an event-driven mechanism. The above diagram shows the high-level overview of the component interactions for the toggling mechanism. + image::togglingMechanism2.png[width="790"] -_Figure 2: Sequence diagram for the first part of the toggling mechanism._ +_Figure 22 : Sequence diagram for the first part of the toggling mechanism._ + +As seen from the sequence diagram above, when the user type the command for toggle, an instance of `ToggleCommand` would be formed first. -As seen from the sequence diagram above, when the user type the command for toggle, an instance of `ToggleCommand` would be formed first. + Upon execution by `LogicManager`, the event `BrowserAndRemindersPanelToggleEvent` would be posted by the `EventCenter`, to the `EventBus`. [source, java] @@ -586,7 +602,7 @@ The method `handleBrowserToggleEvent()` in the `BrowserAndRemindersPanel` class and upon receiving the event, it will invoke the method `toggleBrowserPanel` to trigger the actual toggling. image::togglingMechanism3.png[width="790"] -_Figure 3: Sequence diagram for the second part of the toggling mechanism._ +_Figure 23 : Sequence diagram for the second part of the toggling mechanism._ The `BrowserAndRemindersPanel` class has a variable `currentlyInFront` keeping track of which panel (browser or reminders) is currently being shown (in front). `toggleBrowserPanel` would then use the `currentlyInFront` variable to toggle to the correct panel, and then update `currentlyInFront` appropriately. + @@ -619,9 +635,9 @@ public class BrowserAndRemindersPanel extends UIPart { } ---- -As seen from the code snippet above, 2 other events can still be raised; the `TurnLabelsOnEvent` and `TurnLabelsOffEvent`. +As seen from the code snippet above, two other events `TurnLabelsOnEvent` and `TurnLabelsOffEvent` can still be raised. When the browser is being brought to the front, the *birthdays* and *reminders* heading just above the list of birthday reminders and -reminders should be turned off, and when the reminders panel is brought to the front, these heading should be turned on. The handling of these 2 events +reminders should be turned off. When the reminders panel is brought to the front, these heading should be turned on. The handling of these two events are in the `HeaderPane` class, where the variables `birthdays` and `reminders`, representing the `Label` header object for birthday reminders and reminders respectively, are turned on and off by simply setting their visibility appropriately. @@ -644,7 +660,7 @@ public class HeaderPane extends UIPart { } ---- -One important thing to note is that when the `select` command is executed, the browser panel would be brought forward no matter what. +One important thing to note that when the `select` command is executed, the browser panel would be brought forward no matter what. [source, java] ---- @@ -669,71 +685,41 @@ method, there is the method `bringBrowserToFront`, which would then bring the br ==== Design Considerations -**Aspect:** Usage of browser area + -**Alternative 1 (current choice):** Allow users to toggle between browser and reminders + -Pros: Can use the entire space for either browser or reminders + -Cons: Users need to manually switch between browser and reminders + -**Alternative 2:** Put reminders and browser side-by-side + -Pros: Users do not need to manually switch between browser and reminders + +**Aspect:** Usage of browser area. + +**Alternative 1 (current choice):** Allow users to toggle between browser and reminders. + +Pros: Can use the entire space for either browser or reminders. + +Cons: Users need to manually switch between browser and reminders. + +**Alternative 2:** Place the reminders and browser side-by-side. + +Pros: Users do not need to manually switch between browser and reminders. + Cons: Too little space for browser and reminders. Difficult to read. -**Aspect:** Implementation of toggling mechanism + -**Alternative 1 (current choice):** Bring browser and reminders panel to the front as required + -Pros: Users can interact with both browser and reminders (can scroll through reminders etc) + +**Aspect:** Implementation of toggling mechanism. + +**Alternative 1 (current choice):** Bring the browser and reminders panel to the front as required. + +Pros: Users can interact with both browser and reminders (can scroll through reminders etc.). + Cons: More difficult to implement + -**Alternative 2:** Set visibility of browser as required (set browser visibility to false to display reminders and vice versa) + -Pros: Easier to implement + -Cons: Users cannot interact with the reminders panel (since the browser is technically still at the front) +**Alternative 2:** Set the visibility of browser as required (set the browser visibility to false to display reminders and vice versa). + +Pros: Easier to implement. + +Cons: Users cannot interact with the reminders panel (since the browser is technically still in front). === Logging We are using `java.util.logging` package for logging. The `LogsCenter` class is used to manage the logging levels and logging destinations. -* The logging level can be controlled using the `logLevel` setting in the configuration file (See link:#configuration[Configuration]) -* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level +* The logging level can be controlled using the `logLevel` setting in the configuration file (See link:#configuration[Configuration]). +* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level. * Currently log messages are output through: `Console` and to a `.log` file. *Logging Levels* -* `SEVERE` : Critical problem detected which may possibly cause the termination of the application -* `WARNING` : Can continue, but with caution -* `INFO` : Information showing the noteworthy actions by the App -* `FINE` : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size +* `SEVERE` : Critical problem detected which may possibly cause the termination of the application. +* `WARNING` : Can continue, but with caution. +* `INFO` : Information showing the noteworthy actions by the App. +* `FINE` : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size. === Configuration Certain properties of the application can be controlled (e.g App name, logging level) through the configuration file (default: `config.json`). -== Documentation - -We use asciidoc for writing documentation. - -[NOTE] -We chose asciidoc over Markdown because asciidoc, although a bit more complex than Markdown, provides more flexibility in formatting. - -=== Editing Documentation - -See <> to learn how to render `.adoc` files locally to preview the end result of your edits. -Alternatively, you can download the AsciiDoc plugin for IntelliJ, which allows you to preview the changes you have made to your `.adoc` files in real-time. - -=== Publishing Documentation - -See <> to learn how to deploy GitHub Pages using Travis. - -=== Converting Documentation to PDF format - -We use https://www.google.com/chrome/browser/desktop/[Google Chrome] for converting documentation to PDF format, as Chrome's PDF engine preserves hyperlinks used in webpages. - -Here are the steps to convert the project documentation files to PDF format. - -. Follow the instructions in <> to convert the AsciiDoc files in the `docs/` directory to HTML format. -. Go to your generated HTML files in the `build/docs` folder, right click on them and select `Open with` -> `Google Chrome`. -. Within Chrome, click on the `Print` option in Chrome's menu. -. Set the destination to `Save as PDF`, then click `Save` to save a copy of the file in PDF format. For best results, use the settings indicated in the screenshot below. - -image::chrome_save_as_pdf.png[width="300"] -_Figure 5.6.1 : Saving documentation as PDF files in Chrome_ - == Testing === Running Tests @@ -745,12 +731,12 @@ The most reliable way to run tests is the 3rd one. The first two methods might f *Method 1: Using IntelliJ JUnit test runner* -* To run all tests, right-click on the `src/test/java` folder and choose `Run 'All Tests'` -* To run a subset of tests, you can right-click on a test package, test class, or a test and choose `Run 'ABC'` +* To run all tests, right-click on the `src/test/java` folder and choose `Run 'All Tests'`. +* To run a subset of tests, you can right-click on a test package, test class, or a test and choose `Run 'ABC'`. *Method 2: Using Gradle* -* Open a console and run the command `gradlew clean allTests` (Mac/Linux: `./gradlew clean allTests`) +* Open a console and run the command `gradlew clean allTests` (Mac/Linux: `./gradlew clean allTests`). [NOTE] See <> for more info on how to run tests using Gradle. @@ -759,7 +745,7 @@ See <> for more info on how to run tests using G Thanks to the https://github.com/TestFX/TestFX[TestFX] library we use, our GUI tests can be run in the _headless_ mode. In the headless mode, GUI tests do not show up on the screen. That means the developer can do other things on the Computer while the tests are running. -To run tests in headless mode, open a console and run the command `gradlew clean headless allTests` (Mac/Linux: `./gradlew clean headless allTests`) +To run tests in headless mode, open a console and run the command `gradlew clean headless allTests` (Mac/Linux: `./gradlew clean headless allTests`). === Types of tests @@ -805,253 +791,8 @@ Here are the steps to create a new release. === Managing Dependencies A project often depends on third-party libraries. For example, Address Book depends on the http://wiki.fasterxml.com/JacksonHome[Jackson library] for XML parsing. Managing these _dependencies_ can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives. + -a. Include those libraries in the repo (this bloats the repo size) + -b. Require developers to download those libraries manually (this creates extra work for developers) - -[appendix] -== Suggested Programming Tasks to Get Started - -Suggested path for new programmers: - -1. First, add small local-impact (i.e. the impact of the change does not go beyond the component) enhancements to one component at a time. Some suggestions are given in this section link:#improving-each-component[Improving a Component]. - -2. Next, add a feature that touches multiple components to learn how to implement an end-to-end feature across all components. The section link:#creating-a-new-command-code-remark-code[Creating a new command: `remark`] explains how to go about adding such a feature. - -=== Improving each component - -Each individual exercise in this section is component-based (i.e. you would not need to modify the other components to get it to work). - -[discrete] -==== `Logic` component - -[TIP] -Do take a look at the link:#logic-component[Design: Logic Component] section before attempting to modify the `Logic` component. - -. Add a shorthand equivalent alias for each of the individual commands. For example, besides typing `clear`, the user can also type `c` to remove all persons in the list. -+ -**** -* Hints -** Just like we store each individual command word constant `COMMAND_WORD` inside `*Command.java` (e.g. link:{repoURL}/src/main/java/seedu/address/logic/commands/FindCommand.java[`FindCommand#COMMAND_WORD`], link:{repoURL}/src/main/java/seedu/address/logic/commands/DeleteCommand.java[`DeleteCommand#COMMAND_WORD`]), you need a new constant for aliases as well (e.g. `FindCommand#COMMAND_ALIAS`). -** link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] is responsible for analyzing command words. -* Solution -** Modify the switch statement in link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser#parseCommand(String)`] such that both the proper command word and alias can be used to execute the same intended command. -** See this https://github.com/se-edu/addressbook-level4/pull/590/files[PR] for the full solution. -**** - -[discrete] -==== `Model` component - -[TIP] -Do take a look at the link:#model-component[Design: Model Component] section before attempting to modify the `Model` component. - -. Add a `removeTag(Tag)` method. The specified tag will be removed from everyone in the address book. -+ -**** -* Hints -** The link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model`] API needs to be updated. -** Find out which of the existing API methods in link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`] and link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`] classes can be used to implement the tag removal logic. link:{repoURL}/src/main/java/seedu/address/model/AddressBook.java[`AddressBook`] allows you to update a person, and link:{repoURL}/src/main/java/seedu/address/model/person/Person.java[`Person`] allows you to update the tags. -* Solution -** Add the implementation of `deleteTag(Tag)` method in link:{repoURL}/src/main/java/seedu/address/model/ModelManager.java[`ModelManager`]. Loop through each person, and remove the `tag` from each person. -** See this https://github.com/se-edu/addressbook-level4/pull/591/files[PR] for the full solution. -**** - -[discrete] -==== `Ui` component - -[TIP] -Do take a look at the link:#ui-component[Design: UI Component] section before attempting to modify the `UI` component. - -. Use different colors for different tags inside person cards. For example, `friends` tags can be all in grey, and `colleagues` tags can be all in red. -+ -**Before** -+ -image::getting-started-ui-tag-before.png[width="300"] -+ -**After** -+ -image::getting-started-ui-tag-after.png[width="300"] -+ -**** -* Hints -** The tag labels are created inside link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard#initTags(ReadOnlyPerson)`] (`new Label(tag.tagName)`). https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Label.html[JavaFX's `Label` class] allows you to modify the style of each Label, such as changing its color. -** Use the .css attribute `-fx-background-color` to add a color. -* Solution -** See this https://github.com/se-edu/addressbook-level4/pull/592/files[PR] for the full solution. -**** - -. Modify link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] such that link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay`] can show a different style on error (currently it shows the same regardless of errors). -+ -**Before** -+ -image::getting-started-ui-result-before.png[width="200"] -+ -**After** -+ -image::getting-started-ui-result-after.png[width="200"] -+ -**** -* Hints -** link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] is raised by link:{repoURL}/src/main/java/seedu/address/ui/CommandBox.java[`CommandBox`] which also knows whether the result is a success or failure, and is caught by link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay`] which is where we want to change the style to. -** Refer to link:{repoURL}/src/main/java/seedu/address/ui/CommandBox.java[`CommandBox`] for an example on how to display an error. -* Solution -** Modify link:{repoURL}/src/main/java/seedu/address/commons/events/ui/NewResultAvailableEvent.java[`NewResultAvailableEvent`] 's constructor so that users of the event can indicate whether an error has occurred. -** Modify link:{repoURL}/src/main/java/seedu/address/ui/ResultDisplay.java[`ResultDisplay#handleNewResultAvailableEvent(event)`] to react to this event appropriately. -** See this https://github.com/se-edu/addressbook-level4/pull/593/files[PR] for the full solution. -**** - -. Modify the link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to show the total number of people in the address book. -+ -**Before** -+ -image::getting-started-ui-status-before.png[width="500"] -+ -**After** -+ -image::getting-started-ui-status-after.png[width="500"] -+ -**** -* Hints -** link:{repoURL}/src/main/resources/view/StatusBarFooter.fxml[`StatusBarFooter.fxml`] will need a new `StatusBar`. Be sure to set the `GridPane.columnIndex` properly for each `StatusBar` to avoid misalignment! -** link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] needs to initialize the status bar on application start, and to update it accordingly whenever the address book is updated. -* Solution -** Modify the constructor of link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter`] to take in the number of persons when the application just started. -** Use link:{repoURL}/src/main/java/seedu/address/ui/StatusBarFooter.java[`StatusBarFooter#handleAddressBookChangedEvent(AddressBookChangedEvent)`] to update the number of persons whenever there are new changes to the addressbook. -** See this https://github.com/se-edu/addressbook-level4/pull/596/files[PR] for the full solution. -**** - -[discrete] -==== `Storage` component - -[TIP] -Do take a look at the link:#storage-component[Design: Storage Component] section before attempting to modify the `Storage` component. - -. Add a new method `backupAddressBook(ReadOnlyAddressBook)`, so that the address book can be saved in a fixed temporary location. -+ -**** -* Hint -** Add the API method in link:{repoURL}/src/main/java/seedu/address/storage/AddressBookStorage.java[`AddressBookStorage`] interface. -** Implement the logic in link:{repoURL}/src/main/java/seedu/address/storage/StorageManager.java[`StorageManager`] class. -* Solution -** See this https://github.com/se-edu/addressbook-level4/pull/594/files[PR] for the full solution. -**** - -=== Creating a new command: `remark` - -By creating this command, you will get a chance to learn how to implement a feature end-to-end, touching all major components of the app. - -==== Description -Edits the remark for a person specified in the `INDEX`. + -Format: `remark INDEX r/[REMARK]` - -Examples: - -* `remark 1 r/Likes to drink coffee.` + -Edits the remark for the first person to `Likes to drink coffee.` -* `remark 1 r/` + -Removes the remark for the first person. - -==== Step-by-step Instructions - -===== [Step 1] Logic: Teach the app to accept 'remark' which does nothing -Let's start by teaching the application how to parse a `remark` command. We will add the logic of `remark` later. - -**Main:** - -. Add a `RemarkCommand` that extends link:{repoURL}/src/main/java/seedu/address/logic/commands/UndoableCommand.java[`UndoableCommand`]. Upon execution, it should just throw an `Exception`. -. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] to accept a `RemarkCommand`. - -**Tests:** - -. Add `RemarkCommandTest` that tests that `executeUndoableCommand()` throws an Exception. -. Add new test method to link:{repoURL}/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java[`AddressBookParserTest`], which tests that typing "remark" returns an instance of `RemarkCommand`. - -===== [Step 2] Logic: Teach the app to accept 'remark' arguments -Let's teach the application to parse arguments that our `remark` command will accept. E.g. `1 r/Likes to drink coffee.` - -**Main:** - -. Modify `RemarkCommand` to take in an `Index` and `String` and print those two parameters as the error message. -. Add `RemarkCommandParser` that knows how to parse two arguments, one index and one with prefix 'r/'. -. Modify link:{repoURL}/src/main/java/seedu/address/logic/parser/AddressBookParser.java[`AddressBookParser`] to use the newly implemented `RemarkCommandParser`. - -**Tests:** - -. Modify `RemarkCommandTest` to test the `RemarkCommand#equals()` method. -. Add `RemarkCommandParserTest` that tests different boundary values -for `RemarkCommandParser`. -. Modify link:{repoURL}/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java[`AddressBookParserTest`] to test that the correct command is generated according to the user input. - -===== [Step 3] Ui: Add a placeholder for remark in `PersonCard` -Let's add a placeholder on all our link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] s to display a remark for each person later. - -**Main:** - -. Add a `Label` with any random text inside link:{repoURL}/src/main/resources/view/PersonListCard.fxml[`PersonListCard.fxml`]. -. Add FXML annotation in link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] to tie the variable to the actual label. - -**Tests:** - -. Modify link:{repoURL}/src/test/java/guitests/guihandles/PersonCardHandle.java[`PersonCardHandle`] so that future tests can read the contents of the remark label. - -===== [Step 4] Model: Add `Remark` class -We have to properly encapsulate the remark in our link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`ReadOnlyPerson`] class. Instead of just using a `String`, let's follow the conventional class structure that the codebase already uses by adding a `Remark` class. - -**Main:** - -. Add `Remark` to model component (you can copy from link:{repoURL}/src/main/java/seedu/address/model/person/Address.java[`Address`], remove the regex and change the names accordingly). -. Modify `RemarkCommand` to now take in a `Remark` instead of a `String`. - -**Tests:** - -. Add test for `Remark`, to test the `Remark#equals()` method. - -===== [Step 5] Model: Modify `ReadOnlyPerson` to support a `Remark` field -Now we have the `Remark` class, we need to actually use it inside link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`ReadOnlyPerson`]. - -**Main:** - -. Add three methods `setRemark(Remark)`, `getRemark()` and `remarkProperty()`. Be sure to implement these newly created methods in link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`Person`], which implements the link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`ReadOnlyPerson`] interface. -. You may assume that the user will not be able to use the `add` and `edit` commands to modify the remarks field (i.e. the person will be created without a remark). -. Modify link:{repoURL}/src/main/java/seedu/address/model/util/SampleDataUtil.java/[`SampleDataUtil`] to add remarks for the sample data (delete your `addressBook.xml` so that the application will load the sample data when you launch it.) - -===== [Step 6] Storage: Add `Remark` field to `XmlAdaptedPerson` class -We now have `Remark` s for `Person` s, but they will be gone when we exit the application. Let's modify link:{repoURL}/src/main/java/seedu/address/storage/XmlAdaptedPerson.java[`XmlAdaptedPerson`] to include a `Remark` field so that it will be saved. - -**Main:** - -. Add a new Xml field for `Remark`. -. Be sure to modify the logic of the constructor and `toModelType()`, which handles the conversion to/from link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`ReadOnlyPerson`]. - -**Tests:** - -. Fix `validAddressBook.xml` such that the XML tests will not fail due to a missing `` element. - -===== [Step 7] Ui: Connect `Remark` field to `PersonCard` -Our remark label in link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`] is still a placeholder. Let's bring it to life by binding it with the actual `remark` field. - -**Main:** - -. Modify link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard#bindListeners()`] to add the binding for `remark`. - -**Tests:** - -. Modify link:{repoURL}/src/test/java/seedu/address/ui/testutil/GuiTestAssert.java[`GuiTestAssert#assertCardDisplaysPerson(...)`] so that it will compare the remark label. -. In link:{repoURL}/src/test/java/seedu/address/ui/PersonCardTest.java[`PersonCardTest`], call `personWithTags.setRemark(ALICE.getRemark())` to test that changes in the link:{repoURL}/src/main/java/seedu/address/model/person/ReadOnlyPerson.java[`Person`] 's remark correctly updates the corresponding link:{repoURL}/src/main/java/seedu/address/ui/PersonCard.java[`PersonCard`]. - -===== [Step 8] Logic: Implement `RemarkCommand#execute()` logic -We now have everything set up... but we still can't modify the remarks. Let's finish it up by adding in actual logic for our `remark` command. - -**Main:** - -. Replace the logic in `RemarkCommand#execute()` (that currently just throws an `Exception`), with the actual logic to modify the remarks of a person. - -**Tests:** - -. Update `RemarkCommandTest` to test that the `execute()` logic works. - -==== Full Solution - -See this https://github.com/se-edu/addressbook-level4/pull/599[PR] for the step-by-step solution. +a. Include those libraries in the repo (this bloats the repo size). + +b. Require developers to download those libraries manually (this creates extra work for developers). [appendix] == Target Users From 7da358b81138377dc83cfa5e7b2939c9023b91a6 Mon Sep 17 00:00:00 2001 From: Chua Wei Wen Date: Sat, 21 Oct 2017 22:50:06 +0800 Subject: [PATCH 02/13] Fixed grammar --- docs/DeveloperGuide.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 568fc02..38ce19c 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -103,7 +103,7 @@ The *_Architecture Diagram_* given above explains the high-level design of the a [TIP] The `.pptx` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. To update a diagram, modify the diagram in the pptx file, select the objects of the diagram, and choose `Save as picture`. -`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`], where it does the following: +`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`], and it does the following: * At app launch: Initializes the components in the correct sequence, and connects them up with each other. * At shut down: Shuts down the components and invokes cleanup method where necessary. From 7edab7710064fe84c698eda21692495adeca9178 Mon Sep 17 00:00:00 2001 From: Justin Poh Bing Wei <31033562+justinpoh@users.noreply.github.com> Date: Sat, 21 Oct 2017 22:56:53 +0800 Subject: [PATCH 03/13] Update DeveloperGuide.adoc --- docs/DeveloperGuide.adoc | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 38ce19c..b6bfcfd 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -582,11 +582,11 @@ The toggling mechanism is an event-driven mechanism. The above diagram shows the image::togglingMechanism2.png[width="790"] _Figure 22 : Sequence diagram for the first part of the toggling mechanism._ - -As seen from the sequence diagram above, when the user type the command for toggle, an instance of `ToggleCommand` would be formed first. - -Upon execution by `LogicManager`, the event `BrowserAndRemindersPanelToggleEvent` would be posted by the `EventCenter`, to the `EventBus`. - ++ ++ +As seen from the sequence diagram above, when the user type the command for toggle, an instance of `ToggleCommand` would be instantiated. Upon execution by `LogicManager`, the event `BrowserAndRemindersPanelToggleEvent` would be posted by the `EventCenter`, to the `EventBus`: ++ ++ [source, java] ---- public class ToggleCommand extends Command { @@ -597,16 +597,20 @@ public class ToggleCommand extends Command { } } ---- - -The method `handleBrowserToggleEvent()` in the `BrowserAndRemindersPanel` class in the `UI` component will then listen for the event, ++ ++ +As seen from the diagram below, the method `handleBrowserToggleEvent()` in the `BrowserAndRemindersPanel` class in the `UI` component will then listen for the event, and upon receiving the event, it will invoke the method `toggleBrowserPanel` to trigger the actual toggling. - ++ ++ image::togglingMechanism3.png[width="790"] _Figure 23 : Sequence diagram for the second part of the toggling mechanism._ - -The `BrowserAndRemindersPanel` class has a variable `currentlyInFront` keeping track of which panel (browser or reminders) is currently being shown (in front). -`toggleBrowserPanel` would then use the `currentlyInFront` variable to toggle to the correct panel, and then update `currentlyInFront` appropriately. + - ++ ++ +The `BrowserAndRemindersPanel` class has a variable `currentlyInFront` keeping track of which panel (browser or reminders) is currently being shown. +`toggleBrowserPanel` would then use the `currentlyInFront` variable to toggle to the correct panel, and then update `currentlyInFront` appropriately: ++ ++ [source, java] ---- public class BrowserAndRemindersPanel extends UIPart { @@ -634,13 +638,15 @@ public class BrowserAndRemindersPanel extends UIPart { } } ---- - ++ ++ As seen from the code snippet above, two other events `TurnLabelsOnEvent` and `TurnLabelsOffEvent` can still be raised. When the browser is being brought to the front, the *birthdays* and *reminders* heading just above the list of birthday reminders and reminders should be turned off. When the reminders panel is brought to the front, these heading should be turned on. The handling of these two events are in the `HeaderPane` class, where the variables `birthdays` and `reminders`, representing the `Label` header object for birthday reminders and reminders -respectively, are turned on and off by simply setting their visibility appropriately. - +respectively, are turned on and off by simply setting their visibility appropriately: ++ ++ [source, java] ---- public class HeaderPane extends UIPart { @@ -659,9 +665,11 @@ public class HeaderPane extends UIPart { } } ---- - -One important thing to note that when the `select` command is executed, the browser panel would be brought forward no matter what. - ++ ++ +One important thing to note that when the `select` command is executed, the browser panel would be brought forward no matter what: ++ ++ [source, java] ---- public class BrowserAndRemindersPanel extends UIPart { @@ -679,8 +687,9 @@ public class BrowserAndRemindersPanel extends UIPart { } } ---- - -The `PersonPanelSelectionChangedEvent` is posted whenever the `select` command is executed. Within the `handlePersonPanelSelectionChangedEvent` ++ ++ +As seen from the code snippet above, the `PersonPanelSelectionChangedEvent` is posted whenever the `select` command is executed. Within the `handlePersonPanelSelectionChangedEvent` method, there is the method `bringBrowserToFront`, which would then bring the browser panel to the front no matter what. ==== Design Considerations From f01acf6afb7bc41437247b194a9b8e8131a43775 Mon Sep 17 00:00:00 2001 From: Shradheya Thakre Date: Sun, 22 Oct 2017 13:03:53 +0800 Subject: [PATCH 04/13] Minor Changes. Please review --- .idea/workspace.xml | 86 +++++++++++++++++++++++++-------- docs/DeveloperGuide.adoc | 100 +++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 70 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1370576..07ff153 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,10 @@ - + + + + - + - - + + @@ -25,6 +28,13 @@ + + + + + + + @@ -39,10 +49,17 @@ - + + + + true + DEFINITION_ORDER + +