Skip to content

Commit 75038b0

Browse files
authored
Merge pull request #74 from boydm/boyd
Lots of ViewPort testing, plus some bug fixes
2 parents 1a5eb55 + e260bcc commit 75038b0

File tree

9 files changed

+1399
-605
lines changed

9 files changed

+1399
-605
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 0.9.0
4+
* Much improved testing
5+
* Simplify rules around user-closing a viewport
6+
* Fix bug where captured positional inputs were not casting the transformed location
7+
38
## 0.8.0
49

510
* Many documentation improvements

lib/scenic/view_port.ex

Lines changed: 115 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ defmodule Scenic.ViewPort do
1111
alias Scenic.Primitive
1212
alias Scenic.ViewPort.Context
1313

14-
# import IEx
15-
1614
@moduledoc """
1715
1816
## Overview
@@ -101,7 +99,7 @@ defmodule Scenic.ViewPort do
10199
@doc """
102100
Start a new viewport
103101
"""
104-
@spec start(config :: ViewPort.Config.t()) :: {:ok, pid}
102+
@spec start(config :: map) :: {:ok, pid}
105103
def start(%ViewPort.Config{} = config) do
106104
# start the viewport's supervision tree
107105
{:ok, sup_pid} =
@@ -123,15 +121,8 @@ defmodule Scenic.ViewPort do
123121
{:ok, viewport_pid}
124122
end
125123

126-
# --------------------------------------------------------
127-
@doc """
128-
query the last recorded viewport status
129-
"""
130-
@spec info(viewport :: GenServer.server()) :: {:ok, ViewPort.Status.t()}
131-
def info(viewport)
132-
133-
def info(viewport) when is_atom(viewport) or is_pid(viewport) do
134-
GenServer.call(viewport, :query_info)
124+
def start(%{} = config) do
125+
start(struct(ViewPort.Config, config))
135126
end
136127

137128
# --------------------------------------------------------
@@ -146,7 +137,25 @@ defmodule Scenic.ViewPort do
146137
end
147138

148139
def stop(viewport) when is_pid(viewport) do
149-
DynamicSupervisor.terminate_child(@viewports, viewport)
140+
# dynamic viewports are actually supervised by their own supervisor.
141+
# so first we have to get that, which is what we actually stop
142+
[supervisor_pid | _] =
143+
viewport
144+
|> Process.info()
145+
|> get_in([:dictionary, :"$ancestors"])
146+
147+
DynamicSupervisor.terminate_child(@viewports, supervisor_pid)
148+
end
149+
150+
# --------------------------------------------------------
151+
@doc """
152+
query the last recorded viewport status
153+
"""
154+
@spec info(viewport :: GenServer.server()) :: {:ok, ViewPort.Status.t()}
155+
def info(viewport)
156+
157+
def info(viewport) when is_atom(viewport) or is_pid(viewport) do
158+
GenServer.call(viewport, :query_info)
150159
end
151160

152161
# --------------------------------------------------------
@@ -302,7 +311,7 @@ defmodule Scenic.ViewPort do
302311
# --------------------------------------------------------
303312
@doc false
304313
def init({vp_sup, config}) do
305-
GenServer.cast(self(), {:after_init, vp_sup, config})
314+
GenServer.cast(self(), {:delayed_init, vp_sup, config})
306315
{:ok, nil}
307316
end
308317

@@ -323,14 +332,15 @@ defmodule Scenic.ViewPort do
323332
_,
324333
%{
325334
supervisor: vp_supervisor,
326-
dynamic_supervisor: dyn_sup
335+
dynamic_supervisor: dyn_sup,
336+
size: size
327337
} = state
328338
) do
329339
{
330340
:reply,
331341
DynamicSupervisor.start_child(
332342
dyn_sup,
333-
{Scenic.ViewPort.Driver, {vp_supervisor, config}}
343+
{Scenic.ViewPort.Driver, {vp_supervisor, size, config}}
334344
),
335345
state
336346
}
@@ -363,7 +373,7 @@ defmodule Scenic.ViewPort do
363373
# ============================================================================
364374
# handle_cast
365375

366-
def handle_cast({:after_init, vp_supervisor, config}, _) do
376+
def handle_cast({:delayed_init, vp_supervisor, config}, _) do
367377
# find the viewport and associated pids this driver belongs to
368378
dyn_sup_pid =
369379
vp_supervisor
@@ -376,10 +386,15 @@ defmodule Scenic.ViewPort do
376386
# get the on_close flag or function
377387
on_close =
378388
case config.on_close do
379-
nil -> :stop_system
380-
:stop_system -> :stop_system
381-
:stop_viewport -> :stop_viewport
382-
func when is_function(func, 1) -> func
389+
nil ->
390+
:stop_system
391+
392+
:stop_system ->
393+
:stop_system
394+
395+
:stop_viewport ->
396+
:stop_viewport
397+
# func when is_function(func, 1) -> func
383398
end
384399

385400
# extract the viewport global styles. Do this by reusing tools in Primitive.
@@ -461,11 +476,11 @@ defmodule Scenic.ViewPort do
461476
|> Map.put(:input_captures, %{})
462477

463478
# fetch the dynamic supervisor
464-
dyn_sup =
465-
case dyn_sup do
466-
nil -> find_dyn_supervisor()
467-
dyn_sup -> dyn_sup
468-
end
479+
# dyn_sup =
480+
# case dyn_sup do
481+
# nil -> find_dyn_supervisor()
482+
# dyn_sup -> dyn_sup
483+
# end
469484

470485
# if the scene being set is dynamic, start it up
471486
{scene_pid, scene_ref, dynamic_scene} =
@@ -535,7 +550,7 @@ defmodule Scenic.ViewPort do
535550
{:noreply, %{state | root_scene_pid: scene_pid, dynamic_root_pid: scene_pid}}
536551
end
537552

538-
def handle_cast({:dyn_root_up, _}, state) do
553+
def handle_cast({:dyn_root_up, _, _}, state) do
539554
# ignore stale root_up messages
540555
{:noreply, state}
541556
end
@@ -548,18 +563,20 @@ defmodule Scenic.ViewPort do
548563
{:stop_driver, driver_pid},
549564
%{
550565
drivers: drivers,
551-
dynamic_supervisor: dyn_sup
566+
dynamic_supervisor: dyn_sup,
567+
driver_registry: registry
552568
} = state
553569
) do
554570
DynamicSupervisor.terminate_child(dyn_sup, driver_pid)
555571
drivers = Enum.reject(drivers, fn pid -> pid == driver_pid end)
556-
{:noreply, %{state | drivers: drivers}}
572+
registry = Map.delete(registry, driver_pid)
573+
{:noreply, %{state | drivers: drivers, driver_registry: registry}}
557574
end
558575

559576
# --------------------------------------------------------
560577
def handle_cast({:driver_cast, msg}, %{drivers: drivers} = state) do
561578
# relay the graph_key to all listening drivers
562-
do_driver_cast(drivers, msg)
579+
Enum.each(drivers, &GenServer.cast(&1, msg))
563580
{:noreply, state}
564581
end
565582

@@ -568,28 +585,26 @@ defmodule Scenic.ViewPort do
568585
{:driver_ready, driver_pid},
569586
%{
570587
drivers: drivers,
571-
# root_graph_key: root_key
572588
master_graph_key: master_graph_key
573589
} = state
574590
) do
575591
drivers = [driver_pid | drivers] |> Enum.uniq()
576-
# GenServer.cast(driver_pid, {:set_root, root_key})
577592
GenServer.cast(driver_pid, {:set_root, master_graph_key})
578593
{:noreply, %{state | drivers: drivers}}
579594
end
580595

581596
# --------------------------------------------------------
582-
def handle_cast(
583-
{:driver_stopped, driver_pid},
584-
%{
585-
drivers: drivers,
586-
driver_registry: registry
587-
} = state
588-
) do
589-
drivers = Enum.reject(drivers, fn d -> d == driver_pid end)
590-
registry = Map.delete(registry, driver_pid)
591-
{:noreply, %{state | drivers: drivers, driver_registry: registry}}
592-
end
597+
# def handle_cast(
598+
# {:driver_stopped, driver_pid},
599+
# %{
600+
# drivers: drivers,
601+
# driver_registry: registry
602+
# } = state
603+
# ) do
604+
# drivers = Enum.reject(drivers, fn d -> d == driver_pid end)
605+
# registry = Map.delete(registry, driver_pid)
606+
# {:noreply, %{state | drivers: drivers, driver_registry: registry}}
607+
# end
593608

594609
# --------------------------------------------------------
595610
# def handle_cast({:request_root, to_pid}, %{root_graph_key: root_key} = state) do
@@ -604,16 +619,17 @@ defmodule Scenic.ViewPort do
604619
end
605620

606621
# --------------------------------------------------------
607-
def handle_cast(:user_close, %{on_close: on_close} = state) do
622+
def handle_cast(:user_close, %{on_close: on_close, supervisor: vp_sup} = state) do
608623
case on_close do
609624
:stop_viewport ->
610-
case DynamicSupervisor.terminate_child(@viewports, self()) do
611-
:ok -> :ok
612-
{:error, :not_found} -> Process.exit(self(), :shutdown)
613-
end
625+
DynamicSupervisor.terminate_child(@viewports, vp_sup)
626+
627+
# :ok -> :ok
628+
# {:error, :not_found} -> Process.exit(vp_sup, :shutdown)
629+
# end
614630

615-
func when is_function(func, 1) ->
616-
func.(self())
631+
# func when is_function(func, 1) ->
632+
# func.(self())
617633

618634
:stop_system ->
619635
System.stop(0)
@@ -623,19 +639,19 @@ defmodule Scenic.ViewPort do
623639
end
624640

625641
# --------------------------------------------------------
626-
def handle_cast(:user_close, state) do
627-
case DynamicSupervisor.terminate_child(@viewports, self()) do
628-
:ok ->
629-
:ok
630-
631-
{:error, :not_found} ->
632-
# Process.exit(self(), :normal)
633-
# exit(:shutdown)
634-
System.stop(0)
635-
end
636-
637-
{:noreply, state}
638-
end
642+
# def handle_cast(:user_close, state) do
643+
# case DynamicSupervisor.terminate_child(@viewports, self()) do
644+
# :ok ->
645+
# :ok
646+
647+
# {:error, :not_found} ->
648+
# # Process.exit(self(), :normal)
649+
# # exit(:shutdown)
650+
# System.stop(0)
651+
# end
652+
653+
# {:noreply, state}
654+
# end
639655

640656
# ==================================================================
641657
# management casts from scenes
@@ -649,41 +665,41 @@ defmodule Scenic.ViewPort do
649665
# ============================================================================
650666
# internal utilities
651667

652-
defp do_driver_cast(driver_pids, msg) do
653-
Enum.each(driver_pids, &GenServer.cast(&1, msg))
654-
end
655-
656-
defp find_dyn_supervisor() do
657-
# get the scene supervisors
658-
[supervisor_pid | _] =
659-
self()
660-
|> Process.info()
661-
|> get_in([:dictionary, :"$ancestors"])
662-
663-
# make sure it is a pid and not a name
664-
supervisor_pid =
665-
case supervisor_pid do
666-
name when is_atom(name) -> Process.whereis(name)
667-
pid when is_pid(pid) -> pid
668-
end
668+
# defp do_driver_cast(driver_pids, msg) do
669+
# Enum.each(driver_pids, &GenServer.cast(&1, msg))
670+
# end
669671

670-
case Process.info(supervisor_pid) do
671-
nil ->
672-
nil
673-
674-
info ->
675-
case get_in(info, [:dictionary, :"$initial_call"]) do
676-
{:supervisor, Scenic.ViewPort.Supervisor, _} ->
677-
Supervisor.which_children(supervisor_pid)
678-
# credo:disable-for-next-line Credo.Check.Refactor.Nesting
679-
|> Enum.find_value(fn
680-
{DynamicSupervisor, pid, :supervisor, [DynamicSupervisor]} -> pid
681-
_other -> nil
682-
end)
683-
684-
_other ->
685-
nil
686-
end
687-
end
688-
end
672+
# defp find_dyn_supervisor() do
673+
# # get the scene supervisors
674+
# [supervisor_pid | _] =
675+
# self()
676+
# |> Process.info()
677+
# |> get_in([:dictionary, :"$ancestors"])
678+
679+
# # make sure it is a pid and not a name
680+
# supervisor_pid =
681+
# case supervisor_pid do
682+
# name when is_atom(name) -> Process.whereis(name)
683+
# pid when is_pid(pid) -> pid
684+
# end
685+
686+
# case Process.info(supervisor_pid) do
687+
# nil ->
688+
# nil
689+
690+
# info ->
691+
# case get_in(info, [:dictionary, :"$initial_call"]) do
692+
# {:supervisor, Scenic.ViewPort.Supervisor, _} ->
693+
# Supervisor.which_children(supervisor_pid)
694+
# # credo:disable-for-next-line Credo.Check.Refactor.Nesting
695+
# |> Enum.find_value(fn
696+
# {DynamicSupervisor, pid, :supervisor, [DynamicSupervisor]} -> pid
697+
# _other -> nil
698+
# end)
699+
700+
# _other ->
701+
# nil
702+
# end
703+
# end
704+
# end
689705
end

0 commit comments

Comments
 (0)