250 lines
9.3 KiB
C
250 lines
9.3 KiB
C
/// __ _____ _ __ _ _
|
|
/// \ \/ / _ \ '_ \| | | |
|
|
/// > < __/ | | | |_| |
|
|
/// /_/\_\___|_| |_|\__,_|
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xenu - Tiny menu unity header, depending on Xross and XUI headers, hard to use but efficient.
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, 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 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
typedef enum {
|
|
menu_layout_vertical, menu_layout_horizontal,
|
|
menu_layout_count
|
|
} menu_layout_enumeration;
|
|
|
|
typedef enum {
|
|
menu_type_empty,
|
|
menu_type_window, menu_type_menu, menu_type_status, menu_type_frame,
|
|
menu_type_button, menu_type_separator, menu_type_string, menu_type_sprite,
|
|
menu_type_check_box, menu_type_icon, menu_type_overicon, menu_type_ubericon,
|
|
menu_type_text_field, menu_type_signal_field, menu_type_cursor_field, menu_type_slider_field,
|
|
menu_type_text_box, menu_type_code_box, menu_type_help_box, menu_type_data_box,
|
|
menu_type_count
|
|
} menu_type_enumeration;
|
|
|
|
typedef struct {
|
|
character * data;
|
|
natural font;
|
|
real scale;
|
|
natural colour;
|
|
} menu_string;
|
|
|
|
typedef struct {
|
|
natural data;
|
|
real scale;
|
|
natural colour;
|
|
} menu_sprite;
|
|
|
|
typedef struct {
|
|
menu_layout_enumeration layout;
|
|
menu_type_enumeration type;
|
|
menu_string * string;
|
|
menu_string * number;
|
|
menu_sprite * sprite;
|
|
integer x;
|
|
integer y;
|
|
natural width;
|
|
natural height;
|
|
natural offset;
|
|
natural count;
|
|
generic * * array;
|
|
generic * root;
|
|
} menu_structure;
|
|
|
|
static procedure menu_append (menu_structure * root, menu_structure * menu) {
|
|
++root->count;
|
|
|
|
root->array = reallocate (root->array, root->count * sizeof (* root->array));
|
|
|
|
menu->root = root;
|
|
|
|
root->array [root->count - 1] = menu;
|
|
}
|
|
|
|
static procedure menu_remove (menu_structure * menu) {
|
|
if (menu->string != null) { menu->string = deallocate (menu->string); }
|
|
if (menu->number != null) { menu->number = deallocate (menu->number); }
|
|
if (menu->sprite != null) { menu->sprite = deallocate (menu->sprite); }
|
|
|
|
for (natural index = 0; index < menu->count; ++index) {
|
|
menu_remove (menu->array [index]);
|
|
}
|
|
|
|
if (menu->array != null) {
|
|
menu->array = deallocate (menu->array);
|
|
}
|
|
|
|
menu = deallocate (menu);
|
|
}
|
|
|
|
static menu_string * menu_create_string (character * data, natural font, real scale, natural colour) {
|
|
menu_string * string = allocate (sizeof (* string));
|
|
|
|
string->data = data;
|
|
string->font = font;
|
|
string->scale = scale;
|
|
string->colour = colour;
|
|
|
|
return (string);
|
|
}
|
|
|
|
static menu_sprite * menu_create_sprite (natural data, real scale, natural colour) {
|
|
menu_sprite * sprite = allocate (sizeof (* sprite));
|
|
|
|
sprite->data = data;
|
|
sprite->scale = scale;
|
|
sprite->colour = colour;
|
|
|
|
return (sprite);
|
|
}
|
|
|
|
static menu_structure * menu_create_base (menu_layout_enumeration layout, menu_type_enumeration type, menu_string * string,
|
|
menu_string * number, menu_sprite * sprite, integer x, integer y, natural offset) {
|
|
menu_structure * menu = allocate (sizeof (* menu));
|
|
|
|
menu->layout = layout;
|
|
menu->type = type;
|
|
menu->string = string;
|
|
menu->number = number;
|
|
menu->sprite = sprite;
|
|
menu->x = x;
|
|
menu->y = y;
|
|
menu->offset = offset;
|
|
|
|
return (menu);
|
|
}
|
|
|
|
static menu_structure * menu_create_root (menu_layout_enumeration layout, menu_type_enumeration type, natural offset) {
|
|
return (menu_create_base (layout, type, null, null, null, 0, 0, offset));
|
|
}
|
|
|
|
static menu_structure * menu_create_button (menu_layout_enumeration layout, menu_string * text, menu_sprite * icon, natural offset) {
|
|
return (menu_create_base (layout, menu_type_button, text, null, icon, 0, 0, offset));
|
|
}
|
|
|
|
static natural menu_string_width (cross_structure * cross, menu_string * string) {
|
|
return ((string == null) ? 0 : cross_string_width (cross, string->data, string->font, string->scale));
|
|
}
|
|
|
|
static natural menu_string_height (cross_structure * cross, menu_string * string) {
|
|
return ((string == null) ? 0 : cross_string_height (cross, string->data, string->font, string->scale));
|
|
}
|
|
|
|
static natural menu_sprite_width (cross_structure * cross, menu_sprite * sprite) {
|
|
return ((sprite == null) ? 0 : cross_sprite_width (cross, sprite->data));
|
|
}
|
|
|
|
static natural menu_sprite_height (cross_structure * cross, menu_sprite * sprite) {
|
|
return ((sprite == null) ? 0 : cross_sprite_height (cross, sprite->data));
|
|
}
|
|
|
|
static procedure menu_configure (cross_structure * cross, menu_structure * menu) {
|
|
for (natural index = 0; index < menu->count; ++index) {
|
|
menu_structure * submenu = menu->array [index];
|
|
|
|
menu_configure (cross, submenu);
|
|
}
|
|
|
|
for (natural index = 0; index < menu->count; ++index) {
|
|
menu_structure * submenu = menu->array [index];
|
|
|
|
if (menu->layout == menu_layout_vertical) {
|
|
menu->width = maximum_macro (menu->width, submenu->width + 2 * menu->offset);
|
|
menu->height += submenu->height;
|
|
}
|
|
|
|
if (menu->layout == menu_layout_horizontal) {
|
|
menu->width += submenu->width;
|
|
menu->height = maximum_macro (menu->height, submenu->height + 2 * menu->offset);
|
|
}
|
|
}
|
|
|
|
if (menu->layout == menu_layout_vertical) {
|
|
menu->width += maximum_natural (3, menu_sprite_width (cross, menu->sprite),
|
|
menu_string_width (cross, menu->string),
|
|
menu_string_width (cross, menu->number));
|
|
|
|
menu->height += menu_sprite_height (cross, menu->sprite)
|
|
+ menu_string_height (cross, menu->string)
|
|
+ menu_string_height (cross, menu->number);
|
|
}
|
|
|
|
if (menu->layout == menu_layout_horizontal) {
|
|
menu->width += menu_sprite_width (cross, menu->sprite)
|
|
+ menu_string_width (cross, menu->string)
|
|
+ menu_string_width (cross, menu->number);
|
|
|
|
menu->height += maximum_natural (3, menu_sprite_height (cross, menu->sprite),
|
|
menu_string_height (cross, menu->string),
|
|
menu_string_height (cross, menu->number));
|
|
}
|
|
|
|
menu->width += 2 * menu->offset;
|
|
menu->height += 2 * menu->offset;
|
|
|
|
if ((menu->count != 0) && (menu->root != null)) {
|
|
menu->width -= 2 * menu->offset * (menu->layout == menu_layout_vertical);
|
|
menu->height -= 2 * menu->offset * (menu->layout == menu_layout_horizontal);
|
|
}
|
|
}
|
|
|
|
static procedure menu_center (cross_structure * cross, menu_structure * menu) {
|
|
menu->x = cross_center_x (cross, menu->width);
|
|
menu->y = cross_center_y (cross, menu->height);
|
|
}
|
|
|
|
static procedure menu_subrender (cross_structure * cross, ui_structure * ui, menu_structure * menu) {
|
|
switch (menu->type) {
|
|
case (menu_type_empty): break;
|
|
|
|
case (menu_type_window): ui_render_window (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
|
|
case (menu_type_menu): ui_render_menu (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
|
|
case (menu_type_status): ui_render_status (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
|
|
case (menu_type_frame): ui_render_frame (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
|
|
|
|
case (menu_type_button): {
|
|
boolean sprite_is_used = (menu->sprite != null) && (menu->sprite->data != ~ 0u);
|
|
ui_render_button (cross, ui, menu->x, menu->y, menu->width, menu->height);
|
|
if (sprite_is_used == true) {
|
|
cross_render_sprite_colour (cross, menu->sprite->data, menu->x + menu->offset, menu->y + menu->offset, menu->sprite->colour);
|
|
}
|
|
if ((menu->string != null) && (menu->string->data != null)) {
|
|
integer x = menu->x + menu->offset + (sprite_is_used == true) * menu_sprite_width (cross, menu->sprite) * (menu->layout == menu_layout_horizontal);
|
|
integer y = menu->y + menu->offset + (sprite_is_used == true) * menu_sprite_height (cross, menu->sprite) * (menu->layout == menu_layout_vertical);
|
|
cross_render_string (cross, menu->string->data, menu->string->font, x, y, menu->string->scale, menu->string->colour);
|
|
}
|
|
} break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
static procedure menu_render (cross_structure * cross, ui_structure * ui, menu_structure * menu) {
|
|
menu_subrender (cross, ui, menu);
|
|
|
|
for (natural index = 0; index < menu->count; ++index) {
|
|
menu_structure * submenu = menu->array [index];
|
|
|
|
menu_structure * root = submenu->root;
|
|
|
|
submenu->x = root->x + root->offset;
|
|
submenu->y = root->y + root->offset;
|
|
|
|
for (natural subindex = 0; subindex < index; ++subindex) {
|
|
menu_structure * base = root->array [subindex];
|
|
|
|
submenu->x += (root->layout == menu_layout_horizontal) * base->width;
|
|
submenu->y += (root->layout == menu_layout_vertical) * base->height;
|
|
}
|
|
|
|
menu_render (cross, ui, submenu);
|
|
}
|
|
}
|