CS349

Final Study CS349

The exam tests content from the entire course. The midterm was roughly in the middle of the term, so expect significant content both from before and after the midterm to be tested.

  • No p5 syntax.

  • I could ask higher level questions about computer vision (e.g. general approaches of algorithms I showed, at pseudocode level).

  • I could ask about very general things about p5 (e.g. how it relates to things we talked about earlier in course, like drawing and events).

  • In lecture I specifically said I wouldn’t expect you to write a regex, and I also said this is exactly the kind of thing we should be using co-pilot/AI for.  You can see from past exams that I provide isValid functions for longer problems that need this kind of thing. You should know what regex is, and in general how it’s used.

1. Interactive System

  1. Define user interface
    • Formally. a user is a place where a person expresses intention to an artefact, and the artefact provides feedback to the user.
  2. What is a mental model?
    • How the users perceive, understand, and interact with a system based on their personal expectations and experiences.
  3. What is a user interface? What is interaction?
    • The interface is the external presentation to the user
      1. Controls
      2. Feedback
    • The interactions are the actions by the user and systems over time
  4. What are two advantages of a graphical user interface (GUI)?
    1. Emphasizes recognition over recall for available actions (easier to discover options and experiment)
    2. Uses metaphor and analogy to make the interface more intuitive (usage is closer to how things are done in real works e.g., “desktop” “folder”, “drag”, “icons”)
  5. What are two disadvantages of graphical user interface (GUI)?
    1. Consumes valuables screen space, forcing information off-screen
    2. Switching between keyboard and pointing device is time consuming
    3. Visual representations may not be clear
    4. Visually impaired users can’t see the graphics; no linear flow for screen readers; physically impaired may have difficulty with required movements
  6. What is the purpose of metaphor in a user interface? Give one example of how graphical user interfaces use metaphor.
    • It makes the UI more intuitive to use, because it models how things work in real life
      • e.g.: desktop, folder, etc.
    • In user interfaces, metaphors are employed to leverage users’ existing knowledge by associating digital actions with real-world objects and concepts, thereby making digital environments more intuitive to navigate and understand. Metaphors help bridge the gap between the digital and physical worlds, allowing users to apply familiar experiences to interact with digital interfaces effectively.One classic example of metaphor use in graphical user interfaces is the desktop metaphor used by computer operating systems like Windows and macOS. In this metaphor, the computer’s screen acts as a “desktop,” where documents can be “placed,” “folders” can be used to organize files, and a “trash can” or “recycling bin” is used to delete files. This metaphor helps users quickly grasp how to interact with the operating system by relating digital actions to real-world actions, such as filing papers in folders or throwing away unwanted documents, making the computing environment more accessible and easier to navigate.
  7. Explain the difference between a graphical user interface and a command-line interface in terms of recall and recognition.
    • GUI emphasizes recognition over recall
    • CLI emphasizes recall over recognition
  8. What input device is key to making a graphical user interface possible? Why?
    • Pointing devices are essential for GUIs as they enable the user to easily select, drag and drop items, navigate through menus, and perform other interactions that are visually represented.
    • The ability to point directly at objects on the screen aligns with the natural human tendency to interact with objects by touching or pointing at them, making the computer’s operations more accessible and understandable to a wider range of users. Without such input devices, the rich visual feedback and ease of use provided by GUIs would not be possible.
  9. What output device is key to making a graphical user interface possible? Why?
    • Display screen, such as a monitor or mobile device screen.
    • This device is crucial because a GUI is fundamentally about visual interaction, relying on graphical elements like windows, icons, and menus to convey information and view the system’s response to their actions.

2. Web Apps

  1. What is a web app?
    • A software application accessed through a browser
  2. How does the browser act like an operating system? Describe 3 aspects
    1. Handles input like an OS
    2. Provides UI toolkit (HTML, CSS)
    3. Provides “machine code” layer (i.e. JavaScrip compiler)
  3. Using MVC, define a Single Page Application (SPA).
    • a single page application is a web application that dynamically rewrites a current web page with new data from the web server
      • instead of the default method of a web browser loading entire new pages)
    • The browser handles the full MVC cycle:
      • Model: Manages data and business logic.
      • View: Displays the UI and updates dynamically based on the model.
      • Controller: Connects the model and view, handling user inputs and updating the UI.
    • This structure enables SPAs to offer dynamic, responsive user experiences without full page reloads, by separating concerns for maintainability and scalability.
    • data is loaded from the web server → data in the model is updated → the view is notified → the user sees the new information
  4. What is the Git staging area?
    • Intermediate area where commits are reviewed before completing to the commit.
  5. What is a source code repository?
    • Storage location for software source code, documentation, web pages, and other information related to software development. It serves as a central place for developers to manage, store, track and control any changes to the codebase.
  6. What does git clone do?
    • Makes a copy of a repo in your local machine in the current directory.
  7. Describe what npm is an explain two ways you used in your assignments.
    • npm (Node Package Manager) is a package manager for JS and the default manager for node runtime environment.
    • We used it for:
      • Installing packages, dependencies (libraries) for development npm install simplekit
      • Running project build scrips npm run dev
      • npm helps manage all packages within a project through package.json file, allowing you to specify project dependencies, scripts, and version requirements, ensuring consistency and easy of setup for other developers or environments.
  8. A Node project with one or more installed modules always has these files and directories: package.json, package-lock.json, and node_modules. Which of these (if any) should be committed to a source code repository?
    • package.json is metadata about the project and a list of dependencies
      • Add to repo
    • package-lock.json locks the various versions of all packages and their dependencies, ensuring that every install results in the same file structure in node_modules.
      • Add to repo
    • node_modules
      • Don’t add to repo
  9. What are the two main parts of a web browser like Google Chrome?
    • Rendering Engine: transform HTML documents and other resources of a web page into an interactive user interface.
    • Javascript Engine: execute JS code.
    • Chrome uses V8 JS Engine which has two parts:
      • Interpreter: reads JS code and execute it directly
      • Just-in-time (JIT): compile frequently executed code to machine code (for faster execution)
  10. In a web browser, is JavaScript code interpreted or compiled?
    • Both
      • Interpreter: reads JS code and execute it directly
      • Just-in-time (JIT): compile frequently executed code to machine code (for faster execution)
  11. Is a Vite project also a Node project? Explain why or why not.
    • Yes
    • Vite has its dependencies rooted in node.js
    • Uses node_modules and uses node to run its development server and build process.
  12. When you setup the project for your first two assignments, you executed npm install simplekit. Explain what files this command changed or added in your assignment directory.
    • Adds a node_modules directory where it installs the simplekit package dependencies
    • If the file did not have one previously, creates a package.json and package-lock.json file and adds “simplekit” to the dependencies section of the files.
      • Package lock assures a homogenous installation on all machines.
  13. What are two essential functions that Vite provided for your assignments?
    • Dev server and template types for certain types of projects (vanilla-ts in our case).

