dxx-rebirth/common/ui/listbox.cpp

416 lines
11 KiB
C++
Raw Normal View History

2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING.txt.
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below.
* See COPYING.txt for license details.
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
#include <stdlib.h>
2012-07-01 02:54:33 +00:00
#include "maths.h"
2006-03-20 17:12:09 +00:00
#include "pstypes.h"
#include "event.h"
2006-03-20 17:12:09 +00:00
#include "gr.h"
#include "ui.h"
#include "mouse.h"
2006-03-20 17:12:09 +00:00
#include "key.h"
#include "timer.h"
2015-12-13 18:00:49 +00:00
namespace dcx {
2015-12-05 22:57:24 +00:00
2013-09-22 22:26:27 +00:00
static void gr_draw_sunken_border( short x1, short y1, short x2, short y2 );
2012-03-03 12:19:15 +00:00
void ui_draw_listbox( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox )
2006-03-20 17:12:09 +00:00
{
int i, x, y, stop;
2015-09-29 02:41:22 +00:00
int w, h;
2006-03-20 17:12:09 +00:00
//if (listbox->current_item<0)
// listbox->current_item=0;
//if (listbox->current_item>=listbox->num_items)
// listbox->current_item = listbox->num_items-1;
//if (listbox->first_item<0)
// listbox->first_item=0;
//if (listbox->first_item>(listbox->num_items-listbox->num_items_displayed))
// listbox->first_item=(listbox->num_items-listbox->num_items_displayed);
#if 0 //ndef OGL
2006-03-20 17:12:09 +00:00
if ((listbox->status!=1) && !listbox->moved )
return;
#endif
2006-03-20 17:12:09 +00:00
gr_set_current_canvas( listbox->canvas );
w = listbox->width;
h = listbox->height;
2016-02-12 04:02:28 +00:00
gr_rect( 0, 0, w-1, h-1, CBLACK);
gr_draw_sunken_border( -2, -2, w+listbox->scrollbar->width+4, h+1);
2006-03-20 17:12:09 +00:00
stop = listbox->first_item+listbox->num_items_displayed;
if (stop>listbox->num_items) stop = listbox->num_items;
listbox->status = 0;
x = y = 0;
for (i= listbox->first_item; i< stop; i++ )
{
2016-02-12 04:02:28 +00:00
uint8_t color = (i == listbox->current_item)
? CGREY
: CBLACK;
gr_rect(x, y, listbox->width - 1, y + h - 1, color);
2006-03-20 17:12:09 +00:00
if (i !=listbox->current_item)
{
2014-10-04 22:13:47 +00:00
if ((listbox->current_item == -1) && (dlg->keyboard_focus_gadget == listbox) && (i == listbox->first_item) )
gr_set_fontcolor( CRED, -1 );
2006-03-20 17:12:09 +00:00
else
gr_set_fontcolor( CWHITE, -1 );
2006-03-20 17:12:09 +00:00
}
else
{
2014-10-04 22:13:47 +00:00
if (dlg->keyboard_focus_gadget == listbox)
gr_set_fontcolor( CRED, -1 );
2006-03-20 17:12:09 +00:00
else
gr_set_fontcolor( CBLACK, -1 );
2006-03-20 17:12:09 +00:00
}
2015-09-29 02:41:22 +00:00
gr_get_string_size(listbox->list[i], &w, &h, nullptr);
2015-09-29 02:41:22 +00:00
gr_string(x + 2, y, listbox->list[i], w, h);
2006-03-20 17:12:09 +00:00
y += h;
}
if (stop < listbox->num_items_displayed-1 )
{
2016-02-12 04:02:28 +00:00
gr_rect( x, y, listbox->width-1, listbox->height-1, CBLACK);
2006-03-20 17:12:09 +00:00
}
//gr_ubox( -1, -1, listbox->width, listbox->height);
}
2013-09-22 22:26:27 +00:00
static void gr_draw_sunken_border( short x1, short y1, short x2, short y2 )
2006-03-20 17:12:09 +00:00
{
2016-02-12 04:02:28 +00:00
const uint8_t cgrey = CGREY;
const uint8_t cbright = CBRIGHT;
Hline(x1-1, x2+1, y1-1, cgrey);
2016-02-12 04:02:28 +00:00
Vline( y1-1, y2+1, x1-1, cgrey);
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
Hline(x1-1, x2+1, y2+1, cbright);
2016-02-12 04:02:28 +00:00
Vline( y1, y2+1, x2+1, cbright);
2006-03-20 17:12:09 +00:00
}
std::unique_ptr<UI_GADGET_LISTBOX> ui_add_gadget_listbox(UI_DIALOG *dlg, short x, short y, short w, short h, short numitems, char **list)
2006-03-20 17:12:09 +00:00
{
2015-09-29 02:41:22 +00:00
int th, i;
gr_get_string_size("*", nullptr, &th, nullptr);
2006-03-20 17:12:09 +00:00
i = h / th;
h = i * th;
std::unique_ptr<UI_GADGET_LISTBOX> listbox{ui_gadget_add<UI_GADGET_LISTBOX>( dlg, x, y, x+w-1, y+h-1 )};
2006-03-20 17:12:09 +00:00
listbox->list = list;
listbox->width = w;
listbox->height = h;
listbox->num_items = numitems;
listbox->num_items_displayed = i;
listbox->first_item = 0;
listbox->current_item = -1;
listbox->last_scrolled = 0;
listbox->textheight = th;
listbox->dragging = 0;
listbox->selected_item = -1;
listbox->moved = 1;
listbox->scrollbar = ui_add_gadget_scrollbar( dlg, x+w+3, y, 0, h, 0, numitems-i, 0, i );
listbox->scrollbar->parent = listbox.get();
2006-03-20 17:12:09 +00:00
return listbox;
}
2014-10-04 21:47:13 +00:00
window_event_result ui_listbox_do( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox,const d_event &event )
2006-03-20 17:12:09 +00:00
{
int mitem, oldfakepos, kf;
int keypress = 0;
2014-10-04 21:47:13 +00:00
if (event.type == EVENT_WINDOW_DRAW)
{
ui_draw_listbox( dlg, listbox );
2014-08-06 02:10:49 +00:00
return window_event_result::ignored;
}
2014-10-04 21:47:13 +00:00
if (event.type == EVENT_KEY_COMMAND)
keypress = event_key_get(event);
2006-03-20 17:12:09 +00:00
listbox->selected_item = -1;
listbox->moved = 0;
if (listbox->num_items < 1 ) {
listbox->current_item = -1;
listbox->first_item = 0;
listbox->old_current_item = listbox->current_item;
listbox->old_first_item = listbox->first_item;
//ui_draw_listbox( dlg, listbox );
2006-03-20 17:12:09 +00:00
2014-10-04 22:13:47 +00:00
if (dlg->keyboard_focus_gadget == listbox)
2006-03-20 17:12:09 +00:00
{
2014-10-04 22:13:47 +00:00
dlg->keyboard_focus_gadget = ui_gadget_get_next(listbox);
2006-03-20 17:12:09 +00:00
}
2014-08-06 02:10:49 +00:00
return window_event_result::ignored;
2006-03-20 17:12:09 +00:00
}
listbox->old_current_item = listbox->current_item;
listbox->old_first_item = listbox->first_item;
if (GADGET_PRESSED(listbox->scrollbar.get()))
2006-03-20 17:12:09 +00:00
{
listbox->moved = 1;
listbox->first_item = listbox->scrollbar->position;
if (listbox->current_item<listbox->first_item)
listbox->current_item = listbox->first_item;
if (listbox->current_item>(listbox->first_item+listbox->num_items_displayed-1))
listbox->current_item = listbox->first_item + listbox->num_items_displayed-1;
}
if (B1_JUST_RELEASED)
2006-03-20 17:12:09 +00:00
listbox->dragging = 0;
2014-08-06 02:10:49 +00:00
window_event_result rval = window_event_result::ignored;
2014-10-04 22:13:47 +00:00
if (B1_JUST_PRESSED && ui_mouse_on_gadget( listbox ))
{
2006-03-20 17:12:09 +00:00
listbox->dragging = 1;
2014-08-06 02:10:49 +00:00
rval = window_event_result::handled;
}
2006-03-20 17:12:09 +00:00
2014-10-04 22:13:47 +00:00
if ( dlg->keyboard_focus_gadget==listbox )
2006-03-20 17:12:09 +00:00
{
if (keypress==KEY_ENTER) {
listbox->selected_item = listbox->current_item;
2014-08-06 02:10:49 +00:00
rval = window_event_result::handled;
2006-03-20 17:12:09 +00:00
}
kf = 0;
switch(keypress)
{
case (KEY_UP):
listbox->current_item--;
kf = 1;
break;
case (KEY_DOWN):
listbox->current_item++;
kf = 1;
break;
case (KEY_HOME):
listbox->current_item=0;
kf = 1;
break;
case (KEY_END):
listbox->current_item=listbox->num_items-1;
kf = 1;
break;
case (KEY_PAGEUP):
listbox->current_item -= listbox->num_items_displayed;
kf = 1;
break;
case (KEY_PAGEDOWN):
listbox->current_item += listbox->num_items_displayed;
kf = 1;
break;
}
if (kf==1)
{
listbox->moved = 1;
2014-08-06 02:10:49 +00:00
rval = window_event_result::handled;
2006-03-20 17:12:09 +00:00
if (listbox->current_item<0)
listbox->current_item=0;
if (listbox->current_item>=listbox->num_items)
listbox->current_item = listbox->num_items-1;
if (listbox->current_item<listbox->first_item)
listbox->first_item = listbox->current_item;
if (listbox->current_item>=(listbox->first_item+listbox->num_items_displayed))
listbox->first_item = listbox->current_item-listbox->num_items_displayed+1;
if (listbox->num_items <= listbox->num_items_displayed )
listbox->first_item = 0;
else
{
oldfakepos = listbox->scrollbar->position;
listbox->scrollbar->position = listbox->first_item;
listbox->scrollbar->fake_position = listbox->scrollbar->position-listbox->scrollbar->start;
listbox->scrollbar->fake_position *= listbox->scrollbar->height-listbox->scrollbar->fake_size;
listbox->scrollbar->fake_position /= (listbox->scrollbar->stop-listbox->scrollbar->start);
if (listbox->scrollbar->fake_position<0)
{
listbox->scrollbar->fake_position = 0;
}
if (listbox->scrollbar->fake_position > (listbox->scrollbar->height-listbox->scrollbar->fake_size))
{
listbox->scrollbar->fake_position = (listbox->scrollbar->height-listbox->scrollbar->fake_size);
}
if (oldfakepos != listbox->scrollbar->position )
listbox->scrollbar->status = 1;
}
}
}
2014-10-04 22:13:47 +00:00
if (selected_gadget==listbox)
2006-03-20 17:12:09 +00:00
{
if (listbox->dragging)
2006-03-20 17:12:09 +00:00
{
int x, y, z;
mouse_get_pos(&x, &y, &z);
if (y < listbox->y1)
2006-03-20 17:12:09 +00:00
mitem = -1;
else
mitem = (y - listbox->y1)/listbox->textheight;
2006-03-20 17:12:09 +00:00
if ((mitem < 0) && (timer_query() > listbox->last_scrolled + 1))
2006-03-20 17:12:09 +00:00
{
listbox->current_item--;
listbox->last_scrolled = timer_query();
2006-03-20 17:12:09 +00:00
listbox->moved = 1;
}
if ((mitem >= listbox->num_items_displayed) &&
(timer_query() > listbox->last_scrolled + 1))
2006-03-20 17:12:09 +00:00
{
listbox->current_item++;
listbox->last_scrolled = timer_query();
2006-03-20 17:12:09 +00:00
listbox->moved = 1;
}
if ((mitem>=0) && (mitem<listbox->num_items_displayed))
{
listbox->current_item = mitem+listbox->first_item;
listbox->moved=1;
}
if (listbox->current_item <0 )
listbox->current_item = 0;
if (listbox->current_item >= listbox->num_items )
listbox->current_item = listbox->num_items-1;
if (listbox->current_item<listbox->first_item)
listbox->first_item = listbox->current_item;
if (listbox->current_item>=(listbox->first_item+listbox->num_items_displayed))
listbox->first_item = listbox->current_item-listbox->num_items_displayed+1;
if (listbox->num_items <= listbox->num_items_displayed )
listbox->first_item = 0;
else
{
oldfakepos = listbox->scrollbar->position;
listbox->scrollbar->position = listbox->first_item;
listbox->scrollbar->fake_position = listbox->scrollbar->position-listbox->scrollbar->start;
listbox->scrollbar->fake_position *= listbox->scrollbar->height-listbox->scrollbar->fake_size;
listbox->scrollbar->fake_position /= (listbox->scrollbar->stop-listbox->scrollbar->start);
if (listbox->scrollbar->fake_position<0)
{
listbox->scrollbar->fake_position = 0;
}
if (listbox->scrollbar->fake_position > (listbox->scrollbar->height-listbox->scrollbar->fake_size))
{
listbox->scrollbar->fake_position = (listbox->scrollbar->height-listbox->scrollbar->fake_size);
}
if (oldfakepos != listbox->scrollbar->position )
listbox->scrollbar->status = 1;
}
}
if (B1_DOUBLE_CLICKED )
{
listbox->selected_item = listbox->current_item;
2014-08-06 02:10:49 +00:00
rval = window_event_result::handled;
2006-03-20 17:12:09 +00:00
}
}
2012-03-03 12:19:15 +00:00
if (listbox->moved || (listbox->selected_item > 0))
{
2014-10-04 22:13:47 +00:00
ui_gadget_send_event(dlg, (listbox->selected_item > 0) ? EVENT_UI_LISTBOX_SELECTED : EVENT_UI_LISTBOX_MOVED, listbox);
2014-08-06 02:10:49 +00:00
return window_event_result::handled;
2012-03-03 12:19:15 +00:00
}
2006-03-20 17:12:09 +00:00
return rval;
2006-03-20 17:12:09 +00:00
}
2015-04-02 02:36:54 +00:00
void ui_listbox_change(UI_DIALOG *, UI_GADGET_LISTBOX *listbox, uint_fast32_t numitems, const char *const *list)
2006-03-20 17:12:09 +00:00
{
int stop, start;
UI_GADGET_SCROLLBAR * scrollbar;
listbox->list = list;
listbox->num_items = numitems;
listbox->first_item = 0;
listbox->current_item = -1;
listbox->last_scrolled = timer_query();
2006-03-20 17:12:09 +00:00
listbox->dragging = 0;
listbox->selected_item = -1;
listbox->status = 1;
listbox->first_item = 0;
listbox->current_item = listbox->old_current_item = 0;
listbox->moved = 0;
scrollbar = listbox->scrollbar.get();
2006-03-20 17:12:09 +00:00
start=0;
stop= numitems - listbox->num_items_displayed;
if (stop < start) stop = start;
scrollbar->horz = 0;
scrollbar->start = start;
scrollbar->stop = stop;
scrollbar->fake_length = scrollbar->height;
scrollbar->fake_position = 0;
if (stop!=start)
scrollbar->fake_size = (listbox->num_items_displayed * scrollbar->height)/(stop-start+1+listbox->num_items_displayed);
else
scrollbar->fake_size = scrollbar->height;
if (scrollbar->fake_size < 7) scrollbar->fake_size = 7;
scrollbar->dragging = 0;
scrollbar->moved=0;
scrollbar->status=1;
}
2015-12-05 22:57:24 +00:00
}