Browse Source

Scrollable region

master
Patrick Jakobsen 7 months ago
parent
commit
591a53e627
1 changed files with 165 additions and 23 deletions
  1. +165
    -23
      gui/gui.c

+ 165
- 23
gui/gui.c View File

@ -1116,6 +1116,8 @@ bool gui_slider(
inner->text_string = (GUI_String){0};
assert(*value <= 1.0f);
//inner->semantic_size[GUI_AXIS2_X].value = last_frame_width*(*value);
inner->semantic_size[GUI_AXIS2_Y] =
(GUI_Size){GUI_SIZERULE_PERCENTOFPARENT, 100, 100};
inner->semantic_size[GUI_AXIS2_X].size_rule = GUI_SIZERULE_PERCENTOFPARENT;
inner->semantic_size[GUI_AXIS2_X].value = 100 * (*value);
gui_pop_parent(context);
@ -1128,6 +1130,109 @@ bool gui_slider(
return value_changed;
}
#undef ENABLE_DEBUG
#define ENABLE_DEBUG 0
bool gui_vertical_slider(
GUI_Context *context,
GUI_Node_Reference *last_reference,
GUI_Node_Reference *inner_box_reference,
float *value,
GUI_Style *background_style,
GUI_Style *bar_style,
GUI_Size size[static 2])
{
GUI_Node_Reference new_reference = gui_get_node(
context, *last_reference, GUI_LAYOUT_NONE, background_style, size);
GUI_Node *node = new_reference.node;
node->debug_string = GUI_STRING("gui_slider");
node->text_string = (GUI_String){0};
// NOTE(Zelaven): We need a handle to this node, but we set its values later.
gui_push_parent(context, new_reference);
GUI_Node_Reference new_inner_reference = gui_get_node(
context, *inner_box_reference, GUI_LAYOUT_NONE, bar_style, size);
bool value_changed = false;
bool new_ref_is_top = gui_node_references_equal(
new_reference, context->top_node_under_cursor);
bool inner_ref_is_top = gui_node_references_equal(
new_inner_reference, context->top_node_under_cursor);
DEBUG("%p\n | %p %p\n | %p %p\n",
context->top_node_under_cursor.node,
last_reference->node, inner_box_reference->node,
new_reference.node, new_inner_reference.node);
if(new_ref_is_top || inner_ref_is_top)
{
DEBUG("\n%s: reference is the top node under cursor.\n", __func__);
if(context->mouse_pressed)
{
DEBUG(" Mouse pressed on node\n");
context->focused_node = new_reference;
}
else if(!context->mouse_down)
{
DEBUG(" Mouse released on node\n");
if(gui_node_references_equal(new_reference, context->focused_node))
{
DEBUG(" Mouse released over same node as pressed\n");
context->focused_node.node = NULL;
}
}
}
else if(gui_node_references_equal(new_reference, context->focused_node)
&& !context->mouse_down)
{
context->focused_node.node = NULL;
}
if(gui_node_references_equal(new_reference, context->focused_node))
{
int last_frame_height = node->computed_size[GUI_AXIS2_Y];
if(last_frame_height == 0)
{
DEBUG(
" last_frame_height is 0."
" This shouldn't really happen as the user shouldn't be able to focus"
" a node that hasn't been displayed on the screen yet."
" Not going to change the slider value.");
}
else
{
int offset_y = context->mouse_y - node->rect.y0;
float before_value = *value;
float new_value = ((float)offset_y) / ((float)last_frame_height);
if(new_value < 0.0f)
{
new_value = 0.0f;
}
else if(new_value >= 1.0f)
{
new_value = 1.0f;
}
*value = new_value;
DEBUG(" Value before: %f - Value after: %f\n", before_value, *value);
value_changed = (before_value != new_value);
}
}
// NOTE(Zelaven): Modified by input, so handle input first.
GUI_Node *inner = new_inner_reference.node;
inner->debug_string = GUI_STRING("gui_slider - inner node");
inner->text_string = (GUI_String){0};
assert(*value <= 1.0f);
inner->semantic_size[GUI_AXIS2_X] =
(GUI_Size){GUI_SIZERULE_PERCENTOFPARENT, 100, 100};
inner->semantic_size[GUI_AXIS2_Y].size_rule = GUI_SIZERULE_PERCENTOFPARENT;
inner->semantic_size[GUI_AXIS2_Y].value = 100 * (*value);
gui_pop_parent(context);
*last_reference = new_reference;
*inner_box_reference = new_inner_reference;
if(value_changed) {node->dirty = true;}
return value_changed;
}
@ -1441,14 +1546,16 @@ void test_gui__scrollbars(
middle = gui_layout(
context, middle, GUI_LAYOUT_HORIZONTAL, &outer_style, middle_size);
gui_push_parent(context, middle); {
gui_push_parent(context, middle);
{
static GUI_Node_Reference left = {0};
static GUI_Node_Reference center = {0};
static GUI_Node_Reference right = {0};
left = gui_dumb_block(context, left, &outer_style, side_size);
center = gui_dumb_block(context, center, &outer_style, center_size);
gui_push_parent(context, center); {
gui_push_parent(context, center);
{
static GUI_Node_Reference scrollbox_layout = {0};
static GUI_Size full_size[2] = {
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100},
@ -1456,7 +1563,8 @@ void test_gui__scrollbars(
scrollbox_layout = gui_layout(
context, scrollbox_layout, GUI_LAYOUT_HORIZONTAL, &outer_style, full_size);
gui_push_parent(context, scrollbox_layout); {
gui_push_parent(context, scrollbox_layout);
{
static GUI_Node_Reference scrollregion_layout = {0};
static GUI_Node_Reference scrollbar_layout = {0};
static GUI_Size scrollregion_size[2] = {
@ -1465,17 +1573,46 @@ void test_gui__scrollbars(
static GUI_Size scrollbar_size[2] = {
{GUI_SIZERULE_PERCENTOFPARENT, 10, 100},
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100}};
#if 0
scrollregion_layout = gui_layout(
context, scrollregion_layout, GUI_LAYOUT_VERTICAL,
&outer_style, scrollregion_size);
gui_push_parent(context, scrollregion_layout); {
gui_push_parent(context, scrollregion_layout);
{
static GUI_Node_Reference elements[6] = {0};
for(size_t i = 0; i < ARRAYLENGTH(elements); i++)
{
for(size_t i = 0; i < ARRAYLENGTH(elements); i++) {
elements[i] = gui_dumb_block(
context, elements[i], &element_style, element_size);
}
} gui_pop_parent(context);
#else
scrollregion_layout = gui_dumb_block(
context, scrollregion_layout, &outer_style, scrollregion_size);
static GUI_Subtree_Reference scrollregion_subtree = {0};
scrollregion_subtree = gui_get_subtree(context, scrollregion_subtree);
static GUI_Node_Reference scrollregion_root = {0};
static GUI_Size scrollregion_inner_size[2] = {
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100},
//{GUI_SIZERULE_PIXELS, 100, 100},
{GUI_SIZERULE_PIXELS, 880, 100}};
scrollregion_root = gui_push_subtree(
context, scrollregion_subtree, scrollregion_root,
GUI_LAYOUT_VERTICAL, &outer_style, scrollregion_inner_size,
scrollbox_layout);
// TODO(Zelaven): Instead of this hack, add to the layout code that it
// can set the size of the root relative to the size of its relative
// node.
scrollregion_root.rdic_ref.node->parent = scrollregion_layout.rdic_ref.node;
{
static GUI_Node_Reference elements[6] = {0};
for(size_t i = 0; i < ARRAYLENGTH(elements); i++) {
elements[i] = gui_dumb_block(
context, elements[i], &element_style, element_size);
}
} gui_pop_subtree(context);
#endif
#if 0
scrollbar_layout = gui_layout(
context, scrollbar_layout, GUI_LAYOUT_VERTICAL,
&outer_style, scrollbar_size);
@ -1483,7 +1620,8 @@ void test_gui__scrollbars(
int spacer_total = 90;
int spacer_upper = scroll_position * spacer_total;
int spacer_lower = spacer_total - spacer_upper;
gui_push_parent(context, scrollbar_layout); {
gui_push_parent(context, scrollbar_layout);
{
static GUI_Size bar_knob_size[2] = {
{GUI_SIZERULE_PERCENTOFPARENT, 100, 100},
{GUI_SIZERULE_PERCENTOFPARENT, 10, 100}};
@ -1507,14 +1645,22 @@ void test_gui__scrollbars(
scrollbar_lower_spacer = gui_dumb_block(
context, scrollbar_lower_spacer, &outer_style, bar_lower_spacer_size);
} gui_pop_parent(context); // scrollbar_layout.
#if 0
float contents_height_ratio = 0.0f;
if(scrollbox_layout.node->computed_size[GUI_AXIS2_Y] > 0) {
float layout_height =
(float)scrollbox_layout.node->computed_size[GUI_AXIS2_Y];
float contents_height = 600.0f; // TODO(Zelaven): take from scrollregion_layout. (dependency on CHILDRENSUM).
}
#endif
#else
static float slider_value = 0.0f;
static GUI_Style slider_background = {0, 0, 0, 0,0,0};
static GUI_Style slider_bar = {255, 0, 0, 0,0,0};
static GUI_Node_Reference slider = {0};
static GUI_Node_Reference slider_inner = {0};
gui_vertical_slider(context, &slider, &slider_inner,
&slider_value, &slider_background, &slider_bar, scrollbar_size);
scrollregion_subtree.node->offset_relative_node_percentage_y =
slider_value*100;
scrollregion_subtree.node->offset_own_size_percentage_y =
slider_value*-100;
scrollregion_root.node->dirty = true;
//((GUI_Node*)slider.node)->dirty;
//printf("Slider value: %f\n", slider_value);
#endif
} gui_pop_parent(context); // scrollbox_layout.
} gui_pop_parent(context); // center.
right = gui_dumb_block(context, right, &outer_style, side_size);
@ -1688,11 +1834,6 @@ void test_gui__subtree(
{GUI_SIZERULE_PIXELS, 40, 100}};
//static GUI_Node_Reference slider = {0};
static GUI_Node_Reference slider_inner = {0};
// NOTE(Zelaven): This line is not good because it causes jankyness when
// using the slider, and the slider behaves properly without it.
// NOTE(Zelaven): This line is actually necessary if the value is writable
// by anything other than the slider. If border_thickness is a float
// variable, then there is no issue, though.
gui_slider(context, &slider, &slider_inner,
&slider_value, &slider_background, &slider_bar, slider_size);
@ -1773,7 +1914,7 @@ void test_gui__subtree(
middle_subtree.node->offset_relative_node_percentage_y = slider_value*100;
middle_subtree.node->offset_own_size_percentage_y = slider_value*-100;
#endif
((GUI_Node*)middle_subtree_root.node)->dirty = ((GUI_Node*)slider.node)->dirty;
middle_subtree_root.node->dirty = ((GUI_Node*)slider.node)->dirty;
bottom = gui_dumb_block(context, bottom, &element_style, top_bottom_size);
@ -3499,9 +3640,9 @@ int main(void)
//gui = test_gui;
//gui = test_gui__calculator;
//gui = test_gui__scrollbars;
gui = test_gui__scrollbars;
//gui = test_gui__draw_command_using_sliders;
gui = test_gui__subtree;
//gui = test_gui__subtree;
//gui = test_gui__tmp;
X11_Window xwindow = {0};
@ -3676,6 +3817,7 @@ int main(void)
//gui_layout_nodes(&context);
#if 1
gui_layout_and_draw(&context);
SET_PIXEL(&xwindow.pixel_buffer, 239, 259, 0x00ff0000);
#else
for(
GUI_Subtree *current = (GUI_Subtree*)context.background_layer.subtree_rdic.root;

Loading…
Cancel
Save