Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/colour_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class ColourButton: public wxButton {

/// Get the currently selected color
agi::Color GetColor() { return colour; }

/// Set the currently selected color
void SetColor(agi::Color color) {
colour = color;
UpdateBitmap();
};
};

struct ColorValidator final : public wxValidator {
Expand Down
181 changes: 179 additions & 2 deletions src/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
/// @file preferences.cpp
/// @brief Preferences dialogue
/// @ingroup configuration_ui

#include "preferences.h"

#include "ass_style_storage.h"
Expand All @@ -41,14 +40,18 @@
#include <ffms.h>
#endif

#include "colour_button.h"
#include <libaegisub/cajun/visitor.h>
#include <libaegisub/hotkey.h>
#include <libaegisub/json.h>

#include <unordered_set>

#include <wx/checkbox.h>
#include <wx/combobox.h>
#include <wx/dc.h>
#include <wx/event.h>
#include <wx/filedlg.h>
#include <wx/listctrl.h>
#include <wx/msgdlg.h>
#include <wx/srchctrl.h>
Expand Down Expand Up @@ -241,6 +244,95 @@ void Interface(wxTreebook *book, Preferences *parent) {
p->SetSizerAndFit(p->sizer);
}

struct ThemeImportVisitor final : json::ConstVisitor {
std::string prefix;
Preferences* parent;
ThemeImportVisitor(std::string prefix, Preferences* parent)
: prefix(std::move(prefix))
, parent(parent)
{
}

void Visit(const json::Object& obj) override
{
for (auto const& pair : obj) {
std::string path = prefix;
if (!path.empty())
path += "/";
path += pair.first;

ThemeImportVisitor sub(path, parent);
pair.second.Accept(sub);
}
}

void Visit(const json::Array&) override { }
void Visit(int64_t val) override
{
try {
if (config::opt->Get(prefix)) {
parent->SetOption(std::make_unique<agi::OptionValueInt>(prefix, val));
parent->RefreshControl(prefix);
}
} catch (...) {
}
}
void Visit(double val) override
{
try {
if (config::opt->Get(prefix)) {
parent->SetOption(std::make_unique<agi::OptionValueDouble>(prefix, val));
parent->RefreshControl(prefix);
}
} catch (...) {
}
}
void Visit(const json::String& val) override
{
try {
auto opt = config::opt->Get(prefix);
if (opt->GetType() == agi::OptionType::Color) {
parent->SetOption(std::make_unique<agi::OptionValueColor>(prefix, agi::Color(val)));
} else {
parent->SetOption(std::make_unique<agi::OptionValueString>(prefix, val));
}
parent->RefreshControl(prefix);
wxSafeYield(); // Update UI during loop
} catch (...) {
}
}
void Visit(bool val) override
{
try {
if (config::opt->Get(prefix)) {
parent->SetOption(std::make_unique<agi::OptionValueBool>(prefix, val));
parent->RefreshControl(prefix);
}
} catch (...) {
}
}
void Visit(const json::Null&) override { }
};

void OnImportTheme(wxWindow* parent) {
wxFileDialog dlg(parent, _("Select Theme File"), "", "", "JSON files (*.json)|*.json", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (dlg.ShowModal() == wxID_CANCEL)
return;

try {
auto root = agi::json_util::file(agi::fs::path(dlg.GetPath().ToStdString()), "{}");
ThemeImportVisitor tv("Colour", static_cast<Preferences*>(parent));
root.Accept(tv);

parent->Refresh();
parent->Update();
} catch (agi::Exception const& e) {
wxMessageBox(to_wx(e.GetMessage()), _("Error importing theme"), wxOK | wxICON_ERROR);
} catch (...) {
wxMessageBox(_("Unknown error importing theme"), _("Error importing theme"), wxOK | wxICON_ERROR);
}
}

/// Interface Colours preferences subpage
void Interface_Colours(wxTreebook *book, Preferences *parent) {
auto p = new OptionPage(book, parent, _("Colors"), OptionPage::PAGE_SCROLL|OptionPage::PAGE_SUB);
Expand Down Expand Up @@ -314,7 +406,19 @@ void Interface_Colours(wxTreebook *book, Preferences *parent) {

p->sizer = main_sizer;

p->SetSizerAndFit(p->sizer);
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
auto import_btn = new wxButton(p, -1, _("Import Theme..."));
import_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { OnImportTheme(parent); });
btn_sizer->Add(import_btn, 0, wxALL, 5);
auto reset_btn = new wxButton(p, -1, _("Reset Colors"));
reset_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { parent->ResetColors(); });
btn_sizer->Add(reset_btn, 0, wxALL, 5);
auto wrapper = new wxBoxSizer(wxVERTICAL);
wrapper->Add(main_sizer, 1, wxEXPAND);
wrapper->Add(btn_sizer, 0, wxALIGN_CENTER);
p->sizer = wrapper;
p->SetSizerAndFit(p->sizer);

}

/// Backup preferences page
Expand Down Expand Up @@ -722,6 +826,78 @@ void Preferences::OnResetDefault(wxCommandEvent&) {
EndModal(-1);
}

void Preferences::RefreshControl(std::string const& name)
{
auto it = option_controls.find(name);
if (it == option_controls.end())
return;

agi::OptionValue* opt = nullptr;
auto pending_it = pending_changes.find(name);
if (pending_it != pending_changes.end())
opt = pending_it->second.get();
else {
try {
opt = config::opt->Get(name);
} catch (...) {
return;
}
}

if (!opt)
return;

wxControl* ctrl = it->second;
switch (opt->GetType()) {
case agi::OptionType::Bool:
if (auto cb = dynamic_cast<wxCheckBox*>(ctrl))
cb->SetValue(opt->GetBool());
break;
case agi::OptionType::Int:
if (auto sc = dynamic_cast<wxSpinCtrl*>(ctrl))
sc->SetValue((int)opt->GetInt());
else if (auto cb = dynamic_cast<wxComboBox*>(ctrl))
cb->SetSelection((int)opt->GetInt());
break;
case agi::OptionType::Double:
if (auto scd = dynamic_cast<wxSpinCtrlDouble*>(ctrl))
scd->SetValue(opt->GetDouble());
break;
case agi::OptionType::String:
if (auto tc = dynamic_cast<wxTextCtrl*>(ctrl))
tc->SetValue(to_wx(opt->GetString()));
else if (auto cb = dynamic_cast<wxComboBox*>(ctrl))
cb->SetStringSelection(to_wx(opt->GetString()));
break;
case agi::OptionType::Color:
if (auto cb = dynamic_cast<ColourButton*>(ctrl)) {
cb->SetColor(opt->GetColor());
cb->Update();
}
break;
default:
break;
}
}

void Preferences::RegisterControl(std::string const& name, wxControl* control) { option_controls[name] = control; }

void Preferences::ResetColors()
{
if (wxYES != wxMessageBox(_("Are you sure you want to reset all colors to their default values?"), _("Reset colors?"), wxYES_NO | wxICON_QUESTION, this))
return;
for (auto const& opt_name : option_names) {
if (opt_name.compare(0, 7, "Colour/") == 0) {
agi::OptionValue* opt = OPT_SET(opt_name);
if (!opt->IsDefault()) {
opt->Reset();
RefreshControl(opt_name);
}
}
}
applyButton->Enable(true);

}
Preferences::Preferences(wxWindow *parent): wxDialog(parent, -1, _("Preferences"), wxDefaultPosition, wxSize(-1, -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
SetIcons(GETICONS(options_button));

Expand Down Expand Up @@ -773,4 +949,5 @@ Preferences::Preferences(wxWindow *parent): wxDialog(parent, -1, _("Preferences"

void ShowPreferences(wxWindow *parent) {
while (Preferences(parent).ShowModal() < 0);

}
14 changes: 14 additions & 0 deletions src/preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <wx/dialog.h>

class wxButton;
class wxControl;
class wxTreebook;
namespace agi { class OptionValue; }

Expand All @@ -36,6 +37,7 @@ class Preferences final : public wxDialog {
wxButton *applyButton;

std::map<std::string, std::unique_ptr<agi::OptionValue>> pending_changes;
std::map<std::string, wxControl*> option_controls;
std::vector<Thunk> pending_callbacks;
std::vector<std::string> option_names;

Expand All @@ -62,4 +64,16 @@ class Preferences final : public wxDialog {
/// simply revert to the default config file as a bunch of things other than
/// user options are stored in it. Perhaps that should change in the future.
void AddChangeableOption(std::string const& name);

/// Refresh the UI control for an option
/// @param name Name of the option to refresh
void RefreshControl(std::string const& name);

/// Add a control to the list of controls for an option
/// @param name Name of the option
/// @param control Control to add
void RegisterControl(std::string const& name, wxControl *control);

/// Reset all color options to their default values
void ResetColors();
};
1 change: 1 addition & 0 deletions src/preferences_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ wxControl *OptionPage::OptionAdd(PageSection section, const wxString &name, cons
auto cb = new ColourButton(section.box, wxSize(40,10), false, opt->GetColor());
cb->Bind(EVT_COLOR, ColourUpdater(opt_name, parent));
Add(section, name, cb);
parent->RegisterControl(opt_name, cb);
return cb;
}

Expand Down
Loading