387 lines
15 KiB
C
387 lines
15 KiB
C
/***************************************************************************
|
|
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
|