Ruby: configuration dialogs

Originally committed to SVN as r922.
This commit is contained in:
pomyk 2007-02-03 20:31:20 +00:00
parent 2f52b36910
commit 505e09257e
3 changed files with 244 additions and 256 deletions

View file

@ -55,7 +55,7 @@ namespace Automation4 {
RubyObjects *RubyObjects::inst = NULL; RubyObjects *RubyObjects::inst = NULL;
RubyScript * RubyScript::inst = NULL; // current Ruby Script RubyScript * RubyScript::inst = NULL; // current Ruby Script
RubyProgressSink* RubyProgressSink::inst = NULL; RubyProgressSink* RubyProgressSink::inst = NULL;
VALUE RubyScript::RubyAegisub; VALUE RubyScript::RubyAegisub = Qfalse;
// RubyAssFile *RubyAssFile::raf = NULL; // RubyAssFile *RubyAssFile::raf = NULL;
// RubyScriptReader // RubyScriptReader
@ -115,6 +115,7 @@ namespace Automation4 {
ruby_init(); ruby_init();
ruby_init_loadpath(); ruby_init_loadpath();
RubyScript::inst = this; RubyScript::inst = this;
if(!RubyAegisub) {
RubyAegisub = rb_define_module("Aegisub"); RubyAegisub = rb_define_module("Aegisub");
rb_define_module_function(RubyAegisub, "register_macro",reinterpret_cast<RB_HOOK>(&RubyFeatureMacro::RubyRegister), 4); rb_define_module_function(RubyAegisub, "register_macro",reinterpret_cast<RB_HOOK>(&RubyFeatureMacro::RubyRegister), 4);
rb_define_module_function(RubyAegisub, "register_filter",reinterpret_cast<RB_HOOK>(&RubyFeatureFilter::RubyRegister), 5); rb_define_module_function(RubyAegisub, "register_filter",reinterpret_cast<RB_HOOK>(&RubyFeatureFilter::RubyRegister), 5);
@ -124,6 +125,8 @@ namespace Automation4 {
rb_define_module_function(RubyScript::RubyAegisub, "progress_title",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubySetTitle), 1); rb_define_module_function(RubyScript::RubyAegisub, "progress_title",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubySetTitle), 1);
rb_define_module_function(RubyScript::RubyAegisub, "debug_out",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubyDebugOut), -1); rb_define_module_function(RubyScript::RubyAegisub, "debug_out",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubyDebugOut), -1);
rb_define_module_function(RubyScript::RubyAegisub, "get_cancelled",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubyGetCancelled), 0); rb_define_module_function(RubyScript::RubyAegisub, "get_cancelled",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubyGetCancelled), 0);
rb_define_module_function(RubyScript::RubyAegisub, "display_dialog",reinterpret_cast<RB_HOOK>(&RubyProgressSink::RubyDisplayDialog), 2);
}
VALUE paths = rb_gv_get("$:"); VALUE paths = rb_gv_get("$:");
for(int i = 0; i < include_path.GetCount(); i++) for(int i = 0; i < include_path.GetCount(); i++)
{ {
@ -138,7 +141,9 @@ namespace Automation4 {
if(status > 0) // something bad happened (probably parsing error) if(status > 0) // something bad happened (probably parsing error)
{ {
VALUE err = rb_errinfo(); VALUE err = rb_errinfo();
if(TYPE(err) == T_STRING)
throw StringValueCStr(err); throw StringValueCStr(err);
else throw "Error loading script";
} }
VALUE global_var = rb_gv_get("$script_name"); VALUE global_var = rb_gv_get("$script_name");
@ -166,11 +171,8 @@ namespace Automation4 {
void RubyScript::Destroy() void RubyScript::Destroy()
{ {
if(loaded) { if(loaded) {
ruby_finalize(); // ruby_finalize(); // broken in 1.9 ?_?
ruby_cleanup(0);
} }
// TODO: would be nice to implement this
// RubyObjects::Get()->UnregisterAll();
// remove features // remove features
for (int i = 0; i < (int)features.size(); i++) { for (int i = 0; i < (int)features.size(); i++) {
@ -324,6 +326,7 @@ namespace Automation4 {
RubyThreadedCall call(&arg, &result); RubyThreadedCall call(&arg, &result);
RubyProgressSink::inst->ShowModal(); RubyProgressSink::inst->ShowModal();
wxThread::ExitCode code = call.Wait(); wxThread::ExitCode code = call.Wait();
delete RubyProgressSink::inst;
RubyProgressSink::inst = NULL; RubyProgressSink::inst = NULL;
if(code) if(code)
{ {
@ -331,7 +334,7 @@ namespace Automation4 {
throw StringValueCStr(result); throw StringValueCStr(result);
else throw "Unknown Error"; else throw "Unknown Error";
} }
else if(result != Qnil && result != Qfalse) else if(TYPE(result) == T_ARRAY)
{ {
subsobj->RubyUpdateAssFile(result); subsobj->RubyUpdateAssFile(result);
} }
@ -404,27 +407,27 @@ namespace Automation4 {
void RubyFeatureFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog) void RubyFeatureFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog)
{ {
// TODO: configuration dialog
try { try {
VALUE cfg;
if (has_config && config_dialog) { if (has_config && config_dialog) {
assert(config_dialog->RubyReadBack() == 1); cfg = config_dialog->RubyReadBack();
// TODO, write back stored options here // TODO, write back stored options here
} }
delete RubyProgressSink::inst; // delete RubyProgressSink::inst;
RubyProgressSink::inst = new RubyProgressSink(export_dialog, false); // RubyProgressSink::inst = new RubyProgressSink(export_dialog, false);
RubyProgressSink::inst->SetTitle(GetName()); // RubyProgressSink::inst->SetTitle(GetName());
RubyAssFile *subsobj = new RubyAssFile(subs, true/*modify*/, false/*undo*/); RubyAssFile *subsobj = new RubyAssFile(subs, true/*modify*/, false/*undo*/);
VALUE *argv = ALLOCA_N(VALUE, 2); VALUE *argv = ALLOCA_N(VALUE, 2);
argv[0] = subsobj->rbAssFile; argv[0] = subsobj->rbAssFile;
argv[1] = Qnil; // config argv[1] = cfg; // config
RubyCallArguments arg(rb_mKernel, rb_to_id(filter_fun), 2, argv); RubyCallArguments arg(rb_mKernel, rb_to_id(filter_fun), 2, argv);
VALUE result; VALUE result;
RubyThreadedCall call(&arg, &result); delete RubyProgressSink::inst;
RubyProgressSink::inst->ShowModal();
wxThread::ExitCode code = call.Wait();
RubyProgressSink::inst = NULL; RubyProgressSink::inst = NULL;
RubyThreadedCall call(&arg, &result);
// RubyProgressSink::inst->ShowModal();
wxThread::ExitCode code = call.Wait();
if(code) if(code)
{ {
if(TYPE(result) == T_STRING) if(TYPE(result) == T_STRING)
@ -447,25 +450,26 @@ namespace Automation4 {
if (!has_config) if (!has_config)
return 0; return 0;
//GetFeatureFunction(2); // 2 = config dialog function
// prepare function call
// subtitles (don't allow any modifications during dialog creation, ideally the subs aren't even accessed)
// RubyAssFile *subsobj = new RubyAssFile(AssFile::top, false/*allow modifications*/, false/*disallow undo*/);
// stored options
/* if(RubyProgressSink::inst)
{
delete RubyProgressSink::inst; delete RubyProgressSink::inst;
RubyProgressSink::inst = NULL;
}
RubyProgressSink::inst = new RubyProgressSink(parent, false); RubyProgressSink::inst = new RubyProgressSink(parent, false);
RubyProgressSink::inst->SetTitle(GetName()); RubyProgressSink::inst->SetTitle(GetName());
// do call TODO // prepare function call
RubyProgressSink::inst->ShowModal(); // subtitles (don't allow any modifications during dialog creation, ideally the subs aren't even accessed)
RubyAssFile *subsobj = new RubyAssFile(AssFile::top, false/*allow modifications*/, false/*disallow undo*/);
*/ return config_dialog = new RubyConfigDialog(false); VALUE *argv = ALLOCA_N(VALUE, 2);
argv[0] = subsobj->rbAssFile;
argv[1] = Qnil; // TODO: stored options
RubyCallArguments arg(rb_mKernel, rb_to_id(dialog_fun), 2, argv);
VALUE dialog_data;
RubyThreadedCall call(&arg, &dialog_data);
RubyProgressSink::inst->ShowModal();
wxThread::ExitCode code = call.Wait();
delete RubyProgressSink::inst;
RubyProgressSink::inst = NULL;
return config_dialog = new RubyConfigDialog(dialog_data, Qnil, false);
} }
@ -523,9 +527,19 @@ namespace Automation4 {
return Qtrue; return Qtrue;
} }
int RubyProgressSink::RubyDisplayDialog() VALUE RubyProgressSink::RubyDisplayDialog(VALUE self, VALUE dialog_data, VALUE buttons)
{ {
return 0; // Send the "show dialog" event
ShowConfigDialogEvent evt;
RubyConfigDialog dlg(dialog_data, buttons, true); // magically creates the config dialog structure etc
evt.config_dialog = &dlg;
wxSemaphore sema(0, 1);
evt.sync_sema = &sema;
RubyProgressSink::inst->AddPendingEvent(evt);
sema.Wait();
return dlg.RubyReadBack();
} }

View file

@ -92,7 +92,6 @@ namespace Automation4 {
// Provides progress UI and control functions for a Ruby script // Provides progress UI and control functions for a Ruby script
class RubyProgressSink : public ProgressSink { class RubyProgressSink : public ProgressSink {
private: private:
static int RubyDisplayDialog();
public: public:
RubyProgressSink(wxWindow *parent, bool allow_config_dialog = true); RubyProgressSink(wxWindow *parent, bool allow_config_dialog = true);
@ -103,6 +102,7 @@ namespace Automation4 {
static VALUE RubySetTitle(VALUE self, VALUE title); static VALUE RubySetTitle(VALUE self, VALUE title);
static VALUE RubyGetCancelled(VALUE self); static VALUE RubyGetCancelled(VALUE self);
static VALUE RubyDebugOut(int argc, VALUE *args, VALUE self); static VALUE RubyDebugOut(int argc, VALUE *args, VALUE self);
static VALUE RubyDisplayDialog(VALUE self, VALUE cfg, VALUE buttons);
}; };
@ -115,9 +115,10 @@ namespace Automation4 {
virtual wxControl *Create(wxWindow *parent) = 0; virtual wxControl *Create(wxWindow *parent) = 0;
virtual void ControlReadBack() = 0; virtual void ControlReadBack() = 0;
virtual void RubyReadBack() = 0; virtual VALUE RubyReadBack() = 0;
RubyConfigDialogControl(); RubyConfigDialogControl();
RubyConfigDialogControl(VALUE opts);
virtual ~RubyConfigDialogControl() { } virtual ~RubyConfigDialogControl() { }
}; };
@ -140,9 +141,9 @@ namespace Automation4 {
wxWindow* CreateWindow(wxWindow *parent); wxWindow* CreateWindow(wxWindow *parent);
public: public:
RubyConfigDialog(bool include_buttons); RubyConfigDialog(VALUE cfg, VALUE buttons, bool show_buttons);
virtual ~RubyConfigDialog(); virtual ~RubyConfigDialog();
int RubyReadBack(); // read back internal structure to lua structures VALUE RubyReadBack(); // read back internal structure to Ruby hash
void ReadBack(); // from auto4 base void ReadBack(); // from auto4 base
}; };

View file

@ -47,62 +47,46 @@ namespace Automation4 {
// RubyConfigDialogControl // RubyConfigDialogControl
RubyConfigDialogControl::RubyConfigDialogControl() RubyConfigDialogControl::RubyConfigDialogControl(VALUE opts)
{ {
// Assume top of stack is a control table (don't do checking) VALUE val = rb_hash_aref(opts, rb_str_new2("name"));
if(TYPE(val) == T_STRING)
name = wxString(StringValueCStr(val), wxConvUTF8);
else name = _T("");
/* lua_getfield(L, -1, "name"); val = rb_hash_aref(opts, rb_str_new2("x"));
if (lua_isstring(L, -1)) { if(TYPE(val) == T_FIXNUM) {
name = wxString(lua_tostring(L, -1), wxConvUTF8); x = FIX2INT(val);
} else {
name = _T("");
}
lua_pop(L, 1);
lua_getfield(L, -1, "x");
if (lua_isnumber(L, -1)) {
x = lua_tointeger(L, -1);
if (x < 0) x = 0; if (x < 0) x = 0;
} else {
x = 0;
} }
lua_pop(L, 1); else x = 0;
lua_getfield(L, -1, "y"); val = rb_hash_aref(opts, rb_str_new2("y"));
if (lua_isnumber(L, -1)) { if(TYPE(val) == T_FIXNUM) {
y = lua_tointeger(L, -1); y = FIX2INT(val);
if (y < 0) y = 0; if (y < 0) y = 0;
} else {
y = 0;
} }
lua_pop(L, 1); else y = 0;
lua_getfield(L, -1, "width"); val = rb_hash_aref(opts, rb_str_new2("width"));
if (lua_isnumber(L, -1)) { if(TYPE(val) == T_FIXNUM) {
width = lua_tointeger(L, -1); width = FIX2INT(val);
if (width < 1) width = 1; if (width < 1) width = 1;
} else {
width = 1;
} }
lua_pop(L, 1); else width = 1;
lua_getfield(L, -1, "height"); val = rb_hash_aref(opts, rb_str_new2("height"));
if (lua_isnumber(L, -1)) { if(TYPE(val) == T_FIXNUM) {
height = lua_tointeger(L, -1); height = FIX2INT(val);
if (height < 1) height = 1; if (height < 1) width = 1;
} else {
height = 1;
} }
lua_pop(L, 1); else height = 1;
val = rb_hash_aref(opts, rb_str_new2("hint"));
if(TYPE(val) == T_STRING)
hint = wxString(StringValueCStr(val), wxConvUTF8);
else hint = _T("");
lua_getfield(L, -1, "hint");
if (lua_isstring(L, -1)) {
hint = wxString(lua_tostring(L, -1), wxConvUTF8);
} else {
hint = _T("");
}
lua_pop(L, 1);
*/
wxLogDebug(_T("created control: '%s', (%d,%d)(%d,%d), '%s'"), name.c_str(), x, y, width, height, hint.c_str()); wxLogDebug(_T("created control: '%s', (%d,%d)(%d,%d), '%s'"), name.c_str(), x, y, width, height, hint.c_str());
} }
@ -114,13 +98,15 @@ namespace Automation4 {
public: public:
wxString label; wxString label;
Label() Label(){};
: RubyConfigDialogControl() Label(VALUE opts)
: RubyConfigDialogControl(opts)
{ {
/* lua_getfield(L, -1, "label"); VALUE val = rb_hash_aref(opts, rb_str_new2("label"));
label = wxString(lua_tostring(L, -1), wxConvUTF8); if(TYPE(val) == T_STRING)
lua_pop(L, 1); label = wxString(StringValueCStr(val), wxConvUTF8);
*/ } else label = _T("");
}
virtual ~Label() { } virtual ~Label() { }
@ -134,10 +120,9 @@ namespace Automation4 {
// Nothing here // Nothing here
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// Label doesn't produce output, so let it be nil return Qnil;
// lua_pushnil(L);
} }
}; };
@ -148,13 +133,15 @@ namespace Automation4 {
public: public:
wxString text; wxString text;
Edit() Edit(){};
: RubyConfigDialogControl() Edit(VALUE opts)
: RubyConfigDialogControl(opts)
{ {
/* lua_getfield(L, -1, "text"); VALUE val = rb_hash_aref(opts, rb_str_new2("text"));
text = wxString(lua_tostring(L, -1), wxConvUTF8); if(TYPE(val) == T_STRING)
lua_pop(L, 1); text = wxString(StringValueCStr(val), wxConvUTF8);
*/ } else text = _T("");
}
virtual ~Edit() { } virtual ~Edit() { }
@ -168,9 +155,9 @@ namespace Automation4 {
text = ((wxTextCtrl*)cw)->GetValue(); text = ((wxTextCtrl*)cw)->GetValue();
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// lua_pushstring(L, text.mb_str(wxConvUTF8)); return rb_str_new2(text.mb_str(wxConvUTF8));
} }
}; };
@ -181,8 +168,9 @@ namespace Automation4 {
class Textbox : public Edit { class Textbox : public Edit {
public: public:
Textbox() Textbox(){};
: Edit() Textbox(VALUE opts)
: Edit(opts)
{ {
// Nothing more // Nothing more
} }
@ -207,33 +195,28 @@ namespace Automation4 {
bool hasspin; bool hasspin;
int min, max; int min, max;
IntEdit() IntEdit(){};
: Edit() IntEdit(VALUE opts)
: Edit(opts)
{ {
/* lua_getfield(L, -1, "value"); VALUE val = rb_hash_aref(opts, rb_str_new2("value"));
value = lua_tointeger(L, -1); if(TYPE(val) == T_FIXNUM) {
lua_pop(L, 1); value = FIX2INT(val);
}
hasspin = false; hasspin = false;
val = rb_hash_aref(opts, rb_str_new2("min"));
lua_getfield(L, -1, "min"); if(TYPE(val) == T_FIXNUM) {
if (!lua_isnumber(L, -1)) min = FIX2INT(val);
goto nospin; }
min = lua_tointeger(L, -1); else return;
lua_pop(L, 1);
val = rb_hash_aref(opts, rb_str_new2("min"));
lua_getfield(L, -1, "max"); if(TYPE(val) == T_FIXNUM) {
if (!lua_isnumber(L, -1)) min = FIX2INT(val);
goto nospin; hasspin = true;
max = lua_tointeger(L, -1); }
lua_pop(L, 1);
hasspin = true;
nospin:
if (!hasspin) {
lua_pop(L, 1);
} }
*/ }
virtual ~IntEdit() { } virtual ~IntEdit() { }
@ -260,9 +243,9 @@ nospin:
} }
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// lua_pushinteger(L, value); return INT2FIX(value);
} }
}; };
@ -275,13 +258,16 @@ nospin:
float value; float value;
// FIXME: Can't support spin button atm // FIXME: Can't support spin button atm
FloatEdit() FloatEdit(){};
: Edit() FloatEdit(VALUE opts)
: Edit(opts)
{ {
/* lua_getfield(L, -1, "value"); VALUE val = rb_hash_aref(opts, rb_str_new2("value"));
value = lua_tointeger(L, -1); if(TYPE(val) == T_FLOAT) {
lua_pop(L, 1); value = NUM2DBL(val);
*/ } else if (TYPE(val) == T_FIXNUM) {
value = FIX2INT(val);
}
// TODO: spin button support // TODO: spin button support
} }
@ -302,9 +288,9 @@ nospin:
} }
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// lua_pushnumber(L, value); return rb_float_new(value);
} }
}; };
@ -317,23 +303,26 @@ nospin:
wxArrayString items; wxArrayString items;
wxString value; wxString value;
Dropdown() Dropdown(){};
: RubyConfigDialogControl() Dropdown(VALUE opts)
: RubyConfigDialogControl(opts)
{ {
/* lua_getfield(L, -1, "value"); VALUE val = rb_hash_aref(opts, rb_str_new2("value"));
value = wxString(lua_tostring(L, -1), wxConvUTF8); if(TYPE(val) == T_STRING)
lua_pop(L, 1); value = wxString(StringValueCStr(val), wxConvUTF8);
lua_getfield(L, -1, "items"); val = rb_hash_aref(opts, rb_str_new2("items"));
lua_pushnil(L); if(TYPE(val) == T_ARRAY)
while (lua_next(L, -2)) { {
if (lua_isstring(L, -1)) { long len = RARRAY(val)->len;
items.Add(wxString(lua_tostring(L, -1), wxConvUTF8)); VALUE *ptr = RARRAY(val)->ptr;
for(int i = 0; i < len; i++)
{
if(TYPE(ptr[i]) == T_STRING)
items.Add(wxString(StringValueCStr(ptr[i]), wxConvUTF8));
}
} }
lua_pop(L, 1);
} }
lua_pop(L, 1);
*/ }
virtual ~Dropdown() { } virtual ~Dropdown() { }
@ -347,11 +336,10 @@ nospin:
value = ((wxComboBox*)cw)->GetValue(); value = ((wxComboBox*)cw)->GetValue();
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// lua_pushstring(L, value.mb_str(wxConvUTF8)); return rb_str_new2(value.mb_str(wxConvUTF8));
} }
}; };
@ -362,17 +350,18 @@ nospin:
wxString label; wxString label;
bool value; bool value;
Checkbox() Checkbox(){};
: RubyConfigDialogControl() Checkbox(VALUE opts)
: RubyConfigDialogControl(opts)
{ {
/* lua_getfield(L, -1, "label"); VALUE val = rb_hash_aref(opts, rb_str_new2("label"));
label = wxString(lua_tostring(L, -1), wxConvUTF8); if(TYPE(val) == T_STRING)
lua_pop(L, 1); label = wxString(StringValueCStr(val), wxConvUTF8);
lua_getfield(L, -1, "value"); val = rb_hash_aref(opts, rb_str_new2("value"));
value = lua_toboolean(L, -1) != 0; if(val == Qtrue) value = true;
lua_pop(L, 1); else value = false;
*/ } }
virtual ~Checkbox() { } virtual ~Checkbox() { }
@ -386,9 +375,10 @@ nospin:
value = ((wxCheckBox*)cw)->GetValue(); value = ((wxCheckBox*)cw)->GetValue();
} }
void RubyReadBack() VALUE RubyReadBack()
{ {
// lua_pushboolean(L, value); if(value) return Qtrue;
return Qfalse;
} }
}; };
@ -398,91 +388,77 @@ nospin:
// RubyConfigDialog // RubyConfigDialog
RubyConfigDialog::RubyConfigDialog(bool include_buttons) RubyConfigDialog::RubyConfigDialog(VALUE config, VALUE btn_data, bool include_buttons)
: use_buttons(include_buttons) : use_buttons(include_buttons)
{ {
wxLogDebug(_T("creating RubyConfigDialog, this addr is %p"), this); wxLogDebug(_T("creating RubyConfigDialog, this addr is %p"), this);
button_pushed = 0; button_pushed = 0;
/* if (include_buttons) {
if (!lua_istable(L, -1)) if(include_buttons && TYPE(btn_data) == T_ARRAY)
// Just to avoid deeper indentation... {
goto skipbuttons; long len = RARRAY(config)->len;
// Iterate over items in table VALUE *ptr = RARRAY(config)->ptr;
lua_pushnil(L); // initial key for(int i = 0; i < len; i++)
while (lua_next(L, -2)) { {
// Simply skip invalid items... FIXME, warn here? if(TYPE(ptr[i]) == T_STRING)
if (lua_isstring(L, -1)) { {
wxString s(lua_tostring(L, -1), wxConvUTF8); wxString s(StringValueCStr(ptr[i]), wxConvUTF8);
buttons.push_back(s); buttons.push_back(s);
} }
lua_pop(L, 1);
} }
skipbuttons:
lua_pop(L, 1);
} }
// assume top of stack now contains a dialog table if(TYPE(config) != T_ARRAY) {
if (!lua_istable(L, -1)) { if(rb_respond_to(config, rb_intern("to_ary")))
lua_pushstring(L, "Cannot create config dialog from something non-table"); config = rb_funcall(config, rb_intern("to_ary"), 0);
lua_error(L); else throw "Cannot create config dialog from something non-table";
assert(false);
} }
// Ok, so there is a table with controls long len = RARRAY(config)->len;
lua_pushnil(L); // initial key VALUE *ptr = RARRAY(config)->ptr;
while (lua_next(L, -2)) { for(int i = 0; i < len; i++)
if (lua_istable(L, -1)) { {
// Get control class if(TYPE(ptr[i]) != T_HASH)
lua_getfield(L, -1, "class"); continue; // skip invalid entry
if (!lua_isstring(L, -1))
goto badcontrol; VALUE ctrlclass = rb_hash_aref(ptr[i], rb_str_new2("class"));
wxString controlclass(lua_tostring(L, -1), wxConvUTF8);
if (TYPE(ctrlclass) != T_STRING)
continue; // skip
wxString controlclass(StringValueCStr(ctrlclass), wxConvUTF8);
controlclass.LowerCase(); controlclass.LowerCase();
lua_pop(L, 1);
RubyConfigDialogControl *ctl; RubyConfigDialogControl *ctl;
// Check control class and create relevant control // Check control class and create relevant control
if (controlclass == _T("label")) { if (controlclass == _T("label")) {
ctl = new RubyControl::Label(L); ctl = new RubyControl::Label(ptr[i]);
} else if (controlclass == _T("edit")) { } else if (controlclass == _T("edit")) {
ctl = new RubyControl::Edit(L); ctl = new RubyControl::Edit(ptr[i]);
} else if (controlclass == _T("intedit")) { } else if (controlclass == _T("intedit")) {
ctl = new RubyControl::IntEdit(L); ctl = new RubyControl::IntEdit(ptr[i]);
} else if (controlclass == _T("floatedit")) { } else if (controlclass == _T("floatedit")) {
ctl = new RubyControl::FloatEdit(L); ctl = new RubyControl::FloatEdit(ptr[i]);
} else if (controlclass == _T("textbox")) { } else if (controlclass == _T("textbox")) {
ctl = new RubyControl::Textbox(L); ctl = new RubyControl::Textbox(ptr[i]);
} else if (controlclass == _T("dropdown")) { } else if (controlclass == _T("dropdown")) {
ctl = new RubyControl::Dropdown(L); ctl = new RubyControl::Dropdown(ptr[i]);
} else if (controlclass == _T("checkbox")) { } else if (controlclass == _T("checkbox")) {
ctl = new RubyControl::Checkbox(L); ctl = new RubyControl::Checkbox(ptr[i]);
} else if (controlclass == _T("color")) { } else if (controlclass == _T("color")) {
// FIXME // FIXME
ctl = new RubyControl::Edit(L); ctl = new RubyControl::Edit(ptr[i]);
} else if (controlclass == _T("coloralpha")) { } else if (controlclass == _T("coloralpha")) {
// FIXME // FIXME
ctl = new RubyControl::Edit(L); ctl = new RubyControl::Edit(ptr[i]);
} else if (controlclass == _T("alpha")) { } else if (controlclass == _T("alpha")) {
// FIXME // FIXME
ctl = new RubyControl::Edit(L); ctl = new RubyControl::Edit(ptr[i]);
} else { } else continue; // skip
goto badcontrol;
}
controls.push_back(ctl); controls.push_back(ctl);
} else {
badcontrol:
// not a control...
// FIXME, better error reporting?
lua_pushstring(L, "bad control table entry");
lua_error(L);
} }
lua_pop(L, 1);
} }
*/ }
RubyConfigDialog::~RubyConfigDialog() RubyConfigDialog::~RubyConfigDialog()
{ {
@ -537,42 +513,39 @@ badcontrol:
return w; return w;
} }
int RubyConfigDialog::RubyReadBack() VALUE RubyConfigDialog::RubyReadBack()
{ {
// First read back which button was pressed, if any VALUE cfg = rb_hash_new();
for (size_t i = 0; i < controls.size(); ++i) {
rb_hash_aset(cfg, rb_str_new2(controls[i]->name.mb_str(wxConvUTF8)), controls[i]->RubyReadBack());
}
if (use_buttons) { if (use_buttons) {
VALUE res = rb_ary_new();
wxLogDebug(_T("reading back button_pushed")); wxLogDebug(_T("reading back button_pushed"));
int btn = button_pushed; int btn = button_pushed;
if (btn == 0) { if (btn == 0) {
wxLogDebug(_T("was zero, cancelled")); wxLogDebug(_T("was zero, cancelled"));
// Always cancel/closed // Always cancel/closed
// lua_pushboolean(L, 0); rb_ary_push(res, Qfalse);
} else { } else {
wxLogDebug(_T("nonzero, something else: %d"), btn); wxLogDebug(_T("nonzero, something else: %d"), btn);
if (buttons.size() > 0) { if (buttons.size() > 0) {
wxLogDebug(_T("user button: %s"), buttons[btn-1].c_str()); wxLogDebug(_T("user button: %s"), buttons[btn-1].c_str());
// button_pushed is index+1 to reserve 0 for Cancel // button_pushed is index+1 to reserve 0 for Cancel
// lua_pushstring(L, buttons[btn-1].mb_str(wxConvUTF8)); rb_ary_push(res, rb_str_new2(buttons[btn-1].mb_str(wxConvUTF8)));
} else { } else {
wxLogDebug(_T("default button, must be Ok")); wxLogDebug(_T("default button, must be Ok"));
// Cancel case already covered, must be Ok then // Cancel case already covered, must be Ok then
// lua_pushboolean(L, 1); rb_ary_push(res, Qtrue);
} }
} }
rb_ary_push(res, cfg); // return array [button, hash with config]
return res;
} }
// Then read controls back return cfg; // if no buttons return only hash with config
// lua_newtable(L);
for (size_t i = 0; i < controls.size(); ++i) {
controls[i]->RubyReadBack(); // TODO
// lua_setfield(L, -2, controls[i]->name.mb_str(wxConvUTF8));
}
if (use_buttons) {
return 2;
} else {
return 1;
}
} }
void RubyConfigDialog::ReadBack() void RubyConfigDialog::ReadBack()