3. JavaScrip and TypeScript

  1. What does “truthy” mean in JavaScript? Give an example to illustrate.
    • A truthy value is a value that is considered true when evaluated in a boolean context
    • A falsy value is a value that is considered false when evaluated in a boolean context
    • Falsy values: false, 0, "", null, undefined, NaN
      • null is an intentional absence of a value, used to represent a missing value
      • undefined is when a variable has been declared but not assigned a value, or accessing an object property that doesn’t exist
      • NaN is an operation that doesn’t produce a meaningful result (e.g., 0/0)
    • All other values are truthy

Refer to TypeScript for some syntax.

  1. What is logged to the console?
let v = 0;
v = v || 123;
console.log(v);
  • 123, because 0 is falsy
let v = 0;
v = v ?? 123:
console.log(v);
  • 0, because nullish coalescing will only make undefined and null falsy.
    1. Rewrite the following as a minimal function expression.
function add(a, b) { return a + b; }

So we write it like:

let add = (a, b) => { a + b;}
  1. Explain the bug in the clamp function below.
// return x clamped to the range [min, max]
function clamp(x: number, min?: number, max?: number) {
	min = min || 0;
	max = max || 100;
	return Math.min(Math.max(min, x), max);
}
// tests
console.log(clamp(200)); // should log 100
console.log(clamp(10, 1, 5)); // should log 5
console.log(clamp(10, -100, 0)); // should log 0
  • If you try to set max to 0, max will be falsy, so max = max || 100 will set max to 100.
  1. Rewrite the function expression below as a standard function declaration.
const add = (a: number, b: number) => a + b;

So a standard function will look like this:

function add(a: number, b: number) {
	return a + b;
}
  1. Complete the functions to set and call the callback function stored in callback.
type Callback = () => void;
 
let callback: Callback | undefined;
 
function setCallback(newCallback: Callback) {
	callback = newCallback;
}
 
function callCallback() {
	if(callback){
		callback();
	}
}
  1. What is the value of a and b after this code is executed?
const [a, b] = [1, 2, 3, 4, 5];
  • a = 1, b = 2
  1. What is the value of a, b and c after this code is executed?
const [a, b, ...c] [1, 2, 3, 4, 5]
  • a = 1, b = 2, c = [3, 4, 5]
  1. What is the value of a and c after this code is executed?
const { c, a } = { "a":1, "b": 2, "c": 3 }
  • a = 1, c = 3
  1. Why should the any type be avoided in Typescript?
    • Because it turns off TypeScript type checking
  2. Give an example of a TypeScript union type definition (hint, remember the state property in SKButton).
let state: "idle" | "hover" | "click" = "idle";
  1. What is one risk of JavaScript dynamic weak type checking?
    • Unexpected behaviour, like adding a number and a string.
  2. How does TypeScript code “run” in the browser?
    • Gets transpiled into JS.
  3. Use type narrowing to fix this TypeScript function.
function formatId(id?: string): string | undefined {
	return id.toUpperCase();
}
function formatId(id?: string): string | undefined {
	if(typeof(id) === "string"){
		return id.toUpperCase();
	}
	else{
		return undefined;
	}
}
  1. Use type narrowing to fix this TypeScript function.
function draw() {
	const canvas = document.getElementById("canvas") as HTMLCanvasElement;
	const gc = canvas.getContext("2d");
	gc.fillRect(0, 0, 100, 100);
}
function draw() {
	const canvas = document.getElementById("canvas") as HTMLCanvasElement;
	if(canvas.getContext("2d")){
		const gc = canvas.getContext("2d");
		gc.fillRect(0, 0, 100, 100);
	}
}
  1. What is the TypeScript type for variable v?
let v;
v = 100;
v = "something";
  • Any
  1. Write TypeScript code to declare a constant widgets which is an empty array of SKElements.
const widgets: SKElement[] = [];
  1. Rewrite makeMessage1 as makeMessage2 which returns the message using a single string template literal.
function makeMessage1(todos: Todo[]) {
	if (todos.length <= 0) {
		return "no todos!";
	} else if (todos.length === 1) {
		return "1 todo";
	} else {
		return todos.length + " todos";
	}
}
 
function makeMessage2(todos: Todo[]) {
	const n = todos.length;
	return n <= 0 ? "no todos" : n == 1 ? "1 todo" : `${todos.length} todos`;
}

