Files
scummvm/engines/ags/engine/gui/my_listbox.cpp
T
Walter Agazzi 72888a7a8c AGS: Engine: move cursor and cursor-over-gui updates to the game update fn
This is necessary for the touch-to-mouse emulation to work
properly (and perhaps true touch controls in the future).
The order of updates is a bit wrong historically, where cursor
position and gui control focus is updated later than the
handling of button events. This means, for example, that if the
cursor was positioned over button in game frame 1, then the
mouse click will only trigger button press not later than the frame 2.

Changes:
* moved "cursor over gui" poll from draw_gui_and_overlays()
to update_cursor_over_gui(), call it in the main game update fn.
* moved update_mouse_cursor() call from
construct_game_screen_overlay() to the game update fn
(renamed to update_cursor_view().
* picked out "cursor over location" trigger out of the "render"
function into update_cursor_over_location(), call it explicitly in
the main game update fn.

Effect on user script callbacks:
* the cursor position (and gui focus) will now be updated prior
to `late_repeatedly_execute_always()` callback. Other callbacks
will not be affected, as their relative order won't change
compared with these updates.

From upstream 23493a681d4f66ae0b1088cddb82241b0bc80dbb
2023-04-29 13:11:41 +02:00

194 lines
5.5 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//include <string.h>
#include "ags/shared/ac/common.h"
#include "ags/engine/ac/game_setup.h"
#include "ags/shared/ac/keycode.h"
#include "ags/shared/font/fonts.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/engine/gui/gui_dialog.h"
#include "ags/engine/gui/gui_dialog_internal_defs.h"
#include "ags/engine/gui/my_listbox.h"
namespace AGS3 {
using AGS::Shared::Bitmap;
MyListBox::MyListBox(int xx, int yy, int wii, int hii) {
x = xx;
y = yy;
wid = wii;
hit = hii;
hit -= (hit - 4) % TEXT_HT; // resize to multiple of text height
numonscreen = (hit - 4) / TEXT_HT;
items = 0;
topitem = 0;
selected = -1;
memset(itemnames, 0, sizeof(itemnames));
}
void MyListBox::clearlist() {
for (int kk = 0; kk < items; kk++)
free(itemnames[kk]);
items = 0;
}
MyListBox::~MyListBox() {
clearlist();
}
void MyListBox::draw(Bitmap *ds) {
color_t draw_color = ds->GetCompatibleColor(_G(windowbackgroundcolor));
ds->FillRect(Rect(x, y, x + wid, y + hit), draw_color);
draw_color = ds->GetCompatibleColor(0);
ds->DrawRect(Rect(x, y, x + wid, y + hit), draw_color);
int widwas = wid;
wid -= ARROWWIDTH;
ds->DrawLine(Line(x + wid, y, x + wid, y + hit), draw_color); // draw the up/down arrows
ds->DrawLine(Line(x + wid, y + hit / 2, x + widwas, y + hit / 2), draw_color);
int xmidd = x + wid + (widwas - wid) / 2;
if (topitem < 1)
draw_color = ds->GetCompatibleColor(7);
ds->DrawLine(Line(xmidd, y + 2, xmidd, y + 10), draw_color); // up arrow
ds->DrawLine(Line(xmidd - 1, y + 3, xmidd + 1, y + 3), draw_color);
ds->DrawLine(Line(xmidd - 2, y + 4, xmidd + 2, y + 4), draw_color);
draw_color = ds->GetCompatibleColor(0);
if (topitem + numonscreen >= items)
draw_color = ds->GetCompatibleColor(7);
ds->DrawLine(Line(xmidd, y + hit - 10, xmidd, y + hit - 3), draw_color); // down arrow
ds->DrawLine(Line(xmidd - 1, y + hit - 4, xmidd + 1, y + hit - 4), draw_color);
ds->DrawLine(Line(xmidd - 2, y + hit - 5, xmidd + 2, y + hit - 5), draw_color);
draw_color = ds->GetCompatibleColor(0);
for (int tt = 0; tt < numonscreen; tt++) {
int inum = tt + topitem;
if (inum >= items)
break;
int thisypos = y + 2 + tt * TEXT_HT;
color_t text_color;
if (inum == selected) {
draw_color = ds->GetCompatibleColor(0);
ds->FillRect(Rect(x, thisypos, x + wid, thisypos + TEXT_HT - 1), draw_color);
text_color = ds->GetCompatibleColor(7);
} else text_color = ds->GetCompatibleColor(0);
wouttextxy(ds, x + 2, thisypos, _G(cbuttfont), text_color, itemnames[inum]);
}
wid = widwas;
}
int MyListBox::pressedon(int mousex, int mousey) {
if (mousex > x + wid - ARROWWIDTH) {
if ((mousey - y < hit / 2) & (topitem > 0))
topitem--;
else if ((mousey - y > hit / 2) &(topitem + numonscreen < items))
topitem++;
} else {
selected = ((mousey - y) - 2) / TEXT_HT + topitem;
if (selected >= items)
selected = items - 1;
}
draw(get_gui_screen());
_G(smcode) = CM_SELCHANGE;
return 0;
}
void MyListBox::additem(char *texx) {
if (items >= MAXLISTITEM)
quit("!CSCIUSER16: Too many items added to listbox");
size_t ln = strlen(texx) + 1;
itemnames[items] = (char *)malloc(ln);
Common::strcpy_s(itemnames[items], ln, texx);
items++;
needredraw = 1;
}
int MyListBox::processmessage(int mcode, int wParam, NumberPtr lParam) {
if (mcode == CLB_ADDITEM) {
additem((char *)lParam._ptr);
} else if (mcode == CLB_CLEAR)
clearlist();
else if (mcode == CLB_GETCURSEL)
return selected;
else if (mcode == CLB_SETCURSEL) {
selected = wParam;
if ((selected < topitem) && (selected >= 0))
topitem = selected;
if (topitem + numonscreen <= selected)
topitem = (selected + 1) - numonscreen;
} else if (mcode == CLB_GETTEXT)
Common::strcpy_s((char *)lParam._ptr, 260, itemnames[wParam]);
else if (mcode == CLB_SETTEXT) {
if (wParam < items)
free(itemnames[wParam]);
char *newstri = (char *)lParam._ptr;
size_t ln = strlen(newstri) + 2;
itemnames[wParam] = (char *)malloc(ln);
Common::strcpy_s(itemnames[wParam], ln, newstri);
} else if (mcode == CTB_KEYPRESS) {
if ((wParam == eAGSKeyCodeDownArrow) && (selected < items - 1))
selected++;
if ((wParam == eAGSKeyCodeUpArrow) && (selected > 0))
selected--;
if (wParam == eAGSKeyCodePageUp)
selected -= (numonscreen - 1);
if (wParam == eAGSKeyCodePageDown)
selected += (numonscreen - 1);
if ((selected < 0) && (items > 0))
selected = 0;
if (selected >= items)
selected = items - 1;
if ((selected < topitem) & (selected >= 0))
topitem = selected;
if (topitem + numonscreen <= selected)
topitem = (selected + 1) - numonscreen;
drawandmouse();
_G(smcode) = CM_SELCHANGE;
} else
return -1;
return 0;
}
} // namespace AGS3