small update
This commit is contained in:
parent
8565b10159
commit
089eaa4b3c
97
Readme.md
97
Readme.md
|
@ -1,11 +1,31 @@
|
|||
# GUI
|
||||
This is a bloat-free stateless immedate mode graphical user interface toolkit
|
||||
written in ANSI C. It was designed to be embedded into graphical application and
|
||||
does not have any direct dependencies.
|
||||
The main premise of this toolkit is to be as stateless, simple but as powerful as
|
||||
possible with fast streamlined user development speed in mind.
|
||||
|
||||
WORK IN PROGRESS: I do not garantee that everything works right now
|
||||
## IMGUIs
|
||||
immediate mode in contrast to classic retained GUIs stores as little state as possible
|
||||
by using procedural function calls as "widgets" instead of storing objects.
|
||||
Each "widget" function call takes hereby all its neccessary data and immediatly returns
|
||||
the through the user modified state back to the caller. Immediate mode graphical
|
||||
user interfaces therefore combine drawing and input handling into one unit
|
||||
instead of seperating them like retrain mode GUIs.
|
||||
|
||||
Since there is no to minimal internal state in immediate mode user interfaces,
|
||||
updates have to occur every frame which on one hand is more drawing expensive than classic
|
||||
ratained GUI implementations but on the other hand grants a lot more flexibility and
|
||||
support for overall changes. In addition without any state there is no need to
|
||||
transfer state between your program, the gui state and the user which greatly
|
||||
simplifies code. Further traits of immediate mode graphic user interfaces are a
|
||||
code driven style, centralized flow control, easy extensibility and
|
||||
understandablity.
|
||||
|
||||
## Features
|
||||
- Immediate mode graphical user interface toolkit
|
||||
- Written in C89 (ANSI C)
|
||||
- Small codebase with roughly 2kLOC
|
||||
- Small codebase (~2kLOC)
|
||||
- Focus on portability and minimal internal state
|
||||
- Suited for embedding into graphical applications
|
||||
- No global hidden state
|
||||
|
@ -15,32 +35,71 @@ WORK IN PROGRESS: I do not garantee that everything works right now
|
|||
- Configurable
|
||||
- UTF-8 supported
|
||||
|
||||
## Functionality
|
||||
+ Label
|
||||
+ Buttons(Text, Triangle, Color, Toggle, Icon)
|
||||
+ Slider
|
||||
+ Progressbar
|
||||
+ Checkbox
|
||||
+ Radiobutton
|
||||
+ Input field
|
||||
+ Spinner
|
||||
+ Selector
|
||||
+ Linegraph
|
||||
+ Histogram
|
||||
+ Panels
|
||||
+ Layouts(Tabs, Groups, Shelf)
|
||||
|
||||
## Limitations
|
||||
- Needs a high frame rate loop
|
||||
- Does NOT provide window management
|
||||
- Does NOT provide input handling
|
||||
- Does NOT provide a renderer backend
|
||||
- Does NOT provide overlapping panels
|
||||
- Does NOT implement a font library
|
||||
- Does NOT implement a font library
|
||||
- Does NOT provide overlapping panels
|
||||
Summary: It is only responsible for the actual user interface
|
||||
|
||||
#### Widgets
|
||||
## API
|
||||
The API for this gui toolkit is divided into two different layers. There
|
||||
is the widget layer and the panel layer. The widget layer provides a number of
|
||||
classical widgets in functional immediate mode form without any kind of internal
|
||||
state. Each widget can be placed anywhere on the screen but there is no directy
|
||||
way provided to group widgets together. For this to change there is the panel
|
||||
layer which is build on top of the widget layer and uses most of the widget API
|
||||
internally to form groups of widgets into a layout.
|
||||
|
||||
### Widgets
|
||||
The minimal widget API provides a basic number of widgets and is designed for
|
||||
uses cases where only a small number of basic widgets are needed without any kind of
|
||||
more complex layouts. In order for the GUI to work each widget needs a canvas to
|
||||
draw to, positional and widgets specific data as well as user input
|
||||
and returns the from the user input modified state of the widget.
|
||||
|
||||
```c
|
||||
struct gui_input in = {0};
|
||||
struct gui_canvas canvas = {...};
|
||||
struct gui_button style = {...};
|
||||
gui_default_config(&config);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
if(gui_button_text(&canvas, 0, 0, 100, 30, &style, "ok", GUI_BUTTON_DEFAULT, &input))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
}
|
||||
```
|
||||
|
||||
#### Panels
|
||||
### Panels
|
||||
To further extend the basic widget layer and remove some of the boilerplate
|
||||
code the panel was introduced. The panel groups together a number of
|
||||
widgets but in true immediate mode fashion does not save any widget state from
|
||||
widgets that have been added to the panel. In addition the panel enables a
|
||||
number of nice features for a group of widgets like panel movement, scaling,
|
||||
closing and minimizing. An additional use for panels is to further group widgets
|
||||
in panels to tabs, groups and shelfs. The state of internal panels (tabs,
|
||||
groups. shelf) is only needed over the course of the build up unlike normal
|
||||
panels, which further emphasizes the minimal state mindset.
|
||||
|
||||
```c
|
||||
struct gui_config config;
|
||||
struct gui_input in = {0};
|
||||
|
@ -62,23 +121,37 @@ while (1) {
|
|||
gui_panel_end(&panel);
|
||||
}
|
||||
```
|
||||
## Canvas
|
||||
The Canvas is the abstract drawing interface between the GUI toolkit
|
||||
and the user and contains drawing callbacks for the primitives
|
||||
scissor, line, rectangle, circle, triangle, bitmap and text which need to be
|
||||
provided by the user. In addition to the drawing callbacks the canvas contains
|
||||
font data and the width and height of the canvas drawing area.
|
||||
Therefore the canvas is the heart of the toolkit and is probably the biggest
|
||||
chunk of work to be done by the user.
|
||||
|
||||
## Configuration
|
||||
The gui toolkit provides a number of different attributes that can be
|
||||
configured, like spacing, padding, size and color.
|
||||
While the widget API even expects you to provide the configuration
|
||||
for each and every widget the higher layers provide you with a set of
|
||||
for each and every widget the panel layer provides you with a set of
|
||||
attributes in the `gui_config` structure. The structure either needs to be
|
||||
filled by the user or can be setup with some default values by the function
|
||||
`gui_default_config`. Modification on the fly to the `gui_config` is in
|
||||
`gui_default_config`. Modification on the fly to the `gui_config` struct is in
|
||||
true immedate mode fashion possible and supported.
|
||||
|
||||
## FAQ
|
||||
#### Where is Widget X?
|
||||
A number of basic widgets are provided but some of the more complex widgets like
|
||||
comboboxes, tables and trees are not yet implemented. Maybe if I have more
|
||||
time I will look into adding them, except for comboboxes which are just
|
||||
really hard to implement.
|
||||
time I will look into adding them. Except for comboboxes which are just
|
||||
really hard to implement, but for a smaller datasets there is the selector
|
||||
widget or you could combine a tab with a group and toggle buttons.
|
||||
|
||||
#### Where is the demo/example code
|
||||
The demo and example code can be found in the demo folder. For now there is
|
||||
only example code for Linux with X11 and Xlib but a Win32, OpenGL and Directx
|
||||
demo is in the working.
|
||||
|
||||
#### Why did you use ANSI C and not C99 or C++?
|
||||
Personally I stay out of all "discussions" about C vs C++ since they are totally
|
||||
|
|
|
@ -505,7 +505,7 @@ main(int argc, char *argv[])
|
|||
|
||||
/* GUI */
|
||||
XClearWindow(xw.dpy, xw.win);
|
||||
surface_clear(canvas.userdata, 0x002D2D2D);
|
||||
surface_clear(canvas.userdata, 0x00646464);
|
||||
canvas.width = xw.width; canvas.height = xw.height;
|
||||
running = gui_panel_begin(&panel, "Demo", panel.x, panel.y, panel.w, panel.h,
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_BORDER|
|
||||
|
|
18
gui.c
18
gui.c
|
@ -1021,8 +1021,6 @@ gui_panel_begin(struct gui_panel *panel, const char *text, gui_float x, gui_floa
|
|||
panel->index = 0;
|
||||
panel->row_columns = 0;
|
||||
panel->flags = f;
|
||||
if (!(panel->flags & GUI_PANEL_TAB))
|
||||
panel->flags |= GUI_PANEL_SCROLLBAR;
|
||||
|
||||
config = panel->config;
|
||||
panel->header_height = canvas->font.height + 3 * config->item_padding.y;
|
||||
|
@ -1058,17 +1056,27 @@ gui_panel_begin(struct gui_panel *panel, const char *text, gui_float x, gui_floa
|
|||
}
|
||||
}
|
||||
|
||||
header = &config->colors[GUI_COLOR_TITLEBAR];
|
||||
header_x = panel->x + config->panel_padding.x;
|
||||
header_w = panel->w - 2 * config->panel_padding.x;
|
||||
mouse_x = (panel->in) ? panel->in->mouse_pos.x : -1;
|
||||
mouse_y = (panel->in) ? panel->in->mouse_pos.y: -1;
|
||||
clicked_x = (panel->in) ? panel->in->mouse_clicked_pos.x: - 1;
|
||||
clicked_y = (panel->in) ? panel->in->mouse_clicked_pos.y: - 1;
|
||||
|
||||
header = &config->colors[GUI_COLOR_TITLEBAR];
|
||||
header_x = panel->x + config->panel_padding.x;
|
||||
header_w = panel->w - 2 * config->panel_padding.x;
|
||||
panel->width = panel->w;
|
||||
panel->at_y = panel->y;
|
||||
canvas->draw_rect(canvas->userdata, panel->x, panel->y, panel->w, panel->header_height, *header);
|
||||
|
||||
if (!(panel->flags & GUI_PANEL_TAB)) {
|
||||
panel->flags |= GUI_PANEL_SCROLLBAR;
|
||||
if (in && in->mouse_down) {
|
||||
if (!INBOX(clicked_x, clicked_y, panel->x, panel->y, panel->w, panel->h))
|
||||
panel->flags &= (gui_flag)~GUI_PANEL_ACTIVE;
|
||||
else panel->flags |= GUI_PANEL_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
panel->clip.x = panel->x;
|
||||
panel->clip.w = panel->w;
|
||||
panel->clip.y = panel->y + panel->header_height - 1;
|
||||
|
|
17
gui.h
17
gui.h
|
@ -63,12 +63,6 @@ typedef void(*gui_draw_bitmap)(void*, gui_float, gui_float, gui_float, gui_float
|
|||
typedef void(*gui_draw_text)(void*, gui_float, gui_float, gui_float, gui_float,
|
||||
const gui_char*, gui_size, const struct gui_font*,
|
||||
struct gui_color, struct gui_color);
|
||||
struct gui_font {
|
||||
void *userdata;
|
||||
gui_float height;
|
||||
gui_text_width_f width;
|
||||
};
|
||||
|
||||
enum gui_keys {
|
||||
GUI_KEY_SHIFT,
|
||||
GUI_KEY_CTRL,
|
||||
|
@ -92,6 +86,12 @@ struct gui_input {
|
|||
struct gui_vec2 mouse_clicked_pos;
|
||||
};
|
||||
|
||||
struct gui_font {
|
||||
void *userdata;
|
||||
gui_float height;
|
||||
gui_text_width_f width;
|
||||
};
|
||||
|
||||
struct gui_canvas {
|
||||
void *userdata;
|
||||
gui_size width;
|
||||
|
@ -253,8 +253,9 @@ enum gui_panel_flags {
|
|||
GUI_PANEL_MOVEABLE = 0x10,
|
||||
GUI_PANEL_SCALEABLE = 0x20,
|
||||
/* internal */
|
||||
GUI_PANEL_SCROLLBAR = 0x40,
|
||||
GUI_PANEL_TAB = 0x80
|
||||
GUI_PANEL_ACTIVE = 0x40,
|
||||
GUI_PANEL_SCROLLBAR = 0x80,
|
||||
GUI_PANEL_TAB = 0x100
|
||||
};
|
||||
|
||||
struct gui_panel {
|
||||
|
|
Loading…
Reference in New Issue