4. Drawing

  1. What is a windowing system?

    • An operating system layer to share screen space and user input among applications
  2. What are the three conceptual models for drawing primitives?

    • Pixel: Focuses on setting individual pixels or drawing at specific coordinates. Functions used include SetPixel(x, y, colour) for individual pixels and DrawImage(x, y, w, h,img) for images.
    • Stroke: Involves drawing lines and shapes defined by their outlines. Key functions include DrawLine(x1, y1, x2, y2) for lines and DrawRect(x, y, w, h) for rectangles.
    • Region: Drawing filled areas, including text and filled shapes. Functions like DrawText("A", x, y) and DrawRect(x, y, w, h) (with filling) are used.
  3. What is a graphics context? Why is it useful?

    • An object representing the state and settings for drawing on the canvas.
    • A Graphics Context is a common approach to manage the state of drawing style options. It allows a drawing command, like drawing a line, to be rendered using the currently selected style options, such as stroke colour and thickness. This management system is useful because it streamlines the process of applying consistent styling across multiple drawing commands without the need to specify the style for each command individually. For example, setting the stroke colour to red and the stroke thickness to 5 will apply these styles to all subsequent drawing commands until the styles are changed again. This method enhances efficiency and consistency in graphical applications​​.
  4. What is the painters algorithm?

    • Used to draw more complex shapes
    • We layer primitives, drawing back-to-front
  5. What is a display list? Does the order of the list matter?

    • The display list is an ordered list of Drawable objects
    • Every time draw() is called for a Drawable object, the display list is cleared, then the primitive shapes are added to the display list from back to front, and then drawn one by one.
    • The order matters
  6. How does the display list relate to the Painter Algorithm?

    • The way the display list is rendered follows the painter’s algorithm.
  7. In lecture, you saw a Drawable interface. Provide its definition below (don’t worry about exact types, just make it clear what the type is).

    • Define a reusable draw function for objects.
    • Defined as follows (Drawable interface)
export interface Drawable {
	draw: (gc: CanvasRenderingContext2D) => void;
}
 
 
export class Shape implements Drawable { 
	draw(gc: CanvasRenderingContext2D) { 
		// ... 
	} 
} 
 
const s = new Shape(); s.draw(gc);
  • This interface is used to define objects that can be drawn, specifying that any class implementing Drawable must provide a draw() method that takes an CanvasRenderingContext2D object as its parameter.
  1. What colour is the rendered rectangle? Explain why.
gc.fillStyle = "red";
gc.fillRect(10, 10, 50, 50);
gc.fillStyle = "blue";
  • The rectangle will be red, because the setting at the time we draw the rectangle is red.
  1. What do the graphics context methods save and restore do? Why would you use them?
    • The graphics context methods save and restore are used to manage the state of drawing styles efficiently. The save method pushes the current drawing state onto a stack, including styles such as strokeStyle, fillStyle, lineWidth, font, textAlign, and textBaseline. The restore method pops the last saved state from the stack and restores it. This mechanism allows for multiple save calls without corresponding restore calls immediately, enabling a flexible way to save and revert to previous drawing states without manually resetting each style property. This feature is particularly useful for temporarily changing drawing styles for specific elements without affecting the global drawing state, ensuring that changes do not interfere with other parts of the drawing process​​.

The windowing system enables applications to use a canvas abstraction in their window. What is a canvas abstraction and why is it useful?

A canvas abstraction is the concept of using an API to draw graphics on a canvas

What is the window manager?

  • A part of the window system
  • Allows users to interact with multiple windows
    • Moving, resizing, minimizing, maximizing windows
  • Canvas
    • A drawing area on a web page or in a graphical application where graphics are rendered and manipulated
      • This drawing area has its own coordinate
  • Graphics contextto-understand
    • An abstraction of the canvas
    • Represents the current state and settings of the canvas
    • Provides a set of API functions that enable the creation, manipulation, and display of graphics
  • Drawing in Simplekit
    • When we set the style, we’re setting the gc
    • When we call gc.fillRect(), we’re pushing the shape to the display list, with the settings currently saved in the gc.
setSKDrawCallback((gc) => {
  // fill
  gc.fillStyle = "red";
  gc.fillRect(10, 10, 50, 50); // (position, size)
 
  // stroke
  gc.strokeStyle = "blue";
  gc.lineWidth = 3;
  gc.strokeRect(80, 20, 50, 50);
 
  // draw path
  gc.strokeStyle = "green";
  gc.beginPath();
  gc.moveTo(10, 10); // start point
  gc.lineTo(60, 60); // end point
  gc.stroke(); // draw stroke
 
  // draw polygon
  gc.strokeStyle = "orange";
  gc.beginPath();
  gc.moveTo(100, 10); // start point
  gc.lineTo(150, 60); // intermediate point
  gc.lineTo(100, 60); // end point
  gc.closePath(); // connect start point and end point
  gc.stroke();
 
  // draw circle
  gc.strokeStyle = "purple";
  gc.beginPath();
  gc.arc(200, 30, 20, 0, Math.PI * 2); // (center, radius, start angle, end angle)
  gc.stroke();
 
  // connect a series of points
  const housePoints = [
    [40, 0],
    [80, 40],
    [80, 100],
    [0, 100],
    [0, 40]
  ]
 
  gc.strokeStyle = "black";
 
  gc.beginPath();
  housePoints.forEach((p) => {
    const [x, y] = p;
    gc.lineTo(x, y);
  });
 
  gc.closePath();
  gc.stroke();
 
  // text
  const x = 150;
  const y = 75;
 
  gc.font = "20px sans-serif";
  gc.fillStyle = "black";
  gc.fillText("Hello World", x, y);
 
  gc.fillStyle = "red";
  gc.textAlign = "center"; // shifts the x value from the left of the text to the middle
  gc.textBaseline = "middle"; // shifts the y value from the top of the text to the middle
  gc.fillText("Hello World", x, y);
 
  gc.save();
});

What do the GC functions save() and restore() do? Why is it important to use them?

  • Save pushes the current drawing state to stack
  • Restore pops the last saved drawing state from stack and restores it
  • We should always save the original state, draw our new shape, then restore the original state, to ensure our draw functions don’t tamper with the gc state.

5. Input Events

  1. Explain what an event is in the context of user interface architecture and programming.
    • An event is a message to notify an application that something happened

