aboutsummaryrefslogtreecommitdiff
path: root/termkit.h
// This file is part of libtermkit, a small utility library around
// libtermbox, an alternative to libncurses. It aims to provide a
// convenient and easy to use widget abstraction to build terminal
// based GUIs, in C99.
//
// In principle, termkit only wraps functions provided by termbox,
// but does so while providing state handling and render utilities.
// In termkit, the smallest element is a "node", not a cell. This
// means that the smallest unit is a sentence or visual element.
// A visual element can then either simply be that sentence, or have
// decorations applied to it via `tk_style_t` which is a shared
// style-sheet across an application.
//
// libtermkit is free software, written by Katharina Fey, and licensed
// under the GNU Public License 3.0 or later. See the included license
// reference provided with a copy of this library source code.

#ifndef term_h_INCLUDED
#define term_h_INCLUDED

#include <stdint.h>
#include <bowl.h>

/** 
 * A common stylesheet for termkit applications
 *
 * A stylesheet determines the way that an application looks,
 * beyond setting individual cells to certain fg and bg colours.
 * It supports labels that can be associated with different
 * colour styles (via `tk_sty_color(...)`) or even decorations
 * with `tk_sty_decor(...)` that are applied to an element.
 */
typedef struct {
    uint16_t fg, bg;
    struct bowl *styles;
    struct bowl *decorators;
} tk_style_t;

/** 
 * A decorator element for widgets
 * 
 * A decorator is visible "stuff", that's not directly data related. This
 * could be a colourful frame or shadows. By using characters in the area
 * data, this can be used to also draw UTF-8 compatible characters as
 * outlines.
 * Each decoration element get's colour values from a stylesheet.
 * 
 * See the type constructor for more information.
 */
typedef struct {
    uint32_t ***area; // FIXME: A hack for UTF-8
    tk_style_t *sty;
    char *sty_name;
    // Spans open a container box
    uint16_t ux, uy, lx, ly;
} tk_decor_t;

/** Allocate a new stylesheet */
int tk_sty_init(tk_style_t **, uint16_t fg, uint16_t bg);

/** Add a new color style to the stylesheet */
int tk_sty_add_col(tk_style_t *, char *name, uint16_t fg, uint16_t bg);

/** Add a new dectoration type (TODO: How to express?) */
int tk_sty_add_decor(tk_style_t *, char *name, tk_decor_t *);

/** Get a color from the stylesheet, if it exists */
int tk_sty_color(tk_style_t *, char *name, uint16_t *fg, uint16_t *bg);

/** Get a decorator from the stylesheet, if it exists */
int tk_sty_decor(tk_style_t *, char *name, tk_decor_t **);

/** Free all stylesheet resources */
int tk_sty_free(tk_style_t *);

/** A common termkit orientation descriptor */
enum tk_ori {
    HORIZONTAL,
    VERTICAL,
    DIAGONAL,
    REV_HORIZONTAL,
    REV_VERTICAL,
    REV_DIAGONAL,
};

typedef struct {
    tk_style_t *sty;
    char *sty_name, *decor;
    char *value;
    uint16_t x, y;
    enum tk_ori ori;
    bool clickable;
} tk_widget_t;

/** Initialise a termkit window system */
int tk_init();

/** Draw a termkit widget */
int tk_draw_widget(tk_widget_t *);

/** Simple low-level draw function for termkit elements */
int tk_draw_default(char *str, int x, int y, tk_style_t *sty);

/** Full low-level draw function for termkit elements
 * 
 * If `style_name` or `decor` are set to `NULL` it will
 * assume the default style provided by the tk_style_t
 * sheet and render without decorators.
 * 
 * Missing any other parameter will yield an error.
 */
int tk_draw(tk_style_t *sty, char *str, int x, int y,
            char *style_name, char *decor, enum tk_ori ori);

/** A TermKit menu wrapper */
typedef struct {
    // References the application's stylesheet
    tk_style_t *style;
    // Actual menu styles used
    char *sty_name, *decor;
    // Determines render orientation
    enum tk_ori ori;
    // List of items
    tk_widget_t **items;
    // Number an selection of items
    uint8_t count, select;
    // (x, y) position on screen
    uint16_t x, y;
    // Maximum (width, height) of widget
    uint16_t w, h;
} tk_menu_t;

/** Initialise an empty termkit menu 
 *
 * Note that only HORIZONTAL, VERTICAL, REV_HORIZONTAL and REV_VERTICAL
 * are accepted orientations to this function (no diagonals...).
 * The function will return an error otherwise.
 */
int tk_menu_init(tk_menu_t **, uint16_t x, uint16_t y, 
                 tk_style_t *style, enum tk_ori ori);

/** Set a special style and decoration type for this menu */
int tk_menu_set_style(tk_menu_t *, char *style, char *decor);

/** Set the selected item index */
int tk_menu_set_select(tk_menu_t *, uint8_t select);

/** Get the selected item */
int tk_menu_get_selected(tk_menu_t *, char **select);

/** Add a new item */
int tk_menu_add(tk_menu_t *, char *item);

/** Remove an existing item, compacting following items */
int tk_menu_remove(tk_menu_t *, uint8_t idx);

/** Render the menu via termbox */
int tk_menu_draw(tk_menu_t *);

/** Free all resources */
int tk_menu_free(tk_menu_t *);

#endif // term_h_INCLUDED