Skip to content

Commit

Permalink
Merge pull request #96 from tiuweehan/gui-dg
Browse files Browse the repository at this point in the history
Developer Guide for GUI Enhancements
  • Loading branch information
tiuweehan authored Oct 22, 2019
2 parents 6d453b7 + cd50225 commit 699035f
Show file tree
Hide file tree
Showing 13 changed files with 363 additions and 10 deletions.
91 changes: 91 additions & 0 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,87 @@ _Figure 3. Sequence Diagram for the Execution of `find` Command_
// end::find[]
//@@author le0tan

//@@author tiuweehan
// tag::switchTab[]

=== GUI Enhancements

An intuitive GUI facilitates the overall user friendliness of the application. The user should be able to navigate around the application easily to facilitate a smooth experience using AlgoBase. Additionally, multitasking is important as a user may be tackling multiple algorithmic questions at a single time. One of the main enhancements that we introduced to the GUI is tabbing, which fulfils these 2 requirements.

==== Current Implementation

The state of the GUI is stored in a `GuiState` object. The `GuiState` object contains a `TabManager` object, which manages tab information such as the tabs that are open and the tabs that are currently selected.

The information is linked to the `UI` through listeners. When the attributes of the `TabManager` object is updated, it triggers callback functions in the UI controllers that update the state of the UI displayed.

The following commands facilitate the management of tabs:

* `AlgoBase#switchTab()` - Switch between tabs within a specified Tab pane.
* `AlgoBase#openTab()` - Opens a new tab containing details of a model.
* `AlgoBase#closeTab()` - Closes an existing tab.

These operations are exposed in the `TabManager` class respectively as:

* `SwitchTab()`: `TabManager#setDisplayTabIndex` and `TabManager#setDetailsTabIndex`
* `OpenTab()`: `TabManager#addTab`
* `CloseTab()`: `TabManager#removeTab`

The following Activity Diagrams illustrate what happens when the user executes a `SwitchTabCommand` or `OpenTabCommand`

image::gui/SwitchTabCommandActivityDiagram.png[]
_Figure 1.1 Activity Diagram for the Execution of `switchtab` Command_

image::gui/OpenTabCommandActivityDiagram.png[]
_Figure 1.2 Activity Diagram for the Execution of `opentab` Command_

Given below is an example usage scenario and how the tag mechanism behaves at each step.

image::gui/SwitchTabsSequenceDiagram0.png[]
_Figure 2.1 Sequence Diagram for instantiating a `SwitchCommand` object_

Step 1: The user executes `switchtab t/display i/1` to switch to the first tab in the `display` tabpane.

Step 2: `SwitchTabCommandParser` processes the user input, retrieving the tab type (`display`) and the index (`1`).

Step 3: These two attributes are passed into the constructor of a `SwitchTabCommand` and a corresponding `SwitchTabCommand` object is returned to the LogicManager


image::gui/SwitchTabsSequenceDiagram1.png[]
_Figure 2.2 Sequence Diagram for updating the tab index in the TabManager_

Step 4: `LogicManager` invokes `execute()` method of the returned `SwitchTabCommand`, which retrieves the TabManager from the `Model` object. The `setDisplayTabPaneIndex(1)` method is invoked with the index 1 that the `SwitchTabCommand` was instantiated with.

Step 5: Invoking this method updates the integer value in the `displayTabIndex` field (type `ObservableIntegerValue`) of the `TabManager`.


image::gui/SwitchTabsSequenceDiagram2.png[]
_Figure 3.3 Sequence Diagram for reflecting the tab changes_

Step 6: A listener was added to the `displayTabIndex` field when the application was initialized. When a change in the value is detected, it triggers the `selectTab(1)` method with the value of the new index passed as an argument. This updates the selected tab in the UI.

==== Design Considerations

Aspect: Implementation of Tab Logic

* Alternative 1 (current choice): Implement Tab Logic separately within model and UI.
** Pros: Modularizes the logic and reduces the need for tighter coupling between model and UI
** Cons: Multiple sources of truth and more modules to be implemented
* Alternative 2: Implement Tab Logic as a singular module
** Pros: Single source of truth for state of tabs
** Cons: Increasing coupling between Model and UI, which in turn reduces testability

Aspect: How to update the tab in the UI

* Alternative 1 (current choice): Using a listener to detect changes to state of tab
** Pros: Reduces coupling between the `TabManager` class and the UI
** Cons: As callback functions are utilized, it is not immediately obvious how changes in state of TabManager leads to a change in the UI
* Alternative 2:
** Pros: Execution is sequential and it is easier to keep track of the flow of the program.
** Cons: Increases coupling between the `TabManager` class and the UI and reduces testability.

// end::switchTab[]
//@@author tiuweehan

== Documentation

Refer to the guide <<Documentation#, here>>.
Expand Down Expand Up @@ -679,6 +760,16 @@ Use case ends.
+
Use case ends.

[discrete]
=== Use Case 12: See details of an item

*MSS*

1. User requests to see the details of a specified item from the list of items.
2. AlgoBase displays the details of that item.
+
Use case ends.

[appendix]
== Non Functional Requirements

Expand Down
48 changes: 38 additions & 10 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,44 @@ Examples:

* `undonetask plan/1 task/1`

=== Tabs

==== Switching Tabs: `switchtab`
Switches between tabs in the GUI +
Format: `switchtab t/TAB_TYPE i/TAB_INDEX`

