More progress on themes + workspace resize handles support

Still need to add support for centered resize of boxes with the handles. (Will need a different alignment configuration)

Theme manipulation is getting cleaned up iteratively code is slowly looking less nosiy
This commit is contained in:
2024-05-15 18:48:20 -04:00
parent 48ee98f22d
commit 85cf9d8db2
15 changed files with 360 additions and 258 deletions

View File

@ -81,8 +81,7 @@ ui_hbox_end_auto :: proc( hbox : UI_HBox ) {
UI_Resizable :: struct {
using widget : UI_Widget,
handle_width : f32,
color_non_default : Color,
color_default : Color,
theme : ^UI_Theme,
left : bool,
right : bool,
top : bool,
@ -95,9 +94,8 @@ UI_Resizable :: struct {
}
ui_resizable_begin :: proc( label : string, flags : UI_BoxFlags = {},
handle_width : f32 = 15,
handle_color_non_default : Color = Color_ResizeHandle,
handle_color_default : Color = Color_Transparent,
handle_width : f32 = 15,
theme : ^UI_Theme,
left := true,
right := true,
top := true,
@ -111,18 +109,17 @@ ui_resizable_begin :: proc( label : string, flags : UI_BoxFlags = {},
resizable.box = ui_box_make(flags, label)
resizable.signal = ui_signal_from_box(resizable.box)
resizable.handle_width = handle_width
resizable.color_non_default = handle_color_non_default
resizable.color_default = handle_color_default
resizable.left = left
resizable.right = right
resizable.top = top
resizable.bottom = bottom
resizable.corner_tr = corner_tr
resizable.corner_tl = corner_tl
resizable.corner_br = corner_br
resizable.corner_bl = corner_bl
resizable.compute_layout = compute_layout
resizable.handle_width = handle_width
resizable.theme = theme
resizable.left = left
resizable.right = right
resizable.top = top
resizable.bottom = bottom
resizable.corner_tr = corner_tr
resizable.corner_tl = corner_tl
resizable.corner_br = corner_br
resizable.corner_bl = corner_bl
resizable.compute_layout = compute_layout
return
}
@ -130,8 +127,7 @@ ui_resizable_end :: proc( resizable : ^UI_Resizable, pos, size : ^Vec2 ) {
using resizable
ui_resizable_handles( & widget, pos, size,
handle_width,
color_non_default,
color_default,
theme,
left,
right,
top,
@ -154,9 +150,8 @@ ui_resizable_end_auto :: proc() {
// Adds resizable handles to a widget
// TODO(Ed): Add centered resize support (use center alignment on shift-click)
ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
handle_width : f32 = 15,
handle_color_non_default : Color = Color_ResizeHandle,
handle_color_default : Color = Color_Transparent,
handle_width : f32 = 15,
theme : ^UI_Theme = nil,
left := true,
right := true,
top := true,
@ -176,72 +171,114 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
handle_corner_tl : UI_Widget
handle_corner_br : UI_Widget
handle_corner_bl : UI_Widget
ui_parent(parent)
flags := UI_BoxFlags { .Mouse_Clickable, .Focusable }
layout_bar_width := UI_Layout {
flags = { .Fixed_Width },
alignment = {1, 0},
margins = { handle_width, handle_width, 0, 0 },
size = range2({handle_width, 0}, {}),
@(deferred_none = ui_theme_pop)
theme_handle :: proc( base : ^UI_Theme, margins, size : Vec2, flags : UI_LayoutFlags = {})
{
layout_combo : UI_LayoutCombo
style_combo : UI_StyleCombo
if base != nil
{
layout_combo = base.layout
style_combo = base.style
{
layout_combo.default.margins = {margins.x, margins.x, margins.y, margins.y}
layout_combo.default.size.min = size
}
{
layout_combo.hot.margins = {margins.x, margins.x, margins.y, margins.y}
layout_combo.hot.size.min = size
}
{
layout_combo.active.margins = {margins.x, margins.x, margins.y, margins.y}
layout_combo.active.size.min = size
}
}
else
{
layout := UI_Layout {
flags = flags,
anchor = range2({},{}),
alignment = {0, 0},
text_alignment = {0.0, 0.0},
font_size = 16,
margins = to_ui_layout_side(margins),
padding = {0, 0, 0, 0},
border_width = 0,
pos = {0, 0},
size = range2(size,{})
}
style := UI_Style {
bg_color = Color_Transparent,
border_color = Color_Transparent,
corner_radii = {5, 0, 0, 0},
blur_size = 0,
font = get_state().default_font,
text_color = Color_ThmDark_Text_Default,
cursor = {},
}
layout_combo = to_ui_layout_combo(layout)
style_combo = to_ui_style_combo(style)
{
using layout_combo.hot
using style_combo.hot
bg_color = Color_ThmDark_ResizeHandle_Hot
}
{
using layout_combo.active
using style_combo.active
bg_color = Color_ThmDark_ResizeHandle_Active
}
}
theme := UI_Theme {
layout_combo, style_combo
}
ui_layout_push(theme.layout)
ui_style_push(theme.style)
}
style_bar := UI_Style {
bg_color = Color_ResizeHandle,
corner_radii = { 5, 0, 0, 0 }
}
theme_bar := to_ui_style_combo(style_bar)
theme_bar.default.bg_color = handle_color_default
theme_bar.default.corner_radii[0] = 0
ui_layout(layout_bar_width)
ui_style(theme_bar)
layout_bar_height := layout_bar_width
layout_bar_height.flags = {.Fixed_Height}
layout_bar_height.size.min = {0, handle_width}
layout_bar_height.margins = { 0, 0, handle_width, handle_width }
layout_bar_height.alignment = {0, -1}
context.user_ptr = & parent.label
name :: proc( ) -> StrRunesPair {
flags := UI_BoxFlags { .Mouse_Clickable }
name :: proc( label : string ) -> string {
parent_label := (transmute(^string) context.user_ptr) ^
return str_intern(str_fmt_tmp("%v: %v", ))
return str_intern(str_fmt_alloc("%v: %v", parent_label, label )).str
}
context.user_ptr = & parent.label
if left do handle_left = ui_widget("Settings Menu: Resize Left Handle", flags )
#region("Handle & Corner construction")
theme_handle( theme, {handle_width, 0}, {handle_width,0})
if left {
handle_left = ui_widget(name("resize_handle_left"), flags )
handle_left.layout.anchor.left = 0
handle_left.layout.anchor.right = 1
handle_left.layout.alignment = {1, 0}
}
if right {
handle_right = ui_widget("Settings Menu: Resize Right Handle", flags)
handle_right = ui_widget(name("resize_handle_right"), flags )
handle_right.layout.anchor.left = 1
handle_right.layout.alignment = { 0, 0 }
}
ui_layout(layout_bar_height)
ui_style_ref().default.bg_color = handle_color_default
if top do handle_top = ui_widget("Settings Menu: Resize Top Border", flags )
theme_handle( theme, {0, handle_width}, {0, handle_width})
if top {
handle_top = ui_widget(name("resize_handle_top"), flags )
handle_top.layout.anchor.bottom = 1
handle_top.layout.alignment = {0, -1}
}
if bottom {
handle_bottom = ui_widget("Settings Menu: Resize Bottom Border", flags)
using handle_bottom.layout
anchor.top = 1
alignment = { 0, 0 }
handle_bottom = ui_widget("resize_handle_bottom", flags)
handle_bottom.layout.anchor.top = 1
handle_bottom.layout.alignment = { 0, 0 }
}
layout_corner := UI_Layout {
flags = { .Fixed_Width, .Fixed_Height },
alignment = {1, -1},
size = range2({handle_width, handle_width}, {}),
theme_handle( theme, {0,0}, {handle_width, handle_width}, {.Fixed_Width, .Fixed_Height} )
if corner_tl {
handle_corner_tl = ui_widget(name("corner_top_left"), flags)
handle_corner_tl.layout.alignment = {1, -1}
}
style_corner := UI_Style {
bg_color = Color_ResizeHandle,
corner_radii = { 5, 0, 0, 0 },
}
ui_theme(layout_corner, style_corner)
ui_style_ref().default.bg_color = handle_color_default
if corner_tl do handle_corner_tl = ui_widget("Settings Menu: Corner TL", flags)
if corner_tr {
handle_corner_tr = ui_widget("Settings Menu: Corner TR", flags)
handle_corner_tr = ui_widget(name("corner_top_right"), flags)
handle_corner_tr.layout.anchor = range2({1, 0}, {})
handle_corner_tr.layout.alignment = {0, -1}
}
if corner_bl {
handle_corner_bl = ui_widget("Settings Menu: Corner BL", flags)
handle_corner_bl.layout.anchor = range2({}, {0, 1})
@ -252,27 +289,42 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
handle_corner_br.layout.anchor = range2({1, 0}, {0, 1})
handle_corner_br.layout.alignment = {0, 0}
}
#endregion("Handle & Corner construction")
process_handle_drag :: #force_inline proc ( handle : ^UI_Widget,
direction : Vec2,
size_delta : Vec2,
target_alignment : Vec2,
target_center_aligned : Vec2,
pos : ^Vec2,
size : ^Vec2,
alignment : ^Vec2, ) -> b32
{
ui := get_state().ui_context
if ui.last_pressed_key != handle.key { return false }
@static active_context : ^UI_State
@static was_dragging : b32 = false
@static start_size : Vec2
size_delta := size_delta
ui := get_state().ui_context
if ui.last_pressed_key != handle.key do return false
using handle
direction := direction
target_alignment := target_alignment
size_delta := ui_drag_delta()
pos_adjust := size^ * (alignment^ - target_alignment)
@static was_dragging : b32 = false
using handle
if active
{
size^ += size_delta * direction
if pressed
{
active_context = ui
start_size = size^
if .Origin_At_Anchor_Center in parent.layout.flags {
pos_adjust = size^ * 0.5 * direction
}
}
size^ = start_size + size_delta * direction
if pressed {
pos^ -= pos_adjust
}
@ -283,26 +335,49 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
}
else if released && was_dragging
{
pos^ += pos_adjust
alignment^ = target_alignment
was_dragging = false
// This needed to be added as for some reason, this was getting called in screen_ui even when we were resizing with a handle in a worksapce
if active_context != ui do return false
if .Origin_At_Anchor_Center in parent.layout.flags {
pos_adjust = size^ * 0.5 * direction
}
pos^ += pos_adjust
alignment^ = target_alignment
was_dragging = false
start_size = 0
active_context = ui
}
return was_dragging
}
delta := get_state().input.mouse.delta
state := get_state()
delta := state.input.mouse.delta //state.ui_context == & state.screen_ui ? state.input.mouse.delta : ui_ws_drag_delta()
alignment := & parent.layout.alignment
if right do drag_signal |= process_handle_drag( & handle_right, { 1, 0 }, delta, {0, 0}, pos, size, alignment )
if left do drag_signal |= process_handle_drag( & handle_left, { -1, 0 }, delta, {1, 0}, pos, size, alignment )
if top do drag_signal |= process_handle_drag( & handle_top, { 0, 1 }, delta, {0, 0}, pos, size, alignment )
if bottom do drag_signal |= process_handle_drag( & handle_bottom, { 0, -1 }, delta, {0, 1}, pos, size, alignment )
if corner_tr do drag_signal |= process_handle_drag( & handle_corner_tr, { 1, 1 }, delta, {0, 0}, pos, size, alignment )
if corner_tl do drag_signal |= process_handle_drag( & handle_corner_tl, { -1, 1 }, delta, {1, 0}, pos, size, alignment )
if corner_br do drag_signal |= process_handle_drag( & handle_corner_br, { 1, -1 }, delta, {0, 1}, pos, size, alignment )
if corner_bl do drag_signal |= process_handle_drag( & handle_corner_bl, { -1, -1 }, delta, {1, 1}, pos, size, alignment )
if .Origin_At_Anchor_Center in parent.layout.flags
{
if right do drag_signal |= process_handle_drag( & handle_right, { 1, 0}, delta, { 0.5, 0}, {}, pos, size, alignment )
if left do drag_signal |= process_handle_drag( & handle_left, {-1, 0}, delta, {-0.5, 0}, {}, pos, size, alignment )
if top do drag_signal |= process_handle_drag( & handle_top, { 0, 1}, delta, { 0, 0.5}, {}, pos, size, alignment )
if bottom do drag_signal |= process_handle_drag( & handle_bottom, { 0, -1}, delta, { 0, -0.5}, {}, pos, size, alignment )
if corner_tr do drag_signal |= process_handle_drag( & handle_corner_tr, { 1, 1}, delta, { 0.5, 0.5}, {}, pos, size, alignment )
if corner_tl do drag_signal |= process_handle_drag( & handle_corner_tl, {-1, 1}, delta, {-0.5, 0.5}, {}, pos, size, alignment )
if corner_br do drag_signal |= process_handle_drag( & handle_corner_br, { 1, -1}, delta, { 0.5, -0.5}, {}, pos, size, alignment )
if corner_bl do drag_signal |= process_handle_drag( & handle_corner_bl, {-1, -1}, delta, {-0.5, -0.5}, {}, pos, size, alignment )
}
else
{
if right do drag_signal |= process_handle_drag( & handle_right, { 1, 0 }, delta, {0, 0}, {}, pos, size, alignment )
if left do drag_signal |= process_handle_drag( & handle_left, { -1, 0 }, delta, {1, 0}, {}, pos, size, alignment )
if top do drag_signal |= process_handle_drag( & handle_top, { 0, 1 }, delta, {0, -1}, {}, pos, size, alignment )
if bottom do drag_signal |= process_handle_drag( & handle_bottom, { 0, -1 }, delta, {0, 0}, {}, pos, size, alignment )
if corner_tr do drag_signal |= process_handle_drag( & handle_corner_tr, { 1, 1 }, delta, {0, -1}, {}, pos, size, alignment )
if corner_tl do drag_signal |= process_handle_drag( & handle_corner_tl, { -1, 1 }, delta, {1, -1}, {}, pos, size, alignment )
if corner_br do drag_signal |= process_handle_drag( & handle_corner_br, { 1, -1 }, delta, {0, 0}, {}, pos, size, alignment )
if corner_bl do drag_signal |= process_handle_drag( & handle_corner_bl, { -1, -1 }, delta, {1, 0}, {}, pos, size, alignment )
}
ui_box_compute_layout(parent)
if drag_signal && compute_layout do ui_box_compute_layout(parent)
return
}
#endregion("Resizable")