Skip to content

Instantly share code, notes, and snippets.

@airways
Created May 16, 2012 14:15
Show Gist options
  • Save airways/2710671 to your computer and use it in GitHub Desktop.
Save airways/2710671 to your computer and use it in GitHub Desktop.
Base widget methods for Allegro 5 (source unknown)
#include "widget.h"
//total event controllers
#define MAX_EVENT_CONTROLLERS 10
//event controller
typedef struct EVENT_CONTROLLER
{
ALGUI_EVENT_CONTROLLER_PROC proc;
void *data;
} EVENT_CONTROLLER;
//event controllers
static EVENT_CONTROLLER event_controllers[MAX_EVENT_CONTROLLERS] =
{
{ algui_default_event_controller_proc, 0 }
};
static int current_event_controller = 0;
//return min from two integers
static int min_(int x, int y)
{
return x < y ? x : y;
}
//return max from two integers
static int max_(int x, int y)
{
return x > y ? x : y;
}
//send the message 'SET_PREFERRED_SIZE' to children first, then to parents.
static void set_preferred_size(ALGUI_WIDGET *wgt)
{
ALGUI_WIDGET *child;
if (wgt->geometry_altered_in_tree)
{
wgt->geometry_altered_in_tree = 0;
for(child = wgt->first; child; child = child->next)
{
set_preferred_size(child);
wgt->geometry_altered |= child->geometry_altered;
wgt->geometry_altered_in_tree |=
child->geometry_altered | child->geometry_altered_in_tree;
}
}
if (wgt->geometry_altered)
{
int w = wgt->width, h = wgt->height;
algui_send_message(wgt, ALGUI_MSG_SET_PREFERRED_SIZE, NULL);
wgt->geometry_altered = wgt->width != w || wgt->height != h;
}
}
//sends the message 'DO LAYOUT' to parents first, then to children.
static void do_layout(ALGUI_WIDGET *wgt)
{
ALGUI_WIDGET *child;
if (wgt->geometry_altered)
{
algui_send_message(wgt, ALGUI_MSG_DO_LAYOUT, NULL);
}
if (wgt->geometry_altered_in_tree)
{
wgt->geometry_altered_in_tree = 0;
for(child = wgt->first; child; child = child->next)
{
do_layout(child);
}
}
}
//recursively draws widgets
static void draw_widget(
ALGUI_WIDGET *wgt,
ALLEGRO_BITMAP *parent,
int cl,
int ct,
int cr,
int cb,
int reconstruct_bitmap)
{
ALGUI_WIDGET *child;
//reconstruct the widget's bitmap if the geometry is altered
reconstruct_bitmap |= wgt->geometry_altered || wgt->bitmap == NULL;
wgt->geometry_altered = 0;
//reconstruct the widget's bitmap, if needed
if (reconstruct_bitmap)
{
al_destroy_bitmap(wgt->bitmap);
wgt->bitmap = al_create_sub_bitmap(
parent,
wgt->x,
wgt->y,
wgt->width,
wgt->height);
}
//clip the output to the parent
cl = max_(cl, wgt->x);
ct = max_(ct, wgt->y);
//cr = min_(cr, wgt->x + wgt->width - 1);
//cb = min_(cb, wgt->y + wgt->height - 1);
//make the clipping local to the widget
cl -= wgt->x;
ct -= wgt->y;
//cr -= wgt->x;
//cb -= wgt->y;
//cr = wgt->width;
//cb = wgt->height;
//paint widget only if widget is visible
if (wgt->visible)
{
//set the target bitmap and clipping to the one used by the widget
al_set_target_bitmap(wgt->bitmap);
//al_set_clipping_rectangle(cl, ct, wgt->width, wgt->height);
//paint the widget
algui_send_message(wgt, ALGUI_MSG_PAINT, NULL);
}
//paint the children
for(child = wgt->first; child; child = child->next)
{
draw_widget(child, wgt->bitmap, cl, ct, wgt->width, wgt->height, reconstruct_bitmap);
}
}
//visit the tree and apply the given function to each widget
static void visit_tree(ALGUI_WIDGET *wgt, void (*proc)(ALGUI_WIDGET *))
{
ALGUI_WIDGET *child;
proc(wgt);
for(child = wgt->first; child; child = child->next)
{
visit_tree(child, proc);
}
}
//sets the enabled tree flag
static void set_enabled_tree_proc(ALGUI_WIDGET *wgt)
{
wgt->enabled_tree = wgt->enabled && (!wgt->parent || wgt->parent->enabled_tree);
}
//sets the enabled tree flag.
static void set_enabled_tree(ALGUI_WIDGET *wgt)
{
visit_tree(wgt, set_enabled_tree_proc);
}
//resets the flags of the widget
static void reset_flags_proc(ALGUI_WIDGET *wgt)
{
set_enabled_tree_proc(wgt);
wgt->geometry_altered = 1;
wgt->geometry_altered_in_tree = 1;
wgt->has_focus = 0;
wgt->has_mouse = 0;
}
//resets the flags of each widget in the tree.
static void reset_flags(ALGUI_WIDGET *wgt)
{
visit_tree(wgt, reset_flags_proc);
}
//removes a widget from its parent
static void remove_widget(ALGUI_WIDGET *par, ALGUI_WIDGET *child)
{
//remove from tree
ALGUI_WIDGET *prev = child->prev;
ALGUI_WIDGET *next = child->next;
if (prev) prev->next = next; else par->first = next;
if (next) next->prev = prev; else par->last = prev;
child->parent = child->prev = child->next = NULL;
//set the enabled tree flag of the child tree
reset_flags(child);
//mark the parent for geometry management
algui_mark_widget_for_geometry_management(par);
}
//remove focus from widget
static int lose_focus(ALGUI_WIDGET *wgt)
{
wgt->has_focus = 0;
return 1;
}
//set focus to widget
static int get_focus(ALGUI_WIDGET *wgt)
{
//the widget already has the input focus
if (wgt->has_focus) return 1;
//remove the focus from the previous focus owner
ALGUI_WIDGET *root = algui_get_root_widget(wgt);
ALGUI_WIDGET *prev_focus = algui_get_focus_widget(root);
if (prev_focus && !algui_send_message(prev_focus, ALGUI_MSG_LOSE_FOCUS, NULL))
{
return 0;
}
//set the focus to the widget
wgt->has_focus = 1;
return 1;
}
//send key down event to widget with focus
static int key_down(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *focus = algui_get_focus_widget(wgt);
if (focus && !focus->enabled_tree)
{
return 0;
}
return algui_send_message(focus, ALGUI_MSG_KEY_DOWN, ev);
}
//send key up event to widget with focus
static int key_up(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *focus = algui_get_focus_widget(wgt);
if (!focus || !focus->enabled_tree)
{
return 0;
}
return algui_send_message(focus, ALGUI_MSG_KEY_UP, ev);
}
//unused key char
static int unused_key_char(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
//the widget must be enabled
if (!wgt->enabled_tree)
{
return 0;
}
//if the widget processes the unused key char, stop
if (algui_send_message(wgt, ALGUI_MSG_UNUSED_KEY_CHAR, ev))
{
return 1;
}
//pass the event to children
ALGUI_WIDGET *child;
for(child = wgt->first; child; child = child->next)
{
if (unused_key_char(child, ev))
{
return 1;
}
}
//unused key not processed
return 0;
}
//send key char event to widget with focus;
//if that fails, broadcast the unused char message to all widgets.
static int key_char(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *focus = algui_get_focus_widget(wgt);
//if there is an enabled focus widget, send it the message
if (focus &&
focus->enabled_tree &&
algui_send_message(wgt, ALGUI_MSG_KEY_CHAR, ev))
{
return 1;
}
return unused_key_char(wgt, ev);
}
//find the widget with the mouse flag set
static ALGUI_WIDGET *old_mouse_widget(ALGUI_WIDGET *wgt)
{
if (wgt->has_mouse) return wgt;
ALGUI_WIDGET *child, *res;
for(child = wgt->last; child; child = child->prev)
{
res = old_mouse_widget(child);
if (res) return res;
}
return NULL;
}
//find the widget under the given coordinates
static ALGUI_WIDGET *new_mouse_widget(ALGUI_WIDGET *wgt, int x, int y)
{
x -= wgt->x;
y -= wgt->y;
if (!wgt->visible || x < 0 || x >= wgt->width || y < 0 || y >= wgt->height)
{
return NULL;
}
ALGUI_WIDGET *child, *res;
for(child = wgt->last; child; child = child->prev)
{
res = new_mouse_widget(child, x, y);
if (res) return res;
}
return wgt;
}
//maps an event's mouse coordinates to the coordinate space of a widget
static void map_event_coords_to_widget(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
algui_map_coords(
NULL,
ev->mouse.x,
ev->mouse.y,
wgt,
&ev->mouse.x,
&ev->mouse.y);
}
//handle mouse move
static int mouse_move(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
int processed = 0;
int mouse_x = ev->mouse.x;
int mouse_y = ev->mouse.y;
//find the previous and new mouse widgets
ALGUI_WIDGET *old_mouse = old_mouse_widget(wgt);
ALGUI_WIDGET *new_mouse = new_mouse_widget(wgt, ev->mouse.x, ev->mouse.y);
//if the mouse didn't change widgets, then send a mouse move
if (new_mouse == old_mouse)
{
if (new_mouse && new_mouse->enabled_tree)
{
map_event_coords_to_widget(new_mouse, ev);
processed |= algui_send_message(new_mouse, ALGUI_MSG_MOUSE_MOVE, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
}
}
//else send mouse enter/leave
else
{
if (old_mouse && old_mouse->enabled_tree)
{
old_mouse->has_mouse = 0;
map_event_coords_to_widget(old_mouse, ev);
processed |= algui_send_message(old_mouse, ALGUI_MSG_MOUSE_LEAVE, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
}
if (new_mouse && new_mouse->enabled_tree)
{
new_mouse->has_mouse = 1;
map_event_coords_to_widget(new_mouse, ev);
processed |= algui_send_message(new_mouse, ALGUI_MSG_MOUSE_ENTER, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
}
}
return processed;
}
//handles the mouse wheel event
static int mouse_wheel(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *focus = algui_get_focus_widget(wgt);
if (!focus || !focus->enabled_tree)
{
return 0;
}
int mouse_x = ev->mouse.x;
int mouse_y = ev->mouse.y;
map_event_coords_to_widget(focus, ev);
int res = algui_send_message(focus, ALGUI_MSG_MOUSE_WHEEL, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
return res;
}
//handle the mouse axes event
static int mouse_axes(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
int processed = 0;
//handle move
if (ev->mouse.dx || ev->mouse.dy)
{
processed |= mouse_move(wgt, ev);
}
//handle wheel
if (ev->mouse.dw || ev->mouse.dz)
{
processed |= mouse_wheel(wgt, ev);
}
return processed;
}
//mouse button
static int mouse_button(
ALGUI_WIDGET *wgt,
ALLEGRO_EVENT *ev,
int left_msg,
int right_msg,
int middle_msg)
{
ALGUI_WIDGET *new_mouse = new_mouse_widget(wgt, ev->mouse.x, ev->mouse.y);
if (!new_mouse || !new_mouse->enabled_tree)
{
return 0;
}
int res;
int mouse_x = ev->mouse.x;
int mouse_y = ev->mouse.y;
map_event_coords_to_widget(new_mouse, ev);
new_mouse->has_mouse = 1;
switch (ev->mouse.button)
{
case 1:
res = algui_send_message(new_mouse, left_msg, ev);
break;
case 2:
res = algui_send_message(new_mouse, right_msg, ev);
break;
case 3:
res = algui_send_message(new_mouse, middle_msg, ev);
break;
default:
res = 0;
}
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
return res;
}
//mouse button down
static int mouse_button_down(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
return mouse_button(
wgt,
ev,
ALGUI_MSG_LEFT_BUTTON_DOWN,
ALGUI_MSG_RIGHT_BUTTON_DOWN,
ALGUI_MSG_MIDDLE_BUTTON_DOWN);
}
//mouse button down
static int mouse_button_up(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
return mouse_button(
wgt,
ev,
ALGUI_MSG_LEFT_BUTTON_UP,
ALGUI_MSG_RIGHT_BUTTON_UP,
ALGUI_MSG_MIDDLE_BUTTON_UP);
}
//handle mouse enter
static int mouse_enter(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *new_mouse = new_mouse_widget(wgt, ev->mouse.x, ev->mouse.y);
if (!new_mouse || !new_mouse->enabled_tree)
{
return 0;
}
int mouse_x = ev->mouse.x;
int mouse_y = ev->mouse.y;
map_event_coords_to_widget(new_mouse, ev);
new_mouse->has_mouse = 1;
int res = algui_send_message(new_mouse, ALGUI_MSG_MOUSE_ENTER, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
return res;
}
//handle mouse leave
static int mouse_leave(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
ALGUI_WIDGET *old_mouse = old_mouse_widget(wgt);
if (!old_mouse || !old_mouse->enabled_tree)
{
return 0;
}
int mouse_x = ev->mouse.x;
int mouse_y = ev->mouse.y;
map_event_coords_to_widget(old_mouse, ev);
old_mouse->has_mouse = 0;
int res = algui_send_message(old_mouse, ALGUI_MSG_MOUSE_LEAVE, ev);
ev->mouse.x = mouse_x;
ev->mouse.y = mouse_y;
return res;
}
//handle a timer message
static int timer(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
if (!wgt->enabled_tree)
{
return 0;
}
int processed = algui_send_message(wgt, ALGUI_MSG_TIMER, ev);
ALGUI_WIDGET *child;
for(child = wgt->first; child; child = child->next)
{
processed |= timer(child, ev);
}
return processed;
}
//handle a display expose message
static int display_expose(ALGUI_WIDGET *wgt, ALLEGRO_EVENT *ev)
{
algui_draw_widget_rect(
wgt,
ev->display.x - wgt->x,
ev->display.y - wgt->y,
ev->display.width,
ev->display.height);
return 1;
}
/******************************************************************************
PUBLIC
******************************************************************************/
//the default widget procedure.
int algui_default_widget_proc(ALGUI_WIDGET *wgt, int msg, void *data)
{
switch (msg)
{
case ALGUI_MSG_GET_FOCUS:
return get_focus(wgt);
case ALGUI_MSG_LOSE_FOCUS:
return lose_focus(wgt);
}
return 0;
}
//sends a message to a widget.
int algui_send_message(ALGUI_WIDGET *wgt, int msg, void *data)
{
if(wgt)
{
return wgt->proc(wgt, msg, data);
} else {
return 0;
}
}
//initializes a widget structure to default values.
void algui_init_widget(ALGUI_WIDGET *wgt)
{
wgt->proc = algui_default_widget_proc;
wgt->parent = NULL;
wgt->prev = NULL;
wgt->next = NULL;
wgt->first = NULL;
wgt->last = NULL;
wgt->x = 0;
wgt->y = 0;
wgt->width = 0;
wgt->height = 0;
wgt->bitmap = NULL;
wgt->name = NULL;
wgt->visible = 1;
wgt->enabled = 1;
wgt->enabled_tree = 1;
wgt->geometry_altered = 1;
wgt->geometry_altered_in_tree = 1;
wgt->has_focus = 0;
wgt->has_mouse = 0;
}
//destroys each widget in the widget tree.
void algui_destroy_widget(ALGUI_WIDGET *wgt)
{
// ALGUI_WIDGET *child;
//remove and destroy children
while(wgt->last)
{
ALGUI_WIDGET *child = wgt->last;
remove_widget(wgt, child);
algui_destroy_widget(child);
}
//send the widget the cleanup message.
algui_send_message(wgt, ALGUI_MSG_CLEANUP, NULL);
//free memory
al_free(wgt);
}
//returns the root widget of the tree the given widget belongs.
ALGUI_WIDGET *algui_get_root_widget(ALGUI_WIDGET *wgt)
{
for(; wgt->parent; wgt = wgt->parent);
return wgt;
}
//inserts a widget into another widget.
int algui_insert_widget(
ALGUI_WIDGET *par,
ALGUI_WIDGET *child,
ALGUI_WIDGET *next)
{
ALGUI_WIDGET *prev;
//check parameters
if (child->parent || child == par || (next && next->parent != par))
{
return 0;
}
prev = next ? next->prev : par->last;
//insert widget
if (prev) prev->next = child; else par->first = child;
if (next) next->prev = child; else par->last = child;
child->parent = par;
child->prev = prev;
child->next = next;
//reset the flags in the child tree
reset_flags(child);
//flag the parent widget as having altered geometry so as that geometry is
//negotiated later
algui_mark_widget_for_geometry_management(par);
//success
return 1;
}
//Same as 'algui_insert_widget(par, child, NULL).
int algui_add_widget(ALGUI_WIDGET *par, ALGUI_WIDGET *child)
{
return algui_insert_widget(par, child, NULL);
}
//detaches a widget from its parent, if there is one.
void algui_detach_widget(ALGUI_WIDGET *wgt)
{
if (wgt->parent) remove_widget(wgt->parent, wgt);
}
//sets the position and size of a widget.
void algui_set_widget_geometry(
ALGUI_WIDGET *wgt,
int x,
int y,
int width,
int height)
{
//limit position to sensible values
if (width < 0) width = 0;
if (height < 0) height = 0;
//check for change
if (x == wgt->x &&
y == wgt->y &&
width == wgt->width &&
height == wgt->height)
{
return;
}
//set new position
wgt->x = x;
wgt->y = y;
wgt->width = width;
wgt->height = height;
//flag the parent widget as having altered geometry so as that geometry is
//negotiated later
algui_mark_widget_for_geometry_management(wgt);
}
//flags the widget as needing geometry management.
void algui_mark_widget_for_geometry_management(ALGUI_WIDGET *wgt)
{
ALGUI_WIDGET *par;
//if the widget is already flagged, do nothing else
if (wgt->geometry_altered) return;
//flag the widget
wgt->geometry_altered = 1;
//flag non-flagged ancestors, in order to limit calculations
//only to those widgets that are affected by the change
for(par = wgt->parent;
par && !par->geometry_altered_in_tree;
par = par->parent)
{
par->geometry_altered_in_tree = 1;
}
}
//sets a widget visible or invisible.
void algui_set_widget_visible(ALGUI_WIDGET *wgt, int visible)
{
if (visible == wgt->visible) return;
wgt->visible = visible;
if (wgt->parent)
{
algui_mark_widget_for_geometry_management(wgt->parent);
}
}
//sets a widget enabled or disabled.
void algui_set_widget_enabled(ALGUI_WIDGET *wgt, int enabled)
{
if (enabled == wgt->enabled) return;
wgt->enabled = enabled;
set_enabled_tree(wgt);
algui_mark_widget_for_geometry_management(wgt);
}
//draws part of a widget and its children.
void algui_draw_widget_rect(ALGUI_WIDGET *wgt, int x, int y, int width, int height)
{
ALLEGRO_BITMAP *target;
int cx, cy, cw, ch;
//store the current target and clipping locally
target = al_get_target_bitmap();
al_get_clipping_rectangle(&cx, &cy, &cw, &ch);
//manage the widget's geometry
set_preferred_size(wgt);
do_layout(wgt);
//make the given rectangle relative to the widget's target bitmap
x += wgt->x;
y += wgt->y;
//draw the widgets
draw_widget(
wgt,
target,
max_(x, 0),
max_(y, 0),
min_(x + width - 1 , al_get_bitmap_width(target) - 1),
min_(y + height - 1, al_get_bitmap_height(target) - 1),
0);
//restore the current target and clipping
al_set_target_bitmap(target);
al_set_clipping_rectangle(cx, cy, cw, ch);
}
//draws a widget and its children.
void algui_draw_widget(ALGUI_WIDGET *wgt)
{
algui_draw_widget_rect(wgt, 0, 0, wgt->width, wgt->height);
}
//finds the widget in the tree that has the input focus.
ALGUI_WIDGET *algui_get_focus_widget(ALGUI_WIDGET *wgt)
{
ALGUI_WIDGET *child, *res;
if (wgt->has_focus) return wgt;
for(child = wgt->first; child; child = child->next)
{
res = algui_get_focus_widget(child);
if (res) return res;
}
return NULL;
}
//sends the message ALGUI_MSG_GET_FOCUS to the given widget.
int algui_set_focus_widget(ALGUI_WIDGET *wgt)
{
return algui_send_message(wgt, ALGUI_MSG_GET_FOCUS, NULL);
}
//the default event controller procedure.
int algui_default_event_controller_proc(
ALGUI_WIDGET *root,
ALLEGRO_EVENT *event,
void *data)
{
switch (event->type)
{
case ALLEGRO_EVENT_JOYSTICK_AXIS:
//TODO
break;
case ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN:
//TODO
break;
case ALLEGRO_EVENT_JOYSTICK_BUTTON_UP:
//TODO
break;
case ALLEGRO_EVENT_KEY_DOWN:
return key_down(root, event);
case ALLEGRO_EVENT_KEY_UP:
return key_up(root, event);
case ALLEGRO_EVENT_KEY_CHAR:
return key_char(root, event);
case ALLEGRO_EVENT_MOUSE_AXES:
return mouse_axes(root, event);
case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
return mouse_button_down(root, event);
case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
return mouse_button_up(root, event);
case ALLEGRO_EVENT_MOUSE_WARPED:
return mouse_axes(root, event);
case ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY:
return mouse_enter(root, event);
case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY:
return mouse_leave(root, event);
case ALLEGRO_EVENT_TIMER:
return timer(root, event);
case ALLEGRO_EVENT_DISPLAY_EXPOSE:
return display_expose(root, event);
}
//event not processed
return 0;
}
//returns the current event controller.
ALGUI_EVENT_CONTROLLER_PROC algui_get_event_controller(void **data)
{
if (current_event_controller < 0)
{
if (data) *data = NULL;
return NULL;
}
if (data) *data = event_controllers[current_event_controller].proc;
return event_controllers[current_event_controller].proc;
}
//pushes an event controller in the event controller stack.
int algui_push_event_controller(ALGUI_EVENT_CONTROLLER_PROC proc, void *data)
{
if (current_event_controller == MAX_EVENT_CONTROLLERS - 1)
{
return 0;
}
++current_event_controller;
event_controllers[current_event_controller].proc = proc;
event_controllers[current_event_controller].data = data;
return 1;
}
//pops the current event controller.
int algui_pop_event_controller()
{
if (current_event_controller < 0)
{
return 0;
}
--current_event_controller;
return 1;
}
//dispatches the given ALLEGRO event to the appropriate widget,
int algui_dispatch_event(ALGUI_WIDGET *root, ALLEGRO_EVENT *event)
{
if (current_event_controller < 0)
{
return 0;
}
return event_controllers[current_event_controller].proc(
root,
event,
event_controllers[current_event_controller].data);
}
//map coordinates from one widget to another.
void algui_map_coords(
ALGUI_WIDGET *src,
int srcx,
int srcy,
ALGUI_WIDGET *dst,
int *dstx,
int *dsty)
{
ALGUI_WIDGET *temp;
for(temp = src; temp; temp = temp->parent)
{
srcx += temp->x;
srcy += temp->y;
}
for(temp = dst; temp; temp = temp->parent)
{
srcx -= temp->x;
srcy -= temp->y;
}
*dstx = srcx;
*dsty = srcy;
}
void _hide(ALGUI_WIDGET *wgt)
{
wgt->visible = 0;
}
void hide(ALGUI_WIDGET *wgt)
{
visit_tree(wgt, _hide);
}
void _show(ALGUI_WIDGET *wgt)
{
wgt->visible = 1;
}
void show(ALGUI_WIDGET *wgt)
{
visit_tree(wgt, _show);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment