1
0
Fork 0

Feature: WIP: Draw hotkey hints over some widgets

pull/14369/head
Colin Caine 2025-06-16 20:17:25 +01:00
parent 679f95d1de
commit a92619be89
4 changed files with 106 additions and 0 deletions

View File

@ -196,6 +196,40 @@ static std::string KeycodeToString(uint16_t keycode)
return str;
}
/**
* A short representation of the keycode, for printing as a hotkey hint.
* @param keycode The keycode to convert to a string.
* @return A string representation of this keycode.
*/
std::string KeycodeToShortString(uint16_t keycode)
{
std::string str;
if (keycode & WKC_SHIFT) {
// TODO
str += "»";
}
if (keycode & WKC_CTRL) {
str += "^";
}
if (keycode & WKC_ALT) {
str += "A+";
}
if (keycode & WKC_META) {
str += "M+";
}
keycode = keycode & ~WKC_SPECIAL_KEYS;
for (const auto &kn : _keycode_to_name) {
if (kn.keycode == keycode) {
str += kn.name;
return str;
}
}
assert(keycode < 128);
str.push_back(keycode);
return str;
}
/**
* Convert all keycodes attached to a hotkey to a single string. If multiple
* keycodes are attached to the hotkey they are split by a comma.
@ -350,3 +384,12 @@ void HandleGlobalHotkeys([[maybe_unused]] char32_t key, uint16_t keycode)
}
}
const Hotkey* HotkeyList::GetHotkeyByNum(int num) const
{
for (const Hotkey &hotkey : this->items) {
if (hotkey.num == num) {
return &hotkey;
}
}
return (const Hotkey*) nullptr;
}

View File

@ -44,6 +44,7 @@ struct HotkeyList {
void Save(IniFile &ini) const;
int CheckMatch(uint16_t keycode, bool global_only = false) const;
const Hotkey* GetHotkeyByNum(int num) const;
GlobalHotkeyHandlerFunc global_hotkey_handler;
private:
@ -64,5 +65,6 @@ void SaveHotkeysToConfig();
void HandleGlobalHotkeys(char32_t key, uint16_t keycode);
std::string KeycodeToShortString(uint16_t keycode);
#endif /* HOTKEYS_H */

View File

@ -27,6 +27,9 @@
#include "safeguards.h"
#include "widgets/toolbar_widget.h"
#include "hotkeys.h"
WidgetDimensions WidgetDimensions::scaled = {};
static std::string GetStringForWidget(const Window *w, const NWidgetCore *nwid, bool secondary = false)
@ -3108,6 +3111,63 @@ void NWidgetLeaf::Draw(const Window *w)
}
DrawOutline(w, this);
// TODO: Draw hints only if Alt is being held.
if (!this->IsDisabled()) {
this->DrawHotkeyHint(w);
}
}
void NWidgetLeaf::DrawHotkeyHint(const Window* w) {
// TODO: Use global hotkey for autoroads for rail, road, tram, etc. if
// they have been set.
// TODO: Rect is wrong for edit boxes, and the kind of hint we're showing
// will look bad anyway.
Rect r = this->GetCurrentRect().Shrink(1);
if (w->window_desc.cls == WC_MAIN_TOOLBAR && this->index == WID_TN_FAST_FORWARD) {
// Special-case hint text for Fast-forwards because it's not really a hotkey
DrawStringMultiLine(r, "Tab", TC_WHITE, SA_LEFT | SA_BOTTOM, false, FS_NORMAL);
} else if (w->window_desc.hotkeys != nullptr) {
// Widget IDs can coincidentally overlap with hotkey IDs if
// they aren't assigned properly. Avoid this.
auto hk = w->window_desc.hotkeys->GetHotkeyByNum(this->index);
if (hk != nullptr) {
if (hk->keycodes.size()) {
// Find the "best" of the available keycodes
auto keycode = *(hk->keycodes.begin());
for (auto k : hk->keycodes) {
if (!(keycode & WKC_GLOBAL_HOTKEY) && (k & WKC_GLOBAL_HOTKEY)) {
keycode = k;
} else if ('A' <= (k & ~WKC_SPECIAL_KEYS) && (k & ~WKC_SPECIAL_KEYS) <= 'Z') {
keycode = k;
}
}
// Convert to a string
// TODO: Glyphs for Shift, Alt, etc. Colour for global.
// - On screen keyboard has a sprite for shift.
auto s = KeycodeToShortString(keycode);
// Choose the font-size
auto availableSize = Dimension(r.right - r.left, r.bottom - r.top);
auto desiredSize = GetStringBoundingBox(s, FS_NORMAL);
auto fontsize = FS_NORMAL;
if (availableSize < desiredSize) {
fontsize = FS_SMALL;
}
// Display the hints!
// TODO: not as readable as my mockup :(
// - Outline or a bolder font could help.
auto colour = TC_WHITE;
if (keycode & WKC_GLOBAL_HOTKEY) {
colour = TC_YELLOW;
}
DrawStringMultiLine(r, s, colour, SA_LEFT | SA_BOTTOM, false, fontsize);
}
}
}
}
/**

View File

@ -922,6 +922,7 @@ public:
void SetupSmallestSize(Window *w) override;
void Draw(const Window *w) override;
void DrawHotkeyHint(const Window* window);
bool ButtonHit(const Point &pt);