/// __ _____ _ __ _ _ /// \ \/ / _ \ '_ \| | | | /// > < __/ | | | |_| | /// /_/\_\___|_| |_|\__,_| /// /// 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); } }