OXYGENHUB
◆ main openmsx / src / imgui / ImGuiKeyboard.cc
7.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
// Implementation inspired by:
2
//   https://github.com/CedricGuillemet/ImHotKey
3
4
#include "ImGuiKeyboard.hh"
5
6
#include "ImGuiCpp.hh"
7
#include "ImGuiManager.hh"
8
#include "ImGuiUtils.hh"
9
10
#include "Keyboard.hh"
11
#include "MSXMotherBoard.hh"
12
#include "UnicodeKeymap.hh" // KeyMatrixPosition
13
14
#include <imgui.h>
15
16
#include <array>
17
18
namespace openmsx {
19
20
using namespace std::literals;
21
22
void ImGuiKeyboard::save(ImGuiTextBuffer& buf)
23
{
24
	savePersistent(buf, *this, persistentElements);
25
}
26
27
void ImGuiKeyboard::loadLine(std::string_view name, zstring_view value)
28
{
29
	loadOnePersistent(name, value, *this, persistentElements);
30
}
31
32
void ImGuiKeyboard::paint(MSXMotherBoard* motherBoard)
33
{
34
	if (!show) return;
35
36
	if (!motherBoard) return;
37
	const auto* keyboard = motherBoard->getKeyboard();
38
	if (!keyboard) return;
39
	auto matrix = keyboard->getKeys();
40
41
	ImGui::SetNextWindowSize({640, 200}, ImGuiCond_FirstUseEver);
42
	im::Window("Virtual keyboard", &show, [&]{
43
		struct Key {
44
			const char* label;
45
			gl::vec2 pos;
46
			gl::vec2 size;
47
			KeyMatrixPosition matrixPos;
48
		};
49
		// TODO read this from some (MSX machine specific) config file
50
		static constexpr std::array keys = {
51
			Key{"F1",     {  0,  0}, {52,32}, KeyMatrixPosition{0x65}},
52
			Key{"F2",     { 56,  0}, {52,32}, KeyMatrixPosition{0x66}},
53
			Key{"F3",     {112,  0}, {52,32}, KeyMatrixPosition{0x67}},
54
			Key{"F4",     {168,  0}, {52,32}, KeyMatrixPosition{0x70}},
55
			Key{"F5",     {224,  0}, {52,32}, KeyMatrixPosition{0x71}},
56
			Key{"Select", {300,  0}, {52,32}, KeyMatrixPosition{0x76}},
57
			Key{"Stop",   {356,  0}, {52,32}, KeyMatrixPosition{0x74}},
58
			Key{"Home",   {432,  0}, {52,32}, KeyMatrixPosition{0x81}},
59
			Key{"Ins",    {488,  0}, {52,32}, KeyMatrixPosition{0x82}},
60
			Key{"Del",    {544,  0}, {52,32}, KeyMatrixPosition{0x83}},
61
62
			Key{"Esc",    {  0, 36}, {36,32}, KeyMatrixPosition{0x72}},
63
			Key{"1",      { 40, 36}, {36,32}, KeyMatrixPosition{0x01}},
64
			Key{"2",      { 80, 36}, {36,32}, KeyMatrixPosition{0x02}},
65
			Key{"3",      {120, 36}, {36,32}, KeyMatrixPosition{0x03}},
66
			Key{"4",      {160, 36}, {36,32}, KeyMatrixPosition{0x04}},
67
			Key{"5",      {200, 36}, {36,32}, KeyMatrixPosition{0x05}},
68
			Key{"6",      {240, 36}, {36,32}, KeyMatrixPosition{0x06}},
69
			Key{"7",      {280, 36}, {36,32}, KeyMatrixPosition{0x07}},
70
			Key{"8",      {320, 36}, {36,32}, KeyMatrixPosition{0x10}},
71
			Key{"9",      {360, 36}, {36,32}, KeyMatrixPosition{0x11}},
72
			Key{"0",      {400, 36}, {36,32}, KeyMatrixPosition{0x00}},
73
			Key{"-",      {440, 36}, {36,32}, KeyMatrixPosition{0x12}},
74
			Key{"=",      {480, 36}, {36,32}, KeyMatrixPosition{0x13}},
75
			Key{"\\",     {520, 36}, {36,32}, KeyMatrixPosition{0x14}},
76
			Key{"BS",     {560, 36}, {36,32}, KeyMatrixPosition{0x75}},
77
78
			Key{"Tab",    {  0, 72}, {56,32}, KeyMatrixPosition{0x73}},
79
			Key{"Q",      { 60, 72}, {36,32}, KeyMatrixPosition{0x46}},
80
			Key{"W",      {100, 72}, {36,32}, KeyMatrixPosition{0x54}},
81
			Key{"E",      {140, 72}, {36,32}, KeyMatrixPosition{0x32}},
82
			Key{"R",      {180, 72}, {36,32}, KeyMatrixPosition{0x47}},
83
			Key{"T",      {220, 72}, {36,32}, KeyMatrixPosition{0x51}},
84
			Key{"Y",      {260, 72}, {36,32}, KeyMatrixPosition{0x56}},
85
			Key{"U",      {300, 72}, {36,32}, KeyMatrixPosition{0x52}},
86
			Key{"I",      {340, 72}, {36,32}, KeyMatrixPosition{0x36}},
87
			Key{"O",      {380, 72}, {36,32}, KeyMatrixPosition{0x44}},
88
			Key{"P",      {420, 72}, {36,32}, KeyMatrixPosition{0x45}},
89
			Key{"[",      {460, 72}, {36,32}, KeyMatrixPosition{0x15}},
90
			Key{"]",      {500, 72}, {36,32}, KeyMatrixPosition{0x16}},
91
			Key{"Return", {548, 72}, {48,68}, KeyMatrixPosition{0x77}},
92
93
			Key{"Ctrl",   {  0,108}, {64,32}, KeyMatrixPosition{0x61}},
94
			Key{"A",      { 68,108}, {36,32}, KeyMatrixPosition{0x26}},
95
			Key{"S",      {108,108}, {36,32}, KeyMatrixPosition{0x50}},
96
			Key{"D",      {148,108}, {36,32}, KeyMatrixPosition{0x31}},
97
			Key{"F",      {188,108}, {36,32}, KeyMatrixPosition{0x33}},
98
			Key{"G",      {228,108}, {36,32}, KeyMatrixPosition{0x34}},
99
			Key{"H",      {268,108}, {36,32}, KeyMatrixPosition{0x35}},
100
			Key{"J",      {308,108}, {36,32}, KeyMatrixPosition{0x37}},
101
			Key{"K",      {348,108}, {36,32}, KeyMatrixPosition{0x40}},
102
			Key{"L",      {388,108}, {36,32}, KeyMatrixPosition{0x41}},
103
			Key{";",      {428,108}, {36,32}, KeyMatrixPosition{0x17}},
104
			Key{"'",      {468,108}, {36,32}, KeyMatrixPosition{0x20}},
105
			Key{"`",      {508,108}, {36,32}, KeyMatrixPosition{0x21}},
106
107
			Key{"Shift",  {  0,144}, {80,32}, KeyMatrixPosition{0x60}},
108
			Key{"Z",      { 84,144}, {36,32}, KeyMatrixPosition{0x57}},
109
			Key{"X",      {124,144}, {36,32}, KeyMatrixPosition{0x55}},
110
			Key{"C",      {164,144}, {36,32}, KeyMatrixPosition{0x30}},
111
			Key{"V",      {204,144}, {36,32}, KeyMatrixPosition{0x53}},
112
			Key{"B",      {244,144}, {36,32}, KeyMatrixPosition{0x27}},
113
			Key{"N",      {284,144}, {36,32}, KeyMatrixPosition{0x43}},
114
			Key{"M",      {324,144}, {36,32}, KeyMatrixPosition{0x42}},
115
			Key{",",      {364,144}, {36,32}, KeyMatrixPosition{0x22}},
116
			Key{".",      {404,144}, {36,32}, KeyMatrixPosition{0x23}},
117
			Key{"/",      {444,144}, {36,32}, KeyMatrixPosition{0x24}},
118
			Key{"Acc",    {484,144}, {36,32}, KeyMatrixPosition{0x25}},
119
			Key{"Shift",  {524,144}, {72,32}, KeyMatrixPosition{0x60}},
120
121
			Key{"Cap",    { 84,180}, {36,32}, KeyMatrixPosition{0x63}},
122
			Key{"Grp",    {124,180}, {36,32}, KeyMatrixPosition{0x62}},
123
			Key{"Space",  {164,180},{316,32}, KeyMatrixPosition{0x80}},
124
			Key{"Cod",    {484,180}, {36,32}, KeyMatrixPosition{0x64}},
125
126
			Key{"7",      {632,  0}, {36,32}, KeyMatrixPosition{0xA2}},
127
			Key{"8",      {672,  0}, {36,32}, KeyMatrixPosition{0xA3}},
128
			Key{"9",      {712,  0}, {36,32}, KeyMatrixPosition{0xA4}},
129
			Key{"-",      {752,  0}, {36,32}, KeyMatrixPosition{0xA5}},
130
			Key{"4",      {632, 36}, {36,32}, KeyMatrixPosition{0x97}},
131
			Key{"5",      {672, 36}, {36,32}, KeyMatrixPosition{0xA0}},
132
			Key{"6",      {712, 36}, {36,32}, KeyMatrixPosition{0xA1}},
133
			Key{"/",      {752, 36}, {36,32}, KeyMatrixPosition{0x92}},
134
			Key{"1",      {632, 72}, {36,32}, KeyMatrixPosition{0x94}},
135
			Key{"2",      {672, 72}, {36,32}, KeyMatrixPosition{0x95}},
136
			Key{"3",      {712, 72}, {36,32}, KeyMatrixPosition{0x96}},
137
			Key{"*",      {752, 72}, {36,32}, KeyMatrixPosition{0x90}},
138
			Key{"0",      {632,108}, {36,32}, KeyMatrixPosition{0x93}},
139
			Key{",",      {672,108}, {36,32}, KeyMatrixPosition{0xA6}},
140
			Key{".",      {712,108}, {36,32}, KeyMatrixPosition{0xA7}},
141
			Key{"+",      {752,108}, {36,32}, KeyMatrixPosition{0x91}},
142
143
			Key{"Left",   {652,144}, {36,68}, KeyMatrixPosition{0x84}},
144
			Key{"Up",     {692,144}, {36,32}, KeyMatrixPosition{0x85}},
145
			Key{"Down",   {692,180}, {36,32}, KeyMatrixPosition{0x86}},
146
			Key{"Right",  {732,144}, {36,68}, KeyMatrixPosition{0x87}},
147
		};
148
149
		gl::vec2 maxXY;
150
		for (const auto& key : keys) {
151
			maxXY = max(maxXY, key.pos + key.size);
152
		}
153
		gl::vec2 available = ImGui::GetContentRegionAvail();
154
		float scale = min_component(available / maxXY);
155
156
		gl::vec2 origin = ImGui::GetCursorPos();
157
		im::ID_for_range(keys.size(), [&](int i) {
158
			const auto& key = keys[i];
159
			auto row    = key.matrixPos.getRow();
160
			auto column = key.matrixPos.getColumn();
161
			auto mask = 1 << column;
162
			bool active = !(matrix[row] & mask);
163
164
			ImGui::SetCursorPos(origin + scale * key.pos);
165
			im::StyleColor(ImGuiCol_Button, getColor(active ? imColor::KEY_ACTIVE : imColor::KEY_NOT_ACTIVE), [&]{
166
				ImGui::Button(key.label, scale * key.size);
167
			});
168
169
			if (ImGui::IsItemActivated()) {
170
				manager.execute(makeTclList("keymatrixdown", row, mask));
171
			}
172
			if (ImGui::IsItemDeactivated()) {
173
				manager.execute(makeTclList("keymatrixup", row, mask));
174
			}
175
			if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
176
				manager.execute(makeTclList((active ? "keymatrixup"sv : "keymatrixdown"sv),
177
							row, mask));
178
			}
179
		});
180
	});
181
}
182
183
} // namespace openmsx