mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Start moving the config view functionality into the control panel. The
current config is now displayed there.
This commit is contained in:
@@ -168,7 +168,7 @@ void ConfigView::drawContent()
|
||||
if (ImGui::Button("fluxengine.view.config.rescan"_lang))
|
||||
probeConfig();
|
||||
|
||||
std::set<int> applicableOptions{SOURCESINK};
|
||||
std::set<int> applicableOptions{ANY_SOURCESINK};
|
||||
if ((std::string)driveSetting == DEVICE_MANUAL)
|
||||
{
|
||||
auto manualDevicePathSetting = DynamicSetting<std::fs::path>(
|
||||
|
||||
@@ -37,6 +37,3 @@ private:
|
||||
|
||||
std::shared_ptr<DeviceMap> _devices;
|
||||
};
|
||||
|
||||
static constexpr std::string DEVICE_MANUAL = "manual";
|
||||
static constexpr std::string DEVICE_FLUXFILE = "fluxfile";
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "lib/decoders/decoders.h"
|
||||
#include "lib/imagewriter/imagewriter.h"
|
||||
#include "lib/algorithms/readerwriter.h"
|
||||
#include "lib/usb/usbfinder.h"
|
||||
#include "arch/arch.h"
|
||||
#include "globals.h"
|
||||
#include "datastore.h"
|
||||
@@ -22,6 +23,8 @@
|
||||
#include <deque>
|
||||
#include <semaphore>
|
||||
|
||||
using hex::operator""_lang;
|
||||
|
||||
static std::shared_ptr<const DiskFlux> diskFlux;
|
||||
|
||||
static std::deque<std::function<void()>> pendingTasks;
|
||||
@@ -30,6 +33,7 @@ static std::thread workerThread;
|
||||
static std::atomic<bool> busy;
|
||||
|
||||
static bool configurationValid;
|
||||
static std::map<std::string, Datastore::Device> devices;
|
||||
static std::map<CylinderHead, std::shared_ptr<const TrackInfo>>
|
||||
physicalCylinderLayouts;
|
||||
static std::map<CylinderHeadSector, std::shared_ptr<const Sector>>
|
||||
@@ -112,6 +116,14 @@ static void workerThread_cb()
|
||||
}
|
||||
}
|
||||
|
||||
void Datastore::runOnWorkerThread(std::function<void()> callback)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(pendingTasksMutex);
|
||||
pendingTasks.push_back(callback);
|
||||
if (workerThread.get_id() == std::thread::id())
|
||||
workerThread = std::move(std::thread(workerThread_cb));
|
||||
}
|
||||
|
||||
void Datastore::init()
|
||||
{
|
||||
runOnWorkerThread(
|
||||
@@ -128,6 +140,8 @@ void Datastore::init()
|
||||
});
|
||||
});
|
||||
|
||||
probeDevices();
|
||||
|
||||
Events::SeekToSectorViaPhysicalLocation::subscribe(
|
||||
[](CylinderHeadSector physicalLocation)
|
||||
{
|
||||
@@ -180,6 +194,11 @@ bool Datastore::isConfigurationValid()
|
||||
return isConfigurationValid;
|
||||
}
|
||||
|
||||
const std::map<std::string, Datastore::Device>& Datastore::getDevices()
|
||||
{
|
||||
return devices;
|
||||
}
|
||||
|
||||
const std::map<CylinderHead, std::shared_ptr<const TrackInfo>>&
|
||||
Datastore::getphysicalCylinderLayouts()
|
||||
{
|
||||
@@ -214,14 +233,6 @@ std::optional<unsigned> Datastore::findBlockByLogicalLocation(
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Datastore::runOnWorkerThread(std::function<void()> callback)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(pendingTasksMutex);
|
||||
pendingTasks.push_back(callback);
|
||||
if (workerThread.get_id() == std::thread::id())
|
||||
workerThread = std::move(std::thread(workerThread_cb));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T readSetting(const std::string& leaf, const T defaultValue)
|
||||
{
|
||||
@@ -256,6 +267,30 @@ static void rebuildDiskFluxIndices()
|
||||
}
|
||||
}
|
||||
|
||||
void Datastore::probeDevices()
|
||||
{
|
||||
Datastore::runOnWorkerThread(
|
||||
[]
|
||||
{
|
||||
hex::log::debug("probing USB");
|
||||
auto usbDevices = findUsbDevices();
|
||||
|
||||
hex::TaskManager::doLater(
|
||||
[usbDevices]
|
||||
{
|
||||
devices.clear();
|
||||
devices[DEVICE_FLUXFILE] = {
|
||||
nullptr, "fluxengine.view.config.fluxfile"_lang};
|
||||
devices[DEVICE_MANUAL] = {
|
||||
nullptr, "fluxengine.view.config.manual"_lang};
|
||||
for (auto it : usbDevices)
|
||||
devices["#" + it->serial] = {it,
|
||||
fmt::format(
|
||||
"{}: {}", getDeviceName(it->type), it->serial)};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Datastore::rebuildConfiguration()
|
||||
{
|
||||
hex::TaskManager::doLaterOnce(
|
||||
|
||||
@@ -5,14 +5,28 @@
|
||||
#include "lib/data/layout.h"
|
||||
|
||||
class DiskFlux;
|
||||
class CandidateDevice;
|
||||
|
||||
static constexpr std::string DEVICE_MANUAL = "manual";
|
||||
static constexpr std::string DEVICE_FLUXFILE = "fluxfile";
|
||||
|
||||
class Datastore
|
||||
{
|
||||
public:
|
||||
struct Device
|
||||
{
|
||||
std::shared_ptr<CandidateDevice> coreDevice;
|
||||
std::string label;
|
||||
};
|
||||
|
||||
public:
|
||||
static void init();
|
||||
|
||||
static bool isBusy();
|
||||
static bool isConfigurationValid();
|
||||
static void probeDevices();
|
||||
|
||||
static const std::map<std::string, Device>& getDevices();
|
||||
static const std::map<CylinderHead, std::shared_ptr<const TrackInfo>>&
|
||||
getphysicalCylinderLayouts();
|
||||
static std::shared_ptr<const Sector> findSectorByPhysicalLocation(
|
||||
|
||||
@@ -23,3 +23,12 @@ namespace Events
|
||||
EVENT_DEF(SeekToSectorViaPhysicalLocation, CylinderHeadSector);
|
||||
EVENT_DEF(SeekToTrackViaPhysicalLocation, CylinderHead);
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
inline const V& findOrDefault(const std::map<K, V>& map, const K& key, const V& defaultValue = V())
|
||||
{
|
||||
auto it = map.find(key);
|
||||
if (it == map.end())
|
||||
return defaultValue;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
"fluxengine.summary.controls.read": "Read from device",
|
||||
"fluxengine.summary.controls.write": "Write to device",
|
||||
"fluxengine.summary.controls.stop": "Stop",
|
||||
"fluxengine.view.summary.edit": "Edit",
|
||||
"fluxengine.view.summary.highDensity": "High density",
|
||||
"fluxengine.view.summary.yes": "yes",
|
||||
"fluxengine.view.summary.no": "no",
|
||||
"fluxengine.view.summary.format": "Format",
|
||||
"fluxengine.view.summary.variations": "Variant",
|
||||
|
||||
"fluxengine.view.image.name": "FluxEngine sector map"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/data/flux.h"
|
||||
#include "lib/data/sector.h"
|
||||
#include "lib/config/proto.h"
|
||||
#include "globals.h"
|
||||
#include "summaryview.h"
|
||||
#include "datastore.h"
|
||||
@@ -57,6 +58,179 @@ static void saveSectorImage()
|
||||
fs::openFileBrowser(fs::DialogMode::Save, {}, Datastore::writeImage);
|
||||
}
|
||||
|
||||
static void showOptions() {}
|
||||
|
||||
static void emitOptions(const OptionsMap& options,
|
||||
const ConfigProto* config,
|
||||
const std::set<int>& applicableOptions)
|
||||
{
|
||||
for (auto& it : config->option())
|
||||
{
|
||||
if (!applicableOptions.empty() &&
|
||||
std::ranges::none_of(it.applicability(),
|
||||
[&](int item)
|
||||
{
|
||||
return applicableOptions.contains(item);
|
||||
}))
|
||||
continue;
|
||||
|
||||
ImGui::Text(fmt::format("{}: {}",
|
||||
wolv::util::capitalizeString(it.comment()),
|
||||
options.contains(it.name()) ? "fluxengine.view.summary.yes"_lang
|
||||
: "fluxengine.view.summary.no"_lang));
|
||||
}
|
||||
|
||||
for (auto& it : config->option_group())
|
||||
{
|
||||
if (!applicableOptions.empty() &&
|
||||
std::ranges::none_of(it.applicability(),
|
||||
[&](int item)
|
||||
{
|
||||
return applicableOptions.contains(item);
|
||||
}))
|
||||
continue;
|
||||
|
||||
std::string comment = it.comment();
|
||||
if (comment == "$formats")
|
||||
comment = (std::string) "fluxengine.view.summary.variations"_lang;
|
||||
|
||||
const OptionProto* selectedOption = nullptr;
|
||||
if (it.name().empty())
|
||||
{
|
||||
for (auto& ot : it.option())
|
||||
if (options.contains(ot.name()))
|
||||
selectedOption = &ot;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto value = findOrDefault(options, it.name());
|
||||
for (auto& ot : it.option())
|
||||
if (ot.name() == value)
|
||||
selectedOption = &ot;
|
||||
}
|
||||
|
||||
if (!selectedOption)
|
||||
for (auto& ot : it.option())
|
||||
if (ot.set_by_default())
|
||||
selectedOption = &ot;
|
||||
|
||||
ImGui::Text(fmt::format("{}:", comment));
|
||||
ImGui::SameLine();
|
||||
if (selectedOption)
|
||||
ImGui::TextWrapped(
|
||||
wolv::util::capitalizeString(selectedOption->comment())
|
||||
.c_str());
|
||||
else
|
||||
ImGui::TextWrapped("***bad***");
|
||||
}
|
||||
}
|
||||
|
||||
static void drawDeviceBox()
|
||||
{
|
||||
if (ImGuiExt::BeginSubWindow("Device",
|
||||
nullptr,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiChildFlags_None))
|
||||
{
|
||||
ON_SCOPE_EXIT
|
||||
{
|
||||
ImGuiExt::EndSubWindow();
|
||||
};
|
||||
|
||||
/* Device name */
|
||||
|
||||
std::set<int> applicableOptions = {ANY_SOURCESINK};
|
||||
auto deviceName = hex::ContentRegistry::Settings::read<std::string>(
|
||||
FLUXENGINE_CONFIG, "fluxengine.settings.device", DEVICE_FLUXFILE);
|
||||
auto device = findOrDefault(Datastore::getDevices(),
|
||||
deviceName,
|
||||
{.label = "No device configured"});
|
||||
if (deviceName == DEVICE_FLUXFILE)
|
||||
{
|
||||
ImGui::Text(fmt::format("{}: {}",
|
||||
device.label,
|
||||
hex::ContentRegistry::Settings::read<std::fs::path>(
|
||||
FLUXENGINE_CONFIG,
|
||||
"fluxengine.settings.fluxfile",
|
||||
"no file configured")
|
||||
.filename()
|
||||
.string()));
|
||||
applicableOptions.insert(FLUXFILE_SOURCESINK);
|
||||
}
|
||||
else if (deviceName == DEVICE_MANUAL)
|
||||
{
|
||||
ImGui::Text(fmt::format("Greaseweazle: {}",
|
||||
hex::ContentRegistry::Settings::read<std::string>(
|
||||
FLUXENGINE_CONFIG,
|
||||
"fluxengine.settings.manualDevicePath",
|
||||
"no path configured")));
|
||||
applicableOptions.insert(MANUAL_SOURCESINK);
|
||||
applicableOptions.insert(HARDWARE_SOURCESINK);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text(device.label.c_str());
|
||||
applicableOptions.insert(HARDWARE_SOURCESINK);
|
||||
}
|
||||
|
||||
/* Other options */
|
||||
|
||||
auto globalOptions =
|
||||
stringToOptions(hex::ContentRegistry::Settings::read<std::string>(
|
||||
FLUXENGINE_CONFIG, "fluxengine.settings.globalSettings", ""));
|
||||
emitOptions(
|
||||
globalOptions, formats.at("_global_options"), applicableOptions);
|
||||
|
||||
ImGui::Button(
|
||||
fmt::format("{}##device", "fluxengine.view.summary.edit"_lang)
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void drawFormatBox()
|
||||
{
|
||||
if (ImGuiExt::BeginSubWindow("Format",
|
||||
nullptr,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiChildFlags_None))
|
||||
{
|
||||
ON_SCOPE_EXIT
|
||||
{
|
||||
ImGuiExt::EndSubWindow();
|
||||
};
|
||||
|
||||
/* Format name */
|
||||
|
||||
auto formatName =
|
||||
hex::ContentRegistry::Settings::read<std::string>(FLUXENGINE_CONFIG,
|
||||
"fluxengine.settings.format.selected",
|
||||
DEVICE_FLUXFILE);
|
||||
auto format = findOrDefault(formats, formatName);
|
||||
if (!format)
|
||||
{
|
||||
ImGui::Text("***bad***");
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text(fmt::format("{}:", "fluxengine.view.summary.format"_lang));
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(format->shortname());
|
||||
ImGui::Text(format->comment());
|
||||
ImGui::EndGroup();
|
||||
|
||||
auto formatOptions = stringToOptions(
|
||||
hex::ContentRegistry::Settings::read<std::string>(FLUXENGINE_CONFIG,
|
||||
fmt::format("fluxengine.settings.{}", formatName),
|
||||
""));
|
||||
emitOptions(formatOptions, format, {});
|
||||
|
||||
ImGui::Button(
|
||||
fmt::format("{}##format", "fluxengine.view.summary.edit"_lang)
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SummaryView::drawContent()
|
||||
{
|
||||
auto diskFlux = Datastore::getDiskFlux();
|
||||
@@ -199,9 +373,9 @@ void SummaryView::drawContent()
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosY(
|
||||
ImGui::GetContentRegionAvail().y - ImGui::GetFontSize() * 3);
|
||||
if (ImGui::BeginTable("controlPanel",
|
||||
7,
|
||||
ImGui::GetContentRegionAvail().y - ImGui::GetFontSize() * 6);
|
||||
if (ImGui::BeginTable("controlPanelOuter",
|
||||
3,
|
||||
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoClip))
|
||||
{
|
||||
ON_SCOPE_EXIT
|
||||
@@ -209,107 +383,145 @@ void SummaryView::drawContent()
|
||||
ImGui::EndTable();
|
||||
};
|
||||
|
||||
bool busy = Datastore::isBusy() || !Datastore::isConfigurationValid();
|
||||
bool hasImage = diskFlux && diskFlux->image;
|
||||
|
||||
auto majorButtonWidth = ImGui::GetFontSize() * 10;
|
||||
auto sideWidth = ImGui::GetFontSize() * 20;
|
||||
ImGui::TableSetupColumn(
|
||||
"", ImGuiTableColumnFlags_WidthFixed, sideWidth);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn(
|
||||
"", ImGuiTableColumnFlags_WidthFixed, majorButtonWidth);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn(
|
||||
"", ImGuiTableColumnFlags_WidthFixed, majorButtonWidth * 1.5);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn(
|
||||
"", ImGuiTableColumnFlags_WidthFixed, majorButtonWidth);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
|
||||
"", ImGuiTableColumnFlags_WidthFixed, sideWidth);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
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);
|
||||
drawDeviceBox();
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
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();
|
||||
MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_TA_DOWNLOAD, "Save flux file").c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy || !diskFlux);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TableNextColumn();
|
||||
if (MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_TA_UPLOAD, "Load flux file").c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy))
|
||||
loadFluxFile();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TableNextColumn();
|
||||
MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_VS_NEW_FILE, "Create blank image")
|
||||
.c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy);
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
if (ImGuiExt::BeginSubWindow("Controls",
|
||||
nullptr,
|
||||
ImGui::GetContentRegionAvail(),
|
||||
ImGuiChildFlags_None))
|
||||
{
|
||||
ImGui::PopStyleColor(3);
|
||||
};
|
||||
ON_SCOPE_EXIT
|
||||
{
|
||||
ImGuiExt::EndSubWindow();
|
||||
};
|
||||
if (ImGui::BeginTable("controlPanel",
|
||||
5,
|
||||
ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoClip))
|
||||
{
|
||||
ON_SCOPE_EXIT
|
||||
{
|
||||
ImGui::EndTable();
|
||||
};
|
||||
|
||||
if (MaybeDisabledButton(fmt::format("{} {}",
|
||||
ICON_TA_CANCEL,
|
||||
"fluxengine.summary.controls.stop"_lang),
|
||||
size,
|
||||
!Datastore::isBusy()))
|
||||
Datastore::stop();
|
||||
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();
|
||||
MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_TA_DOWNLOAD, "Save flux file")
|
||||
.c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy || !diskFlux);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_TA_UPLOAD, "Load flux file")
|
||||
.c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy))
|
||||
loadFluxFile();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TableNextColumn();
|
||||
MaybeDisabledButton(
|
||||
fmt::format("{} {}", ICON_VS_NEW_FILE, "Create blank image")
|
||||
.c_str(),
|
||||
ImVec2(ImGui::GetContentRegionAvail().x, 0),
|
||||
busy);
|
||||
}
|
||||
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user