Move the controls into their own panel.

This commit is contained in:
David Given
2025-09-16 00:42:02 +02:00
parent 11a6143d4c
commit 6a826d6eb5
7 changed files with 444 additions and 1225 deletions

View File

@@ -334,6 +334,8 @@ plugin(
"./abstractsectorview.h",
"./configview.cc",
"./configview.h",
"./controlpanelview.cc",
"./controlpanelview.h",
"./datastore.cc",
"./datastore.h",
"./diskprovider.cc",

View File

@@ -0,0 +1,164 @@
#include <hex/api/content_registry/user_interface.hpp>
#include <hex/api/theme_manager.hpp>
#include <hex/helpers/logger.hpp>
#include <fonts/vscode_icons.hpp>
#include <fonts/tabler_icons.hpp>
#include <fmt/format.h>
#include <imgui_internal.h>
#include "lib/core/globals.h"
#include "lib/config/config.h"
#include "lib/data/flux.h"
#include "lib/data/sector.h"
#include "lib/config/proto.h"
#include "globals.h"
#include "controlpanelview.h"
#include "datastore.h"
#include "utils.h"
#include <implot.h>
#include <implot_internal.h>
using namespace hex;
static DynamicSettingFactory settings("fluxengine.settings");
ControlPanelView::ControlPanelView():
View::Window("fluxengine.view.controlpanel.name", ICON_VS_COMPASS)
{
}
static void loadFluxFile()
{
fs::openFileBrowser(fs::DialogMode::Open,
{},
[](const auto& path)
{
settings.get<std::string>("device") = DEVICE_FLUXFILE;
settings.get<std::fs::path>("fluxfile") = path;
});
}
static void saveSectorImage()
{
fs::openFileBrowser(fs::DialogMode::Save, {}, Datastore::writeImage);
}
static void saveFluxFile()
{
fs::openFileBrowser(fs::DialogMode::Save, {}, Datastore::writeFluxFile);
}
static void showOptions() {}
void ControlPanelView::drawContent()
{
auto diskFlux = Datastore::getDiskFlux();
bool busy = Datastore::isBusy() || !Datastore::isConfigurationValid();
bool hasImage = diskFlux && diskFlux->image;
if (ImGui::BeginTable("controlPanelOuter",
3,
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoClip))
{
ON_SCOPE_EXIT
{
ImGui::EndTable();
};
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::TextAligned(0.5f, -FLT_MIN, "Inputs");
ImGui::TableNextColumn();
ImGui::TableHeader(ICON_VS_ARROW_RIGHT);
ImGui::TableNextColumn();
ImGui::TextAligned(0.5f, -FLT_MIN, "Outputs");
auto button = [&](const std::string& icon,
const std::string& label,
std::function<void()> callback,
bool isDisabled)
{
ImGui::TableNextColumn();
ImGui::BeginDisabled(isDisabled);
ON_SCOPE_EXIT
{
ImGui::EndDisabled();
};
if (ImGui::Button(fmt::format("{} {}", icon, label).c_str(),
{ImGui::GetContentRegionAvail().x, 0}))
callback();
};
ImGui::TableNextRow();
button(ICON_TA_DEVICE_FLOPPY,
"fluxengine.views.controlpanel.readDevice"_lang,
Datastore::beginRead,
busy);
ImGui::TableNextColumn();
button(ICON_VS_SAVE_AS,
"fluxengine.views.controlpanel.writeDevice"_lang,
nullptr,
busy || !hasImage);
ImGui::TableNextRow();
button(ICON_TA_UPLOAD,
"fluxengine.views.controlpanel.readFlux"_lang,
loadFluxFile,
busy);
ImGui::TableNextColumn();
button(ICON_TA_DOWNLOAD,
"fluxengine.views.controlpanel.writeFlux"_lang,
saveFluxFile,
busy || !diskFlux);
ImGui::TableNextRow();
button(ICON_VS_FOLDER_OPENED,
"fluxengine.views.controlpanel.readImage"_lang,
nullptr,
busy);
ImGui::TableNextColumn();
button(ICON_VS_SAVE_ALL,
"fluxengine.views.controlpanel.writeImage"_lang,
saveSectorImage,
busy || !hasImage);
ImGui::TableNextRow();
button(ICON_TA_REPEAT,
"fluxengine.views.controlpanel.rereadBad"_lang,
nullptr,
busy || !diskFlux);
ImGui::TableNextRow();
button(ICON_VS_NEW_FILE,
"fluxengine.views.controlpanel.createBlank"_lang,
nullptr,
busy || !Datastore::canFormat());
}
ImGui::Dummy({0, ImGui::GetFontSize()});
{
auto red = ImGuiExt::GetCustomColorU32(ImGuiCustomCol_LoggerError);
auto text = ImGui::GetColorU32(ImGuiCol_Text);
auto redHover = ImMixU32(red, text, 32);
auto redPressed = ImMixU32(red, text, 64);
ImGui::PushStyleColor(ImGuiCol_Button, red);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, redHover);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, redPressed);
ON_SCOPE_EXIT
{
ImGui::PopStyleColor(3);
};
if (maybeDisabledButton(fmt::format("{} {}",
ICON_TA_CANCEL,
"fluxengine.summary.controls.stop"_lang),
{ImGui::GetContentRegionAvail().x, 0},
!busy))
Datastore::stop();
}
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <hex/ui/view.hpp>
class ControlPanelView : public hex::View::Window
{
public:
ControlPanelView();
~ControlPanelView() override = default;
void drawContent() override;
[[nodiscard]] bool shouldDraw() const override
{
return true;
}
[[nodiscard]] bool hasViewMenuItemEntry() const override
{
return true;
}
};

