2014-04-24 19:53:42 +02:00
|
|
|
/*****************************************************************************
|
2022-10-01 09:42:14 +02:00
|
|
|
* Copyright (c) 2014-2022 OpenRCT2 developers
|
2014-04-25 19:25:34 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
2014-04-25 19:25:34 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
2014-04-25 19:25:34 +02:00
|
|
|
*****************************************************************************/
|
2014-04-24 19:53:42 +02:00
|
|
|
|
2018-08-12 13:50:40 +02:00
|
|
|
#include <algorithm>
|
2018-01-03 00:13:37 +01:00
|
|
|
#include <openrct2-ui/interface/Widget.h>
|
2017-12-07 22:26:52 +01:00
|
|
|
#include <openrct2-ui/windows/Window.h>
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2/Context.h>
|
|
|
|
#include <openrct2/Input.h>
|
2018-03-19 23:28:40 +01:00
|
|
|
#include <openrct2/drawing/Drawing.h>
|
2021-12-12 00:06:06 +01:00
|
|
|
#include <openrct2/localisation/Formatter.h>
|
2018-06-22 23:21:44 +02:00
|
|
|
#include <openrct2/localisation/Localisation.h>
|
2014-04-24 19:53:42 +02:00
|
|
|
|
2018-05-16 20:41:29 +02:00
|
|
|
// clang-format off
|
2014-04-24 19:53:42 +02:00
|
|
|
enum {
|
2017-06-06 23:24:18 +02:00
|
|
|
WIDX_BACKGROUND
|
2014-04-24 19:53:42 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static rct_widget window_tooltip_widgets[] = {
|
2020-11-27 04:14:20 +01:00
|
|
|
MakeWidget({0, 0}, {200, 32}, WindowWidgetType::ImgBtn, WindowColour::Primary),
|
2021-09-26 11:11:42 +02:00
|
|
|
WIDGETS_END,
|
2014-04-24 19:53:42 +02:00
|
|
|
};
|
|
|
|
|
2021-11-23 14:18:07 +01:00
|
|
|
static void WindowTooltipUpdate(rct_window *w);
|
|
|
|
static void WindowTooltipPaint(rct_window *w, rct_drawpixelinfo *dpi);
|
2014-04-24 19:53:42 +02:00
|
|
|
|
2022-08-27 16:56:52 +02:00
|
|
|
static WindowEventList window_tooltip_events([](auto& events)
|
2020-09-28 20:36:15 +02:00
|
|
|
{
|
2021-11-23 14:18:07 +01:00
|
|
|
events.update = &WindowTooltipUpdate;
|
|
|
|
events.paint = &WindowTooltipPaint;
|
2020-09-28 20:36:15 +02:00
|
|
|
});
|
2018-05-16 20:41:29 +02:00
|
|
|
// clang-format on
|
2014-04-24 19:53:42 +02:00
|
|
|
|
2016-10-23 22:13:17 +02:00
|
|
|
static utf8 _tooltipText[sizeof(gCommonStringFormatBuffer)];
|
2018-06-20 17:28:51 +02:00
|
|
|
static int16_t _tooltipNumLines;
|
2016-09-05 22:13:53 +02:00
|
|
|
|
2021-11-23 14:18:07 +01:00
|
|
|
void WindowTooltipReset(const ScreenCoordsXY& screenCoords)
|
2014-04-24 19:53:42 +02:00
|
|
|
{
|
2020-10-17 10:10:08 +02:00
|
|
|
gTooltipCursor = screenCoords;
|
2017-06-06 23:24:18 +02:00
|
|
|
gTooltipTimeout = 0;
|
2022-08-21 18:38:25 +02:00
|
|
|
gTooltipWidget.window_classification = WindowClass::Null;
|
2020-07-28 00:51:10 +02:00
|
|
|
input_set_state(InputState::Normal);
|
2017-06-06 23:24:18 +02:00
|
|
|
input_set_flag(INPUT_FLAG_4, false);
|
2014-04-24 19:53:42 +02:00
|
|
|
}
|
|
|
|
|
2020-10-17 10:10:08 +02:00
|
|
|
// Returns the width of the new tooltip text
|
|
|
|
static int32_t FormatTextForTooltip(const OpenRCT2String& message)
|
2014-04-24 19:53:42 +02:00
|
|
|
{
|
2020-12-19 20:53:57 +01:00
|
|
|
utf8 tempBuffer[sizeof(gCommonStringFormatBuffer)];
|
|
|
|
format_string(tempBuffer, sizeof(tempBuffer), message.str, message.args.Data());
|
|
|
|
|
|
|
|
OpenRCT2String formattedMessage{ STR_STRING_TOOLTIP, Formatter() };
|
|
|
|
formattedMessage.args.Add<const char*>(tempBuffer);
|
|
|
|
format_string(_tooltipText, sizeof(_tooltipText), formattedMessage.str, formattedMessage.args.Data());
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2021-02-28 00:22:24 +01:00
|
|
|
auto textWidth = gfx_get_string_width_new_lined(_tooltipText, FontSpriteBase::SMALL);
|
2020-10-17 10:10:08 +02:00
|
|
|
textWidth = std::min(textWidth, 196);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2021-02-27 12:40:20 +01:00
|
|
|
int32_t numLines;
|
2021-02-28 00:22:24 +01:00
|
|
|
textWidth = gfx_wrap_string(_tooltipText, textWidth + 1, FontSpriteBase::SMALL, &numLines);
|
2017-06-06 23:24:18 +02:00
|
|
|
_tooltipNumLines = numLines;
|
2020-10-17 10:10:08 +02:00
|
|
|
return textWidth;
|
|
|
|
}
|
|
|
|
|
2021-11-23 14:18:07 +01:00
|
|
|
void WindowTooltipShow(const OpenRCT2String& message, ScreenCoordsXY screenCoords)
|
2020-10-17 10:10:08 +02:00
|
|
|
{
|
2022-08-21 18:38:25 +02:00
|
|
|
auto* w = window_find_by_class(WindowClass::Error);
|
2020-10-17 10:10:08 +02:00
|
|
|
if (w != nullptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int32_t textWidth = FormatTextForTooltip(message);
|
|
|
|
int32_t width = textWidth + 3;
|
2021-02-28 00:22:24 +01:00
|
|
|
int32_t height = ((_tooltipNumLines + 1) * font_get_line_height(FontSpriteBase::SMALL)) + 4;
|
2017-06-06 23:24:18 +02:00
|
|
|
window_tooltip_widgets[WIDX_BACKGROUND].right = width;
|
|
|
|
window_tooltip_widgets[WIDX_BACKGROUND].bottom = height;
|
|
|
|
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t screenWidth = context_get_width();
|
|
|
|
int32_t screenHeight = context_get_height();
|
2020-03-01 04:47:35 +01:00
|
|
|
screenCoords.x = std::clamp(screenCoords.x - (width / 2), 0, screenWidth - width);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// TODO The cursor size will be relative to the window DPI.
|
|
|
|
// The amount to offset the y should be adjusted.
|
|
|
|
|
2018-06-20 17:28:51 +02:00
|
|
|
int32_t max_y = screenHeight - height;
|
2020-03-01 04:47:35 +01:00
|
|
|
screenCoords.y += 26; // Normally, we'd display the tooltip 26 lower
|
|
|
|
if (screenCoords.y > max_y)
|
2017-06-06 23:24:18 +02:00
|
|
|
// If y is too large, the tooltip could be forced below the cursor if we'd just clamped y,
|
|
|
|
// so we'll subtract a bit more
|
2020-03-01 04:47:35 +01:00
|
|
|
screenCoords.y -= height + 40;
|
|
|
|
screenCoords.y = std::clamp(screenCoords.y, 22, max_y);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
2022-08-21 18:38:25 +02:00
|
|
|
w = WindowCreate(
|
|
|
|
screenCoords, width, height, &window_tooltip_events, WindowClass::Tooltip, WF_TRANSPARENT | WF_STICK_TO_FRONT);
|
2017-06-06 23:24:18 +02:00
|
|
|
w->widgets = window_tooltip_widgets;
|
|
|
|
|
|
|
|
reset_tooltip_not_shown();
|
2014-04-24 19:53:42 +02:00
|
|
|
}
|
|
|
|
|
2015-09-01 08:08:28 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2015-09-01 08:08:28 +02:00
|
|
|
* rct2: 0x006EA10D
|
|
|
|
*/
|
2022-08-21 18:49:23 +02:00
|
|
|
void WindowTooltipOpen(rct_window* widgetWindow, WidgetIndex widgetIndex, const ScreenCoordsXY& screenCords)
|
2015-09-01 08:08:28 +02:00
|
|
|
{
|
2017-08-15 10:07:44 +02:00
|
|
|
if (widgetWindow == nullptr || widgetIndex == -1)
|
2017-06-06 23:24:18 +02:00
|
|
|
return;
|
2015-09-01 08:08:28 +02:00
|
|
|
|
2020-11-30 01:11:07 +01:00
|
|
|
auto widget = &widgetWindow->widgets[widgetIndex];
|
2017-06-06 23:24:18 +02:00
|
|
|
window_event_invalidate_call(widgetWindow);
|
2020-05-01 01:06:58 +02:00
|
|
|
|
2020-11-30 01:11:07 +01:00
|
|
|
OpenRCT2String result;
|
2020-10-10 15:49:56 +02:00
|
|
|
if (widget->flags & WIDGET_FLAGS::TOOLTIP_IS_STRING)
|
|
|
|
{
|
2022-10-03 20:50:19 +02:00
|
|
|
auto tooltipString = widget->sztooltip;
|
|
|
|
if (*tooltipString == 0)
|
|
|
|
return;
|
|
|
|
|
2020-10-10 15:49:56 +02:00
|
|
|
result.str = STR_STRING_TOOLTIP;
|
|
|
|
result.args = Formatter();
|
2022-10-03 20:50:19 +02:00
|
|
|
result.args.Add<const char*>(tooltipString);
|
2020-11-30 01:11:07 +01:00
|
|
|
|
|
|
|
gTooltipWidget.window_classification = widgetWindow->classification;
|
|
|
|
gTooltipWidget.window_number = widgetWindow->number;
|
|
|
|
gTooltipWidget.widget_index = widgetIndex;
|
2020-10-10 15:49:56 +02:00
|
|
|
}
|
2020-11-30 01:11:07 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
auto stringId = widget->tooltip;
|
|
|
|
if (stringId == STR_NONE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gTooltipWidget.window_classification = widgetWindow->classification;
|
|
|
|
gTooltipWidget.window_number = widgetWindow->number;
|
|
|
|
gTooltipWidget.widget_index = widgetIndex;
|
|
|
|
result = window_event_tooltip_call(widgetWindow, widgetIndex, stringId);
|
|
|
|
if (result.str == STR_NONE)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-23 14:18:07 +01:00
|
|
|
WindowTooltipShow(result, screenCords);
|
2015-09-01 08:08:28 +02:00
|
|
|
}
|
|
|
|
|
2014-04-24 19:53:42 +02:00
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-24 19:53:42 +02:00
|
|
|
* rct2: 0x006E98C6
|
|
|
|
*/
|
2021-11-23 14:18:07 +01:00
|
|
|
void WindowTooltipClose()
|
2014-04-24 19:53:42 +02:00
|
|
|
{
|
2022-08-21 18:38:25 +02:00
|
|
|
window_close_by_class(WindowClass::Tooltip);
|
2017-06-06 23:24:18 +02:00
|
|
|
gTooltipTimeout = 0;
|
2022-08-21 18:38:25 +02:00
|
|
|
gTooltipWidget.window_classification = WindowClass::Null;
|
2014-04-24 19:53:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-24 19:53:42 +02:00
|
|
|
* rct2: 0x006EA580
|
|
|
|
*/
|
2021-11-23 14:18:07 +01:00
|
|
|
static void WindowTooltipUpdate(rct_window* w)
|
2014-04-24 19:53:42 +02:00
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
reset_tooltip_not_shown();
|
2014-04-24 19:53:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-10-20 20:16:30 +02:00
|
|
|
*
|
2014-04-24 19:53:42 +02:00
|
|
|
* rct2: 0x006EA41D
|
|
|
|
*/
|
2021-11-23 14:18:07 +01:00
|
|
|
static void WindowTooltipPaint(rct_window* w, rct_drawpixelinfo* dpi)
|
2014-04-24 19:53:42 +02:00
|
|
|
{
|
2020-03-01 20:32:35 +01:00
|
|
|
int32_t left = w->windowPos.x;
|
|
|
|
int32_t top = w->windowPos.y;
|
|
|
|
int32_t right = w->windowPos.x + w->width - 1;
|
|
|
|
int32_t bottom = w->windowPos.y + w->height - 1;
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Background
|
2020-12-05 19:13:59 +01:00
|
|
|
gfx_filter_rect(dpi, { { left + 1, top + 1 }, { right - 1, bottom - 1 } }, FilterPaletteID::Palette45);
|
|
|
|
gfx_filter_rect(dpi, { { left + 1, top + 1 }, { right - 1, bottom - 1 } }, FilterPaletteID::PaletteGlassLightOrange);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Sides
|
2020-12-05 19:13:59 +01:00
|
|
|
gfx_filter_rect(dpi, { { left + 0, top + 2 }, { left + 0, bottom - 2 } }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_rect(dpi, { { right + 0, top + 2 }, { right + 0, bottom - 2 } }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_rect(dpi, { { left + 2, bottom + 0 }, { right - 2, bottom + 0 } }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_rect(dpi, { { left + 2, top + 0 }, { right - 2, top + 0 } }, FilterPaletteID::PaletteDarken3);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Corners
|
2020-12-05 19:13:59 +01:00
|
|
|
gfx_filter_pixel(dpi, { left + 1, top + 1 }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_pixel(dpi, { right - 1, top + 1 }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_pixel(dpi, { left + 1, bottom - 1 }, FilterPaletteID::PaletteDarken3);
|
|
|
|
gfx_filter_pixel(dpi, { right - 1, bottom - 1 }, FilterPaletteID::PaletteDarken3);
|
2017-06-06 23:24:18 +02:00
|
|
|
|
|
|
|
// Text
|
2020-03-01 20:32:35 +01:00
|
|
|
left = w->windowPos.x + ((w->width + 1) / 2) - 1;
|
|
|
|
top = w->windowPos.y + 1;
|
2021-02-28 00:22:24 +01:00
|
|
|
draw_string_centred_raw(dpi, { left, top }, _tooltipNumLines, _tooltipText, FontSpriteBase::SMALL);
|
2015-10-30 15:18:29 +01:00
|
|
|
}
|