mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
[glass] Use JSON files for storage instead of imgui ini
Storage is now nested. Separate "roots" can be configured which save to separate files. In particular, this is used to save wpigui and ImGui window position to a -window.json file. ImGui's ini (for window position) is mapped to JSON. You can optionally specify a directory to load from on the command line. If one isn't provided, it uses the global system directory. Any changes made are automatically saved here. Workspace | Open: select directory, the current layout is replaced with that workspace, and future auto-saves also switch to that location. The main window size/location is not changed, only the contents. Workspace | Save As: select directory, the current layout is saved there, and future auto-saves also switch to that location. Workspace | Reset: window locations are preserved, but all other settings are reset to default (including e.g. removing plot windows). This will also end up clearing the current save file. as with load, the main window size/location is not changed. Workspace | Save As Global: "save as" to the global system location Notably, the main window size/location is only loaded at startup, but is auto-saved as part of the current workspace.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -18,10 +19,10 @@ void glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
|
||||
}
|
||||
|
||||
// build label
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name->empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name->c_str(), index);
|
||||
if (!name.empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name.c_str(), index);
|
||||
} else {
|
||||
std::snprintf(label, sizeof(label), "In[%d]###name", index);
|
||||
}
|
||||
@@ -42,8 +43,8 @@ void glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
|
||||
}
|
||||
|
||||
// context menu to change name
|
||||
if (PopupEditName("name", name)) {
|
||||
voltageData->SetName(name->c_str());
|
||||
if (PopupEditName("name", &name)) {
|
||||
voltageData->SetName(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
#include "glass/other/DeviceTree.h"
|
||||
|
||||
using namespace glass;
|
||||
@@ -26,10 +27,10 @@ void glass::DisplayAnalogOutputsDevice(AnalogOutputsModel* model) {
|
||||
PushID(i);
|
||||
|
||||
// build label
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name->empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name->c_str(), i);
|
||||
if (!name.empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name.c_str(), i);
|
||||
} else {
|
||||
std::snprintf(label, sizeof(label), "Out[%d]###name", i);
|
||||
}
|
||||
@@ -37,9 +38,9 @@ void glass::DisplayAnalogOutputsDevice(AnalogOutputsModel* model) {
|
||||
double value = analogOutData->GetValue();
|
||||
DeviceDouble(label, true, &value, analogOutData);
|
||||
|
||||
if (PopupEditName("name", name)) {
|
||||
if (PopupEditName("name", &name)) {
|
||||
if (analogOutData) {
|
||||
analogOutData->SetName(name->c_str());
|
||||
analogOutData->SetName(name);
|
||||
}
|
||||
}
|
||||
PopID();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/hardware/Encoder.h"
|
||||
#include "glass/support/IniSaverInfo.h"
|
||||
#include "glass/support/NameSetting.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -28,17 +28,18 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
|
||||
auto dutyCycleData = dutyCycle ? dutyCycle->GetValueData() : nullptr;
|
||||
|
||||
bool exists = model->Exists();
|
||||
auto& info = dioData->GetNameInfo();
|
||||
NameSetting dioName{dioData->GetName()};
|
||||
char label[128];
|
||||
if (exists && dpwmData) {
|
||||
dpwmData->GetNameInfo().GetLabel(label, sizeof(label), "PWM", index);
|
||||
NameSetting{dpwmData->GetName()}.GetLabel(label, sizeof(label), "PWM",
|
||||
index);
|
||||
if (auto simDevice = dpwm->GetSimDevice()) {
|
||||
LabelSimDevice(label, simDevice);
|
||||
} else {
|
||||
dpwmData->LabelText(label, "%0.3f", dpwmData->GetValue());
|
||||
}
|
||||
} else if (exists && encoder) {
|
||||
info.GetLabel(label, sizeof(label), " In", index);
|
||||
dioName.GetLabel(label, sizeof(label), " In", index);
|
||||
if (auto simDevice = encoder->GetSimDevice()) {
|
||||
LabelSimDevice(label, simDevice);
|
||||
} else {
|
||||
@@ -48,7 +49,8 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
} else if (exists && dutyCycleData) {
|
||||
dutyCycleData->GetNameInfo().GetLabel(label, sizeof(label), "Dty", index);
|
||||
NameSetting{dutyCycleData->GetName()}.GetLabel(label, sizeof(label), "Dty",
|
||||
index);
|
||||
if (auto simDevice = dutyCycle->GetSimDevice()) {
|
||||
LabelSimDevice(label, simDevice);
|
||||
} else {
|
||||
@@ -60,10 +62,10 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
|
||||
} else {
|
||||
const char* name = model->GetName();
|
||||
if (name[0] != '\0') {
|
||||
info.GetLabel(label, sizeof(label), name);
|
||||
dioName.GetLabel(label, sizeof(label), name);
|
||||
} else {
|
||||
info.GetLabel(label, sizeof(label), model->IsInput() ? " In" : "Out",
|
||||
index);
|
||||
dioName.GetLabel(label, sizeof(label), model->IsInput() ? " In" : "Out",
|
||||
index);
|
||||
}
|
||||
if (auto simDevice = model->GetSimDevice()) {
|
||||
LabelSimDevice(label, simDevice);
|
||||
@@ -87,12 +89,12 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info.PopupEditName(index)) {
|
||||
if (dioName.PopupEditName(index)) {
|
||||
if (dpwmData) {
|
||||
dpwmData->SetName(info.GetName());
|
||||
dpwmData->SetName(dioName.GetName());
|
||||
}
|
||||
if (dutyCycleData) {
|
||||
dutyCycleData->SetName(info.GetName());
|
||||
dutyCycleData->SetName(dioName.GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -66,10 +67,10 @@ void glass::DisplayEncoder(EncoderModel* model) {
|
||||
int chB = model->GetChannelB();
|
||||
|
||||
// build header label
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name->empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d,%d]###name", name->c_str(), chA,
|
||||
if (!name.empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d,%d]###name", name.c_str(), chA,
|
||||
chB);
|
||||
} else {
|
||||
std::snprintf(label, sizeof(label), "Encoder[%d,%d]###name", chA, chB);
|
||||
@@ -79,8 +80,8 @@ void glass::DisplayEncoder(EncoderModel* model) {
|
||||
bool open = CollapsingHeader(label);
|
||||
|
||||
// context menu to change name
|
||||
if (PopupEditName("name", name)) {
|
||||
model->SetName(name->c_str());
|
||||
if (PopupEditName("name", &name)) {
|
||||
model->SetName(name);
|
||||
}
|
||||
|
||||
if (!open) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/Storage.h"
|
||||
#include "glass/support/ExtraGuiWidgets.h"
|
||||
|
||||
using namespace glass;
|
||||
@@ -25,27 +26,27 @@ void glass::DisplayLEDDisplay(LEDDisplayModel* model, int index) {
|
||||
bool running = model->IsRunning();
|
||||
auto& storage = GetStorage();
|
||||
|
||||
int* numColumns = storage.GetIntRef("columns", 10);
|
||||
bool* serpentine = storage.GetBoolRef("serpentine", false);
|
||||
int* order = storage.GetIntRef("order", LEDConfig::RowMajor);
|
||||
int* start = storage.GetIntRef("start", LEDConfig::UpperLeft);
|
||||
int& numColumns = storage.GetInt("columns", 10);
|
||||
bool& serpentine = storage.GetBool("serpentine", false);
|
||||
int& order = storage.GetInt("order", LEDConfig::RowMajor);
|
||||
int& start = storage.GetInt("start", LEDConfig::UpperLeft);
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
|
||||
ImGui::LabelText("Length", "%d", length);
|
||||
ImGui::LabelText("Running", "%s", running ? "Yes" : "No");
|
||||
ImGui::InputInt("Columns", numColumns);
|
||||
ImGui::InputInt("Columns", &numColumns);
|
||||
{
|
||||
static const char* options[] = {"Row Major", "Column Major"};
|
||||
ImGui::Combo("Order", order, options, 2);
|
||||
ImGui::Combo("Order", &order, options, 2);
|
||||
}
|
||||
{
|
||||
static const char* options[] = {"Upper Left", "Lower Left", "Upper Right",
|
||||
"Lower Right"};
|
||||
ImGui::Combo("Start", start, options, 4);
|
||||
ImGui::Combo("Start", &start, options, 4);
|
||||
}
|
||||
ImGui::Checkbox("Serpentine", serpentine);
|
||||
if (*numColumns < 1) {
|
||||
*numColumns = 1;
|
||||
ImGui::Checkbox("Serpentine", &serpentine);
|
||||
if (numColumns < 1) {
|
||||
numColumns = 1;
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
@@ -74,12 +75,12 @@ void glass::DisplayLEDDisplay(LEDDisplayModel* model, int index) {
|
||||
}
|
||||
|
||||
LEDConfig config;
|
||||
config.serpentine = *serpentine;
|
||||
config.order = static_cast<LEDConfig::Order>(*order);
|
||||
config.start = static_cast<LEDConfig::Start>(*start);
|
||||
config.serpentine = serpentine;
|
||||
config.order = static_cast<LEDConfig::Order>(order);
|
||||
config.start = static_cast<LEDConfig::Start>(start);
|
||||
|
||||
DrawLEDs(iData->values.data(), length, *numColumns, iData->colors.data(), 0,
|
||||
0, config);
|
||||
DrawLEDs(iData->values.data(), length, numColumns, iData->colors.data(), 0, 0,
|
||||
config);
|
||||
}
|
||||
|
||||
void glass::DisplayLEDDisplays(LEDDisplaysModel* model) {
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
#include "glass/other/DeviceTree.h"
|
||||
#include "glass/support/ExtraGuiWidgets.h"
|
||||
#include "glass/support/IniSaverInfo.h"
|
||||
#include "glass/support/NameSetting.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -42,10 +43,10 @@ bool glass::DisplayPCMSolenoids(PCMModel* model, int index,
|
||||
}
|
||||
|
||||
// build header label
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name->empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name->c_str(), index);
|
||||
if (!name.empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name.c_str(), index);
|
||||
} else {
|
||||
std::snprintf(label, sizeof(label), "PCM[%d]###name", index);
|
||||
}
|
||||
@@ -53,7 +54,7 @@ bool glass::DisplayPCMSolenoids(PCMModel* model, int index,
|
||||
// header
|
||||
bool open = CollapsingHeader(label);
|
||||
|
||||
PopupEditName("name", name);
|
||||
PopupEditName("name", &name);
|
||||
|
||||
ImGui::SetItemAllowOverlap();
|
||||
ImGui::SameLine();
|
||||
@@ -68,11 +69,11 @@ bool glass::DisplayPCMSolenoids(PCMModel* model, int index,
|
||||
model->ForEachSolenoid([&](SolenoidModel& solenoid, int j) {
|
||||
if (auto data = solenoid.GetOutputData()) {
|
||||
PushID(j);
|
||||
char solenoidName[64];
|
||||
auto& info = data->GetNameInfo();
|
||||
info.GetLabel(solenoidName, sizeof(solenoidName), "Solenoid", j);
|
||||
data->LabelText(solenoidName, "%s", channels[j] == 1 ? "On" : "Off");
|
||||
info.PopupEditName(j);
|
||||
char label[64];
|
||||
NameSetting name{data->GetName()};
|
||||
name.GetLabel(label, sizeof(label), "Solenoid", j);
|
||||
data->LabelText(label, "%s", channels[j] == 1 ? "On" : "Off");
|
||||
name.PopupEditName(j);
|
||||
PopID();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -18,10 +19,10 @@ void glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
// build label
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
char label[128];
|
||||
if (!name->empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name->c_str(), index);
|
||||
if (!name.empty()) {
|
||||
std::snprintf(label, sizeof(label), "%s [%d]###name", name.c_str(), index);
|
||||
} else {
|
||||
std::snprintf(label, sizeof(label), "PWM[%d]###name", index);
|
||||
}
|
||||
@@ -35,8 +36,8 @@ void glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
|
||||
float val = outputsEnabled ? data->GetValue() : 0;
|
||||
data->LabelText(label, "%0.3f", val);
|
||||
}
|
||||
if (PopupEditName("name", name)) {
|
||||
data->SetName(name->c_str());
|
||||
if (PopupEditName("name", &name)) {
|
||||
data->SetName(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/support/IniSaverInfo.h"
|
||||
#include "glass/support/NameSetting.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -19,16 +19,16 @@ static float DisplayChannel(PowerDistributionModel& pdp, int channel) {
|
||||
float width = 0;
|
||||
if (auto currentData = pdp.GetCurrentData(channel)) {
|
||||
ImGui::PushID(channel);
|
||||
auto& leftInfo = currentData->GetNameInfo();
|
||||
NameSetting leftName{currentData->GetName()};
|
||||
char name[64];
|
||||
leftInfo.GetLabel(name, sizeof(name), "", channel);
|
||||
leftName.GetLabel(name, sizeof(name), "", channel);
|
||||
double val = currentData->GetValue();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4);
|
||||
if (currentData->InputDouble(name, &val, 0, 0, "%.3f")) {
|
||||
pdp.SetCurrent(channel, val);
|
||||
}
|
||||
width = ImGui::GetItemRectSize().x;
|
||||
leftInfo.PopupEditName(channel);
|
||||
leftName.PopupEditName(channel);
|
||||
ImGui::PopID();
|
||||
}
|
||||
return width;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/DataSource.h"
|
||||
#include "glass/Storage.h"
|
||||
#include "glass/support/ExtraGuiWidgets.h"
|
||||
|
||||
using namespace glass;
|
||||
@@ -31,20 +32,20 @@ void glass::DisplayRelay(RelayModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string* name = GetStorage().GetStringRef("name");
|
||||
std::string& name = GetStorage().GetString("name");
|
||||
ImGui::PushID("name");
|
||||
if (!name->empty()) {
|
||||
ImGui::Text("%s [%d]", name->c_str(), index);
|
||||
if (!name.empty()) {
|
||||
ImGui::Text("%s [%d]", name.c_str(), index);
|
||||
} else {
|
||||
ImGui::Text("Relay[%d]", index);
|
||||
}
|
||||
ImGui::PopID();
|
||||
if (PopupEditName("name", name)) {
|
||||
if (PopupEditName("name", &name)) {
|
||||
if (forwardData) {
|
||||
forwardData->SetName(name->c_str());
|
||||
forwardData->SetName(name);
|
||||
}
|
||||
if (reverseData) {
|
||||
reverseData->SetName(name->c_str());
|
||||
reverseData->SetName(name);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
Reference in New Issue
Block a user