Implement a platform abstraction for settings.
This commit mostly just changes the settings code to be in line with the rest of the platform abstractions, although it also fixes some settings names to be consistent with others, and uses native bool types where applicable. This commit also makes settings-related operations much less wasteful, not that it should matter.
This commit is contained in:
parent
f324477dd0
commit
eb5501ecd6
@ -283,7 +283,7 @@ void GraphicsWindow::PopulateMainMenu() {
|
|||||||
for(const Locale &locale : Locales()) {
|
for(const Locale &locale : Locales()) {
|
||||||
localeMenu->AddItem(locale.displayName, [&]() {
|
localeMenu->AddItem(locale.displayName, [&]() {
|
||||||
SetLocale(locale.Culture());
|
SetLocale(locale.Culture());
|
||||||
CnfFreezeString(locale.Culture(), "Locale");
|
Platform::GetSettings()->FreezeString("Locale", locale.Culture());
|
||||||
|
|
||||||
SS.UpdateWindowTitles();
|
SS.UpdateWindowTitles();
|
||||||
PopulateMainMenu();
|
PopulateMainMenu();
|
||||||
|
11
src/lib.cpp
11
src/lib.cpp
@ -17,17 +17,6 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *) {
|
|||||||
// Nothing to do for now.
|
// Nothing to do for now.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::CnfFreezeInt(uint32_t, const std::string &)
|
|
||||||
{
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SolveSpace::CnfThawInt(uint32_t, const std::string &)
|
|
||||||
{
|
|
||||||
abort();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SolveSpace::DoMessageBox(const char *, int, int, bool)
|
void SolveSpace::DoMessageBox(const char *, int, int, bool)
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
|
@ -19,49 +19,6 @@ static NSString* Wrap(const std::string &s) {
|
|||||||
return [NSString stringWithUTF8String:s.c_str()];
|
return [NSString stringWithUTF8String:s.c_str()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Settings */
|
|
||||||
|
|
||||||
namespace SolveSpace {
|
|
||||||
void CnfFreezeInt(uint32_t val, const std::string &key) {
|
|
||||||
[[NSUserDefaults standardUserDefaults]
|
|
||||||
setInteger:val forKey:Wrap(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t CnfThawInt(uint32_t val, const std::string &key) {
|
|
||||||
NSString *nsKey = Wrap(key);
|
|
||||||
if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey])
|
|
||||||
return [[NSUserDefaults standardUserDefaults] integerForKey:nsKey];
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeFloat(float val, const std::string &key) {
|
|
||||||
[[NSUserDefaults standardUserDefaults]
|
|
||||||
setFloat:val forKey:Wrap(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
float CnfThawFloat(float val, const std::string &key) {
|
|
||||||
NSString *nsKey = Wrap(key);
|
|
||||||
if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey])
|
|
||||||
return [[NSUserDefaults standardUserDefaults] floatForKey:nsKey];
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeString(const std::string &val, const std::string &key) {
|
|
||||||
[[NSUserDefaults standardUserDefaults]
|
|
||||||
setObject:Wrap(val)
|
|
||||||
forKey:Wrap(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CnfThawString(const std::string &val, const std::string &key) {
|
|
||||||
NSString *nsKey = Wrap(key);
|
|
||||||
if([[NSUserDefaults standardUserDefaults] objectForKey:nsKey]) {
|
|
||||||
NSString *nsNewVal = [[NSUserDefaults standardUserDefaults] stringForKey:nsKey];
|
|
||||||
return [nsNewVal UTF8String];
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Save/load */
|
/* Save/load */
|
||||||
|
|
||||||
bool SolveSpace::GetOpenFile(Platform::Path *filename, const std::string &defExtension,
|
bool SolveSpace::GetOpenFile(Platform::Path *filename, const std::string &defExtension,
|
||||||
|
@ -57,111 +57,6 @@ std::string Title(const std::string &s) {
|
|||||||
return "SolveSpace - " + s;
|
return "SolveSpace - " + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Settings */
|
|
||||||
|
|
||||||
/* Why not just use GSettings? Two reasons. It doesn't allow to easily see
|
|
||||||
whether the setting had the default value, and it requires to install
|
|
||||||
a schema globally. */
|
|
||||||
static json_object *settings = NULL;
|
|
||||||
|
|
||||||
static std::string CnfPrepare() {
|
|
||||||
// Refer to http://standards.freedesktop.org/basedir-spec/latest/
|
|
||||||
|
|
||||||
std::string dir;
|
|
||||||
if(getenv("XDG_CONFIG_HOME")) {
|
|
||||||
dir = std::string(getenv("XDG_CONFIG_HOME")) + "/solvespace";
|
|
||||||
} else if(getenv("HOME")) {
|
|
||||||
dir = std::string(getenv("HOME")) + "/.config/solvespace";
|
|
||||||
} else {
|
|
||||||
dbp("neither XDG_CONFIG_HOME nor HOME are set");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
if(stat(dir.c_str(), &st)) {
|
|
||||||
if(errno == ENOENT) {
|
|
||||||
if(mkdir(dir.c_str(), 0777)) {
|
|
||||||
dbp("cannot mkdir %s: %s", dir.c_str(), strerror(errno));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dbp("cannot stat %s: %s", dir.c_str(), strerror(errno));
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
} else if(!S_ISDIR(st.st_mode)) {
|
|
||||||
dbp("%s is not a directory", dir.c_str());
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir + "/settings.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CnfLoad() {
|
|
||||||
std::string path = CnfPrepare();
|
|
||||||
if(path.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(settings)
|
|
||||||
json_object_put(settings); // deallocate
|
|
||||||
|
|
||||||
settings = json_object_from_file(path.c_str());
|
|
||||||
if(!settings) {
|
|
||||||
if(errno != ENOENT)
|
|
||||||
dbp("cannot load settings: %s", strerror(errno));
|
|
||||||
|
|
||||||
settings = json_object_new_object();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CnfSave() {
|
|
||||||
std::string path = CnfPrepare();
|
|
||||||
if(path.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* json-c <0.12 has the first argument non-const here */
|
|
||||||
if(json_object_to_file_ext((char*) path.c_str(), settings, JSON_C_TO_STRING_PRETTY))
|
|
||||||
dbp("cannot save settings: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeInt(uint32_t val, const std::string &key) {
|
|
||||||
struct json_object *jval = json_object_new_int(val);
|
|
||||||
json_object_object_add(settings, key.c_str(), jval);
|
|
||||||
CnfSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t CnfThawInt(uint32_t val, const std::string &key) {
|
|
||||||
struct json_object *jval;
|
|
||||||
if(json_object_object_get_ex(settings, key.c_str(), &jval))
|
|
||||||
return json_object_get_int(jval);
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeFloat(float val, const std::string &key) {
|
|
||||||
struct json_object *jval = json_object_new_double(val);
|
|
||||||
json_object_object_add(settings, key.c_str(), jval);
|
|
||||||
CnfSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
float CnfThawFloat(float val, const std::string &key) {
|
|
||||||
struct json_object *jval;
|
|
||||||
if(json_object_object_get_ex(settings, key.c_str(), &jval))
|
|
||||||
return json_object_get_double(jval);
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeString(const std::string &val, const std::string &key) {
|
|
||||||
struct json_object *jval = json_object_new_string(val.c_str());
|
|
||||||
json_object_object_add(settings, key.c_str(), jval);
|
|
||||||
CnfSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CnfThawString(const std::string &val, const std::string &key) {
|
|
||||||
struct json_object *jval;
|
|
||||||
if(json_object_object_get_ex(settings, key.c_str(), &jval))
|
|
||||||
return json_object_get_string(jval);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save/load */
|
/* Save/load */
|
||||||
|
|
||||||
static std::string ConvertFilters(std::string active, const FileFilter ssFilters[],
|
static std::string ConvertFilters(std::string active, const FileFilter ssFilters[],
|
||||||
@ -202,12 +97,12 @@ bool GetOpenFile(Platform::Path *filename, const std::string &activeOrEmpty,
|
|||||||
chooser.set_filename(filename->raw);
|
chooser.set_filename(filename->raw);
|
||||||
chooser.add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
|
chooser.add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
|
||||||
chooser.add_button(_("_Open"), Gtk::RESPONSE_OK);
|
chooser.add_button(_("_Open"), Gtk::RESPONSE_OK);
|
||||||
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
chooser.set_current_folder(Platform::GetSettings()->ThawString("FileChooserPath"));
|
||||||
|
|
||||||
ConvertFilters(activeOrEmpty, filters, &chooser);
|
ConvertFilters(activeOrEmpty, filters, &chooser);
|
||||||
|
|
||||||
if(chooser.run() == Gtk::RESPONSE_OK) {
|
if(chooser.run() == Gtk::RESPONSE_OK) {
|
||||||
CnfFreezeString(chooser.get_current_folder(), "FileChooserPath");
|
Platform::GetSettings()->FreezeString("FileChooserPath", chooser.get_current_folder());
|
||||||
*filename = Platform::Path::From(chooser.get_filename());
|
*filename = Platform::Path::From(chooser.get_filename());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -250,7 +145,7 @@ bool GetSaveFile(Platform::Path *filename, const std::string &defExtension,
|
|||||||
std::string activeExtension = ConvertFilters(defExtension, filters, &chooser);
|
std::string activeExtension = ConvertFilters(defExtension, filters, &chooser);
|
||||||
|
|
||||||
if(filename->IsEmpty()) {
|
if(filename->IsEmpty()) {
|
||||||
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
chooser.set_current_folder(Platform::GetSettings()->ThawString("FileChooserPath"));
|
||||||
chooser.set_current_name(std::string(_("untitled")) + "." + activeExtension);
|
chooser.set_current_name(std::string(_("untitled")) + "." + activeExtension);
|
||||||
} else {
|
} else {
|
||||||
chooser.set_current_folder(filename->Parent().raw);
|
chooser.set_current_folder(filename->Parent().raw);
|
||||||
@ -263,7 +158,7 @@ bool GetSaveFile(Platform::Path *filename, const std::string &defExtension,
|
|||||||
connect(sigc::bind(sigc::ptr_fun(&ChooserFilterChanged), &chooser));
|
connect(sigc::bind(sigc::ptr_fun(&ChooserFilterChanged), &chooser));
|
||||||
|
|
||||||
if(chooser.run() == Gtk::RESPONSE_OK) {
|
if(chooser.run() == Gtk::RESPONSE_OK) {
|
||||||
CnfFreezeString(chooser.get_current_folder(), "FileChooserPath");
|
Platform::GetSettings()->FreezeString("FileChooserPath", chooser.get_current_folder());
|
||||||
*filename = Platform::Path::From(chooser.get_filename());
|
*filename = Platform::Path::From(chooser.get_filename());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -458,8 +353,6 @@ int main(int argc, char** argv) {
|
|||||||
gdk_window_add_filter(NULL, GdkSpnavFilter, NULL);
|
gdk_window_add_filter(NULL, GdkSpnavFilter, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CnfLoad();
|
|
||||||
|
|
||||||
const char* const* langNames = g_get_language_names();
|
const char* const* langNames = g_get_language_names();
|
||||||
while(*langNames) {
|
while(*langNames) {
|
||||||
if(SetLocale(*langNames++)) break;
|
if(SetLocale(*langNames++)) break;
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
namespace SolveSpace {
|
namespace SolveSpace {
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Keyboard events
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
std::string AcceleratorDescription(const KeyboardEvent &accel) {
|
std::string AcceleratorDescription(const KeyboardEvent &accel) {
|
||||||
std::string label;
|
std::string label;
|
||||||
if(accel.controlDown) {
|
if(accel.controlDown) {
|
||||||
@ -45,5 +49,25 @@ std::string AcceleratorDescription(const KeyboardEvent &accel) {
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Settings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Settings::FreezeBool(const std::string &key, bool value) {
|
||||||
|
FreezeInt(key, (int)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::ThawBool(const std::string &key, bool defaultValue) {
|
||||||
|
return (bool)ThawInt(key, (int)defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::FreezeColor(const std::string &key, RgbaColor value) {
|
||||||
|
FreezeInt(key, value.ToPackedInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
RgbaColor Settings::ThawColor(const std::string &key, RgbaColor defaultValue) {
|
||||||
|
return RgbaColor::FromPackedInt(ThawInt(key, defaultValue.ToPackedInt()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,32 @@ std::string AcceleratorDescription(const KeyboardEvent &accel);
|
|||||||
// Interfaces
|
// Interfaces
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// A native settings store.
|
||||||
|
class Settings {
|
||||||
|
public:
|
||||||
|
virtual ~Settings() {}
|
||||||
|
|
||||||
|
virtual void FreezeInt(const std::string &key, uint32_t value) = 0;
|
||||||
|
virtual uint32_t ThawInt(const std::string &key, uint32_t defaultValue = 0) = 0;
|
||||||
|
|
||||||
|
virtual void FreezeFloat(const std::string &key, double value) = 0;
|
||||||
|
virtual double ThawFloat(const std::string &key, double defaultValue = 0.0) = 0;
|
||||||
|
|
||||||
|
virtual void FreezeString(const std::string &key, const std::string &value) = 0;
|
||||||
|
virtual std::string ThawString(const std::string &key,
|
||||||
|
const std::string &defaultValue = "") = 0;
|
||||||
|
|
||||||
|
virtual void FreezeBool(const std::string &key, bool value);
|
||||||
|
virtual bool ThawBool(const std::string &key, bool defaultValue = false);
|
||||||
|
|
||||||
|
virtual void FreezeColor(const std::string &key, RgbaColor value);
|
||||||
|
virtual RgbaColor ThawColor(const std::string &key, RgbaColor defaultValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<Settings> SettingsRef;
|
||||||
|
|
||||||
|
SettingsRef GetSettings();
|
||||||
|
|
||||||
// A native single-shot timer.
|
// A native single-shot timer.
|
||||||
class Timer {
|
class Timer {
|
||||||
public:
|
public:
|
||||||
@ -191,8 +217,8 @@ public:
|
|||||||
virtual void GetContentSize(double *width, double *height) = 0;
|
virtual void GetContentSize(double *width, double *height) = 0;
|
||||||
virtual void SetMinContentSize(double width, double height) = 0;
|
virtual void SetMinContentSize(double width, double height) = 0;
|
||||||
|
|
||||||
virtual void FreezePosition(const std::string &key) = 0;
|
virtual void FreezePosition(SettingsRef settings, const std::string &key) = 0;
|
||||||
virtual void ThawPosition(const std::string &key) = 0;
|
virtual void ThawPosition(SettingsRef settings, const std::string &key) = 0;
|
||||||
|
|
||||||
virtual void SetCursor(Cursor cursor) = 0;
|
virtual void SetCursor(Cursor cursor) = 0;
|
||||||
virtual void SetTooltip(const std::string &text) = 0;
|
virtual void SetTooltip(const std::string &text) = 0;
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
// Copyright 2018 whitequark
|
// Copyright 2018 whitequark
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <json-c/json_object.h>
|
||||||
|
#include <json-c/json_util.h>
|
||||||
#include <glibmm/main.h>
|
#include <glibmm/main.h>
|
||||||
#include <gtkmm/box.h>
|
#include <gtkmm/box.h>
|
||||||
#include <gtkmm/checkmenuitem.h>
|
#include <gtkmm/checkmenuitem.h>
|
||||||
@ -20,6 +25,128 @@
|
|||||||
namespace SolveSpace {
|
namespace SolveSpace {
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Settings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class SettingsImplGtk : public Settings {
|
||||||
|
public:
|
||||||
|
// Why aren't we using GSettings? Two reasons. It doesn't allow to easily see whether
|
||||||
|
// the setting had the default value, and it requires to install a schema globally.
|
||||||
|
Path _path;
|
||||||
|
json_object *_json = NULL;
|
||||||
|
|
||||||
|
static Path GetConfigPath() {
|
||||||
|
Path configHome;
|
||||||
|
if(getenv("XDG_CONFIG_HOME")) {
|
||||||
|
configHome = Path::From(getenv("XDG_CONFIG_HOME"));
|
||||||
|
} else if(getenv("HOME")) {
|
||||||
|
configHome = Path::From(getenv("HOME")).Join(".config");
|
||||||
|
} else {
|
||||||
|
dbp("neither XDG_CONFIG_HOME nor HOME are set");
|
||||||
|
return Path::From("");
|
||||||
|
}
|
||||||
|
if(!configHome.IsEmpty()) {
|
||||||
|
configHome = configHome.Join("solvespace");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *configHomeC = configHome.raw.c_str();
|
||||||
|
struct stat st;
|
||||||
|
if(stat(configHomeC, &st)) {
|
||||||
|
if(errno == ENOENT) {
|
||||||
|
if(mkdir(configHomeC, 0777)) {
|
||||||
|
dbp("cannot mkdir %s: %s", configHomeC, strerror(errno));
|
||||||
|
return Path::From("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbp("cannot stat %s: %s", configHomeC, strerror(errno));
|
||||||
|
return Path::From("");
|
||||||
|
}
|
||||||
|
} else if(!S_ISDIR(st.st_mode)) {
|
||||||
|
dbp("%s is not a directory", configHomeC);
|
||||||
|
return Path::From("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return configHome.Join("settings.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsImplGtk() {
|
||||||
|
_path = GetConfigPath();
|
||||||
|
if(_path.IsEmpty()) {
|
||||||
|
dbp("settings will not be saved");
|
||||||
|
} else {
|
||||||
|
_json = json_object_from_file(_path.raw.c_str());
|
||||||
|
if(!_json && errno != ENOENT) {
|
||||||
|
dbp("cannot load settings: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_json == NULL) {
|
||||||
|
_json = json_object_new_object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~SettingsImplGtk() {
|
||||||
|
if(!_path.IsEmpty()) {
|
||||||
|
// json-c <0.12 has the first argument non-const
|
||||||
|
if(json_object_to_file_ext((char *)_path.raw.c_str(), _json,
|
||||||
|
JSON_C_TO_STRING_PRETTY)) {
|
||||||
|
dbp("cannot save settings: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_put(_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeInt(const std::string &key, uint32_t value) override {
|
||||||
|
struct json_object *jsonValue = json_object_new_int(value);
|
||||||
|
json_object_object_add(_json, key.c_str(), jsonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ThawInt(const std::string &key, uint32_t defaultValue) override {
|
||||||
|
struct json_object *jsonValue;
|
||||||
|
if(json_object_object_get_ex(_json, key.c_str(), &jsonValue)) {
|
||||||
|
return json_object_get_int(jsonValue);
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeFloat(const std::string &key, double value) override {
|
||||||
|
struct json_object *jsonValue = json_object_new_double(value);
|
||||||
|
json_object_object_add(_json, key.c_str(), jsonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
double ThawFloat(const std::string &key, double defaultValue) override {
|
||||||
|
struct json_object *jsonValue;
|
||||||
|
if(json_object_object_get_ex(_json, key.c_str(), &jsonValue)) {
|
||||||
|
return json_object_get_double(jsonValue);
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeString(const std::string &key, const std::string &value) override {
|
||||||
|
struct json_object *jsonValue = json_object_new_string(value.c_str());
|
||||||
|
json_object_object_add(_json, key.c_str(), jsonValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ThawString(const std::string &key,
|
||||||
|
const std::string &defaultValue = "") override {
|
||||||
|
struct json_object *jsonValue;
|
||||||
|
if(json_object_object_get_ex(_json, key.c_str(), &jsonValue)) {
|
||||||
|
return json_object_get_string(jsonValue);
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsRef GetSettings() {
|
||||||
|
static std::shared_ptr<SettingsImplGtk> settings;
|
||||||
|
if(!settings) {
|
||||||
|
settings = std::make_shared<SettingsImplGtk>();
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Timers
|
// Timers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -721,7 +848,7 @@ public:
|
|||||||
gtkWindow.get_gl_widget().set_size_request(width, height);
|
gtkWindow.get_gl_widget().set_size_request(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreezePosition(const std::string &key) override {
|
void FreezePosition(SettingsRef settings, const std::string &key) override {
|
||||||
if(!gtkWindow.is_visible()) return;
|
if(!gtkWindow.is_visible()) return;
|
||||||
|
|
||||||
int left, top, width, height;
|
int left, top, width, height;
|
||||||
@ -729,27 +856,27 @@ public:
|
|||||||
gtkWindow.get_size(width, height);
|
gtkWindow.get_size(width, height);
|
||||||
bool isMaximized = gtkWindow.is_maximized();
|
bool isMaximized = gtkWindow.is_maximized();
|
||||||
|
|
||||||
CnfFreezeInt(left, key + "_left");
|
settings->FreezeInt(key + "_Left", left);
|
||||||
CnfFreezeInt(top, key + "_top");
|
settings->FreezeInt(key + "_Top", top);
|
||||||
CnfFreezeInt(width, key + "_width");
|
settings->FreezeInt(key + "_Width", width);
|
||||||
CnfFreezeInt(height, key + "_height");
|
settings->FreezeInt(key + "_Height", height);
|
||||||
CnfFreezeInt(isMaximized, key + "_maximized");
|
settings->FreezeBool(key + "_Maximized", isMaximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThawPosition(const std::string &key) override {
|
void ThawPosition(SettingsRef settings, const std::string &key) override {
|
||||||
int left, top, width, height;
|
int left, top, width, height;
|
||||||
gtkWindow.get_position(left, top);
|
gtkWindow.get_position(left, top);
|
||||||
gtkWindow.get_size(width, height);
|
gtkWindow.get_size(width, height);
|
||||||
|
|
||||||
left = CnfThawInt(left, key + "_left");
|
left = settings->ThawInt(key + "_Left", left);
|
||||||
top = CnfThawInt(top, key + "_top");
|
top = settings->ThawInt(key + "_Top", top);
|
||||||
width = CnfThawInt(width, key + "_width");
|
width = settings->ThawInt(key + "_Width", width);
|
||||||
height = CnfThawInt(height, key + "_height");
|
height = settings->ThawInt(key + "_Height", height);
|
||||||
|
|
||||||
gtkWindow.move(left, top);
|
gtkWindow.move(left, top);
|
||||||
gtkWindow.resize(width, height);
|
gtkWindow.resize(width, height);
|
||||||
|
|
||||||
if(CnfThawInt(false, key + "_maximized")) {
|
if(settings->ThawBool(key + "_Maximized", false)) {
|
||||||
gtkWindow.maximize();
|
gtkWindow.maximize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,72 @@ static NSString* Wrap(const std::string &s) {
|
|||||||
namespace SolveSpace {
|
namespace SolveSpace {
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Settings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class SettingsImplCocoa : public Settings {
|
||||||
|
public:
|
||||||
|
NSUserDefaults *userDefaults;
|
||||||
|
|
||||||
|
SettingsImplCocoa() {
|
||||||
|
userDefaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeInt(const std::string &key, uint32_t value) override {
|
||||||
|
[userDefaults setInteger:value forKey:Wrap(key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ThawInt(const std::string &key, uint32_t defaultValue = 0) override {
|
||||||
|
NSString *nsKey = Wrap(key);
|
||||||
|
if([userDefaults objectForKey:nsKey]) {
|
||||||
|
return [userDefaults integerForKey:nsKey];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeBool(const std::string &key, bool value) override {
|
||||||
|
[userDefaults setBool:value forKey:Wrap(key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThawBool(const std::string &key, bool defaultValue = false) override {
|
||||||
|
NSString *nsKey = Wrap(key);
|
||||||
|
if([userDefaults objectForKey:nsKey]) {
|
||||||
|
return [userDefaults boolForKey:nsKey];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeFloat(const std::string &key, double value) override {
|
||||||
|
[userDefaults setDouble:value forKey:Wrap(key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
double ThawFloat(const std::string &key, double defaultValue = 0.0) override {
|
||||||
|
NSString *nsKey = Wrap(key);
|
||||||
|
if([userDefaults objectForKey:nsKey]) {
|
||||||
|
return [userDefaults doubleForKey:nsKey];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeString(const std::string &key, const std::string &value) override {
|
||||||
|
[userDefaults setObject:Wrap(value) forKey:Wrap(key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ThawString(const std::string &key,
|
||||||
|
const std::string &defaultValue = "") override {
|
||||||
|
NSObject *nsValue = [userDefaults objectForKey:Wrap(key)];
|
||||||
|
if(nsValue && [nsValue isKindOfClass:[NSString class]]) {
|
||||||
|
return [(NSString *)nsValue UTF8String];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsRef GetSettings() {
|
||||||
|
return std::make_shared<SettingsImplCocoa>();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Timers
|
// Timers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -805,11 +871,11 @@ public:
|
|||||||
[nsWindow setContentSize:nsMinSize];
|
[nsWindow setContentSize:nsMinSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreezePosition(const std::string &key) override {
|
void FreezePosition(SettingsRef _settings, const std::string &key) override {
|
||||||
[nsWindow saveFrameUsingName:Wrap(key)];
|
[nsWindow saveFrameUsingName:Wrap(key)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThawPosition(const std::string &key) override {
|
void ThawPosition(SettingsRef _settings, const std::string &key) override {
|
||||||
[nsWindow setFrameUsingName:Wrap(key)];
|
[nsWindow setFrameUsingName:Wrap(key)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,38 @@ std::shared_ptr<ViewportCanvas> CreateRenderer() {
|
|||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Settings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class SettingsImplDummy : public Settings {
|
||||||
|
public:
|
||||||
|
void FreezeInt(const std::string &key, uint32_t value) {}
|
||||||
|
|
||||||
|
uint32_t ThawInt(const std::string &key, uint32_t defaultValue = 0) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeFloat(const std::string &key, double value) {}
|
||||||
|
|
||||||
|
double ThawFloat(const std::string &key, double defaultValue = 0.0) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeString(const std::string &key, const std::string &value) {}
|
||||||
|
|
||||||
|
std::string ThawString(const std::string &key,
|
||||||
|
const std::string &defaultValue = "") {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsRef GetSettings() {
|
||||||
|
static std::shared_ptr<SettingsImplDummy> settings =
|
||||||
|
std::make_shared<SettingsImplDummy>();
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Timers
|
// Timers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -62,76 +94,6 @@ void Exit() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Settings
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class Setting {
|
|
||||||
public:
|
|
||||||
enum class Type {
|
|
||||||
Undefined,
|
|
||||||
Int,
|
|
||||||
Float,
|
|
||||||
String
|
|
||||||
};
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
int valueInt;
|
|
||||||
float valueFloat;
|
|
||||||
std::string valueString;
|
|
||||||
|
|
||||||
void CheckType(Type expectedType) {
|
|
||||||
ssassert(type == Setting::Type::Undefined ||
|
|
||||||
type == expectedType, "Wrong setting type");
|
|
||||||
type = expectedType;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<std::string, Setting> settings;
|
|
||||||
|
|
||||||
void CnfFreezeInt(uint32_t val, const std::string &key) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::Int);
|
|
||||||
setting.valueInt = val;
|
|
||||||
}
|
|
||||||
uint32_t CnfThawInt(uint32_t val, const std::string &key) {
|
|
||||||
if(settings.find(key) != settings.end()) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::Int);
|
|
||||||
val = setting.valueInt;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeFloat(float val, const std::string &key) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::Float);
|
|
||||||
setting.valueFloat = val;
|
|
||||||
}
|
|
||||||
float CnfThawFloat(float val, const std::string &key) {
|
|
||||||
if(settings.find(key) != settings.end()) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::Float);
|
|
||||||
val = setting.valueFloat;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CnfFreezeString(const std::string &val, const std::string &key) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::String);
|
|
||||||
setting.valueString = val;
|
|
||||||
}
|
|
||||||
std::string CnfThawString(const std::string &val, const std::string &key) {
|
|
||||||
std::string ret = val;
|
|
||||||
if(settings.find(key) != settings.end()) {
|
|
||||||
Setting &setting = settings[key];
|
|
||||||
setting.CheckType(Setting::Type::String);
|
|
||||||
ret = setting.valueString;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Dialogs
|
// Dialogs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -102,6 +102,87 @@ static int Clamp(int x, int a, int b) {
|
|||||||
return max(a, min(x, b));
|
return max(a, min(x, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Settings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class SettingsImplWin32 : public Settings {
|
||||||
|
public:
|
||||||
|
HKEY hKey = NULL;
|
||||||
|
|
||||||
|
HKEY GetKey() {
|
||||||
|
if(hKey == NULL) {
|
||||||
|
sscheck(RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\SolveSpace", 0, NULL, 0,
|
||||||
|
KEY_ALL_ACCESS, NULL, &hKey, NULL));
|
||||||
|
}
|
||||||
|
return hKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SettingsImplWin32() {
|
||||||
|
if(hKey != NULL) {
|
||||||
|
sscheck(RegCloseKey(hKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeInt(const std::string &key, uint32_t value) {
|
||||||
|
sscheck(RegSetValueExW(GetKey(), &Widen(key)[0], 0,
|
||||||
|
REG_DWORD, (const BYTE *)&value, sizeof(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ThawInt(const std::string &key, uint32_t defaultValue) {
|
||||||
|
DWORD value;
|
||||||
|
DWORD type, length = sizeof(value);
|
||||||
|
LSTATUS result = RegQueryValueEx(GetKey(), &Widen(key)[0], 0,
|
||||||
|
&type, (BYTE *)&value, &length);
|
||||||
|
if(result == ERROR_SUCCESS && type == REG_DWORD) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeFloat(const std::string &key, double value) {
|
||||||
|
sscheck(RegSetValueExW(GetKey(), &Widen(key)[0], 0,
|
||||||
|
REG_QWORD, (const BYTE *)&value, sizeof(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double ThawFloat(const std::string &key, double defaultValue) {
|
||||||
|
double value;
|
||||||
|
DWORD type, length = sizeof(value);
|
||||||
|
LSTATUS result = RegQueryValueEx(GetKey(), &Widen(key)[0], 0,
|
||||||
|
&type, (BYTE *)&value, &length);
|
||||||
|
if(result == ERROR_SUCCESS && type == REG_QWORD) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreezeString(const std::string &key, const std::string &value) {
|
||||||
|
ssassert(value.length() == strlen(value.c_str()),
|
||||||
|
"illegal null byte in middle of a string setting");
|
||||||
|
std::wstring valueW = Widen(value);
|
||||||
|
sscheck(RegSetValueExW(GetKey(), &Widen(key)[0], 0,
|
||||||
|
REG_SZ, (const BYTE *)&valueW[0], (valueW.length() + 1) * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ThawString(const std::string &key, const std::string &defaultValue) {
|
||||||
|
DWORD type, length = 0;
|
||||||
|
LSTATUS result = RegQueryValueEx(GetKey(), &Widen(key)[0], 0,
|
||||||
|
&type, NULL, &length);
|
||||||
|
if(result == ERROR_SUCCESS && type == REG_SZ) {
|
||||||
|
std::wstring valueW;
|
||||||
|
valueW.resize(length / 2 - 1);
|
||||||
|
sscheck(RegQueryValueEx(GetKey(), &Widen(key)[0], 0,
|
||||||
|
&type, (BYTE *)&valueW[0], &length));
|
||||||
|
return Narrow(valueW);
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SettingsRef GetSettings() {
|
||||||
|
return std::make_shared<SettingsImplWin32>();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Timers
|
// Timers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -960,28 +1041,28 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreezePosition(const std::string &key) override {
|
void FreezePosition(SettingsRef settings, const std::string &key) override {
|
||||||
sscheck(GetWindowPlacement(hWindow, &placement));
|
sscheck(GetWindowPlacement(hWindow, &placement));
|
||||||
|
|
||||||
BOOL isMaximized;
|
BOOL isMaximized;
|
||||||
sscheck(isMaximized = IsZoomed(hWindow));
|
sscheck(isMaximized = IsZoomed(hWindow));
|
||||||
|
|
||||||
RECT rc = placement.rcNormalPosition;
|
RECT rc = placement.rcNormalPosition;
|
||||||
CnfFreezeInt(rc.left, key + "_left");
|
settings->FreezeInt(key + "_Left", rc.left);
|
||||||
CnfFreezeInt(rc.right, key + "_right");
|
settings->FreezeInt(key + "_Right", rc.right);
|
||||||
CnfFreezeInt(rc.top, key + "_top");
|
settings->FreezeInt(key + "_Top", rc.top);
|
||||||
CnfFreezeInt(rc.bottom, key + "_bottom");
|
settings->FreezeInt(key + "_Bottom", rc.bottom);
|
||||||
CnfFreezeInt(isMaximized, key + "_maximized");
|
settings->FreezeBool(key + "_Maximized", isMaximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThawPosition(const std::string &key) override {
|
void ThawPosition(SettingsRef settings, const std::string &key) override {
|
||||||
sscheck(GetWindowPlacement(hWindow, &placement));
|
sscheck(GetWindowPlacement(hWindow, &placement));
|
||||||
|
|
||||||
RECT rc = placement.rcNormalPosition;
|
RECT rc = placement.rcNormalPosition;
|
||||||
rc.left = CnfThawInt(rc.left, key + "_left");
|
rc.left = settings->ThawInt(key + "_Left", rc.left);
|
||||||
rc.right = CnfThawInt(rc.right, key + "_right");
|
rc.right = settings->ThawInt(key + "_Right", rc.right);
|
||||||
rc.top = CnfThawInt(rc.top, key + "_top");
|
rc.top = settings->ThawInt(key + "_Top", rc.top);
|
||||||
rc.bottom = CnfThawInt(rc.bottom, key + "_bottom");
|
rc.bottom = settings->ThawInt(key + "_Bottom", rc.bottom);
|
||||||
|
|
||||||
MONITORINFO mi;
|
MONITORINFO mi;
|
||||||
mi.cbSize = sizeof(mi);
|
mi.cbSize = sizeof(mi);
|
||||||
@ -999,7 +1080,7 @@ public:
|
|||||||
sscheck(SendMessageW(hWindow, WM_SIZING, WMSZ_BOTTOMRIGHT, (LPARAM)&rc));
|
sscheck(SendMessageW(hWindow, WM_SIZING, WMSZ_BOTTOMRIGHT, (LPARAM)&rc));
|
||||||
|
|
||||||
placement.flags = 0;
|
placement.flags = 0;
|
||||||
if(CnfThawInt(false, key + "_maximized")) {
|
if(settings->ThawBool(key + "_Maximized", false)) {
|
||||||
placement.showCmd = SW_SHOWMAXIMIZED;
|
placement.showCmd = SW_SHOWMAXIMIZED;
|
||||||
} else {
|
} else {
|
||||||
placement.showCmd = SW_SHOW;
|
placement.showCmd = SW_SHOW;
|
||||||
|
@ -177,102 +177,6 @@ void SolveSpace::OpenWebsite(const char *url) {
|
|||||||
L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Helpers so that we can read/write registry keys from the platform-
|
|
||||||
// independent code.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static HKEY GetRegistryKey()
|
|
||||||
{
|
|
||||||
HKEY Software;
|
|
||||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Software", 0,
|
|
||||||
KEY_ALL_ACCESS, &Software) != ERROR_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
HKEY SolveSpace;
|
|
||||||
if(RegCreateKeyExW(Software, L"SolveSpace", 0, NULL, 0,
|
|
||||||
KEY_ALL_ACCESS, NULL, &SolveSpace, NULL) != ERROR_SUCCESS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
RegCloseKey(Software);
|
|
||||||
|
|
||||||
return SolveSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SolveSpace::CnfFreezeInt(uint32_t val, const std::string &name)
|
|
||||||
{
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
|
||||||
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
}
|
|
||||||
void SolveSpace::CnfFreezeFloat(float val, const std::string &name)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(float) == sizeof(DWORD),
|
|
||||||
"sizes of float and DWORD must match");
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
|
||||||
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
}
|
|
||||||
void SolveSpace::CnfFreezeString(const std::string &str, const std::string &name)
|
|
||||||
{
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
std::wstring strW = Widen(str);
|
|
||||||
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
|
||||||
REG_SZ, (const BYTE*) &strW[0], (strW.length() + 1) * 2);
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SolveSpace::CnfThawInt(uint32_t val, const std::string &name)
|
|
||||||
{
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
DWORD type, newval, len = sizeof(DWORD);
|
|
||||||
LONG result = RegQueryValueEx(SolveSpace, &Widen(name)[0], NULL,
|
|
||||||
&type, (BYTE*) &newval, &len);
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
|
|
||||||
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
|
||||||
return newval;
|
|
||||||
else
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
float SolveSpace::CnfThawFloat(float val, const std::string &name)
|
|
||||||
{
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
DWORD type, len = sizeof(DWORD);
|
|
||||||
float newval;
|
|
||||||
LONG result = RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
|
||||||
&type, (BYTE*) &newval, &len);
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
|
|
||||||
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
|
||||||
return newval;
|
|
||||||
else
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
std::string SolveSpace::CnfThawString(const std::string &val, const std::string &name)
|
|
||||||
{
|
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
|
||||||
DWORD type, len;
|
|
||||||
if(RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
|
||||||
&type, NULL, &len) != ERROR_SUCCESS || type != REG_SZ) {
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring newval;
|
|
||||||
newval.resize(len / 2 - 1);
|
|
||||||
if(RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
|
||||||
NULL, (BYTE*) &newval[0], &len) != ERROR_SUCCESS) {
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(SolveSpace);
|
|
||||||
return Narrow(newval);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Common dialog routines, to open or save a file.
|
// Common dialog routines, to open or save a file.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -834,7 +834,7 @@ public:
|
|||||||
static void CreateAllDefaultStyles();
|
static void CreateAllDefaultStyles();
|
||||||
static void CreateDefaultStyle(hStyle h);
|
static void CreateDefaultStyle(hStyle h);
|
||||||
static void FillDefaultStyle(Style *s, const Default *d = NULL, bool factory = false);
|
static void FillDefaultStyle(Style *s, const Default *d = NULL, bool factory = false);
|
||||||
static void FreezeDefaultStyles();
|
static void FreezeDefaultStyles(Platform::SettingsRef settings);
|
||||||
static void LoadFactoryDefaults();
|
static void LoadFactoryDefaults();
|
||||||
|
|
||||||
static void AssignSelectionToStyle(uint32_t v);
|
static void AssignSelectionToStyle(uint32_t v);
|
||||||
|
@ -16,95 +16,97 @@ void SolveSpaceUI::Init() {
|
|||||||
dbp("%s", LoadString("banner.txt").data());
|
dbp("%s", LoadString("banner.txt").data());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Platform::SettingsRef settings = Platform::GetSettings();
|
||||||
|
|
||||||
SS.tangentArcRadius = 10.0;
|
SS.tangentArcRadius = 10.0;
|
||||||
|
|
||||||
// Then, load the registry settings.
|
// Then, load the registry settings.
|
||||||
// Default list of colors for the model material
|
// Default list of colors for the model material
|
||||||
modelColor[0] = CnfThawColor(RGBi(150, 150, 150), "ModelColor_0");
|
modelColor[0] = settings->ThawColor("ModelColor_0", RGBi(150, 150, 150));
|
||||||
modelColor[1] = CnfThawColor(RGBi(100, 100, 100), "ModelColor_1");
|
modelColor[1] = settings->ThawColor("ModelColor_1", RGBi(100, 100, 100));
|
||||||
modelColor[2] = CnfThawColor(RGBi( 30, 30, 30), "ModelColor_2");
|
modelColor[2] = settings->ThawColor("ModelColor_2", RGBi( 30, 30, 30));
|
||||||
modelColor[3] = CnfThawColor(RGBi(150, 0, 0), "ModelColor_3");
|
modelColor[3] = settings->ThawColor("ModelColor_3", RGBi(150, 0, 0));
|
||||||
modelColor[4] = CnfThawColor(RGBi( 0, 100, 0), "ModelColor_4");
|
modelColor[4] = settings->ThawColor("ModelColor_4", RGBi( 0, 100, 0));
|
||||||
modelColor[5] = CnfThawColor(RGBi( 0, 80, 80), "ModelColor_5");
|
modelColor[5] = settings->ThawColor("ModelColor_5", RGBi( 0, 80, 80));
|
||||||
modelColor[6] = CnfThawColor(RGBi( 0, 0, 130), "ModelColor_6");
|
modelColor[6] = settings->ThawColor("ModelColor_6", RGBi( 0, 0, 130));
|
||||||
modelColor[7] = CnfThawColor(RGBi( 80, 0, 80), "ModelColor_7");
|
modelColor[7] = settings->ThawColor("ModelColor_7", RGBi( 80, 0, 80));
|
||||||
// Light intensities
|
// Light intensities
|
||||||
lightIntensity[0] = CnfThawFloat(1.0f, "LightIntensity_0");
|
lightIntensity[0] = settings->ThawFloat("LightIntensity_0", 1.0f);
|
||||||
lightIntensity[1] = CnfThawFloat(0.5f, "LightIntensity_1");
|
lightIntensity[1] = settings->ThawFloat("LightIntensity_1", 0.5f);
|
||||||
ambientIntensity = 0.3; // no setting for that yet
|
ambientIntensity = 0.3; // no setting for that yet
|
||||||
// Light positions
|
// Light positions
|
||||||
lightDir[0].x = CnfThawFloat(-1.0f, "LightDir_0_Right" );
|
lightDir[0].x = settings->ThawFloat("LightDir_0_Right", -1.0f);
|
||||||
lightDir[0].y = CnfThawFloat( 1.0f, "LightDir_0_Up" );
|
lightDir[0].y = settings->ThawFloat("LightDir_0_Up", 1.0f);
|
||||||
lightDir[0].z = CnfThawFloat( 0.0f, "LightDir_0_Forward" );
|
lightDir[0].z = settings->ThawFloat("LightDir_0_Forward", 0.0f);
|
||||||
lightDir[1].x = CnfThawFloat( 1.0f, "LightDir_1_Right" );
|
lightDir[1].x = settings->ThawFloat("LightDir_1_Right", 1.0f);
|
||||||
lightDir[1].y = CnfThawFloat( 0.0f, "LightDir_1_Up" );
|
lightDir[1].y = settings->ThawFloat("LightDir_1_Up", 0.0f);
|
||||||
lightDir[1].z = CnfThawFloat( 0.0f, "LightDir_1_Forward" );
|
lightDir[1].z = settings->ThawFloat("LightDir_1_Forward", 0.0f);
|
||||||
|
|
||||||
exportMode = false;
|
exportMode = false;
|
||||||
// Chord tolerance
|
// Chord tolerance
|
||||||
chordTol = CnfThawFloat(0.5f, "ChordTolerancePct");
|
chordTol = settings->ThawFloat("ChordTolerancePct", 0.5f);
|
||||||
// Max pwl segments to generate
|
// Max pwl segments to generate
|
||||||
maxSegments = CnfThawInt(10, "MaxSegments");
|
maxSegments = settings->ThawInt("MaxSegments", 10);
|
||||||
// Chord tolerance
|
// Chord tolerance
|
||||||
exportChordTol = CnfThawFloat(0.1f, "ExportChordTolerance");
|
exportChordTol = settings->ThawFloat("ExportChordTolerance", 0.1f);
|
||||||
// Max pwl segments to generate
|
// Max pwl segments to generate
|
||||||
exportMaxSegments = CnfThawInt(64, "ExportMaxSegments");
|
exportMaxSegments = settings->ThawInt("ExportMaxSegments", 64);
|
||||||
// View units
|
// View units
|
||||||
viewUnits = (Unit)CnfThawInt((uint32_t)Unit::MM, "ViewUnits");
|
viewUnits = (Unit)settings->ThawInt("ViewUnits", (uint32_t)Unit::MM);
|
||||||
// Number of digits after the decimal point
|
// Number of digits after the decimal point
|
||||||
afterDecimalMm = CnfThawInt(2, "AfterDecimalMm");
|
afterDecimalMm = settings->ThawInt("AfterDecimalMm", 2);
|
||||||
afterDecimalInch = CnfThawInt(3, "AfterDecimalInch");
|
afterDecimalInch = settings->ThawInt("AfterDecimalInch", 3);
|
||||||
// Camera tangent (determines perspective)
|
// Camera tangent (determines perspective)
|
||||||
cameraTangent = CnfThawFloat(0.3f/1e3f, "CameraTangent");
|
cameraTangent = settings->ThawFloat("CameraTangent", 0.3f/1e3f);
|
||||||
// Grid spacing
|
// Grid spacing
|
||||||
gridSpacing = CnfThawFloat(5.0f, "GridSpacing");
|
gridSpacing = settings->ThawFloat("GridSpacing", 5.0f);
|
||||||
// Export scale factor
|
// Export scale factor
|
||||||
exportScale = CnfThawFloat(1.0f, "ExportScale");
|
exportScale = settings->ThawFloat("ExportScale", 1.0f);
|
||||||
// Export offset (cutter radius comp)
|
// Export offset (cutter radius comp)
|
||||||
exportOffset = CnfThawFloat(0.0f, "ExportOffset");
|
exportOffset = settings->ThawFloat("ExportOffset", 0.0f);
|
||||||
// Rewrite exported colors close to white into black (assuming white bg)
|
// Rewrite exported colors close to white into black (assuming white bg)
|
||||||
fixExportColors = CnfThawBool(true, "FixExportColors");
|
fixExportColors = settings->ThawBool("FixExportColors", true);
|
||||||
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
||||||
drawBackFaces = CnfThawBool(true, "DrawBackFaces");
|
drawBackFaces = settings->ThawBool("DrawBackFaces", true);
|
||||||
// Check that contours are closed and not self-intersecting
|
// Check that contours are closed and not self-intersecting
|
||||||
checkClosedContour = CnfThawBool(true, "CheckClosedContour");
|
checkClosedContour = settings->ThawBool("CheckClosedContour", true);
|
||||||
// Draw closed polygons areas
|
// Draw closed polygons areas
|
||||||
showContourAreas = CnfThawBool(false, "ShowContourAreas");
|
showContourAreas = settings->ThawBool("ShowContourAreas", false);
|
||||||
// Export shaded triangles in a 2d view
|
// Export shaded triangles in a 2d view
|
||||||
exportShadedTriangles = CnfThawBool(true, "ExportShadedTriangles");
|
exportShadedTriangles = settings->ThawBool("ExportShadedTriangles", true);
|
||||||
// Export pwl curves (instead of exact) always
|
// Export pwl curves (instead of exact) always
|
||||||
exportPwlCurves = CnfThawBool(false, "ExportPwlCurves");
|
exportPwlCurves = settings->ThawBool("ExportPwlCurves", false);
|
||||||
// Background color on-screen
|
// Background color on-screen
|
||||||
backgroundColor = CnfThawColor(RGBi(0, 0, 0), "BackgroundColor");
|
backgroundColor = settings->ThawColor("BackgroundColor", RGBi(0, 0, 0));
|
||||||
// Whether export canvas size is fixed or derived from bbox
|
// Whether export canvas size is fixed or derived from bbox
|
||||||
exportCanvasSizeAuto = CnfThawBool(true, "ExportCanvasSizeAuto");
|
exportCanvasSizeAuto = settings->ThawBool("ExportCanvasSizeAuto", true);
|
||||||
// Margins for automatic canvas size
|
// Margins for automatic canvas size
|
||||||
exportMargin.left = CnfThawFloat(5.0f, "ExportMargin_Left");
|
exportMargin.left = settings->ThawFloat("ExportMargin_Left", 5.0f);
|
||||||
exportMargin.right = CnfThawFloat(5.0f, "ExportMargin_Right");
|
exportMargin.right = settings->ThawFloat("ExportMargin_Right", 5.0f);
|
||||||
exportMargin.bottom = CnfThawFloat(5.0f, "ExportMargin_Bottom");
|
exportMargin.bottom = settings->ThawFloat("ExportMargin_Bottom", 5.0f);
|
||||||
exportMargin.top = CnfThawFloat(5.0f, "ExportMargin_Top");
|
exportMargin.top = settings->ThawFloat("ExportMargin_Top", 5.0f);
|
||||||
// Dimensions for fixed canvas size
|
// Dimensions for fixed canvas size
|
||||||
exportCanvas.width = CnfThawFloat(100.0f, "ExportCanvas_Width");
|
exportCanvas.width = settings->ThawFloat("ExportCanvas_Width", 100.0f);
|
||||||
exportCanvas.height = CnfThawFloat(100.0f, "ExportCanvas_Height");
|
exportCanvas.height = settings->ThawFloat("ExportCanvas_Height", 100.0f);
|
||||||
exportCanvas.dx = CnfThawFloat( 5.0f, "ExportCanvas_Dx");
|
exportCanvas.dx = settings->ThawFloat("ExportCanvas_Dx", 5.0f);
|
||||||
exportCanvas.dy = CnfThawFloat( 5.0f, "ExportCanvas_Dy");
|
exportCanvas.dy = settings->ThawFloat("ExportCanvas_Dy", 5.0f);
|
||||||
// Extra parameters when exporting G code
|
// Extra parameters when exporting G code
|
||||||
gCode.depth = CnfThawFloat(10.0f, "GCode_Depth");
|
gCode.depth = settings->ThawFloat("GCode_Depth", 10.0f);
|
||||||
gCode.passes = CnfThawInt(1, "GCode_Passes");
|
gCode.passes = settings->ThawInt("GCode_Passes", 1);
|
||||||
gCode.feed = CnfThawFloat(10.0f, "GCode_Feed");
|
gCode.feed = settings->ThawFloat("GCode_Feed", 10.0f);
|
||||||
gCode.plungeFeed = CnfThawFloat(10.0f, "GCode_PlungeFeed");
|
gCode.plungeFeed = settings->ThawFloat("GCode_PlungeFeed", 10.0f);
|
||||||
// Show toolbar in the graphics window
|
// Show toolbar in the graphics window
|
||||||
showToolbar = CnfThawBool(true, "ShowToolbar");
|
showToolbar = settings->ThawBool("ShowToolbar", true);
|
||||||
// Recent files menus
|
// Recent files menus
|
||||||
for(size_t i = 0; i < MAX_RECENT; i++) {
|
for(size_t i = 0; i < MAX_RECENT; i++) {
|
||||||
std::string rawPath = CnfThawString("", "RecentFile_" + std::to_string(i));
|
std::string rawPath = settings->ThawString("RecentFile_" + std::to_string(i), "");
|
||||||
if(rawPath.empty()) continue;
|
if(rawPath.empty()) continue;
|
||||||
recentFiles.push_back(Platform::Path::From(rawPath));
|
recentFiles.push_back(Platform::Path::From(rawPath));
|
||||||
}
|
}
|
||||||
// Autosave timer
|
// Autosave timer
|
||||||
autosaveInterval = CnfThawInt(5, "AutosaveInterval");
|
autosaveInterval = settings->ThawInt("AutosaveInterval", 5);
|
||||||
// Locale
|
// Locale
|
||||||
std::string locale = CnfThawString("", "Locale");
|
std::string locale = settings->ThawString("Locale", "");
|
||||||
if(!locale.empty()) {
|
if(!locale.empty()) {
|
||||||
SetLocale(locale);
|
SetLocale(locale);
|
||||||
}
|
}
|
||||||
@ -129,9 +131,9 @@ void SolveSpaceUI::Init() {
|
|||||||
AfterNewFile();
|
AfterNewFile();
|
||||||
|
|
||||||
if(TW.window && GW.window) {
|
if(TW.window && GW.window) {
|
||||||
TW.window->ThawPosition("TextWindow");
|
TW.window->ThawPosition(settings, "TextWindow");
|
||||||
|
GW.window->ThawPosition(settings, "GraphicsWindow");
|
||||||
TW.window->SetVisible(true);
|
TW.window->SetVisible(true);
|
||||||
GW.window->ThawPosition("GraphicsWindow");
|
|
||||||
GW.window->SetVisible(true);
|
GW.window->SetVisible(true);
|
||||||
GW.window->Focus();
|
GW.window->Focus();
|
||||||
}
|
}
|
||||||
@ -169,8 +171,10 @@ bool SolveSpaceUI::Load(const Platform::Path &filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::Exit() {
|
void SolveSpaceUI::Exit() {
|
||||||
GW.window->FreezePosition("GraphicsWindow");
|
Platform::SettingsRef settings = Platform::GetSettings();
|
||||||
TW.window->FreezePosition("TextWindow");
|
|
||||||
|
GW.window->FreezePosition(settings, "GraphicsWindow");
|
||||||
|
TW.window->FreezePosition(settings, "TextWindow");
|
||||||
|
|
||||||
// Recent files
|
// Recent files
|
||||||
for(size_t i = 0; i < MAX_RECENT; i++) {
|
for(size_t i = 0; i < MAX_RECENT; i++) {
|
||||||
@ -178,80 +182,80 @@ void SolveSpaceUI::Exit() {
|
|||||||
if(recentFiles.size() > i) {
|
if(recentFiles.size() > i) {
|
||||||
rawPath = recentFiles[i].raw;
|
rawPath = recentFiles[i].raw;
|
||||||
}
|
}
|
||||||
CnfFreezeString(rawPath, "RecentFile_" + std::to_string(i));
|
settings->FreezeString("RecentFile_" + std::to_string(i), rawPath);
|
||||||
}
|
}
|
||||||
// Model colors
|
// Model colors
|
||||||
for(size_t i = 0; i < MODEL_COLORS; i++)
|
for(size_t i = 0; i < MODEL_COLORS; i++)
|
||||||
CnfFreezeColor(modelColor[i], "ModelColor_" + std::to_string(i));
|
settings->FreezeColor("ModelColor_" + std::to_string(i), modelColor[i]);
|
||||||
// Light intensities
|
// Light intensities
|
||||||
CnfFreezeFloat((float)lightIntensity[0], "LightIntensity_0");
|
settings->FreezeFloat("LightIntensity_0", (float)lightIntensity[0]);
|
||||||
CnfFreezeFloat((float)lightIntensity[1], "LightIntensity_1");
|
settings->FreezeFloat("LightIntensity_1", (float)lightIntensity[1]);
|
||||||
// Light directions
|
// Light directions
|
||||||
CnfFreezeFloat((float)lightDir[0].x, "LightDir_0_Right");
|
settings->FreezeFloat("LightDir_0_Right", (float)lightDir[0].x);
|
||||||
CnfFreezeFloat((float)lightDir[0].y, "LightDir_0_Up");
|
settings->FreezeFloat("LightDir_0_Up", (float)lightDir[0].y);
|
||||||
CnfFreezeFloat((float)lightDir[0].z, "LightDir_0_Forward");
|
settings->FreezeFloat("LightDir_0_Forward", (float)lightDir[0].z);
|
||||||
CnfFreezeFloat((float)lightDir[1].x, "LightDir_1_Right");
|
settings->FreezeFloat("LightDir_1_Right", (float)lightDir[1].x);
|
||||||
CnfFreezeFloat((float)lightDir[1].y, "LightDir_1_Up");
|
settings->FreezeFloat("LightDir_1_Up", (float)lightDir[1].y);
|
||||||
CnfFreezeFloat((float)lightDir[1].z, "LightDir_1_Forward");
|
settings->FreezeFloat("LightDir_1_Forward", (float)lightDir[1].z);
|
||||||
// Chord tolerance
|
// Chord tolerance
|
||||||
CnfFreezeFloat((float)chordTol, "ChordTolerancePct");
|
settings->FreezeFloat("ChordTolerancePct", (float)chordTol);
|
||||||
// Max pwl segments to generate
|
// Max pwl segments to generate
|
||||||
CnfFreezeInt((uint32_t)maxSegments, "MaxSegments");
|
settings->FreezeInt("MaxSegments", (uint32_t)maxSegments);
|
||||||
// Export Chord tolerance
|
// Export Chord tolerance
|
||||||
CnfFreezeFloat((float)exportChordTol, "ExportChordTolerance");
|
settings->FreezeFloat("ExportChordTolerance", (float)exportChordTol);
|
||||||
// Export Max pwl segments to generate
|
// Export Max pwl segments to generate
|
||||||
CnfFreezeInt((uint32_t)exportMaxSegments, "ExportMaxSegments");
|
settings->FreezeInt("ExportMaxSegments", (uint32_t)exportMaxSegments);
|
||||||
// View units
|
// View units
|
||||||
CnfFreezeInt((uint32_t)viewUnits, "ViewUnits");
|
settings->FreezeInt("ViewUnits", (uint32_t)viewUnits);
|
||||||
// Number of digits after the decimal point
|
// Number of digits after the decimal point
|
||||||
CnfFreezeInt((uint32_t)afterDecimalMm, "AfterDecimalMm");
|
settings->FreezeInt("AfterDecimalMm", (uint32_t)afterDecimalMm);
|
||||||
CnfFreezeInt((uint32_t)afterDecimalInch, "AfterDecimalInch");
|
settings->FreezeInt("AfterDecimalInch", (uint32_t)afterDecimalInch);
|
||||||
// Camera tangent (determines perspective)
|
// Camera tangent (determines perspective)
|
||||||
CnfFreezeFloat((float)cameraTangent, "CameraTangent");
|
settings->FreezeFloat("CameraTangent", (float)cameraTangent);
|
||||||
// Grid spacing
|
// Grid spacing
|
||||||
CnfFreezeFloat(gridSpacing, "GridSpacing");
|
settings->FreezeFloat("GridSpacing", gridSpacing);
|
||||||
// Export scale
|
// Export scale
|
||||||
CnfFreezeFloat(exportScale, "ExportScale");
|
settings->FreezeFloat("ExportScale", exportScale);
|
||||||
// Export offset (cutter radius comp)
|
// Export offset (cutter radius comp)
|
||||||
CnfFreezeFloat(exportOffset, "ExportOffset");
|
settings->FreezeFloat("ExportOffset", exportOffset);
|
||||||
// Rewrite exported colors close to white into black (assuming white bg)
|
// Rewrite exported colors close to white into black (assuming white bg)
|
||||||
CnfFreezeBool(fixExportColors, "FixExportColors");
|
settings->FreezeBool("FixExportColors", fixExportColors);
|
||||||
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
// Draw back faces of triangles (when mesh is leaky/self-intersecting)
|
||||||
CnfFreezeBool(drawBackFaces, "DrawBackFaces");
|
settings->FreezeBool("DrawBackFaces", drawBackFaces);
|
||||||
// Draw closed polygons areas
|
// Draw closed polygons areas
|
||||||
CnfFreezeBool(showContourAreas, "ShowContourAreas");
|
settings->FreezeBool("ShowContourAreas", showContourAreas);
|
||||||
// Check that contours are closed and not self-intersecting
|
// Check that contours are closed and not self-intersecting
|
||||||
CnfFreezeBool(checkClosedContour, "CheckClosedContour");
|
settings->FreezeBool("CheckClosedContour", checkClosedContour);
|
||||||
// Export shaded triangles in a 2d view
|
// Export shaded triangles in a 2d view
|
||||||
CnfFreezeBool(exportShadedTriangles, "ExportShadedTriangles");
|
settings->FreezeBool("ExportShadedTriangles", exportShadedTriangles);
|
||||||
// Export pwl curves (instead of exact) always
|
// Export pwl curves (instead of exact) always
|
||||||
CnfFreezeBool(exportPwlCurves, "ExportPwlCurves");
|
settings->FreezeBool("ExportPwlCurves", exportPwlCurves);
|
||||||
// Background color on-screen
|
// Background color on-screen
|
||||||
CnfFreezeColor(backgroundColor, "BackgroundColor");
|
settings->FreezeColor("BackgroundColor", backgroundColor);
|
||||||
// Whether export canvas size is fixed or derived from bbox
|
// Whether export canvas size is fixed or derived from bbox
|
||||||
CnfFreezeBool(exportCanvasSizeAuto, "ExportCanvasSizeAuto");
|
settings->FreezeBool("ExportCanvasSizeAuto", exportCanvasSizeAuto);
|
||||||
// Margins for automatic canvas size
|
// Margins for automatic canvas size
|
||||||
CnfFreezeFloat(exportMargin.left, "ExportMargin_Left");
|
settings->FreezeFloat("ExportMargin_Left", exportMargin.left);
|
||||||
CnfFreezeFloat(exportMargin.right, "ExportMargin_Right");
|
settings->FreezeFloat("ExportMargin_Right", exportMargin.right);
|
||||||
CnfFreezeFloat(exportMargin.bottom, "ExportMargin_Bottom");
|
settings->FreezeFloat("ExportMargin_Bottom", exportMargin.bottom);
|
||||||
CnfFreezeFloat(exportMargin.top, "ExportMargin_Top");
|
settings->FreezeFloat("ExportMargin_Top", exportMargin.top);
|
||||||
// Dimensions for fixed canvas size
|
// Dimensions for fixed canvas size
|
||||||
CnfFreezeFloat(exportCanvas.width, "ExportCanvas_Width");
|
settings->FreezeFloat("ExportCanvas_Width", exportCanvas.width);
|
||||||
CnfFreezeFloat(exportCanvas.height, "ExportCanvas_Height");
|
settings->FreezeFloat("ExportCanvas_Height", exportCanvas.height);
|
||||||
CnfFreezeFloat(exportCanvas.dx, "ExportCanvas_Dx");
|
settings->FreezeFloat("ExportCanvas_Dx", exportCanvas.dx);
|
||||||
CnfFreezeFloat(exportCanvas.dy, "ExportCanvas_Dy");
|
settings->FreezeFloat("ExportCanvas_Dy", exportCanvas.dy);
|
||||||
// Extra parameters when exporting G code
|
// Extra parameters when exporting G code
|
||||||
CnfFreezeFloat(gCode.depth, "GCode_Depth");
|
settings->FreezeFloat("GCode_Depth", gCode.depth);
|
||||||
CnfFreezeInt(gCode.passes, "GCode_Passes");
|
settings->FreezeInt("GCode_Passes", gCode.passes);
|
||||||
CnfFreezeFloat(gCode.feed, "GCode_Feed");
|
settings->FreezeFloat("GCode_Feed", gCode.feed);
|
||||||
CnfFreezeFloat(gCode.plungeFeed, "GCode_PlungeFeed");
|
settings->FreezeFloat("GCode_PlungeFeed", gCode.plungeFeed);
|
||||||
// Show toolbar in the graphics window
|
// Show toolbar in the graphics window
|
||||||
CnfFreezeBool(showToolbar, "ShowToolbar");
|
settings->FreezeBool("ShowToolbar", showToolbar);
|
||||||
// Autosave timer
|
// Autosave timer
|
||||||
CnfFreezeInt(autosaveInterval, "AutosaveInterval");
|
settings->FreezeInt("AutosaveInterval", autosaveInterval);
|
||||||
|
|
||||||
// And the default styles, colors and line widths and such.
|
// And the default styles, colors and line widths and such.
|
||||||
Style::FreezeDefaultStyles();
|
Style::FreezeDefaultStyles(settings);
|
||||||
|
|
||||||
Platform::Exit();
|
Platform::Exit();
|
||||||
}
|
}
|
||||||
@ -444,6 +448,8 @@ void SolveSpaceUI::UpdateWindowTitles() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::MenuFile(Command id) {
|
void SolveSpaceUI::MenuFile(Command id) {
|
||||||
|
Platform::SettingsRef settings = Platform::GetSettings();
|
||||||
|
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case Command::NEW:
|
case Command::NEW:
|
||||||
if(!SS.OkayToStartNewFile()) break;
|
if(!SS.OkayToStartNewFile()) break;
|
||||||
@ -480,9 +486,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::EXPORT_VIEW: {
|
case Command::EXPORT_VIEW: {
|
||||||
Platform::Path exportFile = SS.saveFile;
|
Platform::Path exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "ViewExportFormat"),
|
if(!GetSaveFile(&exportFile,
|
||||||
|
Platform::GetSettings()->ThawString("ViewExportFormat"),
|
||||||
VectorFileFilter)) break;
|
VectorFileFilter)) break;
|
||||||
CnfFreezeString(exportFile.Extension(), "ViewExportFormat");
|
settings->FreezeString("ViewExportFormat", exportFile.Extension());
|
||||||
|
|
||||||
// If the user is exporting something where it would be
|
// If the user is exporting something where it would be
|
||||||
// inappropriate to include the constraints, then warn.
|
// inappropriate to include the constraints, then warn.
|
||||||
@ -502,9 +509,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::EXPORT_WIREFRAME: {
|
case Command::EXPORT_WIREFRAME: {
|
||||||
Platform::Path exportFile = SS.saveFile;
|
Platform::Path exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "WireframeExportFormat"),
|
if(!GetSaveFile(&exportFile,
|
||||||
|
Platform::GetSettings()->ThawString("WireframeExportFormat"),
|
||||||
Vector3dFileFilter)) break;
|
Vector3dFileFilter)) break;
|
||||||
CnfFreezeString(exportFile.Extension(), "WireframeExportFormat");
|
settings->FreezeString("WireframeExportFormat", exportFile.Extension());
|
||||||
|
|
||||||
SS.ExportViewOrWireframeTo(exportFile, /*exportWireframe*/true);
|
SS.ExportViewOrWireframeTo(exportFile, /*exportWireframe*/true);
|
||||||
break;
|
break;
|
||||||
@ -512,9 +520,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::EXPORT_SECTION: {
|
case Command::EXPORT_SECTION: {
|
||||||
Platform::Path exportFile = SS.saveFile;
|
Platform::Path exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SectionExportFormat"),
|
if(!GetSaveFile(&exportFile,
|
||||||
|
Platform::GetSettings()->ThawString("SectionExportFormat"),
|
||||||
VectorFileFilter)) break;
|
VectorFileFilter)) break;
|
||||||
CnfFreezeString(exportFile.Extension(), "SectionExportFormat");
|
settings->FreezeString("SectionExportFormat", exportFile.Extension());
|
||||||
|
|
||||||
SS.ExportSectionTo(exportFile);
|
SS.ExportSectionTo(exportFile);
|
||||||
break;
|
break;
|
||||||
@ -522,9 +531,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::EXPORT_MESH: {
|
case Command::EXPORT_MESH: {
|
||||||
Platform::Path exportFile = SS.saveFile;
|
Platform::Path exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "MeshExportFormat"),
|
if(!GetSaveFile(&exportFile,
|
||||||
|
Platform::GetSettings()->ThawString("MeshExportFormat"),
|
||||||
MeshFileFilter)) break;
|
MeshFileFilter)) break;
|
||||||
CnfFreezeString(exportFile.Extension(), "MeshExportFormat");
|
settings->FreezeString("MeshExportFormat", exportFile.Extension());
|
||||||
|
|
||||||
SS.ExportMeshTo(exportFile);
|
SS.ExportMeshTo(exportFile);
|
||||||
break;
|
break;
|
||||||
@ -532,9 +542,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::EXPORT_SURFACES: {
|
case Command::EXPORT_SURFACES: {
|
||||||
Platform::Path exportFile = SS.saveFile;
|
Platform::Path exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SurfacesExportFormat"),
|
if(!GetSaveFile(&exportFile,
|
||||||
|
Platform::GetSettings()->ThawString("SurfacesExportFormat"),
|
||||||
SurfaceFileFilter)) break;
|
SurfaceFileFilter)) break;
|
||||||
CnfFreezeString(exportFile.Extension(), "SurfacesExportFormat");
|
settings->FreezeString("SurfacesExportFormat", exportFile.Extension());
|
||||||
|
|
||||||
StepFileWriter sfw = {};
|
StepFileWriter sfw = {};
|
||||||
sfw.ExportSurfacesTo(exportFile);
|
sfw.ExportSurfacesTo(exportFile);
|
||||||
@ -543,9 +554,10 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||||||
|
|
||||||
case Command::IMPORT: {
|
case Command::IMPORT: {
|
||||||
Platform::Path importFile;
|
Platform::Path importFile;
|
||||||
if(!GetOpenFile(&importFile, CnfThawString("", "ImportFormat"),
|
if(!GetOpenFile(&importFile,
|
||||||
|
Platform::GetSettings()->ThawString("ImportFormat"),
|
||||||
ImportableFileFilter)) break;
|
ImportableFileFilter)) break;
|
||||||
CnfFreezeString(importFile.Extension(), "ImportFormat");
|
settings->FreezeString("ImportFormat", importFile.Extension());
|
||||||
|
|
||||||
if(importFile.HasExtension("dxf")) {
|
if(importFile.HasExtension("dxf")) {
|
||||||
ImportDxf(importFile);
|
ImportDxf(importFile);
|
||||||
|
@ -173,13 +173,6 @@ void dbp(const char *str, ...);
|
|||||||
void SetMousePointerToHand(bool yes);
|
void SetMousePointerToHand(bool yes);
|
||||||
void DoMessageBox(const char *str, int rows, int cols, bool error);
|
void DoMessageBox(const char *str, int rows, int cols, bool error);
|
||||||
|
|
||||||
void CnfFreezeInt(uint32_t val, const std::string &name);
|
|
||||||
void CnfFreezeFloat(float val, const std::string &name);
|
|
||||||
void CnfFreezeString(const std::string &val, const std::string &name);
|
|
||||||
std::string CnfThawString(const std::string &val, const std::string &name);
|
|
||||||
uint32_t CnfThawInt(uint32_t val, const std::string &name);
|
|
||||||
float CnfThawFloat(float val, const std::string &name);
|
|
||||||
|
|
||||||
std::vector<std::string> InitPlatform(int argc, char **argv);
|
std::vector<std::string> InitPlatform(int argc, char **argv);
|
||||||
|
|
||||||
void *AllocTemporary(size_t n);
|
void *AllocTemporary(size_t n);
|
||||||
@ -263,10 +256,6 @@ void MultMatrix(double *mata, double *matb, double *matr);
|
|||||||
int64_t GetMilliseconds();
|
int64_t GetMilliseconds();
|
||||||
void Message(const char *str, ...);
|
void Message(const char *str, ...);
|
||||||
void Error(const char *str, ...);
|
void Error(const char *str, ...);
|
||||||
void CnfFreezeBool(bool v, const std::string &name);
|
|
||||||
void CnfFreezeColor(RgbaColor v, const std::string &name);
|
|
||||||
bool CnfThawBool(bool v, const std::string &name);
|
|
||||||
RgbaColor CnfThawColor(RgbaColor v, const std::string &name);
|
|
||||||
|
|
||||||
class System {
|
class System {
|
||||||
public:
|
public:
|
||||||
|
@ -81,12 +81,18 @@ void Style::CreateDefaultStyle(hStyle h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
|
void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
|
||||||
|
Platform::SettingsRef settings = Platform::GetSettings();
|
||||||
|
|
||||||
if(d == NULL) d = &Defaults[0];
|
if(d == NULL) d = &Defaults[0];
|
||||||
s->color = (factory) ? d->color : CnfThawColor(d->color, CnfColor(d->cnfPrefix));
|
s->color = (factory)
|
||||||
s->width = (factory) ? d->width : CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
? d->color
|
||||||
|
: settings->ThawColor(CnfColor(d->cnfPrefix), d->color);
|
||||||
|
s->width = (factory)
|
||||||
|
? d->width
|
||||||
|
: settings->ThawFloat(CnfWidth(d->cnfPrefix), (float)(d->width));
|
||||||
s->widthAs = UnitsAs::PIXELS;
|
s->widthAs = UnitsAs::PIXELS;
|
||||||
s->textHeight = (factory) ? 11.5
|
s->textHeight = (factory) ? 11.5
|
||||||
: CnfThawFloat(11.5, CnfTextHeight(d->cnfPrefix));
|
: settings->ThawFloat(CnfTextHeight(d->cnfPrefix), 11.5);
|
||||||
s->textHeightAs = UnitsAs::PIXELS;
|
s->textHeightAs = UnitsAs::PIXELS;
|
||||||
s->textOrigin = TextOrigin::NONE;
|
s->textOrigin = TextOrigin::NONE;
|
||||||
s->textAngle = 0;
|
s->textAngle = 0;
|
||||||
@ -109,12 +115,12 @@ void Style::LoadFactoryDefaults() {
|
|||||||
SS.backgroundColor = RGBi(0, 0, 0);
|
SS.backgroundColor = RGBi(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Style::FreezeDefaultStyles() {
|
void Style::FreezeDefaultStyles(Platform::SettingsRef settings) {
|
||||||
const Default *d;
|
const Default *d;
|
||||||
for(d = &(Defaults[0]); d->h.v; d++) {
|
for(d = &(Defaults[0]); d->h.v; d++) {
|
||||||
CnfFreezeColor(Color(d->h), CnfColor(d->cnfPrefix));
|
settings->FreezeColor(CnfColor(d->cnfPrefix), Color(d->h));
|
||||||
CnfFreezeFloat((float)Width(d->h), CnfWidth(d->cnfPrefix));
|
settings->FreezeFloat(CnfWidth(d->cnfPrefix), (float)Width(d->h));
|
||||||
CnfFreezeFloat((float)TextHeight(d->h), CnfTextHeight(d->cnfPrefix));
|
settings->FreezeFloat(CnfTextHeight(d->cnfPrefix), (float)TextHeight(d->h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/util.cpp
12
src/util.cpp
@ -173,18 +173,6 @@ void SolveSpace::Message(const char *str, ...)
|
|||||||
va_end(f);
|
va_end(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::CnfFreezeBool(bool v, const std::string &name)
|
|
||||||
{ CnfFreezeInt(v ? 1 : 0, name); }
|
|
||||||
|
|
||||||
void SolveSpace::CnfFreezeColor(RgbaColor v, const std::string &name)
|
|
||||||
{ CnfFreezeInt(v.ToPackedInt(), name); }
|
|
||||||
|
|
||||||
bool SolveSpace::CnfThawBool(bool v, const std::string &name)
|
|
||||||
{ return CnfThawInt(v ? 1 : 0, name) != 0; }
|
|
||||||
|
|
||||||
RgbaColor SolveSpace::CnfThawColor(RgbaColor v, const std::string &name)
|
|
||||||
{ return RgbaColor::FromPackedInt(CnfThawInt(v.ToPackedInt(), name)); }
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Solve a mostly banded matrix. In a given row, there are LEFT_OF_DIAG
|
// Solve a mostly banded matrix. In a given row, there are LEFT_OF_DIAG
|
||||||
// elements to the left of the diagonal element, and RIGHT_OF_DIAG elements to
|
// elements to the left of the diagonal element, and RIGHT_OF_DIAG elements to
|
||||||
|
Loading…
Reference in New Issue
Block a user