View File

@@ -8,6 +8,7 @@
#include "physicalview.h"
#include "summaryview.h"
#include "configview.h"
#include "controlpanelview.h"
#include "diskprovider.h"
#include "datastore.h"
@@ -27,6 +28,7 @@ IMHEX_PLUGIN_SETUP("FluxEngine", "David Given", "FluxEngine integration")
hex::ContentRegistry::Views::add<PhysicalView>();
hex::ContentRegistry::Views::add<SummaryView>();
hex::ContentRegistry::Views::add<ConfigView>();
hex::ContentRegistry::Views::add<ControlPanelView>();
Datastore::init();
}

View File

@@ -12,7 +12,7 @@
"fluxengine.view.config.highDensity": "High density disk",
"fluxengine.view.config.rescan": "Rescan",
"fluxengine.view.summary.name":"FluxEngine control panel",
"fluxengine.view.summary.name":"FluxEngine status",
"fluxengine.summary.controls.read": "Read from device",
"fluxengine.summary.controls.write": "Write to device",
"fluxengine.summary.controls.stop": "Stop",
@@ -37,5 +37,15 @@
"fluxengine.view.config.fluxFile": "Flux file",
"fluxengine.view.config.formatProperties": "Format properties",
"fluxengine.view.config.deviceProperties": "Device properties",
"fluxengine.view.config.customProperties": "Custom properties"
"fluxengine.view.config.customProperties": "Custom properties",
"fluxengine.view.controlpanel.name": "FluxEngine controls",
"fluxengine.views.controlpanel.readDevice": "Read from device",
"fluxengine.views.controlpanel.writeDevice": "Write to device",
"fluxengine.views.controlpanel.readFlux": "Load flux file",
"fluxengine.views.controlpanel.writeFlux": "Save flux file",
"fluxengine.views.controlpanel.readImage": "Load disk image",
"fluxengine.views.controlpanel.writeImage": "Save disk image",
"fluxengine.views.controlpanel.rereadBad": "Re-read bad tracks",
"fluxengine.views.controlpanel.createBlank": "Create blank disk"
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -202,160 +202,4 @@ void SummaryView::drawContent()
}
}
}
ImGui::SetCursorPosY(
ImGui::GetContentRegionAvail().y - ImGui::GetFontSize() * 8);
if (ImGui::BeginTable("controlPanelOuter",
3,
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoClip))
{
ON_SCOPE_EXIT
{
ImGui::EndTable();
};
auto sideWidth = ImGui::GetFontSize() * 10;
ImGui::TableSetupColumn(
"", ImGuiTableColumnFlags_WidthFixed, sideWidth);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn(
"", ImGuiTableColumnFlags_WidthFixed, sideWidth);
ImGui::TableNextRow();
ImGui::TableNextColumn();
// drawDeviceBox();
ImGui::TableNextColumn();
if (ImGuiExt::BeginSubWindow("Controls",
nullptr,
ImGui::GetContentRegionAvail(),
ImGuiChildFlags_None))
{
ON_SCOPE_EXIT
{
ImGuiExt::EndSubWindow();
};
if (ImGui::BeginTable("controlPanel",
5,
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoClip))
{
ON_SCOPE_EXIT
{
ImGui::EndTable();
};
bool busy =
Datastore::isBusy() || !Datastore::isConfigurationValid();
bool hasImage = diskFlux && diskFlux->image;
auto majorButtonWidth = ImGui::GetFontSize() * 10;
ImGui::TableSetupColumn(
"", ImGuiTableColumnFlags_WidthFixed, majorButtonWidth);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn(
"", ImGuiTableColumnFlags_WidthFixed, majorButtonWidth);
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (maybeDisabledButton(
fmt::format(
"{} {}", ICON_TA_DEVICE_FLOPPY, "Read disk"),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy))
Datastore::beginRead();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
maybeDisabledButton(
fmt::format(
"{} {}", ICON_VS_FOLDER_OPENED, "Load sector image"),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
maybeDisabledButton(
fmt::format("{} {}", ICON_VS_SAVE_AS, "Write disk").c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy || !hasImage);
ImGui::TableNextRow();
ImGui::TableNextColumn();
maybeDisabledButton(
fmt::format("{} {}", ICON_TA_REPEAT, "Reread bad tracks")
.c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy);
ImGui::TableNextColumn();
ImGui::Text(ICON_VS_ARROW_RIGHT);
ImGui::TableNextColumn();
if (maybeDisabledButton(
fmt::format(
"{} {}", ICON_VS_SAVE_ALL, "Save sector image")
.c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy || !hasImage))
saveSectorImage();
ImGui::TableNextColumn();
ImGui::Text(ICON_VS_ARROW_RIGHT);
ImGui::TableNextColumn();
if (maybeDisabledButton(
fmt::format("{} {}", ICON_TA_DOWNLOAD, "Save flux file")
.c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy || !diskFlux))
saveFluxFile();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (maybeDisabledButton(
fmt::format("{} {}", ICON_TA_UPLOAD, "Setup flux file")
.c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy))
loadFluxFile();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
if (maybeDisabledButton(
fmt::format(
"{} {}", ICON_VS_NEW_FILE, "Create blank image")
.c_str(),
ImVec2(ImGui::GetContentRegionAvail().x, 0),
busy || !Datastore::canFormat()))
Datastore::createBlankImage();
}
{
auto size = ImVec2(ImGui::GetWindowSize().x * 0.6, 0);
ImGui::SetCursorPos({ImGui::GetWindowSize().x / 2 - size.x / 2,
ImGui::GetWindowSize().y - ImGui::GetFontSize() * 1.5f});
auto red =
ImGuiExt::GetCustomColorU32(ImGuiCustomCol_LoggerError);
auto text = ImGui::GetColorU32(ImGuiCol_Text);
auto redHover = ImMixU32(red, text, 32);
auto redPressed = ImMixU32(red, text, 64);
ImGui::PushStyleColor(ImGuiCol_Button, red);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, redHover);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, redPressed);
ON_SCOPE_EXIT
{
ImGui::PopStyleColor(3);
};
if (maybeDisabledButton(
fmt::format("{} {}",
ICON_TA_CANCEL,
"fluxengine.summary.controls.stop"_lang),
size,
!Datastore::isBusy()))
Datastore::stop();
}
}
ImGui::TableNextColumn();
// drawFormatBox();
}
}