Event types:

  1. Are events only initiated by the user? Explain why they are, or provide a counter-example.
    • event is a message to notify an application that something happened
  2. What are the three fundamental mouse events?
    • Mousedown
    • Mouseup
    • Mousemove
  3. Describe the high level architecture used for events.
  • Low-Level Input: This includes the basic input from devices such as mice and keyboards. The OS polls these devices to get their current state, which includes data like X and Y relative movement, button states (up or down), and keyboard key states.
  • Event Creation: The OS transforms the low-level input into a more meaningful state. For example, it will track whether a keyboard key is “up” or “down” and the current position of the mouse on the display. When a state change occurs (e.g., a key press, mouse button click, or mouse movement), the OS generates an event.
  • Window Dispatch: The windowing system maintains a list of all windows ordered from back to front, with the frontmost window having focus. A hit test using the mousedown position determines which window should receive the event. Events are then sent to the focused window, usually to a UI Toolkit for further processing.
  • Event Queue: The event queue acts as a buffer between the user’s actions and each window’s event handling mechanism. This queuing allows for efficient handling of user input events, which can occur in bursts. The UI toolkit running in the window will handle events from this queue.
  • Toolkit Handling and UI Toolkit Run Loop: The application running within the window uses a UI Toolkit (such as a DOM rendering engine, JavaFX, Cocoa, etc.) to handle OS events. The UI Toolkit has its own run loop that constantly checks for fundamental events in the event queue, processes these events, and may also handle other tasks such as animation timers and UI re-renders.
  1. What does event translation mean? Give one example.

  • Converting low-level OS input events into higher-order events that are more meaningful for application development.

  • For example: the UI toolkit, such as a web browser or web framework, takes fundamental events from the OS, like mouse movements or keyboard presses, and translates them before dispatching to the application. This translation process may include combining multiple low-level events into a single higher-level event or interpreting a sequence of events as a specific action.

  • One example of event translation is the interpretation of a sequence of “mousedown” followed by “mouseup” events within a short time and without significant cursor movement as a “click” event. This process simplifies event handling for application developers by allowing them to listen for more abstract events (e.g., “click”) rather than having to manually interpret the low-level events (e.g., “mousedown” and “mouseup”)​​.

  1. What is event coalescing? Give an example of one type of event that a toolkit would coalesce.
    • Event coalescing refers to the process of consolidating multiple similar events into a single event to optimize performance and reduce the load on the event processing system. This technique is particularly useful for events that are generated at a high frequency, where processing every single event may not be necessary or efficient. For example, mousemove events can occur very rapidly as the mouse is moved across the screen. If each mousemove event were to be processed individually, it could lead to performance issues due to the high volume of events. By coalescing these events, the system can remove or combine intermediate events since the last update, effectively reducing the number of events that need to be processed. This allows for smoother and more efficient handling of user interactions without sacrificing the accuracy of the input.
    • An example of an event that a toolkit would coalesce is the mousemove event. As mentioned, mousemove events are generated at a high frequency (more than 60Hz), and the toolkit may not be able to consume them as quickly as they’re generated. Multiple mousemove events describing a continuous state can be coalesced by removing or combining intermediate events since the last update. This helps in avoiding performance issues while still providing a responsive user experience. However, it’s important to note that coalescing should be avoided if precise movement trajectory without interactive feedback is needed, such as in the case of saving a signature​​.
  2. Draw the state machine for a “click” event translator.

  1. Draw the state machine for an event translator to generate drag events.

6. Hit-Testing

  1. What is a shape model? Why is it useful?
    • The mathematical representation of the rendered shape
    • Includes:
      • Geometry (points, bounds, key dimensions)
      • Visual style properties (fill, stroke)
      • Transformations (translations, rotations)
      • Operations (event handling, hit testing)
    • Its useful because:
      • It encapsulates related information and functions
      • We can manipulate them dynamically
      • We can use multiple instances of the same shape

  1. What properties do you need to represent circle geometry in a shape model?
    • center, radius
  2. What fields would you use to represent rectangle geometry in a shape model?
    • top left corner (x,y)
    • width and height
  3. What is a hit-test? When would you use it?
    • A test to detect when a cursor is inside a shape or on its edge.
  4. What are two hit-test paradigms? When would you use them?
    • Inside hit-test
      • is mouse cursor inside the shape?
      • used for closed shapes
    • Edge hit-test
      • is mouse cursor on the shape stroke?
      • used for open shapes

  1. Describe the hit-testing algorithm whether a point (e.g. p or q in the figure below) is inside or outside the polygon S. No math is needed, you can explain it all in owrds.
  • In general, if we draw a y = 0 line and count how many times it intersects the line segments of a polygon
  • In general, if this count is odd, it’s inside the shape, if it’s even, it’s outside the shape
  • Special case: if the y = 0 line intersects with a point, it will intersect two segments
  1. Explain the algorithm for an rectangle inside hit-test. You can explain in math, pseudo code or words (but be specific in terms of dimensions and coordinates).
    • Given
      • mouse position (mx, my)
      • rectangle top left corner (x, y)
      • rectangle width and height (w, h)
return (mx >= x && mx <= x + w && my >= y && my < y + h)
  1. Describe the algorithm for a circle inside hit-test. You can explain in math, pseudo code or words (but be specific in terms of dimensions and coordinates).
    • Given
      • mouse position (mx, my)
      • circle center (x, y)
      • circle radius r
distance = distance from (mx, my) to (x, y)
 
if(distance < r) {
	return true;
}
  1. Describe the algorithm for an rectangle edge hit-test. You can explain in math, pseudo code or words (but be specific in terms of dimensions and coordinates).
    • Given:
      • mouse position (mx, my)
      • rectangle top left corner (x, y)
      • rectangle width and height (w, h)
      • stroke width s
    • Check that it’s inside the rectangle after adding the stroke, but not inside the inner rectangle after subtracting stroke
