Use spin controls for numeric fields in the style editor

Closes #1741.
This commit is contained in:
Thomas Goyne 2014-04-28 07:07:07 -07:00
parent 63f4bf1beb
commit c74045cf20
6 changed files with 82 additions and 78 deletions

View File

@ -208,9 +208,9 @@ namespace Automation4 {
bool use_buttons; bool use_buttons;
/// Id of the button pushed (once a button has been pushed) /// Id of the button pushed (once a button has been pushed)
int button_pushed; int button_pushed = -1;
wxWindow *window; wxWindow *window = nullptr;
public: public:
LuaDialog(lua_State *L, bool include_buttons); LuaDialog(lua_State *L, bool include_buttons);

View File

@ -162,13 +162,12 @@ namespace Automation4 {
class Edit : public LuaDialogControl { class Edit : public LuaDialogControl {
protected: protected:
std::string text; std::string text;
wxTextCtrl *cw; wxTextCtrl *cw = nullptr;
public: public:
Edit(lua_State *L) Edit(lua_State *L)
: LuaDialogControl(L) : LuaDialogControl(L)
, text(get_field(L, "value")) , text(get_field(L, "value"))
, cw(nullptr)
{ {
// Undocumented behaviour, 'value' is also accepted as key for text, // Undocumented behaviour, 'value' is also accepted as key for text,
// mostly so a text control can stand in for other things. // mostly so a text control can stand in for other things.
@ -237,14 +236,13 @@ namespace Automation4 {
/// Integer only edit /// Integer only edit
class IntEdit final : public Edit { class IntEdit final : public Edit {
wxSpinCtrl *cw; wxSpinCtrl *cw = nullptr;
int value; int value;
int min, max; int min, max;
public: public:
IntEdit(lua_State *L) IntEdit(lua_State *L)
: Edit(L) : Edit(L)
, cw(nullptr)
, value(get_field(L, "value", 0)) , value(get_field(L, "value", 0))
, min(get_field(L, "min", INT_MIN)) , min(get_field(L, "min", INT_MIN))
, max(get_field(L, "max", INT_MAX)) , max(get_field(L, "max", INT_MAX))
@ -277,29 +275,7 @@ namespace Automation4 {
double min; double min;
double max; double max;
double step; double step;
wxSpinCtrlDouble *scd; wxSpinCtrlDouble *scd = nullptr;
struct DoubleValidator final : public wxValidator {
double *value;
DoubleValidator(double *value) : value(value) { }
wxValidator *Clone() const override { return new DoubleValidator(value); }
bool Validate(wxWindow*) override { return true; }
bool TransferToWindow() override {
static_cast<wxSpinCtrlDouble*>(GetWindow())->SetValue(*value);
return true;
}
bool TransferFromWindow() override {
auto ctrl = static_cast<wxSpinCtrlDouble*>(GetWindow());
#ifndef wxHAS_NATIVE_SPINCTRLDOUBLE
wxFocusEvent evt;
ctrl->OnTextLostFocus(evt);
#endif
*value = ctrl->GetValue();
return true;
}
};
public: public:
FloatEdit(lua_State *L) FloatEdit(lua_State *L)
@ -308,7 +284,6 @@ namespace Automation4 {
, min(get_field(L, "min", -DBL_MAX)) , min(get_field(L, "min", -DBL_MAX))
, max(get_field(L, "max", DBL_MAX)) , max(get_field(L, "max", DBL_MAX))
, step(get_field(L, "step", 0.0)) , step(get_field(L, "step", 0.0))
, scd(nullptr)
{ {
if (min >= max) { if (min >= max) {
max = DBL_MAX; max = DBL_MAX;
@ -323,13 +298,12 @@ namespace Automation4 {
wxControl *Create(wxWindow *parent) override { wxControl *Create(wxWindow *parent) override {
if (step > 0) { if (step > 0) {
scd = new wxSpinCtrlDouble(parent, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, min, max, value, step); scd = new wxSpinCtrlDouble(parent, -1, "", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, min, max, value, step);
scd->SetValidator(DoubleValidator(&value)); scd->SetValidator(DoubleSpinValidator(&value));
scd->SetToolTip(to_wx(hint)); scd->SetToolTip(to_wx(hint));
return scd; return scd;
} }
::DoubleValidator val(&value, min, max); DoubleValidator val(&value, min, max);
cw = new wxTextCtrl(parent, -1, "", wxDefaultPosition, wxDefaultSize, 0, val); cw = new wxTextCtrl(parent, -1, "", wxDefaultPosition, wxDefaultSize, 0, val);
cw->SetToolTip(to_wx(hint)); cw->SetToolTip(to_wx(hint));
return cw; return cw;
@ -344,13 +318,12 @@ namespace Automation4 {
class Dropdown final : public LuaDialogControl { class Dropdown final : public LuaDialogControl {
std::vector<std::string> items; std::vector<std::string> items;
std::string value; std::string value;
wxComboBox *cw; wxComboBox *cw = nullptr;
public: public:
Dropdown(lua_State *L) Dropdown(lua_State *L)
: LuaDialogControl(L) : LuaDialogControl(L)
, value(get_field(L, "value")) , value(get_field(L, "value"))
, cw(nullptr)
{ {
lua_getfield(L, -1, "items"); lua_getfield(L, -1, "items");
read_string_array(L, items); read_string_array(L, items);
@ -374,14 +347,13 @@ namespace Automation4 {
class Checkbox final : public LuaDialogControl { class Checkbox final : public LuaDialogControl {
std::string label; std::string label;
bool value; bool value;
wxCheckBox *cw; wxCheckBox *cw = nullptr;
public: public:
Checkbox(lua_State *L) Checkbox(lua_State *L)
: LuaDialogControl(L) : LuaDialogControl(L)
, label(get_field(L, "label")) , label(get_field(L, "label"))
, value(get_field(L, "value", false)) , value(get_field(L, "value", false))
, cw(nullptr)
{ {
} }
@ -406,8 +378,6 @@ namespace Automation4 {
// LuaDialog // LuaDialog
LuaDialog::LuaDialog(lua_State *L, bool include_buttons) LuaDialog::LuaDialog(lua_State *L, bool include_buttons)
: use_buttons(include_buttons) : use_buttons(include_buttons)
, button_pushed(-1)
, window(nullptr)
{ {
LOG_D("automation/lua/dialog") << "creating LuaDialoug, addr: " << this; LOG_D("automation/lua/dialog") << "creating LuaDialoug, addr: " << this;

View File

@ -64,8 +64,8 @@
/// updating references to it /// updating references to it
class StyleRenamer { class StyleRenamer {
agi::Context *c; agi::Context *c;
bool found_any; bool found_any = false;
bool do_replace; bool do_replace = false;
std::string source_name; std::string source_name;
std::string new_name; std::string new_name;
@ -105,8 +105,6 @@ class StyleRenamer {
public: public:
StyleRenamer(agi::Context *c, std::string source_name, std::string new_name) StyleRenamer(agi::Context *c, std::string source_name, std::string new_name)
: c(c) : c(c)
, found_any(false)
, do_replace(false)
, source_name(std::move(source_name)) , source_name(std::move(source_name))
, new_name(std::move(new_name)) , new_name(std::move(new_name))
{ {
@ -124,19 +122,6 @@ public:
} }
}; };
static void add_with_label(wxSizer *sizer, wxWindow *parent, wxString const& label, wxWindow *ctrl) {
sizer->Add(new wxStaticText(parent, -1, label), wxSizerFlags().Center().Right().Border(wxLEFT | wxRIGHT));
sizer->Add(ctrl, wxSizerFlags(1).Left().Expand());
}
static wxSpinCtrl *spin_ctrl(wxWindow *parent, float value, int max_value) {
return new wxSpinCtrl(parent, -1, wxString::Format("%g", value), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 0, max_value, value);
}
static wxTextCtrl *num_text_ctrl(wxWindow *parent, double *value, bool allow_negative, wxSize size = wxSize(70, 20)) {
return new wxTextCtrl(parent, -1, "", wxDefaultPosition, size, 0, DoubleValidator(value, allow_negative));
}
DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Context *c, AssStyleStorage *store, std::string const& new_name, wxArrayString const& font_list) DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Context *c, AssStyleStorage *store, std::string const& new_name, wxArrayString const& font_list)
: wxDialog (parent, -1, _("Style Editor"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) : wxDialog (parent, -1, _("Style Editor"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
, c(c) , c(c)
@ -157,6 +142,32 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
SetIcon(GETICON(style_toolbutton_16)); SetIcon(GETICON(style_toolbutton_16));
auto add_with_label = [&](wxSizer *sizer, wxString const& label, wxWindow *ctrl) {
sizer->Add(new wxStaticText(this, -1, label), wxSizerFlags().Center().Right().Border(wxLEFT | wxRIGHT));
sizer->Add(ctrl, wxSizerFlags(1).Left().Expand());
};
auto spin_ctrl = [&](float value, int max_value) {
return new wxSpinCtrl(this, -1, wxString::Format("%g", value), wxDefaultPosition, wxSize(60, -1), wxSP_ARROW_KEYS, 0, max_value, value);
};
auto num_text_ctrl = [&](double *value, double min, double max, double step) -> wxSpinCtrlDouble * {
auto scd = new wxSpinCtrlDouble(this, -1, "", wxDefaultPosition,
wxSize(75, -1), wxSP_ARROW_KEYS, min, max, *value, step);
scd->SetValidator(DoubleSpinValidator(value));
scd->Bind(wxEVT_SPINCTRLDOUBLE, [=](wxSpinDoubleEvent &evt) {
evt.Skip();
if (updating) return;
bool old = updating;
updating = true;
scd->GetValidator()->TransferFromWindow();
updating = old;
SubsPreview->SetStyle(*work);
});
return scd;
};
// Prepare control values // Prepare control values
wxString EncodingValue = std::to_wstring(style->encoding); wxString EncodingValue = std::to_wstring(style->encoding);
wxString alignValues[9] = { "7", "8", "9", "4", "5", "6", "1", "2", "3" }; wxString alignValues[9] = { "7", "8", "9", "4", "5", "6", "1", "2", "3" };
@ -177,7 +188,7 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
// Create controls // Create controls
StyleName = new wxTextCtrl(this, -1, to_wx(style->name)); StyleName = new wxTextCtrl(this, -1, to_wx(style->name));
FontName = new wxComboBox(this, -1, to_wx(style->font), wxDefaultPosition, wxSize(150, -1), 0, nullptr, wxCB_DROPDOWN); FontName = new wxComboBox(this, -1, to_wx(style->font), wxDefaultPosition, wxSize(150, -1), 0, nullptr, wxCB_DROPDOWN);
FontSize = num_text_ctrl(this, &work->fontsize, false, wxSize(50, -1)); auto FontSize = num_text_ctrl(&work->fontsize, 0, 10000.0, 1.0);
BoxBold = new wxCheckBox(this, -1, _("&Bold")); BoxBold = new wxCheckBox(this, -1, _("&Bold"));
BoxItalic = new wxCheckBox(this, -1, _("&Italic")); BoxItalic = new wxCheckBox(this, -1, _("&Italic"));
BoxUnderline = new wxCheckBox(this, -1, _("&Underline")); BoxUnderline = new wxCheckBox(this, -1, _("&Underline"));
@ -189,15 +200,15 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
new ColourButton(this, wxSize(55, 16), true, style->shadow, ColorValidator(&work->shadow)) new ColourButton(this, wxSize(55, 16), true, style->shadow, ColorValidator(&work->shadow))
}; };
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
margin[i] = spin_ctrl(this, style->Margin[i], 9999); margin[i] = spin_ctrl(style->Margin[i], 9999);
Alignment = new wxRadioBox(this, -1, _("Alignment"), wxDefaultPosition, wxDefaultSize, 9, alignValues, 3, wxRA_SPECIFY_COLS); Alignment = new wxRadioBox(this, -1, _("Alignment"), wxDefaultPosition, wxDefaultSize, 9, alignValues, 3, wxRA_SPECIFY_COLS);
Outline = num_text_ctrl(this, &work->outline_w, false, wxSize(50, -1)); auto Outline = num_text_ctrl(&work->outline_w, 0.0, 1000.0, 0.1);
Shadow = num_text_ctrl(this, &work->shadow_w, true, wxSize(50, -1)); auto Shadow = num_text_ctrl(&work->shadow_w, 0.0, 1000.0, 0.1);
OutlineType = new wxCheckBox(this, -1, _("&Opaque box")); OutlineType = new wxCheckBox(this, -1, _("&Opaque box"));
ScaleX = num_text_ctrl(this, &work->scalex, false); auto ScaleX = num_text_ctrl(&work->scalex, 0.0, 10000.0, 1.0);
ScaleY = num_text_ctrl(this, &work->scaley, false); auto ScaleY = num_text_ctrl(&work->scaley, 0.0, 10000.0, 1.0);
Angle = num_text_ctrl(this, &work->angle, true); auto Angle = num_text_ctrl(&work->angle, -180.0, 180.0, 1.0);
Spacing = num_text_ctrl(this, &work->spacing, true); auto Spacing = num_text_ctrl(&work->spacing, 0.0, 1000.0, 0.1);
Encoding = new wxComboBox(this, -1, "", wxDefaultPosition, wxDefaultSize, encodingStrings, wxCB_READONLY); Encoding = new wxComboBox(this, -1, "", wxDefaultPosition, wxDefaultSize, encodingStrings, wxCB_READONLY);
// Set control tooltips // Set control tooltips
@ -292,19 +303,19 @@ DialogStyleEditor::DialogStyleEditor(wxWindow *parent, AssStyle *style, agi::Con
MarginAlign->Add(Alignment, 0, wxLEFT | wxEXPAND, 5); MarginAlign->Add(Alignment, 0, wxLEFT | wxEXPAND, 5);
// Outline // Outline
add_with_label(OutlineBox, this, _("Outline:"), Outline); add_with_label(OutlineBox, _("Outline:"), Outline);
add_with_label(OutlineBox, this, _("Shadow:"), Shadow); add_with_label(OutlineBox, _("Shadow:"), Shadow);
OutlineBox->Add(OutlineType, 0, wxLEFT | wxALIGN_CENTER, 5); OutlineBox->Add(OutlineType, 0, wxLEFT | wxALIGN_CENTER, 5);
// Misc // Misc
auto MiscBoxTop = new wxFlexGridSizer(2, 4, 5, 5); auto MiscBoxTop = new wxFlexGridSizer(2, 4, 5, 5);
add_with_label(MiscBoxTop, this, _("Scale X%:"), ScaleX); add_with_label(MiscBoxTop, _("Scale X%:"), ScaleX);
add_with_label(MiscBoxTop, this, _("Scale Y%:"), ScaleY); add_with_label(MiscBoxTop, _("Scale Y%:"), ScaleY);
add_with_label(MiscBoxTop, this, _("Rotation:"), Angle); add_with_label(MiscBoxTop, _("Rotation:"), Angle);
add_with_label(MiscBoxTop, this, _("Spacing:"), Spacing); add_with_label(MiscBoxTop, _("Spacing:"), Spacing);
wxSizer *MiscBoxBottom = new wxBoxSizer(wxHORIZONTAL); wxSizer *MiscBoxBottom = new wxBoxSizer(wxHORIZONTAL);
add_with_label(MiscBoxBottom, this, _("Encoding:"), Encoding); add_with_label(MiscBoxBottom, _("Encoding:"), Encoding);
MiscBox->Add(MiscBoxTop, wxSizerFlags().Expand().Center()); MiscBox->Add(MiscBoxTop, wxSizerFlags().Expand().Center());
MiscBox->Add(MiscBoxBottom, wxSizerFlags().Expand().Center().Border(wxTOP)); MiscBox->Add(MiscBoxBottom, wxSizerFlags().Expand().Center().Border(wxTOP));
@ -453,7 +464,9 @@ void DialogStyleEditor::Apply(bool apply, bool close) {
} }
void DialogStyleEditor::UpdateWorkStyle() { void DialogStyleEditor::UpdateWorkStyle() {
updating = true;
TransferDataFromWindow(); TransferDataFromWindow();
updating = false;
work->font = from_wx(FontName->GetValue()); work->font = from_wx(FontName->GetValue());

View File

@ -56,6 +56,8 @@ class DialogStyleEditor final : public wxDialog {
/// the style /// the style
bool is_new = false; bool is_new = false;
bool updating = false;
/// The style currently being edited /// The style currently being edited
AssStyle *style; AssStyle *style;
@ -68,21 +70,14 @@ class DialogStyleEditor final : public wxDialog {
wxTextCtrl *StyleName; wxTextCtrl *StyleName;
wxComboBox *FontName; wxComboBox *FontName;
wxTextCtrl *FontSize;
wxCheckBox *BoxBold; wxCheckBox *BoxBold;
wxCheckBox *BoxItalic; wxCheckBox *BoxItalic;
wxCheckBox *BoxUnderline; wxCheckBox *BoxUnderline;
wxCheckBox *BoxStrikeout; wxCheckBox *BoxStrikeout;
wxSpinCtrl *margin[3]; wxSpinCtrl *margin[3];
wxRadioBox *Alignment; wxRadioBox *Alignment;
wxTextCtrl *Outline;
wxTextCtrl *Shadow;
wxCheckBox *OutlineType; wxCheckBox *OutlineType;
wxTextCtrl *ScaleX;
wxTextCtrl *ScaleY;
wxTextCtrl *Angle;
wxComboBox *Encoding; wxComboBox *Encoding;
wxTextCtrl *Spacing;
wxTextCtrl *PreviewText; wxTextCtrl *PreviewText;
SubtitlesPreview *SubsPreview; SubtitlesPreview *SubsPreview;

View File

@ -153,6 +153,21 @@ bool DoubleValidator::TransferFromWindow() {
return true; return true;
} }
bool DoubleSpinValidator::TransferToWindow() {
static_cast<wxSpinCtrlDouble*>(GetWindow())->SetValue(*value);
return true;
}
bool DoubleSpinValidator::TransferFromWindow() {
auto ctrl = static_cast<wxSpinCtrlDouble*>(GetWindow());
#ifndef wxHAS_NATIVE_SPINCTRLDOUBLE
wxFocusEvent evt;
ctrl->OnTextLostFocus(evt);
#endif
*value = ctrl->GetValue();
return true;
}
bool StringBinder::TransferFromWindow() { bool StringBinder::TransferFromWindow() {
wxWindow *window = GetWindow(); wxWindow *window = GetWindow();
if (wxTextCtrl *ctrl = dynamic_cast<wxTextCtrl*>(window)) if (wxTextCtrl *ctrl = dynamic_cast<wxTextCtrl*>(window))

View File

@ -60,6 +60,17 @@ public:
explicit DoubleValidator(double *val, double min, double max); explicit DoubleValidator(double *val, double min, double max);
}; };
class DoubleSpinValidator final : public wxValidator {
double *value;
wxValidator *Clone() const override { return new DoubleSpinValidator(value); }
bool Validate(wxWindow*) override { return true; }
bool TransferToWindow() override;
bool TransferFromWindow() override;
public:
DoubleSpinValidator(double *value) : value(value) { }
};
template<typename T> template<typename T>
class EnumBinder final : public wxValidator { class EnumBinder final : public wxValidator {
T *value; T *value;