Skip to content

Commit f7340d0

Browse files
authored
Merge pull request #141 from boydm/update_callbacks
Update callbacks
2 parents bb74090 + 8ad5fe7 commit f7340d0

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
* FontMetrics can be used to measure strings, trim to fit, and more
1818
* Dynamic Textures in the form of raw pixel maps are now supported. This should allow you to capture raw images off of a camera and display them without encoding/decoding
1919
* leading spaces in a text primitive are now rendered
20+
* Scene callbacks are all updated to support the OTP 21+ callback returns.
21+
* Scenes now have the terminate callback.
22+
* push_graph is deprecated in favor of returning {:push, graph} options form the callbacks
2023

2124
## 0.9.0
2225
* Much improved testing

guides/upgrading_to_v0.10.md

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
Version 0.10 of Scenic contains breaking changes, which will need to be updated in your app in order to run. This is all good through as it enables goodness in the forms of proper font metrics and dynamic raw pixel textures.
44

5+
## Overview
6+
7+
Version v0.10 contains two fairly major changes in how things work.
8+
9+
* `Scenic.Cache` has been reorganized into asset-specific caches. **This is a breaking change.**
10+
* `push_graph` is deprecated and replaced with a more functional-style return value. This is not a breaking change, but it throws warnings as going forward, the new return values are the way to go.
11+
12+
The changes to the cache are described first as they are breaking changes. The non-breaking push_graph deprecation will probably be more work to integrate, but you don't need to do it as immedately.
13+
514
## Changes to the Cache
615

716
The most important (and immediate) change you need to deal with is to the cache. In order to handle static items with different life-cycle requirements, the cache has been broken out into multiple smaller caches, each for a specific type of content.
@@ -21,11 +30,100 @@ Note that caches are marked as either static or dynamic. Things that do not chan
2130

2231
The Dynamic.Texture cache is for images that change over time. For example, this could be an image coming off of a camera, or something that you generate directly in your own code. Note that Dynamic caches are more expensive overall as they will not get the same level of optimization in the future.
2332

24-
## Custom Fonts
33+
### Custom Fonts
2534

2635
If you have used custom fonts in your application, you need to use a new process to get them to load and render.
2736

2837
1. use the `truetype_metrics` tool in hex to generate a `\*.metrics` file for your custom font. This will live in the same folder as your font.
2938
2. Make sure the name of the font file itself ends with the hash of its content. If you use the `-d` option in `truetype_metrics`, then that will be done for you.
3039
3. Load the font metrics file into the `Scenic.Cache.Static.FontMetrics` cache. The hash of this file is the hash that you will use to refer to the font in the graphs.
31-
4. Load the font itself into the `Scenic.Cache.Static.Font`
40+
4. Load the font itself into the `Scenic.Cache.Static.Font`
41+
42+
## Deprecation of push_graph()
43+
44+
The `push-graph/1` function is now deprecated. It still works, but has been replaced with a much more functional-style `{:push, graph}` return value.
45+
46+
This has several immediate benefits. The main advantage is that you can now use all the standard OTP 21+ callbacks, including handle_continue, timeouts and the like. If you call push_graph(), it sends a message back to the scene, so the timeouts will not work. The new form corrects this situation.
47+
48+
It also lowers the overall draw latency a little bit. There is one less passed-message for rendering to serialize on.
49+
50+
### Changes to make
51+
52+
Making the switch is fairly straight forward. A typical scene pattern with push_graph would look like this
53+
54+
```elixir
55+
defmodule MyApp.Scene.Example do
56+
use Scenic.Scene
57+
alias Scenic.Graph
58+
import Scenic.Primitives
59+
import Scenic.Components
60+
61+
@graph Graph.build()
62+
|> text("Hello World", id: :my_text, font_size: 22, translate: {20, 80})
63+
|> button({"Do Something", :my_btn}, translate: {20, 180})
64+
65+
def init( _scene_args, _options ) do
66+
push_graph( @graph )
67+
{:ok, {:could_be_any_state, @graph}}
68+
end
69+
70+
def handle_event({:click, :my_btn}, _, {inner_state,graph}) do
71+
graph = Graph.modify(graph, :my_text, &text(&1, "Hello Scene"))
72+
|> push_graph()
73+
{:noreply, {inner_state,graph}}
74+
end
75+
end
76+
77+
```
78+
79+
This same scene would now look like this
80+
81+
```elixir
82+
defmodule MyApp.Scene.Example do
83+
use Scenic.Scene
84+
alias Scenic.Graph
85+
import Scenic.Primitives
86+
import Scenic.Components
87+
88+
@graph Graph.build()
89+
|> text("Hello World", id: :my_text, font_size: 22, translate: {20, 80})
90+
|> button({"Do Something", :my_btn}, translate: {20, 180})
91+
92+
def init( _scene_args, _options ) do
93+
{:ok, {:could_be_any_state, @graph}, push: @graph}
94+
end
95+
96+
def handle_event({:click, :my_btn}, _, {inner_state,graph}) do
97+
graph = Graph.modify(graph, :my_text, &text(&1, "Hello Scene"))
98+
{:noreply, {inner_state,graph}, push: graph}
99+
end
100+
end
101+
```
102+
103+
This may not look like a very big change, but the impact is significant, and simpler under the covers.
104+
105+
The key is that you indicate that you want to push a graph by returning a `{:push, graph}` option when you exit any scene handler function. This optional value can be combined with `timeout` or `{:continue, term}` options as well (although not both at the same time...)
106+
107+
```elixir
108+
defmodule MyApp.Scene.Example do
109+
use Scenic.Scene
110+
alias Scenic.Graph
111+
import Scenic.Primitives
112+
import Scenic.Components
113+
114+
@graph Graph.build()
115+
|> text("Hello World", id: :my_text, font_size: 22, translate: {20, 80})
116+
|> button({"Do Something", :my_btn}, translate: {20, 180})
117+
118+
def init( _scene_args, _options ) do
119+
{:ok, {:could_be_any_state, @graph}, push: @graph, continue: :some_term}
120+
end
121+
122+
def handle_event({:click, :my_btn}, _, {inner_state,graph}) do
123+
graph = Graph.modify(graph, :my_text, &text(&1, "Hello Scene"))
124+
{:noreply, {inner_state,graph}, push: graph, timeout: 1000}
125+
end
126+
end
127+
```
128+
129+
The [callbacks section of the scene documentation](Scenic.Scene.html#callbacks) is now properly filled out, so please refer to that for more information on each of the available return values.

guides/welcome.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ and more.
88
Scenic is primarily aimed at fixed screen connected devices (IoT), but can also
99
be used to build portable applications.
1010

11+
## Upgrading to v0.10
12+
13+
If you have used versions before v0.10, please see the [Upgrading to v0.10 Guide](upgrading_to_v0-10.html).
14+
1115
## How to get started?
1216

1317
If you are new to Scenic, then you should read the following guides.

0 commit comments

Comments
 (0)