const outer = (mx >= x - s/2 && mx <= x + w + s/2 && my >= y - s/2 && my <= y + h + s/2)
const inner = (mx >= x + s/2 && mx <= x + w - s/2 && my >= y + s/2 && my <= y + h - s/2)
return outer && !inner

Note

  • mx is greater than or equal to x + s/2: Left boundary
  • mx is less than or equal to x + w - s/2: Right boundary
  • my is greater than or equal to y + s/2: Top boundary
  • my is less than or equal to y + h - s/2: Bottom boundary
  1. Describe the algorithm for a circle edge hit-test. You can explain in math, pseudo code or words (but be specific in terms of dimensions and coordinates).
    • Same as circle inside hit-test
  2. Given a circle at location cx, cy with radius r and stroke width s, write pseudo code for a hit test with the mouse position mx, my.
    • Given
      • mouse position (mx, my)
      • circle center (x, y)
      • circle radius s
      • stroke width s
distance = distance from (mx, my) to (x, y)

const outer = (distance < r + s/2)
const inner = (distance < r - s/2)

return outer && !inner
  1. Hit-testing a polyline with many edges can become resource intensive, what is an optimization you can make to a polyline hit-test function?
    • Use a simpler, less precise hit testing first for early rejects
    • Split into cells, and track which ones each shape is in (quadtree)

7. Animations

  1. What is the definition of animation?
    • The simulation of movement using a series of images
  2. What is the animation frame, frame rate, tweening, easing, key frame?
    • Frame: each image of an animation sequence
    • Frame rate: number of frames to display per second
    • Tweening: generating intermediate frames between two frames to achieve the illusion of motion
    • Lerping/easing: a function that controls how tweening is calculated
    • Key frame: the state of an image at a specific point; defines the beginning and end of a tween

  1. Explain why animation appears very smooth when the frame rate is about 60 FPS or more.
    • Some events are generated at high frequency and the toolkit may not be able to process the events at the rate they are produced. Multiple events can be coalesced into a single event to increase efficiency at the cost of reduced precision movemouse is often coalesced as the precise position of the mouse at every point in the travel is often not needed and updates to movemouse can come in hundreds of times a second
    • The smoothness is a result of a higher frame rate providing individual frames per second
  2. What is the definition of a timer in the context of user interface code?
    • Something that triggers an event after some time period
    • Interval Timer
    • Timeout Timer
  3. Why won’t the code below create an animation? How can it be fixed? Initally:
// draws a 50px red circle at x, y
function drawDot(gc: CanvasRenderingContext2D, x: number, y: number) { ... }
 
setSKDrawCallback((gc) => {
	for (let x = 0; x < gc.canvas.width; x++) {
		gc.clearRect(0, 0, gc.canvas.width, gc.canvas.height);
		drawDot(gc, x, gc.canvas.height /2);
	}
});
 
startSimpleKit();
 

Fix:

// draws a 50px red circle at x, y
function drawDot(gc: CanvasRenderingContext2D, x: number, y: number) { ... }
 
let x = 0;
 
setSKDrawCallback((gc) => {
	if (x < gc.canvas.width) {
		x++;
	}
	gc.clearRect(0, 0, gc.canvas.width, gc.canvas.height);
	drawDot(gc, x, gc.canvas.height / 2);
});
 
startSimpleKit();
  • The code provided initially is not creating an animation because it’s attempting to draw all frames of the animation in a single iteration of the draw loop. This means that for each iteration of the loop, the entire canvas is cleared and a new dot is drawn at a different position along the x-axis, but because this process is instantaneous, it appears as if only the final position is being displayed.
  • To fix this issue and create a smooth animation, we need to increment the position of the dot within each iteration of the draw loop. This incrementation allows the dot to gradually move across the canvas, giving the appearance of animation. The corrected code achieves this by incrementing the x coordinate within the draw loop and then redrawing the dot at the updated position.
  • Initialization of x outside the loop:
    • In the fixed code, x is initialized outside the draw loop. This ensures that x persists across iterations of the loop and can be updated to animate the dot’s movement.
  • Incrementation of x within the loop:
    • Inside the draw loop, x is incremented by one (x++) with each iteration, effectively moving the dot horizontally across the canvas.
  • Condition to check x against canvas width:
    • Before updating the dot’s position and redrawing it, the code checks if x is still within the bounds of the canvas width. This ensures that the animation stops once the dot reaches the edge of the canvas, preventing unnecessary iterations of the draw loop.
  • Clearing the canvas and redrawing the dot:
    • Within each iteration of the draw loop, the canvas is cleared (gc.clearRect(...)) to remove the previously drawn dot. Then, the drawDot function is called to draw the dot at the updated position (x) on the canvas.
  1. Why is it problematic to update widgets in the scene graph from a timer running in a dedicated thread? Explain how the problem relates to typical UI framework architecture.
    • Most UI frameworks are single-threaded, so all updates and interactions exist on a single thread. When you try to update UI components (widgets in the scene graph) from a separate thread (such as one running a timer), you risk encountering concurrency conflicts and race conditions. Thus updates that occur asynchronously must be synchronized with the UI updates.
  2. Complete the lerp function below:
  • start and end are the positions
  • returns the position an intermediate frame for a given time should be at
// Linear interpolation from start to end, using time factor t (t should be in [0, 1]) 
function lerp(start: number, end: number, t: number): number {
	return start + (end - start) * t;
}
  1. Complete the function to calculate the proportion of elapsed time in an animation.
// returns a value between 0 and 1 representing proportion of time elapsed
// @param start the start time
// @param end the end time
// @param time the current time
 
function elapsed(start: number, end: number, time: number) {
	return (time - start)/(end - start);
}
  1. What is the difference between animation by simulation and animation with keyframes?
    • animation with keyframes defines images at certain times, then generates intermediate frames to create the illusion of movement
    • animation by simulation uses physical or mathematical constraints

What is an animation manager?

  • Allows the programmer to not manage the animation themselves
  • Roles
    • Keeps a list of active animations
    • Updates each animation every frame
    • Removes animations when they finish

