This is the CSE340-SP19 final website. You may be looking for the current version of the class

A2: Undo

Last revised: 2:00 PM, Monday, May 20, 2019
Assigned: Thursday, May 16, 2019

Android Goals:

  • Be able to understand and modify an existing user interface
  • Learn about floating action buttons
  • Implement core data structure for Undo
Due: 11:59 PM Tuesday, May 21, 2019; Heuristic evaluation in lab on May 23, 2019

HCI Goals:

  • Modify and existing app in a consistent fashion
  • Make your modifications accessible
  • Make your modifications usable
  • Use heuristic evaluation to assess an app

Tasks:

Explanation of Codebase

This is one of the more complex programs we are giving you in terms of code, it is a fairly functional application.

The initial interactor hierarchy at instantiation looks like this (shown at the side is a legend for the visibility status of different interactors). Hidden means on screen and drawn but hidden behind something else.

The FAB subtrees are the menus at the top of the screen (for undo and redo) and bottom (for color and thickness), made up of one or more floating action buttons. The DrawingView is the place where drawing takes place. Each new stroke is saved as a separate, new StrokeView added to the DrawingView.

graph TD M[MainActivity] --> D[DrawingView] M --> FUndo[FAB:Undo] M --> FRedo[FAB:Redo] M --> FColor[FAB:Color] M --> FThick[FAB:Thickness] FColor --> Red[Red] FColor --> Green[Green] FColor --> Blue[Blue] FThick --> Thin[Thin] FThick --> Med[Med] FThick --> Thick[Thick] Vis[Visible] --> In[Invisible] In --> Hid[Hidden] classDef normal fill:#e6f3ff,stroke:#333,stroke-width:2px; classDef start fill:#d1e0e0,stroke:#333,stroke-width:4px; class M,D,FColor,FThick,Vis start class Red,Green,Blue,Thin,Med,Thick,Hid normal

When the user draws on screen (by clicking and dragging inside the DrawingView, this adds a new StrokeView to the interface. Notice that the Undo button is now visible instead of invisible because there is an action to undo.

graph TD M[MainActivity] --> D[DrawingView] D --> Stroke1[StrokeView] M --> FUndo[FAB:Undo] M --> FRedo[FAB:Redo] M --> FColor[FAB:Color] M --> FThick[FAB:Thickness] FColor --> Red[Red] FColor --> Green[Green] FColor --> Blue[Blue] FThick --> Thin[Thin] FThick --> Med[Med] FThick --> Thick[Thick] Vis[Visible] --> In[Invisible] In --> Hid[Hidden] classDef normal fill:#e6f3ff,stroke:#333,stroke-width:2px; classDef start fill:#d1e0e0,stroke:#333,stroke-width:4px; class M,D,Stroke1,FUndo,FColor,FThick,Vis start class Red,Green,Blue,Thin,Med,Thick,Hid normal

The sequence in the interface:

:img Empty drawing program window, 100% :img Drawing program window with one red stroke and undo button visible, 100%

You can play around with the interface to change color and thickness. Each new stroke you add adds another StrokeView to the interface.

Codebase Structure

This is a complete codebase for a drawing program. It is designed to be as modular as possible and includes support for Command Objects which encapsulate changes to the application model.

Actions

Actions are Command Objects, which encapsulate changes to the application model. An Action has a single (abstract) method, doAction(view) which, when called, applies the action to the view.

ReversibleAction extends Action to add undoAction(view) which, when called, reverses the action.

As with events, Actions are part of an inheritance hierarchy. ReversibleAction has three subclasses – ChangeThicknessAction, ChangeColorAction and StrokeAction. All of them modify properties of the DrawingView class (specifically the stroke width and current color of its Paint object, and the its child views (painted strokes are encapsulated in a StrokeView that is added to the DrawingView.

Requirement 0: Implement ChangeThicknessAction

In order to familiarize yourself with Actions and reversible logic, implement ChangeThicknessAction. This will be very similar to ChangeColorAction and should be very straight forward once you’ve read the action code. Because it’s so simple, this requirement is part of the code organization and style point. See turn-in for more details.

History (Requirement 1: Handle undo/redo)

Actions are the raw material that is used in the history. An AbstractHistory simply allows an action to be added and supports undo() and redo(). We subclass this with a stack-based history class called StackHistory that you will implement some methods for, to support undo and redo.

A StackHistory has a capacity (a max number of actions that it can store), a undoStack (the history) and a redoStack (actions that have been undone and can be re-applied). It also supports specific capabilities you must implement (see comments in the code for specifically what to do):

Undo/Redo behavior

Here is a scenario where the user draws a stroke in the default color/thickness (1), changes the color (2), changes the thickness (3), and draws another stroke (4) in the original thickness and color, with various undos and redos mixed in.

Action Undo Stack Redo Stack Interface state
drawstroke (1) 1   1
change color (2) 1,2   1,2
undo 1 2 1
redo 1, 2   1, 2
change thickness (3) 1, 2, 3   1, 2, 3
undo 1, 2 3 1, 2
undo 1 3, 2 1
drawstroke (4) 1, 4 CLEARED 1, 4
undo 1 4 1

Application Code (/app)

We’ve mentioned a DrawingView (which is the main canvas for the drawing application) and StrokeView (which encapsulates a specific stroke for the drawing application).

graph LR S((.)) --> A((Start)) A -- "Press:onDrawStart()" --> I((Drawing)) I -- "Release:onDrawEnd()" --> E[End] I -- "Cancel:onDrawCancel()" --> E[End] I -- "Move:onDrawMove()" --> I classDef finish outline-style:double,fill:#d1e0e0,stroke:#333,stroke-width:2px; classDef normal fill:#e6f3ff,stroke:#333,stroke-width:2px; classDef start fill:#d1e0e0,stroke:#333,stroke-width:4px; classDef invisible fill:#FFFFFF,stroke:#FFFFFF,color:#FFFFFF class S invisible class A start class E finish class I normal

Requirement 2: Adding a thickness 0 FAB to the thickness menu

The FABs in this assignment refer to Floating Action Buttons.

There are two main things you will need to do to add one.

First, you right place in thickness_menu.xml to modify. For example, this is the XML in that file for the thickest FAB Action Button:

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_thickness_30"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:layout_marginBottom="@dimen/fab_label_margin"
        android:alpha="0"
        android:clickable="false"
        android:contentDescription="@string/thick_desc"
        app:fabSize="mini"
        app:srcCompat="@drawable/ic_thickness_30" />

Next, you will need to update onThicknessSelected to respond when your FAB is pressed. It should change the stroke width to 0. Once you do that, everything should work!

Requirement 3: Improving the application

You can add any feature you want to the app (except another option in the thickness menu since you’ve already done that). When you do, make sure your change is accessible. We have some suggestions that will help guide you. Whatever you add, please describe your addition in the provided README.

Optional addition: Improving usability

Peer grading: Heuristic evaluation

This will take place in lab on Thursday May 23rd, 2019, and be due over the next 24 hours as with the previous peer grading exercise

The Task:

You will take notes on paper about issues you run into. When you have completed all the tasks, you will fill out a survey with the 3 most severe issues. This will include questions about:

You will also tell us if they customized a command and what it was. You will submit 3 things for each of 3 handins.

Turn-in

Submission Instructions

You will turn in the following files via GitGrade. It will accept:

Remember, edit the README to add a description of the new features/usability changes you made.

Follow these instructions to submit part 2 of your assignment

Grading (10pts)