Skip to content

Commit a872a6d

Browse files
committed
add the :direction option to the Dropdown component
1 parent 5510507 commit a872a6d

File tree

3 files changed

+53
-17
lines changed

3 files changed

+53
-17
lines changed

changelist.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
an inconsistency where sometimes the incoming point would be in local coordinate
1212
space and sometimes it would be global. If you want to capture that sort of input, either
1313
cover the space with a clear rect, or capture the input.
14+
* Add the `:direction` option to the `Dropdown` component so can can go either up or down.
1415

1516
### 0.7.0
1617
* First public release

lib/scenic/component/input/dropdown.ex

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,22 @@ defmodule Scenic.Component.Input.Dropdown do
1515

1616
@default_width 160
1717
@default_height 30
18+
@default_direction :down
1819

1920
@default_font :roboto
2021
@default_font_size 20
2122

2223
@drop_click_window_ms 400
2324

24-
@carat {{0, 0}, {12, 0}, {6, 6}}
25+
@caret {{0, 0}, {12, 0}, {6, 6}}
2526
@text_id :__dropbox_text__
26-
@carat_id :__carat__
27+
@caret_id :__caret__
2728
@dropbox_id :__dropbox__
2829
@button_id :__dropbox_btn__
2930

30-
@rad :math.pi() / 2
31+
@rotate_neutral :math.pi() / 2
32+
@rotate_down 0
33+
@rotate_up :math.pi()
3134

3235
# --------------------------------------------------------
3336
def info(data) do
@@ -83,6 +86,21 @@ defmodule Scenic.Component.Input.Dropdown do
8386
item_count = Enum.count(items)
8487
drop_height = item_count * height
8588

89+
# get the drop direction
90+
direction = styles[:direction] || @default_direction
91+
92+
# calculate the where to put the drop box. Depends on the direction
93+
translate_menu = case direction do
94+
:down -> {0, height + 1}
95+
:up -> {0, height * -item_count - 1}
96+
end
97+
98+
# get the direction to rotate the caret
99+
rotate_caret = case direction do
100+
:down -> @rotate_down
101+
:up -> -@rotate_up
102+
end
103+
86104
graph =
87105
Graph.build(font: font, font_size: font_size)
88106
|> rect({width, height}, fill: theme.background, stroke: {2, theme.border})
@@ -92,12 +110,12 @@ defmodule Scenic.Component.Input.Dropdown do
92110
text_align: :left,
93111
id: @text_id
94112
)
95-
|> triangle(@carat,
113+
|> triangle(@caret,
96114
fill: theme.text,
97115
translate: {width - 18, height * 0.5},
98116
pin: {6, 0},
99-
rotate: @rad,
100-
id: @carat_id
117+
rotate: @rotate_neutral,
118+
id: @caret_id
101119
)
102120

103121
# an invisible rect for hit-test purposes
@@ -132,7 +150,7 @@ defmodule Scenic.Component.Input.Dropdown do
132150

133151
g
134152
end,
135-
translate: {0, height + 1},
153+
translate: translate_menu,
136154
id: @dropbox_id,
137155
hidden: true
138156
)
@@ -145,7 +163,8 @@ defmodule Scenic.Component.Input.Dropdown do
145163
down: false,
146164
hover_id: nil,
147165
items: items,
148-
drop_time: 0
166+
drop_time: 0,
167+
rotate_caret: rotate_caret
149168
}
150169

151170
push_graph(graph)
@@ -170,15 +189,15 @@ defmodule Scenic.Component.Input.Dropdown do
170189
def handle_input(
171190
{:cursor_button, {:left, :press, _, _}},
172191
%{id: @button_id} = context,
173-
%{down: false, graph: graph} = state
192+
%{down: false, graph: graph, rotate_caret: rotate_caret } = state
174193
) do
175194
# capture input
176195
ViewPort.capture_input(context, [:cursor_button, :cursor_pos])
177196

178197
# drop the menu
179198
graph =
180199
graph
181-
|> Graph.modify(@carat_id, &update_opts(&1, rotate: 0))
200+
|> Graph.modify(@caret_id, &update_opts(&1, rotate: rotate_caret))
182201
|> Graph.modify(@dropbox_id, &update_opts(&1, hidden: false))
183202
|> push_graph()
184203

@@ -228,7 +247,12 @@ defmodule Scenic.Component.Input.Dropdown do
228247
def handle_input(
229248
{:cursor_button, {:left, :press, _, _}},
230249
%{id: nil} = context,
231-
%{down: true, items: items, theme: theme, selected_id: selected_id} = state
250+
%{
251+
down: true,
252+
items: items,
253+
theme: theme,
254+
selected_id: selected_id
255+
} = state
232256
) do
233257
# release the input capture
234258
ViewPort.release_input(context, [:cursor_button, :cursor_pos])
@@ -238,7 +262,7 @@ defmodule Scenic.Component.Input.Dropdown do
238262
# restore standard highliting
239263
|> update_highlighting(items, selected_id, nil, theme)
240264
# raise the dropdown
241-
|> Graph.modify(@carat_id, &update_opts(&1, rotate: @rad))
265+
|> Graph.modify(@caret_id, &update_opts(&1, rotate: @rotate_neutral))
242266
|> Graph.modify(@dropbox_id, &update_opts(&1, hidden: true))
243267
# push to the viewport
244268
|> push_graph()
@@ -268,7 +292,7 @@ defmodule Scenic.Component.Input.Dropdown do
268292
graph =
269293
graph
270294
|> update_highlighting(items, selected_id, nil, theme)
271-
|> Graph.modify(@carat_id, &update_opts(&1, rotate: @rad))
295+
|> Graph.modify(@caret_id, &update_opts(&1, rotate: @rotate_neutral))
272296
|> Graph.modify(@dropbox_id, &update_opts(&1, hidden: true))
273297
|> push_graph()
274298

@@ -284,7 +308,12 @@ defmodule Scenic.Component.Input.Dropdown do
284308
def handle_input(
285309
{:cursor_button, {:left, :release, _, _}},
286310
%{id: nil} = context,
287-
%{down: true, items: items, theme: theme, selected_id: selected_id} = state
311+
%{
312+
down: true,
313+
items: items,
314+
theme: theme,
315+
selected_id: selected_id
316+
} = state
288317
) do
289318
# release the input capture
290319
ViewPort.release_input(context, [:cursor_button, :cursor_pos])
@@ -294,7 +323,7 @@ defmodule Scenic.Component.Input.Dropdown do
294323
# restore standard highliting
295324
|> update_highlighting(items, selected_id, nil, theme)
296325
# raise the dropdown
297-
|> Graph.modify(@carat_id, &update_opts(&1, rotate: @rad))
326+
|> Graph.modify(@caret_id, &update_opts(&1, rotate: @rotate_neutral))
298327
|> Graph.modify(@dropbox_id, &update_opts(&1, hidden: true))
299328
# push to the viewport
300329
|> push_graph()
@@ -307,7 +336,12 @@ defmodule Scenic.Component.Input.Dropdown do
307336
def handle_input(
308337
{:cursor_button, {:left, :release, _, _}},
309338
%{id: item_id} = context,
310-
%{down: true, id: id, items: items, theme: theme} = state
339+
%{
340+
down: true,
341+
id: id,
342+
items: items,
343+
theme: theme
344+
} = state
311345
) do
312346
# release the input capture
313347
ViewPort.release_input(context, [:cursor_button, :cursor_pos])
@@ -325,7 +359,7 @@ defmodule Scenic.Component.Input.Dropdown do
325359
# restore standard highliting
326360
|> update_highlighting(items, item_id, nil, theme)
327361
# raise the dropdown
328-
|> Graph.modify(@carat_id, &update_opts(&1, rotate: @rad))
362+
|> Graph.modify(@caret_id, &update_opts(&1, rotate: @rotate_neutral))
329363
|> Graph.modify(@dropbox_id, &update_opts(&1, hidden: true))
330364
# push to the viewport
331365
|> push_graph()

lib/scenic/components.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ defmodule Scenic.Components do
293293
Buttons honor the following list of additional styles.
294294
* `:width` - pass in a number to set the width of the button.
295295
* `:height` - pass in a number to set the height of the button.
296+
* `:direction` - what direction should the menu drop. Can be either `:down` or `:up`. The default is `:down`.
296297
297298
## Theme
298299

0 commit comments

Comments
 (0)