8. Widgets

  1. What is a user interface widget?
    • A widget is a generic name for parts of an interface that have their own behaviour
    • E.g.: buttons, drop downs, spinners, etc.
  2. Explain two things that a user interface widget does.
    • Display user feedback
    • Handle user input
  3. What is a widget logical input device? Give one example.
    • a logical input device is a category of widgets based on a common functionality, instead of appearance
    • e.g.: logical button device
      • sends “action happened” event
    • e.g.: logical number device
      • sends “value changed” event
  4. Explain what part of an MVC architecture the widget logical device represents in a widget?
    • Controller
    • Typically, the controller is responsible for interpreting user inputs, such as keyboard and mouse actions, and translating them into actions on the model or view.
  5. What is the difference between a container widget and a simple widget?
    • A container widget can contain other widgets, a simple widget can’t
  6. Draw the state diagram for a typical button widget
  7. Why does the SKButton class measure the width and height of the button text?
    • If the size of the button need to be adjusted dynamically, the size of the text in the button may also need to be adjusted dynamically
  8. In a hierarchical widget tree, what coordinate system do widgets use for drawing?
    • Widgets use a local coordinate system relative to their parent widget for drawing
  9. Explain what is meant by the focus state in the context of a textfield widget?
    • We clicked into the textfield

9. Dispatch

View hierarchy

  • widgets are organized into a tree
  • child order dictates draw order (left to right)

What is event dispatch?

  • When we route an event to the appropriate widget or code

What are the steps of event dispatch?

  • target selection
    • frontmost widget under the mouse
  • route construction
    • find the path from root to target widget
  • propagation
    • updating nodes on the path from root to target
    • first does capture
      • we walk top-down from root to target, calling event capture on each element
      • if we want to update something in the parents before we update the target node
      • we can interrupt this at some intermediate node
    • then does bubbling
      • we walk bottom-up from target to root, calling event bubbling on each element
      • if we want to update something in the parents after we update the target node

What is event binding? What are the ways we do event binding? What does simplekit use?

  • Associating events with specific code
  • Ways to implement:
    • switch statement binding (switch on the event type)
    • inheritance binding (event handling implementation is in the widget itself)
  • Simplekit uses inheritance binding
  1. What is a scene graph?
    • A data structure used to manage the hierarchical organization of graphical objects in a scene
  2. What is positional dispatch?
    • When the target is the node at the location of the cursor
  3. What is focus dispatch?
    • When the target is the node that currently has focus
  4. Which input device would not work at all without focus dispatch?
    • Focus dispatch is needed for all keyboard events
    • E.g.: click on text field, move cursor off, start typing
  5. Give an example where pure positional dispatch would fail. What is a solution?
    • A mouse tries to drag a scrollbar, then while still dragging, leaves the dimensions of the scroll box
    • Solution: when we leave the dimensions of the scroll box, we switch to focus dispatch, which keeps a reference to the thing being held down

  1. Name two approaches for event dispatch.
    • Positional dispatch
    • Focus dispatch
  2. What is an event listener?
    • A function that listens for and responds to events triggered by user interactions or other sources
    • When an event occurs, the listener is notified and then can execute the appropriate code to handle the event
  3. What is a global hook? Why would it be useful?
    • A mechanism that allows an application to handle and access events that occur outside its own window (system-wide events)
    • We can use it to:
      • Monitor fundamental events across all applications
      • Inject fundamental events to another application

Event Listeners

Global hook

// add keyboard event listener for shift key
setSKEventListener((event: SKEvent) => {
    if (event instanceof SKKeyboardEvent){
        if (event.type === "keydown" && event.key === "Shift") {
            // ...
        } 
        else if (event.type === "keyup" && event.key === "Shift") {
            // ...
        }
    }
 
    return false;
});

Event listener on a specific component

this.addStarButton.addEventListener("action", () => {
    // ...
});
 
handleMouseEvent(me: SKMouseEvent) {
    let clickedOutsideShapes: boolean = true;
 
    switch (me.type) {
        case "mousedown":
            // ...
		}
}

10. Layout

  1. What is layout?
    • The visual arrangement of widgets in a user interface.
  2. What is the strategy design pattern? Why is it useful for layout?
    • When we define a family of interchangeable layout algorithms (fillRow, fillColumn, etc.)
    • We can select a layout strategy, depending on the specific requirements of the container
    • This separates the algorithm from the client code, making it easier to switch between different layout strategies without modifying the client code
  3. What is the factory design pattern? Why is it useful for layout?
    • Allows us to create different types of layout objects based on their input parameters or configuration
  4. What is a fixed-size layout? What is one problem with this approach?
    • Allows elements to set their x, y, width, height
    • not responsive to screen sizes
  5. What is intrinsic size layout? Give a high-level example.
    • Attempts to use the widget preferred basis sizes, but checks all the widgets first and allocates space for them as a group
    • Gets all the desired sizes (basis) for the element, then decides how to allocate the space to elements, and their paddings and margins.
  6. Name and describe two other general layout strategies where the size of widgets are determined dynamically
    • Wrap and fill
  7. What is the difference between widget basis size and layout size?
    • Basis is the size of the actual content and object, without adding the margin and padding space. Layout adds the margin and padding space.
  8. Suppose you are designing a modal dialog box whose window size can’t be resized. You are tempted to use a fixed layout strategy for the dialog box. Describe a specific situation where the choice of a fixed layout would lead to undesirable results
    • If you resize the window, and the textbox was at the far right side of the screen, it could go ff screen and you wouldn’t be able to add text to the box.

11. MVC

