mii_emu/libmui/mui/mui.h
Michel Pollet ab8a746bc8
Mostly libmui general cleanup
Moved the new drwable control in it's own file. Removed unused headers
etc etc.

Signed-off-by: Michel Pollet <buserror@gmail.com>
2024-02-15 10:45:46 +00:00

1100 lines
29 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* mui.h
*
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
*
* SPDX-License-Identifier: MIT
*/
/*
* This is the main include file for the libmui UI library, it should be
* the only one you need to include.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <pixman.h>
#include "c2_arrays.h"
#include "bsd_queue.h"
#include "stb_ttc.h"
/* Four Character Constants are used everywhere. Wish this had become a standard,
* as it is so handy -- but nope, thus the macro. Annoyingly, the little-
* endianess of them makes it a pain to do a printf() with them, this is why
* the values are reversed here.
*/
#ifndef FCC
#define FCC(_a,_b,_c,_d) (((_d)<<24)|((_c)<<16)|((_b)<<8)|(_a))
#endif
enum mui_event_e {
MUI_EVENT_KEYUP = 0,
MUI_EVENT_KEYDOWN,
MUI_EVENT_BUTTONUP,
MUI_EVENT_BUTTONDOWN,
MUI_EVENT_WHEEL,
MUI_EVENT_DRAG,
// the following ones aren't supported yet
MUI_EVENT_MOUSEENTER,
MUI_EVENT_MOUSELEAVE,
MUI_EVENT_RESIZE,
MUI_EVENT_CLOSE,
MUI_EVENT_COUNT,
};
enum mui_key_e {
MUI_KEY_ESCAPE = 0x1b,
MUI_KEY_LEFT = 0x80,
MUI_KEY_UP,
MUI_KEY_RIGHT,
MUI_KEY_DOWN,
MUI_KEY_INSERT,
MUI_KEY_HOME,
MUI_KEY_END,
MUI_KEY_PAGEUP,
MUI_KEY_PAGEDOWN,
MUI_KEY_MODIFIERS = 0x90,
MUI_KEY_LSHIFT = MUI_KEY_MODIFIERS,
MUI_KEY_RSHIFT,
MUI_KEY_LCTRL,
MUI_KEY_RCTRL,
MUI_KEY_LALT,
MUI_KEY_RALT,
MUI_KEY_RSUPER,
MUI_KEY_LSUPER,
MUI_KEY_MODIFIERS_LAST,
MUI_KEY_F1 = 0x100,
MUI_KEY_F2,
MUI_KEY_F3,
MUI_KEY_F4,
MUI_KEY_F5,
MUI_KEY_F6,
MUI_KEY_F7,
MUI_KEY_F8,
MUI_KEY_F9,
MUI_KEY_F10,
MUI_KEY_F11,
MUI_KEY_F12,
};
enum mui_modifier_e {
MUI_MODIFIER_LSHIFT = (1 << (MUI_KEY_LSHIFT - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_RSHIFT = (1 << (MUI_KEY_RSHIFT - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_LCTRL = (1 << (MUI_KEY_LCTRL - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_RCTRL = (1 << (MUI_KEY_RCTRL - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_LALT = (1 << (MUI_KEY_LALT - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_RALT = (1 << (MUI_KEY_RALT - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_RSUPER = (1 << (MUI_KEY_RSUPER - MUI_KEY_MODIFIERS)),
MUI_MODIFIER_LSUPER = (1 << (MUI_KEY_LSUPER - MUI_KEY_MODIFIERS)),
// special flag, trace events handling for this event
MUI_MODIFIER_EVENT_TRACE= (1 << 15),
MUI_MODIFIER_SHIFT = (MUI_MODIFIER_LSHIFT | MUI_MODIFIER_RSHIFT),
MUI_MODIFIER_CTRL = (MUI_MODIFIER_LCTRL | MUI_MODIFIER_RCTRL),
MUI_MODIFIER_ALT = (MUI_MODIFIER_LALT | MUI_MODIFIER_RALT),
MUI_MODIFIER_SUPER = (MUI_MODIFIER_LSUPER | MUI_MODIFIER_RSUPER),
};
/*
* The following constants are in UTF8 format, and relate to glyphs in
* the TTF fonts
*/
/* These are from the icon font */
#define MUI_ICON_FOLDER ""
#define MUI_ICON_FOLDER_OPEN ""
#define MUI_ICON_ROOT ""
#define MUI_ICON_FILE ""
#define MUI_ICON_POPUP_ARROWS ""
#define MUI_ICON_HOME ""
#define MUI_ICON_SBAR_UP ""
#define MUI_ICON_SBAR_DOWN ""
/* These are specific to our custom version of the Charcoal System font */
#define MUI_GLYPH_APPLE "" // solid apple
#define MUI_GLYPH_OAPPLE "" // open apple
#define MUI_GLYPH_COMMAND ""
#define MUI_GLYPH_OPTION ""
#define MUI_GLYPH_CONTROL ""
#define MUI_GLYPH_SHIFT ""
#define MUI_GLYPH_TICK "" // tickmark for menus
#define MUI_GLYPH_SUBMENU "" // custom, for the hierarchical menus
#define MUI_GLYPH_IIE "" // custom, IIe glyph
/* These are also from Charcoal System font (added to the original) */
#define MUI_GLYPH_F1 ""
#define MUI_GLYPH_F2 ""
#define MUI_GLYPH_F3 ""
#define MUI_GLYPH_F4 ""
#define MUI_GLYPH_F5 ""
#define MUI_GLYPH_F6 ""
#define MUI_GLYPH_F7 ""
#define MUI_GLYPH_F8 ""
#define MUI_GLYPH_F9 ""
#define MUI_GLYPH_F10 ""
#define MUI_GLYPH_F11 ""
#define MUI_GLYPH_F12 ""
typedef uint64_t mui_time_t;
/*
* Event description. pretty standard stuff here -- the 'when' field is
* only used really to detect double clicks so far.
*
* Even handlers should return true if the event was handled, (in which case
* even processing stops for that event) or false to continue passing the even
* down the chain.
*
* Events are passed to the top window first, and then down the chain of
* windows, until one of them returns true.
* Implicitely, it means the menubar gets to see the events first, even clicks,
* even if the click wasn't in the menubar. This is also true of key events of
* course, which allows the menu to detect key combos, first.
*/
typedef struct mui_event_t {
uint8_t type;
mui_time_t when;
uint32_t modifiers;
union {
struct key {
uint32_t key;
bool up;
} key;
struct {
uint32_t button;
c2_pt_t where;
} mouse;
struct {
int32_t delta;
c2_pt_t where;
} wheel;
};
} mui_event_t;
/*
* Key equivalent, used to match key events to menu items
* Might be extended to controls, right now only the 'key' is checked,
* mostly for Return and ESC.
*/
typedef union mui_key_equ_t {
struct {
uint16_t mod;
uint16_t key;
};
uint32_t value;
} mui_key_equ_t;
#define MUI_KEY_EQU(_mask, _key) \
(mui_key_equ_t){ .mod = (_mask), .key = (_key) }
struct mui_t;
typedef struct mui_listbox_elem_t {
uint32_t disabled : 1;
char icon[8];
void * elem; // char * or... ?
} mui_listbox_elem_t;
DECLARE_C_ARRAY(mui_listbox_elem_t, mui_listbox_elems, 2);
IMPLEMENT_C_ARRAY(mui_listbox_elems);
struct mui_control_t;
struct mui_window_t;
struct mui_listbox_elem_t;
/*
* Window DEFinition -- Handle all related to a window, from drawing to
* event handling.
*/
enum {
MUI_WDEF_INIT = 0,
MUI_WDEF_DISPOSE,
MUI_WDEF_DRAW,
MUI_WDEF_EVENT,
};
typedef bool (*mui_wdef_p)(
struct mui_window_t * win,
uint8_t what,
void * param);
enum mui_cdef_e {
MUI_CDEF_INIT = 0,
MUI_CDEF_DISPOSE,
MUI_CDEF_DRAW,
MUI_CDEF_EVENT,
MUI_CDEF_SET_STATE,
MUI_CDEF_SET_VALUE,
MUI_CDEF_SET_TITLE,
MUI_CDEF_SELECT,
};
typedef bool (*mui_cdef_p)(
struct mui_control_t * c,
uint8_t what,
void * param);
typedef void (*mui_ldef_p)(
struct mui_control_t * c,
uint32_t elem_index,
struct mui_listbox_elem_t * elem);
/*
* Timer callback definition. Behaves in a pretty standard way; the timer
* returns 0 to be cancelled (for one shot timers for example) or return
* the delay to the next call.
*/
typedef mui_time_t (*mui_timer_p)(
struct mui_t * mui,
mui_time_t now,
void * param);
/*
* Actions are the provided way to add custom response to events for the
* application; action handlers are called for a variety of things, from clicks
* in controls, to menu selections, to window close etc.
*
* The 'what' parameter is a 4 character code, that can be used to identify
* the action, and the 'param' is a pointer to a structure that depends on
* the 'what' action (hopefully documented with that action constant)
*
* the 'cb_param' is specific to this action function pointer and is passed as
* is to the callback.
*/
typedef int (*mui_window_action_p)(
struct mui_window_t * win,
void * cb_param,
uint32_t what,
void * param);
typedef int (*mui_control_action_p)(
struct mui_control_t *c,
void * cb_param,
uint32_t what,
void * param);
/*
* This is a standardized way of installing 'action' handlers onto windows
* and controls. The 'current' field is used to prevent re-entrance. This structure
* is opaque and is not accessible by the application, typically.
*/
typedef struct mui_action_t {
STAILQ_ENTRY(mui_action_t) self;
uint32_t current; // prevents re-entrance
union {
mui_window_action_p window_cb;
mui_control_action_p control_cb;
};
void * cb_param;
} mui_action_t;
typedef STAILQ_HEAD(, mui_action_t) mui_action_queue_t;
struct cg_surface_t;
struct cg_ctx_t;
/*
* Describes a pixmap. Currently only used for the screen destination pixels.
* And really, only bpp:32 for ARGB is supported.
*/
typedef struct mui_pixmap_t {
uint8_t * pixels;
uint32_t bpp : 8;
c2_pt_t size;
uint32_t row_bytes;
} mui_pixmap_t;
typedef pixman_region32_t mui_region_t;
DECLARE_C_ARRAY(mui_region_t, mui_clip_stack, 2);
/*
* The Drawable is a drawing context -- currently there's only one for the
* whole screen, but technically we could have several. The important feature
* of this is that it keeps a context for the pixman library destination
* image, AND also the context for the 'cg' vectorial library.
* Furthermore it keeps track of a stack of clipping rectangles, and is able
* to 'sync' the current clipping area for either (or both) cg and libpixman.
*
* Important note: the cg vectorial library coordinate system is placed on the
* space *between* pixels, ie, if you moveto(1,1) and draw a line down, you
* will light up pixels in columns zero AND one. This differs significantly from
* for example, pixman that is uses pixel coordinates on hard pixels.
* It's worth remembering as if you draw for example around the border of a
* control, it will very likely be 'clipped' somewhat because half the pixels
* are technically outside the control bounding/clipping rectangle.
* You can easily adjust for this by adding 0.5 to the coordinates, if you
* require it.
*/
typedef struct mui_drawable_t {
mui_pixmap_t pix; // *has* to be first in struct
void * _pix_hash; // used to detect if pix has changed
struct cg_surface_t * cg_surface;
struct cg_ctx_t * cg;
union pixman_image * pixman; // (try) not to use these directly
unsigned int pixman_clip_dirty: 1,
cg_clip_dirty : 1,
dispose_pixels : 1,
dispose_drawable : 1;
// not used internally, but useful for the application
unsigned int texture_id;
// (default) position in destination when drawing
c2_pt_t origin;
mui_clip_stack_t clip;
} mui_drawable_t;
// Use IMPLEMENT_C_ARRAY(mui_drawable_array); if you need this
DECLARE_C_ARRAY(mui_drawable_t *, mui_drawable_array, 4);
/*
* Drawable related
*/
/* create a new mui_draware of size w x h, bpp depth.
* Optionally allocate the pixels if pixels is NULL. Allocated pixels
* are not cleared. */
mui_drawable_t *
mui_drawable_new(
c2_pt_t size,
uint8_t bpp,
void * pixels, // if NULL, will allocate
uint32_t row_bytes);
/* initialize a mui_drawable_t structure with the given parameters
* note it is not assumed 'd' contains anything valid, it will be
* overwritten */
mui_drawable_t *
mui_drawable_init(
mui_drawable_t * d,
c2_pt_t size,
uint8_t bpp,
void * pixels, // if NULL, will allocate
uint32_t row_bytes);
void
mui_drawable_dispose(
mui_drawable_t * dr);
// get/allocate a pixman structure for this drawable
union pixman_image *
mui_drawable_get_pixman(
mui_drawable_t * dr);
// get/allocate a cg drawing context for this
struct cg_ctx_t *
mui_drawable_get_cg(
mui_drawable_t * dr);
// return 0 (no intersect), 1: fully contained and 2: partial contains
int
mui_drawable_clip_intersects(
mui_drawable_t * dr,
c2_rect_p r );
void
mui_drawable_set_clip(
mui_drawable_t * dr,
c2_rect_array_p clip );
int
mui_drawable_clip_push(
mui_drawable_t * dr,
c2_rect_p r );
int
mui_drawable_clip_push_region(
mui_drawable_t * dr,
pixman_region32_t * rgn );
int
mui_drawable_clip_substract_region(
mui_drawable_t * dr,
pixman_region32_t * rgn );
void
mui_drawable_clip_pop(
mui_drawable_t * dr );
pixman_region32_t *
mui_drawable_clip_get(
mui_drawable_t * dr);
/*
* Your typical ARGB color. Note that the components are NOT
* alpha-premultiplied at this stage.
* This struct should be able to be passed as a value, not a pointer
*/
typedef union mui_color_t {
struct {
uint8_t a,r,g,b;
} __attribute__((packed));
uint32_t value;
uint8_t v[4];
} mui_color_t;
typedef struct mui_control_color_t {
mui_color_t fill, frame, text;
} mui_control_color_t;
#define MUI_COLOR(_v) ((mui_color_t){ .value = (_v)})
#define CG_COLOR(_c) (struct cg_color_t){ \
.a = (_c).a / 255.0, .r = (_c).r / 255.0, \
.g = (_c).g / 255.0, .b = (_c).b / 255.0 }
/*
* Pixman use premultiplied alpha values
*/
#define PIXMAN_COLOR(_c) (pixman_color_t){ \
.alpha = (_c).a * 257, .red = (_c).r * (_c).a, \
.green = (_c).g * (_c).a, .blue = (_c).b * (_c).a }
typedef struct mui_font_t {
mui_drawable_t font; // points to ttc pixels!
char * name; // not filename, internal name, aka 'main'
unsigned int size; // in pixels
TAILQ_ENTRY(mui_font_t) self;
struct stb_ttc_info ttc;
} mui_font_t;
/*
* Font related
*/
void
mui_font_init(
struct mui_t * ui);
void
mui_font_dispose(
struct mui_t * ui);
mui_font_t *
mui_font_find(
struct mui_t * ui,
const char * name);
mui_font_t *
mui_font_from_mem(
struct mui_t * ui,
const char *name,
unsigned int size,
const void *font_data,
unsigned int font_size );
void
mui_font_text_draw(
mui_font_t * font,
mui_drawable_t *dr,
c2_pt_t where,
const char * text,
unsigned int text_len,
mui_color_t color);
int
mui_font_text_measure(
mui_font_t * font,
const char * text,
struct stb_ttc_measure *m );
enum mui_text_align_e {
MUI_TEXT_ALIGN_LEFT = 0,
MUI_TEXT_ALIGN_CENTER = (1 << 0),
MUI_TEXT_ALIGN_RIGHT = (1 << 1),
MUI_TEXT_ALIGN_TOP = 0,
MUI_TEXT_ALIGN_MIDDLE = (MUI_TEXT_ALIGN_CENTER << 2),
MUI_TEXT_ALIGN_BOTTOM = (MUI_TEXT_ALIGN_RIGHT << 2),
};
void
mui_font_textbox(
mui_font_t * font,
mui_drawable_t *dr,
c2_rect_t bbox,
const char * text,
unsigned int text_len,
mui_color_t color,
uint16_t flags );
DECLARE_C_ARRAY(unsigned int, mui_glyph_array, 8, int x, y, w; );
DECLARE_C_ARRAY(mui_glyph_array_t, mui_glyph_line_array, 8);
/*
* Measure a text string, return the number of lines, and each glyphs
* position already aligned to the MUI_TEXT_ALIGN_* flags.
*/
void
mui_font_measure(
mui_font_t * font,
c2_rect_t bbox,
const char * text,
unsigned int text_len,
mui_glyph_line_array_t *lines,
uint16_t flags);
// to be used exclusively with mui_font_measure
void
mui_font_measure_draw(
mui_font_t *font,
mui_drawable_t *dr,
c2_rect_t bbox,
mui_glyph_line_array_t *lines,
mui_color_t color,
uint16_t flags);
// clear all the lines, and glyph lists. Use it after mui_font_measure
void
mui_font_measure_clear(
mui_glyph_line_array_t *lines);
enum mui_window_layer_e {
MUI_WINDOW_LAYER_NORMAL = 0,
MUI_WINDOW_LAYER_MODAL = 3,
MUI_WINDOW_LAYER_ALERT = 5,
MUI_WINDOW_LAYER_TOP = 15,
// Menubar and Menus (popups) are also windows
MUI_WINDOW_MENUBAR_LAYER = MUI_WINDOW_LAYER_TOP - 1,
MUI_WINDOW_MENU_LAYER,
};
enum mui_window_action_e {
MUI_WINDOW_ACTION_NONE = 0,
MUI_WINDOW_ACTION_CLOSE = FCC('w','c','l','s'),
};
typedef struct mui_window_t {
TAILQ_ENTRY(mui_window_t) self;
struct mui_t * ui;
mui_wdef_p wdef;
uint32_t uid; // optional, pseudo unique id
struct {
unsigned long hidden: 1,
zombie: 1, // is in pre-delete ui->zombies
layer : 4,
hit_part : 8;
} flags;
c2_pt_t click_loc;
struct mui_drawable_t * dr;
// both these rectangles are in screen coordinates, even tho
// 'contents' is fully included in 'frame'
c2_rect_t frame, content;
char * title;
mui_action_queue_t actions;
TAILQ_HEAD(controls, mui_control_t) controls;
// anything deleted during an action goes in zombies
TAILQ_HEAD(zombies, mui_control_t) zombies;
struct mui_control_t * control_clicked;
mui_region_t inval;
} mui_window_t;
/*
* Window related
*/
/*
* This is the main function to create a window. The
* * 'wdef' is the window definition (or NULL for a default window).
* see mui_wdef_p for the callback definition.
* * 'layer' layer to put it in (default to zero for normal windows)
* * 'instance_size' zero (for default) or the size of the window instance
* object that is returned, you can therefore have your own custom field
* attached to a window.
*/
mui_window_t *
mui_window_create(
struct mui_t * ui,
c2_rect_t frame,
mui_wdef_p wdef,
uint8_t layer,
const char * title,
uint32_t instance_size);
// Dispose of a window and it's content (controls).
/*
* Note: if an action is in progress the window is not freed immediately
* but added to the zombie list, and freed when the action is done.
* This is to prevent re-entrance problems. This allows window actions to
* delete their own window without crashing.
*/
void
mui_window_dispose(
mui_window_t * win);
// Invalidate 'r' in window coordinates, or the whole window if 'r' is NULL
void
mui_window_inval(
mui_window_t * win,
c2_rect_t * r);
// return true if the window is the frontmost window (in that window's layer)
bool
mui_window_isfront(
mui_window_t * win);
// return the top (non menubar/menu) window
mui_window_t *
mui_window_front(
struct mui_t *ui);
// move win to the front (of its layer), return true if it was moved
bool
mui_window_select(
mui_window_t * win);
// call the window action callback, if any
void
mui_window_action(
mui_window_t * c,
uint32_t what,
void * param );
// add an action callback for this window
void
mui_window_set_action(
mui_window_t * c,
mui_window_action_p cb,
void * param );
// return the window whose UID is 'uid', or NULL if not found
mui_window_t *
mui_window_get_by_id(
struct mui_t * ui,
uint32_t uid );
// set the window UID
void
mui_window_set_id(
mui_window_t * win,
uint32_t uid);
struct mui_menu_items_t;
/*
* This is a menu item descriptor (also used for the titles, bar a few bits).
* This is not a *control* in the window, instead this is used to describe
* the menus and menu item controls that are created when the menu becomes
* visible.
*/
typedef struct mui_menu_item_t {
uint32_t disabled : 1, hilited : 1;
uint32_t index: 9;
uint32_t uid;
char * title;
char mark[8]; // UTF8 -- Charcoal
char icon[8]; // UTF8 -- Wider, icon font
char kcombo[16]; // UTF8 -- display only
mui_key_equ_t key_equ; // keystroke to select this item
struct mui_menu_item_t * submenu;
c2_pt_t location; // calculated by menu creation code
} mui_menu_item_t;
/*
* The menu item array is atypical as the items ('e' field) are not allocated
* by the array, but by the menu creation code. This is because the menu
* reuses the pointer to the items that is passed when the menu is added to
* the menubar.
* the 'read only' field is used to prevent the array from trying to free the
* items when being disposed.
*/
DECLARE_C_ARRAY(mui_menu_item_t, mui_menu_items, 2,
bool read_only; );
IMPLEMENT_C_ARRAY(mui_menu_items);
enum mui_menubar_action_e {
// parameter is a mui_menu_item_t* for the first item of the menu,
// this is exactly the parameter passed to add_simple()
// you can use this to disable/enable menu items etc
MUI_MENUBAR_ACTION_PREPARE = FCC('m','b','p','r'),
// parameter 'target' is a mui_menuitem_t*
MUI_MENUBAR_ACTION_SELECT = FCC('m','b','a','r'),
};
/*
* Menu related.
* Menubar, and menus/popups are windows as well, in a layer above the
* normal ones.
*/
mui_window_t *
mui_menubar_new(
struct mui_t * ui );
// return the previously created menubar (or NULL)
mui_window_t *
mui_menubar_get(
struct mui_t * ui );
/*
* Add a menu to the menubar. 'items' is an array of mui_menu_item_t
* terminated by an element with a NULL title.
* Note: The array is NOT const, it will be tweaked for storing items position,
* it can also be tweaked to set/reset the disabled state, check marks etc
*/
struct mui_control_t *
mui_menubar_add_simple(
mui_window_t * win,
const char * title,
uint32_t menu_uid,
mui_menu_item_t * items );
/* Turn off any highlighted menu titles */
mui_window_t *
mui_menubar_highlight(
mui_window_t * win,
bool ignored );
enum mui_button_style_e {
MUI_BUTTON_STYLE_NORMAL = 0,
MUI_BUTTON_STYLE_DEFAULT = 1,
MUI_BUTTON_STYLE_RADIO,
MUI_BUTTON_STYLE_CHECKBOX,
};
enum mui_control_state_e {
MUI_CONTROL_STATE_NORMAL = 0,
MUI_CONTROL_STATE_HOVER,
MUI_CONTROL_STATE_CLICKED,
MUI_CONTROL_STATE_DISABLED,
MUI_CONTROL_STATE_COUNT
};
enum mui_control_action_e {
MUI_CONTROL_ACTION_NONE = 0,
MUI_CONTROL_ACTION_VALUE_CHANGED = FCC('c','v','a','l'),
MUI_CONTROL_ACTION_CLICKED = FCC('c','l','k','d'),
MUI_CONTROL_ACTION_SELECT = FCC('c','s','e','l'),
MUI_CONTROL_ACTION_DOUBLECLICK = FCC('c','d','c','l'),
};
/*
* Control record... this are the 'common' fields, most of the controls
* have their own 'extended' record using their own fields.
*/
typedef struct mui_control_t {
TAILQ_ENTRY(mui_control_t) self;
struct mui_window_t * win;
mui_cdef_p cdef;
uint32_t state;
uint32_t type;
uint32_t style;
struct {
unsigned int hidden : 1,
zombie : 1,
hit_part : 8;
} flags;
uint32_t value;
uint32_t uid;
uint32_t uid_mask; // for radio buttons
c2_rect_t frame;
mui_key_equ_t key_equ; // keystroke to select this control
char * title;
mui_action_queue_t actions;
} mui_control_t;
/*
* Control related
*/
/*
* This is the 'low level' control creation function, you can pass the
* 'cdef' function pointer and a control 'type' that will be passed to it,
* so you can implement variants of controls.
* The instance_size is the size of the extended control record, if any.
*/
mui_control_t *
mui_control_new(
mui_window_t * win,
uint32_t type, // specific to the CDEF
mui_cdef_p cdef,
c2_rect_t frame,
const char * title,
uint32_t uid,
uint32_t instance_size );
void
mui_control_dispose(
mui_control_t * c );
uint32_t
mui_control_get_type(
mui_control_t * c );
uint32_t
mui_control_get_uid(
mui_control_t * c );
mui_control_t *
mui_control_locate(
mui_window_t * win,
c2_pt_t pt );
mui_control_t *
mui_control_get_by_id(
mui_window_t * win,
uint32_t uid );
void
mui_control_inval(
mui_control_t * c );
void
mui_control_action(
mui_control_t * c,
uint32_t what,
void * param );
void
mui_control_set_action(
mui_control_t * c,
mui_control_action_p cb,
void * param );
void
mui_control_set_state(
mui_control_t * c,
uint32_t state );
uint32_t
mui_control_get_state(
mui_control_t * c );
int32_t
mui_control_get_value(
mui_control_t * c);
int32_t
mui_control_set_value(
mui_control_t * c,
int32_t selected);
const char *
mui_control_get_title(
mui_control_t * c );
void
mui_control_set_title(
mui_control_t * c,
const char * text );
/* Drawable control is just an offscreen buffer (icon, pixel view) */
mui_control_t *
mui_drawable_control_new(
mui_window_t * win,
c2_rect_t frame,
mui_drawable_t * dr,
mui_drawable_t * mask,
uint16_t flags);
mui_drawable_t *
mui_drawable_control_get_drawable(
mui_control_t * c);
mui_control_t *
mui_button_new(
mui_window_t * win,
c2_rect_t frame,
uint8_t style, // one of mui_button_style_e
const char * title,
uint32_t uid );
/*
* Create a static text box. Font is optional (default to the system main font),
* flags corresponds to the MUI_TEXT_ALIGN_* * PLUS the extra(s) listed below.
*/
enum mui_textbox_e {
// draw the frame around the text box
MUI_CONTROL_TEXTBOX_FRAME = (1 << 8),
};
mui_control_t *
mui_textbox_new(
mui_window_t * win,
c2_rect_t frame,
const char * text,
const char * font,
uint16_t flags );
mui_control_t *
mui_groupbox_new(
mui_window_t * win,
c2_rect_t frame,
const char * title,
uint16_t flags );
mui_control_t *
mui_scrollbar_new(
mui_window_t * win,
c2_rect_t frame,
uint32_t uid );
uint32_t
mui_scrollbar_get_max(
mui_control_t * c);
void
mui_scrollbar_set_max(
mui_control_t * c,
uint32_t max);
void
mui_scrollbar_set_page(
mui_control_t * c,
uint32_t page);
mui_control_t *
mui_listbox_new(
mui_window_t * win,
c2_rect_t frame,
uint32_t uid );
void
mui_listbox_prepare(
mui_control_t * c);
mui_listbox_elems_t *
mui_listbox_get_elems(
mui_control_t * c);
mui_control_t *
mui_separator_new(
mui_window_t * win,
c2_rect_t frame);
mui_control_t *
mui_popupmenu_new(
mui_window_t * win,
c2_rect_t frame,
const char * title,
uint32_t uid );
mui_menu_items_t *
mui_popupmenu_get_items(
mui_control_t * c);
void
mui_popupmenu_prepare(
mui_control_t * c);
/*
* Standard file dialog
*/
enum mui_std_action_e {
MUI_STDF_ACTION_NONE = 0,
// parameter 'target' is a char * with full pathname of selected file
MUI_STDF_ACTION_SELECT = FCC('s','t','d','s'),
MUI_STDF_ACTION_CANCEL = FCC('s','t','d','c'),
};
enum mui_std_flags_e {
// 'pattern' is a GNU extended regexp applied to filenames.
MUI_STDF_FLAG_REGEXP = (1 << 0),
// don't use the 'pref_directory', load, or same preference files
MUI_STDF_FLAG_NOPREF = (1 << 1),
};
/*
* Standard file dialog related
*
* Presents a standard 'get' file dialog, with optional prompt, regexp and
* start path. The return value is a pointer to a window, you can add your own
* 'action' function to get MUI_STDF_ACTION_* events.
* Once in the action function, you can call mui_stdfile_get_selected_path()
* to get the selected path, and free it when done.
* NOTE: The dialog does not auto-close, your own action function should close
* the dialog using mui_window_dispose().
*
* The dialog will attempt to remember the last directory used *for this
* particular pattern* and will use it as the default start path when called
* again. This is optional, it requires a mui->pref_directory to be set.
* You can also disable this feature by setting the MUI_STDF_FLAG_NOPREF flag.
*
* + 'pattern' is a regular expression to filter the files, or NULL for no
* filter.
* + if 'start_path' is NULL, the $HOME directory is used.
* + 'where' is the location of the dialog, (0,0) will center it.
*/
mui_window_t *
mui_stdfile_get(
struct mui_t * ui,
c2_pt_t where,
const char * prompt,
const char * pattern,
const char * start_path,
uint16_t flags );
// return the curently selected pathname -- caller must free() it
char *
mui_stdfile_get_selected_path(
mui_window_t * w );
/*
* Alert dialog
*/
enum mui_alert_flag_e {
MUI_ALERT_FLAG_OK = (1 << 0),
MUI_ALERT_FLAG_CANCEL = (1 << 1),
MUI_ALERT_ICON_INFO = (1 << 8),
MUI_ALERT_INFO = (MUI_ALERT_FLAG_OK | MUI_ALERT_ICON_INFO),
MUI_ALERT_WARN = (MUI_ALERT_FLAG_OK | MUI_ALERT_FLAG_CANCEL),
};
enum {
MUI_ALERT_BUTTON_OK = FCC('o','k',' ',' '),
MUI_ALERT_BUTTON_CANCEL = FCC('c','a','n','c'),
};
mui_window_t *
mui_alert(
struct mui_t * ui,
c2_pt_t where, // (0,0) will center it
const char * title,
const char * message,
uint16_t flags );
enum mui_time_e {
MUI_TIME_RES = 1,
MUI_TIME_SECOND = 1000000,
MUI_TIME_MS = (MUI_TIME_SECOND/1000),
};
mui_time_t
mui_get_time();
#define MUI_TIMER_COUNT 64
typedef struct mui_timer_group_t {
uint64_t map;
struct {
mui_time_t when;
mui_timer_p cb;
void * param;
} timers[MUI_TIMER_COUNT];
} mui_timer_group_t;
/*
* Register 'cb' to be called after 'delay'. Returns a timer id (0 to 63)
* or 0xff if no timer is available. The timer function cb can return 0 for a
* one shot timer, or another delay that will be added to the current stamp
* for a further call of the timer.
* 'param' will be also passed to the timer callback.
*/
uint8_t
mui_timer_register(
struct mui_t * ui,
mui_timer_p cb,
void * param,
uint32_t delay);
/*
* Reset timer 'id' if 'cb' matches what was registered. Set a new delay,
* or cancel the timer if delay is 0.
* Returns the time that was left on the timer, or 0 if the timer was
* not found.
*/
mui_time_t
mui_timer_reset(
struct mui_t * ui,
uint8_t id,
mui_timer_p cb,
mui_time_t delay);
typedef struct mui_t {
c2_pt_t screen_size;
struct {
mui_color_t clear;
mui_color_t highlight;
} color;
uint16_t modifier_keys;
int draw_debug;
// this is the sum of all the window's dirty regions, inc moved windows etc
mui_region_t inval;
// once the pixels have been refreshed, 'inval' is copied to 'redraw'
// to push the pixels to the screen.
mui_region_t redraw;
TAILQ_HEAD(, mui_font_t) fonts;
TAILQ_HEAD(windows, mui_window_t) windows;
mui_window_t * menubar;
TAILQ_HEAD(, mui_window_t) zombies;
// this is used to track any active action callbacks to
// prevent recursion problem and track any 'delete' happening
// during an action callback
uint32_t action_active;
mui_window_t * event_capture;
mui_timer_group_t timer;
char * pref_directory; /* optional */
} mui_t;
void
mui_init(
mui_t * ui);
void
mui_dispose(
mui_t * ui);
void
mui_draw(
mui_t * ui,
mui_drawable_t *dr,
uint16_t all);
void
mui_run(
mui_t * ui);
// return true if the event was handled by the ui
bool
mui_handle_event(
mui_t * ui,
mui_event_t * ev);
// return true if event 'ev' is a key combo matching key_equ
bool
mui_event_match_key(
mui_event_t * ev,
mui_key_equ_t key_equ);
/* Return true if the ui has any active windows, ie, not hidden, zombie;
* This does not include the menubar, but it does include any menus or popups
*
* This is used to decide wether to hide the mouse cursor or not
*/
bool
mui_has_active_windows(
mui_t * ui);
/* Return a hash value for string inString */
uint32_t
mui_hash(
const char * inString );