* Tab Type
** can be `display` or `details`

Examples:

* `switchtab t/display i/1`
* `switchtab t/details i/2`

==== Open Tabs: `opentab`
Opens a new tab in the GUI +
Format: `opentab m/MODEL_TYPE i/MODEL_INDEX`

* Model Type
** can be `problem`, `tag` or `plan`

Examples:

* `opentab m/problem i/1`
* `opentab m/plan i/2`

==== Close Tabs: `closetab`
Closes a tab in the GUI +
Format: `closetab t/TAB_TYPE i/TAB_INDEX`

* Tab Type
** can be `display` or `details`

Examples:

* `closetab t/display i/1`
* `closetab t/details i/2`

=== Importing and Exporting data

==== Importing data: `import`
Expand Down Expand Up @@ -285,16 +323,6 @@ Examples:

=== Miscellaneous

==== Switching tabs : `switch`

Switches to a tab display in the application. +
Format: `switch INDEX`

Examples:

* `switch 1`
Switches to the tab at index 1.

==== Viewing help : `help`

List all possible commands or find command usage using the command word. +
Expand Down
19 changes: 19 additions & 0 deletions docs/diagrams/gui/OpenTabCommandActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@startuml

start

:User executes a open tab command;

if () then ([command is valid])
:Instantiate a OpenTabCommand with the model type and index;
:Execute OpenTabCommand;
:Update list of tab data in TabManager with the index of the model;
:Listener is activated and new tab is reflected in UI;
else ([else])
:Throw an exception;
:Update UI to notify the user;
endif

stop

@enduml
19 changes: 19 additions & 0 deletions docs/diagrams/gui/SwitchTabCommandActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@startuml

start

:User executes a switch tab command;

if () then ([command is valid])
:Instantiate a SwitchTabCommand with the tab type and index;
:Execute SwitchTabCommand;
:Update TabManager with new index for given tab type;
:Listener is activated and tab change is reflected in UI;
else ([else])
:Throw an exception;
:Update UI to notify the user;
endif

stop

@enduml
45 changes: 45 additions & 0 deletions docs/diagrams/gui/SwitchTabsSequenceDiagram0.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@startuml
!include style.puml

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant ":SwitchTabCommandParser" as SwitchTabCommandParser LOGIC_COLOR
participant "s:SwitchTabCommand" as SwitchTabCommand LOGIC_COLOR
end box

[-> LogicManager : execute("switchtab t/display i/1")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand("switchtab t/display i/1")
activate AddressBookParser

create SwitchTabCommandParser
AddressBookParser -> SwitchTabCommandParser
activate SwitchTabCommandParser

SwitchTabCommandParser --> AddressBookParser
deactivate SwitchTabCommandParser

AddressBookParser -> SwitchTabCommandParser : parse("t/display i/1")
activate SwitchTabCommandParser

create SwitchTabCommand
SwitchTabCommandParser -> SwitchTabCommand : SwitchTabCommand(tabType, index)
activate SwitchTabCommand

SwitchTabCommand --> SwitchTabCommandParser : s
deactivate SwitchTabCommand

SwitchTabCommandParser --> AddressBookParser : s
deactivate SwitchTabCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
SwitchTabCommandParser -[hidden]-> AddressBookParser
destroy SwitchTabCommandParser

AddressBookParser --> LogicManager : s
deactivate AddressBookParser

deactivate SwitchTabCommand

@enduml
48 changes: 48 additions & 0 deletions docs/diagrams/gui/SwitchTabsSequenceDiagram1.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@startuml
!include style.puml

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant "s:SwitchTabCommand" as SwitchTabCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
end box

box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
participant "g:GuiState" as GuiState MODEL_COLOR
participant "t:TabManager" as TabManager MODEL_COLOR
end box

activate LogicManager

LogicManager -> SwitchTabCommand : execute()
activate SwitchTabCommand

SwitchTabCommand -> Model : getGuiState()
activate Model

Model --> SwitchTabCommand : g
deactivate Model

SwitchTabCommand -> GuiState : getTabManager()
activate GuiState

GuiState --> SwitchTabCommand : t
deactivate GuiState

SwitchTabCommand -> TabManager : setDisplayTabPaneIndex(1)
activate TabManager

TabManager --> SwitchTabCommand
deactivate TabManager

create CommandResult
SwitchTabCommand -> CommandResult
activate CommandResult

CommandResult --> SwitchTabCommand
deactivate CommandResult

SwitchTabCommand --> LogicManager : result
deactivate SwitchTabCommand
@enduml
28 changes: 28 additions & 0 deletions docs/diagrams/gui/SwitchTabsSequenceDiagram2.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@startuml
!include style.puml

box UI UI_COLOR_T1
participant ":DetailsTabPane" as DetailsTabPane UI_COLOR
participant "tabPane:TabPane" as TabPane UI_COLOR
participant "sm:SingleSelectionModel<Tab>" as SelectionModel UI_COLOR
end box

[-> DetailsTabPane : selectTab(1)
activate DetailsTabPane

DetailsTabPane -> TabPane : getSelectionModel()
activate TabPane

TabPane --> DetailsTabPane: sm
deactivate TabPane

DetailsTabPane -> SelectionModel : select(1)
activate SelectionModel

SelectionModel --> DetailsTabPane
deactivate SelectionModel

[<-- DetailsTabPane
deactivate DetailsTabPane

@enduml
Loading

0 comments on commit 699035f

Please sign in to comment.