What is MVC? What does the model look like?

  • The controller manages the interaction that modifies the data (clicks, keyboard, etc.)
  • The model manages the application data and its modification
  • The view manages the interface and presents the data

  1. State two benefits of using Model-View-Controller (MVC) architecture.
    • separates the data, state and logic from the UI
    • supports multiple views of the same data
  2. Normal MVC: why do models only communicate with the view through an interface?
    • the interface that model and view communicate through is notify() in observer pattern

  1. The Observer pattern has a subject and observers. How do these relate to MVC?

  • The subject would be the model, the item that changes occur to it.
  • Then once it does have a change, done by the controller, which would implement an observer, it would then go ahead and modify the other observers, so all the view and controllers based on this change so they all have up to date information.
  1. When implementing MVC, the View and Controller are often tightly coupled or even combined into a single class. Why is this the case?
    • Often, users view data and input data are in the same place.
    • They both deal directly with the user interface: the View handles the display, and the Controller manages user input.
    • Combining them simplifies event handling and reduces the complexity of updating the UI in response to user actions, making the development process more efficient and straightforward.
  2. When implementing MVC, you typically instantiate the model and view in the order below. Why this order? Why is the model passed as an argument to the view?
const m = new MyModel()
const v = new MyView(model)
  • when the View is created, it adds itself to the list of observers
  • the View has a reference to the subject it’s observing
  • This order ensures the View has access to the Model right from its creation, allowing it to display data or respond to changes in the Model immediately.
  • Passing the Model as an argument to the View establishes a direct link for data access and updates, making it possible for the View to reflect the current state of the Model without requiring additional mechanisms for data retrieval.
  1. What is Model-view-viewmodel?
    • the viewmodel mediates between the model and view
    • useful when you have view data/states that the logic doesn’t care about
    • useful when you have view data/states that the logic doesn’t care about

12. HTML/CSS

Tag, attribute, element

<input type="text" />
  • <input> is the tag
  • type="text" is the attribute
  • together, they make the element
  1. What is the purpose of HTML? What is the purpose of CSS?

    • html is document structure for our interfaces, defines inputs, views, objects
    • css is styling
  2. What is the Document Object Model (DOM)?

    • A cross-platform and language independent representation of the structure of a webpage, constructed as a tree of nodes
    • Each node represents a part of the document (an element, attribute, comment, etc.)
    • The thing that organizes the children displayed on the page, like a giant container, that manages events.
  3. What are the tree parts of a CSS rule?

    • selector
    • declaration block
    • properties
  4. What is a CSS selector?

    • A pattern to select elements in the DOM, so we can apply a styling to them.

  1. Give the CSS selector to select all buttons that are children of a div with id “left”.
div#left > button{
 
}
  1. Give the CSS selector to select all divs and buttons
div, button {
 
}
  1. Give the CSS selector to select all textfield widgets
input[type="text"] {
 
}
  1. In the context of CSS selectors, what is a pseudo class? Provide an example of a selector using a pseudo class.

    • selects elements based on their state (unvisited vs. visited link, hover over, etc.)
    • e.g.: hover, active, focus, etc.
  2. What is the CSS cascade? Describe two things that influence the CSS cascade?

    • The CSS cascade is the process by which browsers determine which styles should be applied to an element
    • Two things that influence:
      • specificity and ordering of source
      • !important
      • which file/location it was specified
  3. Getting references to DOM elements

    • Get element using unique element id
      • document.getElementbyID("my-id")
    • Get element using CSS selector syntax
      • querySelector("#my-id")
  4. Imperative

    • A programming paradigm where the focus on describing how to achieve a certain result, not what should be achieved
    • often by giving step by step instructions
      • createElement(), appendChild(), etc.

13. Visual Design

14. Text

15. Undo

  1. What is are two benefits of undo/redo?
    • undo
      • let’s you recover from errors
      • enables exploratory learning (trying new solutions without fear or commitment)
      • let’s you evaluate modifications

  1. What is undo/redo important for direct manipulation interaction?
    • Enables users to explore and try things without fear

  1. Given an example of an action that can’t be undone
    • not easily undone
      • quitting program with unsaved data
      • emptying trash
    • can’t be undone
      • printing
  2. What should an interface provide when performing an action that can’t be undone?
    • ask for confirmation
  3. Referring to MVC architecture, what kinds of actions should always be undoable? What actions are most likely not undoable?
    • changes to the model should always be undoable
    • changes to view is usually not undoable
      • e.g.: selection, scrollbar positioning
  4. Using the example of deleting a selected word in a text editor, then undoing that action, explain what is meant by state restoration after undo.
    • restore prior selection of objects restored by redo (restore the word)
    • scroll to show restored objects
    • give focus to the control where state was restored (word is still selected)
  5. In terms of undo granularity, what is a chunk?
    • a chunk is a conceptual change from one state to another
    • undoing reverses one chunk
  6. Make an argument for good and bad chunking when undoing a sequence of text immediately after it was typed.
    • good chunking: separated by white space
    • bad chunking: undo character by character
  7. Make an argument for good and bad chunking when undoing direct manipulation to drag an object from one location to another.
    • good chunking: go back to the last mousedown
    • bad chunking: pixel by pixel
  8. Make an argument for good and bad chunking when undoing handwritten pen input. Think about letters like lowercase “i” and “j”.
    • good chunking: undo the entire character
    • bad chunking: undo every stroke
  9. We talked about scope for undo, what is the most common level of scope for undo?
    • one for each window (as opposed to one for all windows)
  10. Explain the difference between forward and backward undo. A diagram may help.
    • forward undo
      • start from the base document
      • maintain a list of changes to compute the current document
      • undo by removing the last change from the list when computing the current document
      • In forward undo, the application starts from the base document (the initial state).
      • It maintains a list of changes or operations that have been applied to the document to reach the current state.
      • To undo an action, the application removes the last change from the list and recomputes the document from the base state using the remaining changes.
      • This approach requires storing a history of changes, which can consume memory, especially if the document is large or there are many changes.
    • reverse undo
      • compute the current state by applying the forward operation on the previous state
      • save the reverse operation on the undo stack
      • undo by doing the reverse operation
      • In backward undo, the application computes the current state by applying forward operations (e.g., adding text, modifying properties) on the previous state.
      • Each operation that modifies the document is saved as a reverse operation on the undo stack.
      • To undo an action, the application performs the reverse operation stored on the undo stack.
      • This approach doesn’t require storing a history of changes; instead, it only stores the reverse operations needed to revert the changes.

  1. What is one potential disadvantage of a forward undo implementation?
    • maintaining a list of changes / past states may become expensive
  2. What is one potential disadvantage of a reverse undo implementation?
    • May be more complicated to implement and manage
  3. Explain the difference between a memento and a command change record implementation. - memento pattern saves snapshots of each document state - command pattern saves the command and reverse command
  4. Describe how the memento and command design patterns can each (separately) be used to implement undo.
    • memento
      • undo: move the top memento to redo stack, then set the model state to be the new top of undo stack
    • command
      • for each change to model, save the command and reverse command
  5. You need to implement reverse undo with a command pattern to existing properties in an MVC Model. You are not allowed to use any special caching. Do you need to add code to “get”, “set”, or both “get” and “set”? Explain.
    • set (execute reverse operation)
  6. You need to implement forward undo with a command pattern to existing properties in an MVC Model. You are not allowed to use any special caching. Do you need to add code to “get”, “set”, or both “get” and “set”? Explain.
    • get (compute state)
    • set (apply new state)
  7. Consider the asymptotic time (“big Oh”) of executing an undo action after the user has performed N user interface actions. What is it for forward undo? What is it for reverse undo? Assume there is no special caching.
    • forward:
    • reverse:
  8. What is the command to “un-execute” a command that inserts a line of text at the end of a document?
    • delete the line
  9. What happens to the undo and redo stacks after the user executes an interface command like delete?
    • add the reverse command of restoring what we deleted to the undo stack

