OXYGENHUB
◆ main openmsx / src / imgui / ImGuiConnector.cc
4.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "ImGuiConnector.hh"
2
3
#include "ImGuiCpp.hh"
4
#include "ImGuiManager.hh"
5
#include "ImGuiUtils.hh"
6
7
#include "Connector.hh"
8
#include "MSXMotherBoard.hh"
9
#include "Pluggable.hh"
10
#include "PluggingController.hh"
11
12
#include "ImGuiPluggable.hh"
13
14
#include <imgui.h>
15
16
#include <algorithm>
17
18
using namespace std::literals;
19
20
namespace openmsx {
21
22
[[nodiscard]] static zstring_view pluggableToGuiString(zstring_view pluggable)
23
{
24
	if (pluggable == "msxjoystick1")       return "MSX joystick 1";
25
	if (pluggable == "msxjoystick2")       return "MSX joystick 2";
26
	if (pluggable == "joymega1")           return "JoyMega controller 1";
27
	if (pluggable == "joymega2")           return "JoyMega controller 2";
28
	if (pluggable == "joyhandle1")         return "Panasonic FS-JH1 Joy Handle 1";
29
	if (pluggable == "joyhandle2")         return "Panasonic FS-JH1 Joy Handle 2";
30
	if (pluggable == "arkanoidpad")        return "Arkanoid Vaus paddle";
31
	if (pluggable == "ninjatap")           return "Ninja Tap";
32
	if (pluggable == "cassetteplayer")     return "Tape deck";
33
	if (pluggable == "simpl")              return "SIMPL";
34
	if (pluggable == "msx-printer")        return "MSX printer";
35
	if (pluggable == "epson-printer")      return "Epson printer";
36
	if (pluggable == "MSXPlotter")         return "MSX plotter";
37
	if (pluggable == "tetris2-protection") return "Tetris II SE dongle";
38
	if (pluggable == "circuit-designer-rd-dongle") return "Circuit Designer RD dongle";
39
	return pluggable;
40
}
41
42
void ImGuiConnector::showMenu(MSXMotherBoard* motherBoard)
43
{
44
	im::Menu("Connectors", motherBoard != nullptr, [&]{
45
		showPluggables(motherBoard->getPluggingController(), Mode::COMBO);
46
	});
47
}
48
49
void ImGuiConnector::paintPluggableSelectables(PluggingController& controller, const Connector& connector)
50
{
51
	const auto& currentPluggable = connector.getPlugged();
52
	const auto& connectorName = connector.getName();
53
	if (!currentPluggable.getName().empty()) {
54
		if (ImGui::Selectable("[unplug]")) {
55
			manager.executeDelayed(makeTclList("unplug", connectorName));
56
		}
57
	}
58
	auto connectorClass = connector.getClass();
59
	for (const auto& plug : controller.getPluggables()) {
60
		if (plug->getClass() != connectorClass) continue;
61
		auto plugName = plug->getName();
62
		bool selected = plug.get() == &currentPluggable;
63
		int flags = !selected && plug->getConnector() ? ImGuiSelectableFlags_Disabled : 0; // plugged in another connector
64
		if (ImGui::Selectable(pluggableToGuiString(plugName).c_str(), selected, flags)) {
65
			manager.executeDelayed(makeTclList("plug", connectorName, plugName));
66
		}
67
		simpleToolTip(plug->getDescription());
68
		if (selected) {
69
			ImGui::SetItemDefaultFocus();
70
		}
71
	}
72
}
73
74
void ImGuiConnector::paintImGuiExtra(Pluggable& pluggable)
75
{
76
	if (auto* extra = dynamic_cast<ImGuiPluggable*>(&pluggable)) {
77
		extra->handleImGuiExtraMenuItems();
78
	}
79
}
80
81
void ImGuiConnector::showPluggables(PluggingController& controller, Mode mode)
82
{
83
	im::Table("##shared-table", 2, [&]{
84
		ImGui::TableSetupColumn("Label", ImGuiTableColumnFlags_WidthFixed);
85
		ImGui::TableSetupColumn("Value");
86
		for (const auto* connector : controller.getConnectors()) {
87
			if (ImGui::TableNextColumn()) { // connector
88
				ImGui::TextUnformatted(connector->getDescription());
89
			}
90
			if (ImGui::TableNextColumn()) { // pluggable
91
				auto& currentPluggable = connector->getPlugged();
92
				const auto& plugName = currentPluggable.getName();
93
				const auto& connectorName = connector->getName();
94
				using enum ImGuiConnector::Mode;
95
				switch (mode) {
96
				case VIEW:
97
					ImGui::TextUnformatted(plugName.empty() ? "(empty)"sv : pluggableToGuiString(plugName));
98
					simpleToolTip(currentPluggable.getDescription());
99
					break;
100
				case COMBO:
101
					ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12.0f);
102
					im::Combo(tmpStrCat("##", connectorName).c_str(), pluggableToGuiString(plugName).c_str(), [&]{
103
						paintPluggableSelectables(controller, *connector);
104
					});
105
					simpleToolTip(currentPluggable.getDescription());
106
					paintImGuiExtra(currentPluggable);
107
					break;
108
				case SUBMENU:
109
					if (plugName.empty() && std::ranges::none_of(controller.getPluggables(), [&](const auto& plug) {
110
							return plug->getClass() == connector->getClass(); })) {
111
						// nothing to choose from, avoid an empty submenu
112
						ImGui::TextUnformatted("(empty)"sv);
113
						break;
114
					}
115
					im::Menu(tmpStrCat(strCat_if(plugName.empty(), "(empty)##", connectorName).else_(STRCAT_LAZY(pluggableToGuiString(plugName)))).c_str(), [&] {
116
						paintPluggableSelectables(controller, *connector);
117
					});
118
					paintImGuiExtra(currentPluggable);
119
					break;
120
				default:
121
					UNREACHABLE;
122
				}
123
			}
124
		}
125
	});
126
}
127
128
129
} // namespace openmsx