/***************************************************************************
gui_widget.h - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __GUI_WIDGET_H
#define __GUI_WIDGET_H
#include "list.h"
#include "stk.h"
#include "gui_theme.h"
//#define GUI_DEBUG
#define GUI_ABORT( msg ) \
{ fprintf( stderr, "Fatal GUI Error!\n%s\n", msg ); exit( 1 ); }
/*
====================================================================
GUI events
====================================================================
*/
/* types */
enum {
GUI_NONE = 0,
GUI_DESTROY, /* widget is deleted */
GUI_ACTIVATED,
GUI_DEACTIVATED, /* handle _input_ events or not */
GUI_DRAW, /* draw widget to stk_display */
GUI_TIME_PASSED, /* msecs since last TIME_PASSED event */
GUI_FOCUS_IN, /* widget lost focus */
GUI_FOCUS_OUT, /* widget gained focus */
GUI_MOTION, /* motion within widget */
GUI_BUTTON_PRESSED,
GUI_BUTTON_RELEASED, /* mouse button */
GUI_KEY_PRESSED,
GUI_KEY_RELEASED, /* key */
GUI_CLICKED, /* mouse button pressed + released */
GUI_CHANGED, /* type-dependent data changed */
GUI_ITEM_SELECTED,
GUI_ITEM_UNSELECTED /* list item (un)selected */
};
/* event */
typedef union {
int type;
struct {
int type;
int x, y, button;
} button;
struct {
int type;
int x, y, xrel, yrel;
int button; /* first button pressed */
int state; /* full button mask */
} motion;
struct {
int type;
int keysym;
int unicode;
} key;
struct {
int type;
int x, y;
} item;
struct {
int type;
int ms;
} time;
} GuiEvent;
/*
====================================================================
Return pointer to simple event (one that doesn't need
additional data)
====================================================================
*/
GuiEvent *gui_event_get_simple( int type );
/*
====================================================================
Initiate a GUI event from an SDL event.
====================================================================
*/
void gui_event_init( GuiEvent *gui_event, SDL_Event *sdl_event );
/*
====================================================================
GUI widget
====================================================================
*/
/* types */
enum {
GUI_BOX = 0,
GUI_BUTTON,
GUI_LABEL,
GUI_ICON,
GUI_PROGRESSBAR,
GUI_RADIOGROUP,
GUI_SCROLLBAR,
GUI_EDIT,
GUI_LIST,
GUI_SPINBUTTON
};
/* GUI widget -
for simplicity only one is used for all types */
typedef struct _GuiWidget {
struct _GuiWidget *parent; /* widget's parent */
struct _GuiWidget *root; /* widget's root (top parent) */
List *widgets; /* widget's children */
struct _GuiWidget *focused_widget; /* recursivly in widgets */
struct _GuiWidget *default_key_widget;
/* child 'default_key_widget' will grab key input if this
is a root widget that is shown */
int type; /* button, label, icon ... */
int visible; /* gui_widget_draw() updates screen */
int active; /* accept events */
int focused; /* mouse pointer somewhere in widget */
int grab_input; /* deny event handling to lower roots */
int grab_keys; /* grab key input if clicked */
int grab_focus; /* grab focus IF PRESSED thus motion events
are directly passed to widgets handler.
the focus is not updated until mouse button
is released again. */
int pressed; /* memorize 'button_pressed' event */
SDL_Rect screen_region; /* absolute region in screen (clipped) */
SDL_Rect parent_region; /* relative region in parent */
/* CALLBACKS */
void (*default_event_handler)(struct _GuiWidget*,GuiEvent*);
/* handles event and updates a widget (graphics etc) */
void (*user_event_handler)(struct _GuiWidget*,GuiEvent*);
/* user's possibility to react on event. is NOT called
from the default_event_handler but from
gui_widget_handle_event() itself. */
/* USED BY ALL WIDGETS BUT TYPE DEPENDANT */
int border; /* size of frame around widget */
int width, height; /* widget's size w/o border */
int event_mask; /* events passed to user's event_handler */
SDL_Surface *surface; /* picture of widget */
/* SPECS */
union {
/* LABEL */
struct {
StkFont *font;
int align; /* alignment of text */
char *text; /* text */
} label;
/* PROGRESSBAR */
struct {
int max; /* maximum value */
int value; /* current value */
int length; /* current length */
SDL_Surface *wallpaper; /* current beam wallpaper */
} progressbar;
/* RADIOGROUP */
struct {
int min; /* minimum selections required */
int max; /* minimum selections allowed */
int size; /* number of items */
int *checks; /* 'checked' flag for each item */
int check_count; /* number of selections */
int single_check; /* id of last item selected */
int x, y; /* position of first checkbox in parent */
int offset; /* offset from one item to next */
} radiogroup;
/* SCROLLBAR */
struct {
int vertical; /* vertical scrollbar? */
int button_size; /* size of (square) buttons */
int value; /* current value */
int min, max; /* range of value */
int step; /* offset for up/down */
int jump; /* offset for pgup/pgdown */
struct _GuiWidget *inc;
struct _GuiWidget *dec; /* pointers to 'widgets' */
struct _GuiWidget *track; /* special widget that is NOT
in the 'widgets' list */
} scrollbar;
/* EDIT */
struct {
int filter[SDLK_LAST]; /* characters accepted */
int multi_line; /* single-line edit or text area? */
int size; /* character limit */
char *buffer; /* string of edit */
char *display_buffer; /* contains 'height' lines of
length 'width' separated by \0 which will be
displayed when drawing. is rendered by
gui_edit_adjust_cursor() */
int length; /* current string length */
int width; /* characters per line */
int height; /* number of lines */
int x, y; /* position in visible characters */
int y_offset; /* used to center single-line edits */
int pos; /* position of edit cursor */
int start; /* first character displayed */
int line; /* first line displayed (start/width) */
} edit;
/* LIST */
struct {
int columns; /* (fixed) number of columns */
int item_width;
int item_height; /* item size */
int gap; /* space between items */
int rows_per_page; /* number of rows displayed */
int item_count; /* number of items */
int rows; /* number of rows */
int select_type; /* no, single, multi select */
int *checks; /* NO_SELECT: unused
SINGLE_SELECT: id of selected item
MULTI_SELECT: flags for all items
whether they are
selected or not */
SDL_Surface
*render_buffer; /* 'render_item' renders item
into this surface*/
int (*render_item)(int,int,SDL_Surface*); /* user
defined render callback to render item x,y into
surface. This item is only displayed
if 'render_item' returns True. */
struct _GuiWidget *scrollbar; /* pointer to
'widgets' */
} list;
/* SPINBUTTON */
struct {
int min, max, step; /* range of value */
int value; /* value */
struct _GuiWidget *edit; /* pointer to edit */
struct _GuiWidget *inc;
struct _GuiWidget *dec; /* pointer to buttons */
} spinbutton;
} spec;
} GuiWidget;
/*
====================================================================
Create a basic widget and setup things all different widget types
have in common. If a parent is specified this widget is added to
it's 'widgets' list. 'x' or 'y' -1 means to center the
widget.
====================================================================
*/
GuiWidget* gui_widget_create(
GuiWidget *parent, int type,
int x, int y, int width, int height,
void (*default_event_handler)(GuiWidget*,GuiEvent*),
void (*user_event_handler)(GuiWidget*,GuiEvent*) );
/*
====================================================================
This function will delete a root widget including all subwidgets.
Subwidgets can't be directly deleted. Resets the widget
pointer to NULL.
====================================================================
*/
void gui_widget_delete( GuiWidget **widget );
/*
====================================================================
If button is deactivated no input events (key,button,motion)
are handled.
====================================================================
*/
void gui_widget_set_active( GuiWidget *widget, int active );
/*
====================================================================
Draw the widget and its children if visible.
====================================================================
*/
void gui_widget_draw( GuiWidget *widget );
/*
====================================================================
Set 'visible' flag and draw widget (store update rects)
if either parent is visible or it has no parent.
(thus is a root window). If it is a root window add it to the
root window stack. This new window will handle incoming events
first.
====================================================================
*/
void gui_widget_show( GuiWidget *widget );
/*
====================================================================
Clear 'visible' flag and restore widget if parent is visible.
If there is no parent (thus is a root window) remove it from
stack and redraw the underlying window (which regains control). If
a root widget is hidden the background cannot be restored
as it is unknown.
====================================================================
*/
void gui_widget_hide( GuiWidget *widget );
/*
====================================================================
Modify the event mask of a widget to define which events will
be passed to user_event_handler. Update timed_stack if
GUI_TIME_PASSED is enabled/disabled.
====================================================================
*/
void gui_widget_enable_event( GuiWidget *widget, int event );
void gui_widget_disable_event( GuiWidget *widget, int event );
/*
====================================================================
Pass GuiEvent to user defined callback if it has been installed
and the event mask flag is True for this event.
====================================================================
*/
void gui_widget_call_user_event_handler(
GuiWidget *widget, GuiEvent *event );
/*
====================================================================
Handle the GUI event by calling the default_event_handler()
and the user_event_handler() if one has been installed.
====================================================================
*/
void gui_widget_handle_event( GuiWidget *widget, GuiEvent *event );
/*
====================================================================
Move widget within parent window by a relative value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_move( GuiWidget *widget, int rel_x, int rel_y );
/*
====================================================================
Move widget within parent window by an absolute value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_warp( GuiWidget *widget, int abs_x, int abs_y );
/*
====================================================================
Apply parents background or wallpaper within the frame (if
any) of the widget's surface.
====================================================================
*/
void gui_widget_apply_wallpaper(
GuiWidget *widget, SDL_Surface *wallpaper, int alpha );
/*
====================================================================
Browse the widget tree and set 'focused' true for all widgets
that have the mouse pointer above them. 'focused_widget'
returns the deepest widget that is focused.
====================================================================
*/
void gui_widget_update_focus(
GuiWidget *widget, int mx, int my, GuiWidget **focused_widget );
/*
====================================================================
Get direct access to widget's surface.
====================================================================
*/
SDL_Surface *gui_widget_get_surface( GuiWidget *widget );
/*
====================================================================
That key grabbing child of a root widget.
====================================================================
*/
void gui_widget_set_default_key_widget(
GuiWidget *root, GuiWidget *key_widget );
#endif