16. Asynchronous

  1. Name two general ways that a user interface can be “responsive”.
    • designing to meet human expectations and perceptions
    • loading data efficiently so it’s available quickly
  2. What are two general ways that you can make user interface feedback responsive?
    • not making the user wait any longer than necessary
    • communicating the state of long tasks to the user

  1. Explain why responsiveness is not necessarily the same as system performance.
    • responsiveness is how quickly a system reacts to the user interactions or requests
    • system performance is how quickly a system can execute tasks
    • a system can have slow performance (takes a long time to actually complete the task), but the responsiveness (let the user know their input was received, let them know how long the operation will take, etc.)
  2. Give one user interface design implication based on human perception of time.
    • minimal time to be affected by a visual stimulus
      • continuous input latency should be less than 10ms
    • maximum interval between cause-effect events
      • If UI feedback takes longer than 140 ms to appear, the perception of cause and effect is broken
    • visual-motor reaction time to an observed event

  1. Use a specific example to explain how to increase responsiveness by progressive loading.
    • We can provide the user with some data while loading the rest of the data
    • e.g.: search function displays some items as soon as it finds them

  1. Use a specific example to explain how to increase responsiveness by predicting the next operation.
    • we can use periods of low load to pre-compute response to high probability next requests
    • e.g.: text search function look for the next occurrence of the target word while the user looks at the current occurrence
  2. Use a specific example to explain how to increase responsiveness by graceful degradation of feedback.
    • offer simplified / partial feedback for high computation tasks
    • we still offer some responsiveness, but try not to compromise usabiliity
    • e.g.: window manager, when a user drags a window, the system may update the window’s position rendering at a lower frequency to reduce the computational load
  3. What is one user interface goal when handling long processing tasks?
    • keep UI responsive
    • provide progress feedback
    • allow the long task to be paused or cancelled

Example:

function greet(name, sayGoodbye) {
  console.log("Hello, " + name + "!");
  sayGoodbye();
}
 
function sayGoodbye() {
  console.log("Goodbye!");
}
 
greet("John", sayGoodbye);
 
/* output:
Hello, John!
Goodbye!
*/
  • can lead to “callback hell”, which is many nested callbacks that make the code hard to read

  1. Consider the code below. What is a reasonable maximum processing time for doTask() so that users will still perceive the interface as responsive? Why?
    • button.addListener("click", () => doTask);
    • 140 ms
    • max interval between cause effect events
  2. Consider the code below. If doTask takes 5 seconds to process, what can you do to keep your interface responsive? No code is needed, just a description.
    • button.addListener("click", () => doTask());
    • add a loading spinner

  1. One strategy to handle long tasks is to break the task into smaller subtasks and run periodically execute those subtasks between handling UI events. What is the approximate upper bound for subtask execution time? What are disadvantages with this approach?
    • upper bound for subtask execution time: 30s
    • disadvantages:
      • user will keep getting interrupted
  2. One strategy to handle long tasks is to run the task in a separate “worker” thread. What should the worker thread always communicate to the UI thread? What data or events would the UI thread want to communicate to the worker thread?
    • A worker thread is a separate thread of execution that can run concurrently with other threads in a program
    • The worker thread should communicate the progress of the subtask it’s handling
  3. In some UI Toolkits like JavaFX, worker threads need to be careful about directly accessing UI widgets. Why is this the case? How is this handled?
    • Worker threads are concurrent
    • The UI threads is not designed to handle concurrency
    • Multiple threads accessing/editing the user thread can lead to data corruption
  4. Consider this code fragment for a button controller:
startButton.addListener("click", () => {
	while (network.isBusy()) {
		sleep(50); // stops all execution for 50 milliseconds
	}
	doTask();
}
  1. If network.isBusy() takes about 100ms to return and it almost always returns true at least 10 times before returning false, what will happen to the user interface when startButton is clicked?
    • 1500 ms
  2. Describe three kinds of messages that should be sent between a web worker and the main user interface program. Indicate whether the message is sent from main to thread, or thread to main.
    • main to thread: start
    • thread to main: progress
    • thread to main: done

17. Declarative , 18 Reactive