Skip to content

Commit

Permalink
add UIState to track hot/active widgets (#22)
Browse files Browse the repository at this point in the history
* pass null_widget as an argument

* create widget_id.jl

* rename ui_state.jl to utils.jl

* add widget!! to have single interface for all widgets (with or without side effects)

* add UIState to tracker user's interaction

* use UIState in example.jl

* rename widget_id.jl to ui_state.jl

* move UIState out of SimpleWidgets
  • Loading branch information
Sid-Bhatia-0 authored Apr 30, 2022
1 parent 4295abb commit 3aaf25b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 59 deletions.
21 changes: 13 additions & 8 deletions examples/example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import SimpleWidgets as SW

include("opengl_utils.jl")

mutable struct UIState <: SW.AbstractUIState
hot_widget::SW.WidgetID
active_widget::SW.WidgetID
null_widget::SW.WidgetID
end

function update_button(button, action)
if action == GLFW.PRESS
return SW.press_button(button)
Expand Down Expand Up @@ -50,8 +56,7 @@ function start()
drawing_time_buffer = DS.CircularBuffer{typeof(time_ns())}(sliding_window_size)
push!(drawing_time_buffer, zero(UInt))

hot_widget = SW.NULL_WIDGET_ID
active_widget = SW.NULL_WIDGET_ID
ui_state = UIState(SW.NULL_WIDGET_ID, SW.NULL_WIDGET_ID, SW.NULL_WIDGET_ID)
slider_value = 1
text_line = collect("Text box")

Expand Down Expand Up @@ -140,7 +145,7 @@ function start()

button1_shape = SD.Rectangle(SD.Point(577, 1), 32, 200)
button1_id = SW.WidgetID(@__LINE__, @__FILE__)
hot_widget, active_widget, button1_value = SW.widget(hot_widget, active_widget, button1_id, SW.BUTTON, SD.get_i_min(button1_shape), SD.get_j_min(button1_shape), SD.get_i_max(button1_shape), SD.get_j_max(button1_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count)
button1_value = SW.widget!(ui_state, button1_id, SW.BUTTON, SD.get_i_min(button1_shape), SD.get_j_min(button1_shape), SD.get_i_max(button1_shape), SD.get_j_max(button1_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count)
if button1_value
text_color = 0x00aa0000
end
Expand All @@ -149,7 +154,7 @@ function start()

button2_shape = SD.Rectangle(SD.Point(609, 1), 32, 200)
button2_id = SW.WidgetID(@__LINE__, @__FILE__)
hot_widget, active_widget, button2_value = SW.widget(hot_widget, active_widget, button2_id, SW.BUTTON, SD.get_i_min(button2_shape), SD.get_j_min(button2_shape), SD.get_i_max(button2_shape), SD.get_j_max(button2_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count)
button2_value = SW.widget!(ui_state, button2_id, SW.BUTTON, SD.get_i_min(button2_shape), SD.get_j_min(button2_shape), SD.get_i_max(button2_shape), SD.get_j_max(button2_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count)
if button2_value
text_color = 0x00000000
end
Expand All @@ -158,15 +163,15 @@ function start()

slider_shape = SD.Rectangle(SD.Point(641, 1), 32, 200)
slider_id = SW.WidgetID(@__LINE__, @__FILE__)
hot_widget, active_widget, slider_value = SW.widget(hot_widget, active_widget, slider_id, SW.SLIDER, SD.get_i_min(slider_shape), SD.get_j_min(slider_shape), SD.get_i_max(slider_shape), SD.get_j_max(slider_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count, slider_value)
slider_value = SW.widget!(ui_state, slider_id, SW.SLIDER, SD.get_i_min(slider_shape), SD.get_j_min(slider_shape), SD.get_i_max(slider_shape), SD.get_j_max(slider_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count, slider_value)
SD.draw!(image, slider_shape, text_color)
slider_value_shape = SD.FilledRectangle(SD.Point(641, 1), 32, slider_value)
SD.draw!(image, slider_value_shape, text_color)
SD.draw!(image, SD.TextLine(SD.Point(641, 1), "Slider", SD.TERMINUS_32_16), 0x00ffffff)

text_input_shape = SD.Rectangle(SD.Point(673, 1), 32, 200)
text_input_id = SW.WidgetID(@__LINE__, @__FILE__)
hot_widget, active_widget = SW.widget!(hot_widget, active_widget, text_input_id, SW.TEXT_INPUT, SD.get_i_min(text_input_shape), SD.get_j_min(text_input_shape), SD.get_i_max(text_input_shape), SD.get_j_max(text_input_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count, text_line, characters)
SW.widget!(ui_state, text_input_id, SW.TEXT_INPUT, SD.get_i_min(text_input_shape), SD.get_j_min(text_input_shape), SD.get_i_max(text_input_shape), SD.get_j_max(text_input_shape), cursor.i, cursor.j, mouse_left.ended_down, mouse_left.half_transition_count, text_line, characters)
SD.draw!(image, text_input_shape, text_color)
text_input_value_shape = SD.TextLine(SD.Point(673, 1), String(text_line), SD.TERMINUS_32_16)
SD.draw!(image, text_input_value_shape, text_color)
Expand All @@ -188,8 +193,8 @@ function start()
push!(lines, "button2_value: $(button2_value)")
push!(lines, "text_color: $(repr(text_color))")
push!(lines, "slider_value: $(slider_value)")
push!(lines, "hot_widget: $(hot_widget)")
push!(lines, "active_widget: $(active_widget)")
push!(lines, "ui_state.hot_widget: $(ui_state.hot_widget)")
push!(lines, "ui_state.active_widget: $(ui_state.active_widget)")

draw_lines!(image, lines, text_color)

Expand Down
3 changes: 2 additions & 1 deletion src/SimpleWidgets.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module SimpleWidgets

include("input.jl")
include("ui_state.jl")
include("utils.jl")
include("widgets.jl")
include("ui_state.jl")

end
43 changes: 11 additions & 32 deletions src/ui_state.jl
Original file line number Diff line number Diff line change
@@ -1,41 +1,20 @@
struct WidgetID
abstract type AbstractWidgetID end

struct WidgetID <: AbstractWidgetID
line_number::Int
file_name::String
end

const NULL_WIDGET_ID = WidgetID(0, "")

went_down(ended_down, half_transition_count) = (half_transition_count >= 2) || ((half_transition_count == 1) && ended_down)
went_up(ended_down, half_transition_count) = (half_transition_count >= 2) || ((half_transition_count == 1) && !ended_down)
abstract type AbstractUIState end

function try_set_hot_widget(hot_widget, active_widget, widget, condition)
if (active_widget == NULL_WIDGET_ID) && condition
return widget
else
return hot_widget
end
end
const NULL_WIDGET_ID = WidgetID(0, "")

function try_set_active_widget(hot_widget, active_widget, widget, condition)
if (hot_widget == widget) && (active_widget == NULL_WIDGET_ID) && condition
return widget
else
return active_widget
end
end
function widget!(ui_state::AbstractUIState, args...; kwargs...)
hot_widget, active_widget, null_widget, values = widget!!(ui_state.hot_widget, ui_state.active_widget, ui_state.null_widget, args...; kwargs...)

function try_reset_hot_widget(hot_widget, active_widget, widget, condition)
if (hot_widget == widget) && (active_widget != widget) && condition
return NULL_WIDGET_ID
else
return hot_widget
end
end
ui_state.hot_widget = hot_widget
ui_state.active_widget = active_widget
ui_state.null_widget = null_widget

function try_reset_active_widget(hot_widget, active_widget, widget, condition)
if (active_widget == widget) && (hot_widget == widget) && condition
return NULL_WIDGET_ID
else
return active_widget
end
return values
end
34 changes: 34 additions & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
went_down(ended_down, half_transition_count) = (half_transition_count >= 2) || ((half_transition_count == 1) && ended_down)
went_up(ended_down, half_transition_count) = (half_transition_count >= 2) || ((half_transition_count == 1) && !ended_down)

function try_set_hot_widget(hot_widget, active_widget, null_widget, widget, condition)
if (active_widget == null_widget) && condition
return widget
else
return hot_widget
end
end

function try_set_active_widget(hot_widget, active_widget, null_widget, widget, condition)
if (hot_widget == widget) && (active_widget == null_widget) && condition
return widget
else
return active_widget
end
end

function try_reset_hot_widget(hot_widget, active_widget, null_widget, widget, condition)
if (hot_widget == widget) && (active_widget != widget) && condition
return null_widget
else
return hot_widget
end
end

function try_reset_active_widget(hot_widget, active_widget, null_widget, widget, condition)
if (active_widget == widget) && (hot_widget == widget) && condition
return null_widget
else
return active_widget
end
end
42 changes: 24 additions & 18 deletions src/widgets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,26 @@ function get_widget_value(hot_widget, active_widget, widget, ::Button, condition
end
end

function widget(hot_widget, active_widget, widget, widget_type::Button, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count)
function widget(hot_widget, active_widget, null_widget, widget, widget_type::Button, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count)
mouse_over_button = (i_min <= i_mouse <= i_max) && (j_min <= j_mouse <= j_max)
mouse_went_down = went_down(ended_down, half_transition_count)
mouse_went_up = went_up(ended_down, half_transition_count)

hot_widget = try_set_hot_widget(hot_widget, active_widget, widget, mouse_over_button)
hot_widget = try_set_hot_widget(hot_widget, active_widget, null_widget, widget, mouse_over_button)

active_widget = try_set_active_widget(hot_widget, active_widget, widget, mouse_over_button && mouse_went_down)
active_widget = try_set_active_widget(hot_widget, active_widget, null_widget, widget, mouse_over_button && mouse_went_down)

value = get_widget_value(hot_widget, active_widget, widget, widget_type, mouse_over_button && mouse_went_up)

active_widget = try_reset_active_widget(hot_widget, active_widget, widget, mouse_went_up)
active_widget = try_reset_active_widget(hot_widget, active_widget, null_widget, widget, mouse_went_up)

hot_widget = try_reset_hot_widget(hot_widget, active_widget, widget, !mouse_over_button)
hot_widget = try_reset_hot_widget(hot_widget, active_widget, null_widget, widget, !mouse_over_button)

return hot_widget, active_widget, value
return hot_widget, active_widget, null_widget, value
end

widget!!(hot_widget, active_widget, null_widget, widg, widget_type::Button, args...; kwargs...) = widget(hot_widget, active_widget, null_widget, widg, widget_type, args...; kwargs...)

#####
##### Slider
#####
Expand All @@ -51,24 +53,26 @@ function get_widget_value(hot_widget, active_widget, widget, ::Slider, active_va
end
end

function widget(hot_widget, active_widget, widget, widget_type::Slider, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count, last_value)
function widget(hot_widget, active_widget, null_widget, widget, widget_type::Slider, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count, last_value)
mouse_over_slider = (i_min <= i_mouse <= i_max) && (j_min <= j_mouse <= j_max)
mouse_went_down = went_down(ended_down, half_transition_count)
mouse_went_up = went_up(ended_down, half_transition_count)

hot_widget = try_set_hot_widget(hot_widget, active_widget, widget, mouse_over_slider)
hot_widget = try_set_hot_widget(hot_widget, active_widget, null_widget, widget, mouse_over_slider)

active_widget = try_set_active_widget(hot_widget, active_widget, widget, mouse_over_slider && mouse_went_down)
active_widget = try_set_active_widget(hot_widget, active_widget, null_widget, widget, mouse_over_slider && mouse_went_down)

value = get_widget_value(hot_widget, active_widget, widget, widget_type, clamp(j_mouse - j_min + one(j_min), one(j_min), j_max - j_min + one(j_min)), last_value)

active_widget = try_reset_active_widget(hot_widget, active_widget, widget, mouse_went_up)
active_widget = try_reset_active_widget(hot_widget, active_widget, null_widget, widget, mouse_went_up)

hot_widget = try_reset_hot_widget(hot_widget, active_widget, widget, !mouse_over_slider)
hot_widget = try_reset_hot_widget(hot_widget, active_widget, null_widget, widget, !mouse_over_slider)

return hot_widget, active_widget, value
return hot_widget, active_widget, null_widget, value
end

widget!!(hot_widget, active_widget, null_widget, widg, widget_type::Slider, args...; kwargs...) = widget(hot_widget, active_widget, null_widget, widg, widget_type, args...; kwargs...)

#####
##### TextInput
#####
Expand All @@ -91,20 +95,22 @@ function update_widget_value!(hot_widget, active_widget, widget, ::TextInput, te
return nothing
end

function widget!(hot_widget, active_widget, widget, widget_type::TextInput, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count, text_line, characters)
function widget!(hot_widget, active_widget, null_widget, widget, widget_type::TextInput, i_min, j_min, i_max, j_max, i_mouse, j_mouse, ended_down, half_transition_count, text_line, characters)
mouse_over_widget = (i_min <= i_mouse <= i_max) && (j_min <= j_mouse <= j_max)
mouse_went_down = went_down(ended_down, half_transition_count)
mouse_went_up = went_up(ended_down, half_transition_count)

hot_widget = try_set_hot_widget(hot_widget, active_widget, widget, mouse_over_widget)
hot_widget = try_set_hot_widget(hot_widget, active_widget, null_widget, widget, mouse_over_widget)

active_widget = try_set_active_widget(hot_widget, active_widget, widget, mouse_over_widget && mouse_went_up)
active_widget = try_set_active_widget(hot_widget, active_widget, null_widget, widget, mouse_over_widget && mouse_went_up)

update_widget_value!(hot_widget, active_widget, widget, widget_type, text_line, characters)

active_widget = try_reset_active_widget(hot_widget, active_widget, widget, !mouse_over_widget && mouse_went_up)
active_widget = try_reset_active_widget(hot_widget, active_widget, null_widget, widget, !mouse_over_widget && mouse_went_up)

hot_widget = try_reset_hot_widget(hot_widget, active_widget, widget, !mouse_over_widget)
hot_widget = try_reset_hot_widget(hot_widget, active_widget, null_widget, widget, !mouse_over_widget)

return hot_widget, active_widget
return hot_widget, active_widget, null_widget
end

widget!!(hot_widget, active_widget, null_widget, widg, widget_type::TextInput, args...; kwargs...) = (widget!(hot_widget, active_widget, null_widget, widg, widget_type, args...; kwargs...)..., nothing)

0 comments on commit 3aaf25b

Please sign in to comment.