Files
asarium 16be3b7cc5 Add support for TrueType fonts
This allows to use standard TrueType Fonts for text rendering in FSO. It uses the NanoVG library which provides the ability of drawing 2D shapes. This library is used for most 2D operations now and can also be used directly by using the PathRenderer class.
2016-08-02 10:57:28 +02:00

558 lines
11 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "globalincs/alphacolors.h"
#include "io/timer.h"
#include "ui/ui.h"
#include "ui/uidefs.h"
#define KEY_BUFFER_TIMEOUT 1000 // time to clear buffer in milliseconds
#define DEFAULT_LISTBOX_ITEM_LENGTH 128
// --------------------------------------------------------------------
// UI_LISTBOX::link_hotspot
//
//
void UI_LISTBOX::link_hotspot(int up_button_num, int down_button_num)
{
scrollbar.link_hotspot(up_button_num,down_button_num);
}
// --------------------------------------------------------------------
// UI_LISTBOX::set_bmaps
//
// Call the UI_SCROLLBAR::set_bmaps() function for the scroll bar gadget.
//
// returns: -1 ==> error
// 0 ==> success
//
int UI_LISTBOX::set_bmaps(char *lbox_fname, char *b_up_fname, char *b_down_fname, char *sb_fname)
{
if (has_scrollbar) {
scrollbar.set_bmaps(b_up_fname, b_down_fname, sb_fname);
}
// set the bitmaps for the list box rectangle
UI_GADGET::set_bmaps(lbox_fname);
uses_bmaps = 1;
return 0;
}
void UI_LISTBOX::create(UI_WINDOW *wnd, int _x, int _y, int _w, int _h, int _numitems, char **_list, char *_check_list, int _max_items)
{
int tw, th, nrows;
int real_h;
font::set_font(wnd->f_id);
gr_get_string_size(&tw, &th, "*");
nrows = _h / th;
real_h = nrows * th;
base_create( wnd, UI_KIND_LISTBOX, _x, _y, _w, real_h );
max_items = _max_items;
list = _list;
num_items = _numitems;
check_list = _check_list;
num_items_displayed = nrows;
first_item = 0;
current_item = -1;
toggled_item = -1;
last_scrolled = 0;
textheight = th;
dragging = 0;
selected_item = -1;
key_buffer_count = 0;
last_typed = timer_get_milliseconds();
if (_numitems > nrows) {
scrollbar.create( wnd, _x+_w+3, _y, real_h, 0, _numitems-nrows, 0, nrows );
scrollbar.set_parent(this);
has_scrollbar = 1;
} else {
has_scrollbar = 0;
}
// kazan
draw_frame = 1;
}
void UI_LISTBOX::set_drawframe(int mode)
{
draw_frame = mode;
}
void UI_LISTBOX::draw()
{
int i, x1, y1, stop;
int w1, h1;
UI_GADGET::draw();
font::set_font(my_wnd->f_id);
if (uses_bmaps) {
if (disabled_flag) {
if ( bmap_ids[LBOX_DISABLED] >= 0 ) {
gr_set_bitmap(bmap_ids[LBOX_DISABLED]);
gr_bitmap(x, y, GR_RESIZE_MENU);
}
} else {
if ( bmap_ids[LBOX_NORMAL] >= 0 ) {
gr_set_bitmap(bmap_ids[LBOX_NORMAL]);
gr_bitmap(x, y, GR_RESIZE_MENU);
}
}
} else {
gr_set_color_fast(&CBLACK);
gr_set_clip( x, y, w, h, GR_RESIZE_MENU );
ui_rect( 0, 0, w-1, h-1 );
gr_reset_clip();
if (draw_frame)
{
if (has_scrollbar) {
ui_draw_sunken_border( x-2, y-2, x+w+scrollbar.w+4, y+h+1 );
} else {
ui_draw_sunken_border( x-2, y-2, x+w+4, y+h+1 );
}
}
}
stop = first_item+num_items_displayed;
if (stop>num_items) stop = num_items;
x1 = y1 = 0;
gr_set_clip( x, y, w, h, GR_RESIZE_MENU );
for ( i=first_item; i<stop; i++ ) {
gr_get_string_size( &w1, &h1,list[i] );
if (check_list)
w1 += 18;
if (i !=current_item) {
/*
if ((current_item == -1) && (my_wnd->selected_gadget == this ) && (i == first_item) ) {
if ( !uses_bmaps ) {
gr_set_color_fast( &CBLACK );
gr_rect( x1, y1, w1+2, h1, GR_RESIZE_MENU_NO_OFFSET );
}
current_item = first_item;
gr_set_color_fast( &CBRIGHT_GREEN );
} else {
if ( !uses_bmaps ) {
gr_set_color_fast( &CBLACK );
gr_rect( x1, y1, w1+2, h1, GR_RESIZE_MENU_NO_OFFSET );
}
gr_set_color_fast( &CWHITE );
}
*/
if (!uses_bmaps) {
gr_set_color_fast( &CBLACK );
gr_rect( x1, y1, w1+2, h1, GR_RESIZE_MENU_NO_OFFSET );
}
gr_set_color_fast(&CWHITE);
} else {
if (my_wnd->selected_gadget == this) {
gr_set_color_fast( &CGRAY );
gr_rect( x1, y1, w1+2, h1, GR_RESIZE_MENU_NO_OFFSET );
gr_set_color_fast( &CBRIGHT_GREEN );
} else {
gr_set_color_fast( &CGRAY );
gr_rect( x1, y1, w1+2, h1, GR_RESIZE_MENU_NO_OFFSET );
gr_set_color_fast( &CBLACK );
}
}
if ( check_list ) {
if ( check_list[i] ) {
gr_string( x1+2, y1, "X", GR_RESIZE_MENU );
}
gr_string( x1+16, y1, list[i], GR_RESIZE_MENU );
} else
gr_string( x1+2, y1, list[i], GR_RESIZE_MENU );
if (i==current_item)
gr_set_color_fast( &CGRAY );
else
gr_set_color_fast( &CBLACK );
if ( !uses_bmaps ) {
ui_rect( x1+w1+2, y1, w-1, y1+h1-1 );
ui_rect( x1, y1, x1+1, y1+h1-1 );
}
y1 += h1;
}
if (stop < num_items_displayed-1 && !uses_bmaps) {
gr_set_color_fast(&CBLACK);
ui_rect( x1, y1, w-1, h-1 );
}
}
void UI_LISTBOX::process(int focus)
{
int OnMe, mitem, kf = 0;
int i, j;
selected_item = -1;
toggled_item = -1;
if (disabled_flag)
return;
if (my_wnd->selected_gadget == this)
focus = 1;
if (has_scrollbar) {
scrollbar.process(0);
if (my_wnd->selected_gadget == &scrollbar) {
set_focus();
focus = 1;
}
}
if (num_items < 1) {
current_item = -1;
first_item = 0;
old_current_item = current_item;
old_first_item = first_item;
// if (my_wnd->selected_gadget == this) {
// my_wnd->selected_gadget == get_next();
// }
return;
}
old_current_item = current_item;
old_first_item = first_item;
OnMe = is_mouse_on();
if (has_scrollbar) {
if (scrollbar.moved) {
first_item = scrollbar.position;
Assert(first_item >= 0);
if (current_item<first_item)
current_item = first_item;
if (current_item > first_item + num_items_displayed - 1)
current_item = first_item + num_items_displayed - 1;
}
}
if (!B1_PRESSED)
dragging = 0;
if (B1_PRESSED && OnMe) {
set_focus();
dragging = 1;
}
if ( key_buffer_count && (timer_get_milliseconds() > last_typed + KEY_BUFFER_TIMEOUT) )
key_buffer_count = 0;
if (focus) {
if (my_wnd->keypress) {
kf = 0;
switch (my_wnd->keypress) {
case KEY_ENTER:
selected_item = current_item;
break;
case KEY_SPACEBAR:
toggled_item = current_item;
break;
case KEY_UP:
current_item--;
kf = 1;
break;
case KEY_DOWN:
current_item++;
kf = 1;
break;
case KEY_HOME:
current_item = 0;
kf = 1;
break;
case KEY_END:
current_item=num_items - 1;
kf = 1;
break;
case KEY_PAGEUP:
current_item -= num_items_displayed;
kf = 1;
break;
case KEY_PAGEDOWN:
current_item += num_items_displayed;
kf = 1;
break;
default: // enter the key in the key buffer
if (my_wnd->keypress == KEY_BACKSP) {
key_buffer_count = 0;
} else if (key_buffer_count < MAX_KEY_BUFFER) {
key_buffer[key_buffer_count++] = (char) my_wnd->keypress;
last_typed = timer_get_milliseconds();
}
if (!key_buffer_count)
break;
for (i=0; i<num_items; i++) {
char *current_text;
current_text = get_string(i);
for (j=0; j<key_buffer_count; j++)
if ( (current_text[j] != ascii_table[key_buffer[j]]) && (current_text[j] != shifted_ascii_table[key_buffer[j]]) )
break;
if (j == key_buffer_count) {
set_first_item(i - num_items_displayed / 2);
set_current(i);
break;
}
}
}
}
if (kf == 1) {
if (current_item < 0)
current_item = 0;
if (current_item >= num_items)
current_item = num_items - 1;
if (current_item < first_item)
first_item = current_item;
if (current_item >= first_item + num_items_displayed)
first_item = current_item - num_items_displayed + 1;
if (num_items <= num_items_displayed ) {
first_item = 0;
} else {
if (has_scrollbar) {
scrollbar.position = first_item;
scrollbar.bar_position = scrollbar.position - scrollbar.start;
scrollbar.bar_position *= scrollbar.h - scrollbar.bar_size;
scrollbar.bar_position /= scrollbar.stop - scrollbar.start;
if (scrollbar.bar_position < 0) {
scrollbar.bar_position = 0;
}
if (scrollbar.bar_position > scrollbar.h - scrollbar.bar_size) {
scrollbar.bar_position = scrollbar.h - scrollbar.bar_size;
}
}
}
}
}
if (focus) {
if (B1_PRESSED && dragging) {
if (ui_mouse.y < y )
mitem = -1;
else
mitem = (ui_mouse.y - y)/textheight;
if ( (mitem < 0) && (timer_get_milliseconds() > last_scrolled + 1000 / 18) ) {
current_item--;
last_scrolled = timer_get_milliseconds();
}
if ( (mitem >= num_items_displayed) && (timer_get_milliseconds() > last_scrolled + 1000 / 18) ) {
current_item++;
last_scrolled = timer_get_milliseconds();
}
if ((mitem >= 0) && (mitem<num_items_displayed)) {
current_item = mitem + first_item;
}
if (current_item < 0)
current_item = 0;
if (current_item >= num_items)
current_item = num_items - 1;
if (current_item < first_item)
first_item = current_item;
if (current_item >= first_item + num_items_displayed)
first_item = current_item - num_items_displayed + 1;
if (num_items <= num_items_displayed) {
first_item = 0;
} else if (has_scrollbar) {
scrollbar.position = first_item;
scrollbar.bar_position = scrollbar.position - scrollbar.start;
scrollbar.bar_position *= scrollbar.h - scrollbar.bar_size;
scrollbar.bar_position /= scrollbar.stop - scrollbar.start;
if (scrollbar.bar_position < 0) {
scrollbar.bar_position = 0;
}
if (scrollbar.bar_position > scrollbar.h - scrollbar.bar_size) {
scrollbar.bar_position = scrollbar.h - scrollbar.bar_size;
}
}
}
if (check_list) {
if (B1_JUST_RELEASED)
toggled_item = current_item;
}
if (B1_DOUBLE_CLICKED) {
selected_item = current_item;
}
}
}
int UI_LISTBOX::toggled()
{
if (check_list) {
return toggled_item;
} else {
return -1;
}
}
int UI_LISTBOX::selected()
{
if (check_list) {
return -1;
} else {
return selected_item;
}
}
int UI_LISTBOX::current()
{
return current_item;
}
void UI_LISTBOX::set_current(int _index)
{
current_item = _index;
}
void UI_LISTBOX::set_first_item(int _index)
{
if (_index < 0)
_index = 0;
else if (_index > num_items)
_index = num_items;
first_item = _index;
}
char *UI_LISTBOX::get_string(int _index)
{
return list[_index];
}
void UI_LISTBOX::clear_all_items()
{
int idx;
for ( idx=0; idx<num_items; idx++ )
list[idx][0] = 0;
num_items = 0;
first_item = 0;
}
void UI_LISTBOX::set_new_list(int _numitems, char **_list)
{
num_items = _numitems;
list = _list;
current_item = 0;
}
void UI_LISTBOX::ScrollEnd()
{
if (num_items > num_items_displayed)
first_item = num_items - num_items_displayed + 1;
}
void UI_LISTBOX::RemoveFirstItem()
{
for (int i = 0; i < num_items-1; i++)
list[i] = list[i+1];
num_items--;
}
int UI_LISTBOX::MaxSize()
{
return max_items;
}
int UI_LISTBOX::CurSize()
{
return num_items;
}
int UI_LISTBOX::add_string(char *str)
{
if (max_items < 0) // only if we created an "empty" listbox can we add items
return 0;
else {
if ( (num_items == max_items - 1) || (strlen(str) > DEFAULT_LISTBOX_ITEM_LENGTH) )
return 0; // we've reached our limit
else {
list[num_items] = vm_strdup(str);
num_items++;
return 1;
}
}
}
int UI_LISTBOX::sel_changed()
{
return old_current_item == current_item ? 0 : 1;
}