Skip to content

Instantly share code, notes, and snippets.

@oeloeloel
Last active August 30, 2024 14:13
Show Gist options
  • Save oeloeloel/9689594b5451780ccd37f8ce65f4c788 to your computer and use it in GitHub Desktop.
Save oeloeloel/9689594b5451780ccd37f8ce65f4c788 to your computer and use it in GitHub Desktop.
DragonRuby Button Experiment (low responsibility three-state button)
# A small POC experiment with buttons (it doesn't attempt to solve all the problems)
# the button method implements behaviour for a three-state button
# it accounts for button "layers" that can be formed from multiple primitives
# it doesn't impose other constraints on the dev, so the dev is free to make
# the buttons any way they like. This code shows:
# • A button made from a basic rect and label (with a bonus arbitrary rect for the active state)
# • A resizable button with rounded ends and a 2 pixel outline (1 label, 6 sprites)
def tick args
args.outputs.background_color = {r: 88, g: 124, b: 204}
$gtk.set_system_cursor(:arrow)
button_rect = { x: 640, y: 460, w: 400, h: 70, anchor_x: 0.5, anchor_y: 0.5 }
button_action = -> { $gtk.notify 'Stop that' }
button_state_enabled = [
{ path: :solid, r: 255, g: 255, b: 0 },
{ text: 'I am an enabled button', r: 0, g: 0, b: 255, size_enum: 6 }
]
button_state_focused = [
{ path: :solid, r: 0, g: 255, b: 255 },
{ text: 'I am a focused button', r: 255, g: 0, b: 0, size_enum: 6 }
]
button_state_active = [
{ w: 410 + args.tick_count.*(3).sin * 10, h: 80 + args.tick_count.*(3).cos * 10, path: :solid, r: 0, g: 0, b: 255 },
{ path: :solid, r: 255, g: 0, b: 255 },
{ text: 'I am an active button', r: 0, g: 255, b: 0, size_enum: 6 }
]
args.outputs.primitives << button(
args,
rect: button_rect, # required
action: button_action, # required
enabled: button_state_enabled, # required
focused: button_state_focused, # optional
active: button_state_active # optional
)
pill_button_base = { x: 640, y: 300, w: 300, h: 70, anchor_x: 0.5, anchor_y: 0.5, text: "Click Me" }
args.outputs.primitives << button(
args,
rect: pill_button_base,
action: button_action,
enabled: pill_button_layer(args, rect: pill_button_base, color: {r: 0, g: 0, b: 0}, bg: {r: 153, g: 153, b: 153}),
focused: pill_button_layer(args, rect: pill_button_base, color: {r: 188, g: 51, b: 51}, bg: {r: 204, g: 204, b: 204}),
active: pill_button_layer(args, rect: pill_button_base, color: {r: 204, g: 204, b: 204}, bg: {r: 188, g: 51, b: 51})
)
end
def button args, **kwargs
if (kwargs.keys & [:rect, :action, :enabled]).size < 3
raise "Missing argument(s). Provide required rect, action and enabled state."
end
within = args.inputs.mouse.inside_rect? kwargs.rect
was_pushed_within = args.inputs.mouse.previous_click&.inside_rect? kwargs.rect
active = within && was_pushed_within && args.inputs.mouse.held
args.gtk.set_system_cursor(:hand) if within
kwargs.action.call if args.inputs.mouse.up && within && was_pushed_within
primitives = if active && kwargs.active
kwargs.active
elsif within && kwargs.focused
kwargs.focused
else
kwargs.enabled
end
primitives.map do |prim|
{
**prim,
**kwargs.rect,
x: (prim.x || 0) + kwargs.rect.x,
w: prim.w || kwargs.rect.w,
h: prim.h || kwargs.rect.h
}
end
end
def pill_button_layer args, **params
[
{
path: 'sprites/circles/path1.png',
x: -params.rect.w.half + params.rect.h.half,
w: params.rect.h, h: params.rect.h,
**params.color,
}.sprite!,
{
path: 'sprites/circles/path1.png',
x: params.rect.w.half - params.rect.h.half,
w: params.rect.h, h: params.rect.h,
**params.color
}.sprite!,
{
path: :solid, **params.color,
w: params.rect.w - params.rect.h
}.sprite!,
{
path: 'sprites/circles/path1.png',
x: -params.rect.w.half + params.rect.h.half,
w: params.rect.h - 4, h: params.rect.h - 4,
**params.bg,
}.sprite!,
{
path: 'sprites/circles/path1.png',
x: params.rect.w.half - params.rect.h.half,
w: params.rect.h - 4, h: params.rect.h - 4,
**params.bg
}.sprite!,
{
path: :solid, **params.bg,
w: params.rect.w - params.rect.h,
h: params.rect.h - 4
}.sprite!,
{
text: params.text, **params.color, size_enum: 6
}
]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment