name: inverse layout: true class: center, middle, inverse --- # The Whole Toolkit Part II ## Output Lauren Bricker CSE 340 Winter 23 --- layout:false [//]: # (Outline Slide) # Goals - Get input from the user (part 1) - **Produce output for the user** (part 2) - How to store application specific data (part 3) --- # The Whole Toolkit Architecture - Input - Input models (events) - Event dispatch - Event handling (state machine) - Callbacks to application - **Output** - Interactor Hierarchy design & use [more info](/courses/cse340/23wi/slides/wk01/drawing.html#9) - Drawing models (`onDraw()`) [more info](/courses/cse340/23wi/slides/wk02/layout.html#8) - Layout (`onLayout()` or `XML`) more info [here](/courses/cse340/23wi/slides/wk02/layout.html#25) and [here](/courses/cse340/23wi/slides/wk03/layout-algorithm.html#1) - Damage and redraw process [more info](/courses/cse340/23wi/slides/wk03/layout-algorithm.html#21) - Storage - Bundles - Shared Preferences --- # Interactor Hierarchy .left-column40[
graph TD A[0: Drawing Canvas] --> B(1: CircleA, Green) A --> C(2: LineB, Orange) B --> D(3: LineA, Black) C --> E(4: PointA, Blue) C --> F(5: PointB, Black)
![:img A picture of lines and circles, 70%, width](img/whole/lines-circles.png) ] --- .left-column-half[ # Core Toolkit Architecture `damage` is a bit kept on each view. If state changes, `damage` becomes true If there is `damage` do - *layout* (may change) - position - size - *redraw* ] .right-column40[
graph TD A[0: Drawing Canvas] --> B(1: CircleA, Green) A --> C(2: LineB, Orange) B --> D(3: LineA, Black) C --> E(4: PointA, Blue) C --> F(5: PointB, Black) classDef dirty fill:#ff9999,color:#ffffff; class A,B,D dirty
![:img A picture of lines and circles, 70%, width](img/whole/lines-circles.png) ] --- .left-column-half[ # Core Toolkit Architecture `damage` is a bit kept on each view. If state changes, `damage` becomes true If there is `damage` do - *layout* (may change) - position - size - *redraw* ] .right-column-half[ # Component Developer - May need to implement `onMeasure()` and `onLayout()` (if a container) - Will always implement `onDraw()` but *never call it* (call `invalidate()` instead) ] --- # View Update: .red[Damage/Redraw] How does the toolkit know what to redraw? What causes damage? ??? concrete example on next slide --- # View Update: .red[Damage/Redraw] What should be redrawn? ![:img google doc with scrollbar, 50%, width](img/whole/window.png) --- # View Update: .red[Damage/Redraw] What should be redrawn? ![:img google doc with scrollbar, 50%, width](img/whole/window-with-menu.png) --- # View Update: .red[Damage/Redraw] What should be redrawn? ![:img google doc with scrollbar, 50%, width](img/whole/combined.png) --- # View Update: .red[Damage/Redraw] How does the toolkit know what to redraw? What causes damage? -- - Window hidden and re-exposed - Resizing - Redrawing - Reacting to system or other events - others??? --- ## View Update: .red[Damage/Redraw] Naive approach to redraw ![:img pic of original screen and changed screen, 72%, width](img/whole/original-new.png) -- count: false - Can be slow (redrawing everything unecessary) - Can cause flickering - double buffering is better, - hence the 'Canvas' abstraction or equivalent - can then switch which FB is displayed (very fast) ??? TODO ADD pic like this using divs? --- ## View Update: .red[Damage/Redraw] Naive approach to redraw - redraw the entire screen ![:img pic of original screen and changed screen, 72%, width](img/whole/original-new.png) More efficient: calculate only the region necessary ![:img pic with double buffering included, 70%, width](img/whole/full-solution-buffering.png) --- ## View Update: .red[Damage/Redraw] Naive approach to redraw - redraw the entire screen ![:img pic of original screen and changed screen, 72%, width](img/whole/original-new.png) --- ## View Update: .red[Damage/Redraw] More efficient: calculate only the region necessary ![:img pic with double buffering included, 70%, width](img/whole/full-solution-buffering.png) **Never** just draw (more efficient this way) -- - Update *state* - Report *damage* (by calling `repaint()`) - Wait for *toolkit to request redraw* (also works if damage comes from elsewhere) --- ## View Update: .red[Damage/Redraw] How does the toolkit know what to redraw? - Let the component report: Damage/Redraw invoked by `invalidate()` or equivalent --- ## View Update: .red[Damage/Redraw] How does the toolkit know what to redraw? - Let the component report: (`invalidate()`) - **NOTE** we are *not* calling `onDraw()` directly - Aggregate - Usually calculate bounding box --- ## View Update: .red[Draw/Redraw] Virtual device abstractions provided by windowing system Component abstractions provided by toolkit - Enforced using clipping - Supported using coordinate system transformations Drawing is recursive - Makes it possible for parent to *decorate* kids - Parent responsible for making kids think they are the center of the universe (translate) - Clipping: intersect parent and child, also handled by parent ??? Allows each program to (mostly) pretend that it has the screen (frame buffer) to itself Allows each component to (mostly) pretend that it has the screen to itself --- # Core Toolkit Architecture If damage do - *layout* (may change) - position - size - do *redraw* - Union of damage (any of those can cause it) used to trigger redraw of anything inside that union - Drawing + clipping – standard drawing order, but only for things damaged; clipped to damage region - Clear damage --- # END OF DECK