OSDN Git Service

Ruby Dialog: behavior of the close button is improved (hopefully)
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 10 Mar 2014 11:07:25 +0000 (11:07 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 10 Mar 2014 11:07:25 +0000 (11:07 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@448 a2be9bc6-48de-4e38-9406-05402d4bc13c

MolLib/Ruby_bind/ruby_bind.c
MolLib/Ruby_bind/ruby_dialog.c
MolLib/Ruby_bind/ruby_dialog.h

index 53ac963..106e7c0 100644 (file)
@@ -11130,6 +11130,15 @@ Molby_startup(const char *script, const char *dir)
        rb_define_const(rb_mMolby, "MbsfPath", val);    
        free(p);
        
+       p = MyAppCallback_getHomeDir();
+       val = (p == NULL ? Qnil : Ruby_NewFileStringValue(p));
+       rb_define_const(rb_mMolby, "HomeDirectory", val);
+       free(p);
+       p = MyAppCallback_getDocumentHomeDir();
+       val = (p == NULL ? Qnil : Ruby_NewFileStringValue(p));
+       rb_define_const(rb_mMolby, "DocumentDirectory", val);
+       free(p);
+       
 #if defined(__CMDMAC__)
        rb_define_const(rb_mMolby, "HasGUI", Qfalse);
 #else
index 1e0043f..19cb79f 100644 (file)
@@ -74,6 +74,8 @@ s_RubyDialog_GetController(VALUE self)
        else return NULL;
 }
 
+/*  Deallocate handler: may be called when the Ruby object is deallocated while the RubyDialogFrame is not
+    deallocated yet.  */
 static void
 s_RubyDialog_Release(void *p)
 {
@@ -88,6 +90,16 @@ s_RubyDialog_Release(void *p)
        }
 }
 
+/*  Deallocate the RubyDialogFrame while the Ruby object is still alive  */
+static void
+s_RubyDialog_Forget(VALUE self)
+{
+       RubyDialogInfo *di;
+       Data_Get_Struct(self, RubyDialogInfo, di);
+       if (di != NULL)
+               di->dref = NULL;
+}
+
 static VALUE
 s_RubyDialog_Alloc(VALUE klass)
 {
@@ -648,6 +660,9 @@ s_RubyDialog_Initialize(int argc, VALUE *argv, VALUE self)
        
        rb_iv_set(self, "_items", items);
        
+       if (rb_ary_includes(gRubyDialogList, self) == Qfalse)
+               rb_ary_push(gRubyDialogList, self);
+
        return Qnil;
 }
 
@@ -774,30 +789,9 @@ s_RubyDialog_Run(VALUE self)
        iflag = Ruby_SetInterruptFlag(Qfalse);
        retval = RubyDialogCallback_runModal(dref);
        Ruby_SetInterruptFlag(iflag);
-       RubyDialogCallback_close(dref);
+       RubyDialogCallback_destroy(dref);
+       s_RubyDialog_Forget(self);
        return rb_iv_get(self, "_retval");
-#if 0
-       if (retval == 0) {
-               VALUE items = rb_iv_get(self, "_items");
-               int len = RARRAY_LEN(items);
-               VALUE *ptr = RARRAY_PTR(items);
-               VALUE hash = rb_hash_new();
-               int i;
-               /*  Get values for controls with defined tags  */
-               for (i = 2; i < len; i++) {
-                       /*  Items 0, 1 are OK/Cancel buttons  */
-               /*      VALUE type = rb_hash_aref(ptr[i], sTypeSymbol); */
-                       VALUE tag = rb_ivar_get(ptr[i], SYM2ID(sTagSymbol));
-                       if (tag != Qnil) {
-                               VALUE val;
-                               val = s_RubyDialogItem_Attr(ptr[i], sValueSymbol);
-                               rb_hash_aset(hash, tag, val);
-                       }
-               }
-               return hash;
-       } else
-               return Qfalse;
-#endif
 }
 
 /*
@@ -814,8 +808,8 @@ s_RubyDialog_Show(VALUE self)
 {
        RubyDialog *dref = s_RubyDialog_GetController(self);
        RubyDialogCallback_show(dref);
-       if (rb_ary_includes(gRubyDialogList, self) == Qfalse)
-               rb_ary_push(gRubyDialogList, self);
+//     if (rb_ary_includes(gRubyDialogList, self) == Qfalse)
+//             rb_ary_push(gRubyDialogList, self);
        return self;
 }
 
@@ -824,7 +818,6 @@ s_RubyDialog_Show(VALUE self)
  *     hide
  *
  *  Hide the modeless dialog. This is to be used with Dialog#show in pairs.
- *  If the dialog is registered in the ruby_dialog_list global variable, it becomes unregistered.
  *  Mixing Dialog#hide and Dialog#run will lead to unpredictable results, including crash.
  */
 static VALUE
@@ -832,11 +825,24 @@ s_RubyDialog_Hide(VALUE self)
 {
        RubyDialog *dref = s_RubyDialog_GetController(self);
        RubyDialogCallback_hide(dref);
-       if (rb_ary_includes(gRubyDialogList, self) == Qtrue)
-               rb_ary_delete(gRubyDialogList, self);
        return self;
 }
 
+/*
+ *  call-seq:
+ *     close
+ *
+ *  Close the modeless dialog. The normal close handler of the platform is invoked.
+ *  If the dialog is registered in the ruby_dialog_list global variable, it becomes unregistered.
+ *  If force is true, or this method is called recursively, the window will be destroyed unconditionally.
+ */
+static VALUE
+s_RubyDialog_Close(VALUE self)
+{
+       RubyDialog *dref = s_RubyDialog_GetController(self);
+       RubyDialogCallback_close(dref);
+       return self;
+}
 
 /*
  *  call-seq:
@@ -1350,6 +1356,8 @@ s_RubyDialog_EndModal(int argc, VALUE *argv, VALUE self)
        }
        rb_iv_set(self, "_retval", retval);
        RubyDialogCallback_endModal(s_RubyDialog_GetController(self), (flag ? 1 : 0));
+       if (rb_ary_includes(gRubyDialogList, self) == Qtrue)
+               rb_ary_delete(gRubyDialogList, self);
        return Qnil;
 }
 
@@ -2495,18 +2503,42 @@ RubyDialog_getFlexFlags(RubyValue self, RDItem *ip)
        else return (int)args[2];
 }
 
-/*  Handle close box.  Invokes Dialog.end_modal or Dialog.hide in Ruby world  */
-void
-RubyDialog_doCloseWindow(RubyValue self, int isModal)
+static VALUE
+s_RubyDialog_doCloseWindow(VALUE val)
 {
-       int status;
-       VALUE val;
+       void **values = (void **)val;
+       VALUE self = (VALUE)values[0];
+       int isModal = (int)values[1];
        if (isModal) {
-               val = INT2NUM(1);
-               Ruby_funcall2_protect((VALUE)self, rb_intern("end_modal"), 1, &val, &status);
+               rb_funcall(self, rb_intern("end_modal"), 1, INT2NUM(1));
+               return Qnil;
        } else {
-               Ruby_funcall2_protect((VALUE)self, rb_intern("hide"), 0, NULL, &status);
+               VALUE rval;
+               VALUE actval = rb_iv_get(self, "@on_close");
+               if (actval != Qnil) {
+                       if (TYPE(actval) == T_SYMBOL)
+                               rval = rb_funcall(self, SYM2ID(actval), 0);
+                       else
+                               rval = rb_funcall(actval, rb_intern("call"), 0);
+               } else rval = Qtrue;
+               if (RTEST(rval)) {
+                       if (rb_ary_includes(gRubyDialogList, self) == Qtrue)
+                               rb_ary_delete(gRubyDialogList, self);
+                       RubyDialogCallback_destroy(s_RubyDialog_GetController(self));
+                       s_RubyDialog_Forget(self);
+               }
+               return rval;
        }
+}
+
+/*  Handle close box.  Invokes Dialog.end_modal or Dialog.close in Ruby world  */
+void
+RubyDialog_doCloseWindow(RubyValue self, int isModal)
+{
+       int status;
+       VALUE rval;
+       void *args[2] = { (void *)self, (void *)isModal };
+       rval = rb_protect(s_RubyDialog_doCloseWindow, (VALUE)args, &status);
        if (status != 0) {
                Molby_showError(status);
        }
@@ -2538,6 +2570,7 @@ RubyDialogInitClass(void)
        rb_define_method(rb_cDialog, "end_modal", s_RubyDialog_EndModal, -1);
        rb_define_method(rb_cDialog, "show", s_RubyDialog_Show, 0);
        rb_define_method(rb_cDialog, "hide", s_RubyDialog_Hide, 0);
+       rb_define_method(rb_cDialog, "close", s_RubyDialog_Close, 0);
        rb_define_method(rb_cDialog, "start_timer", s_RubyDialog_StartTimer, -1);
        rb_define_method(rb_cDialog, "stop_timer", s_RubyDialog_StopTimer, 0);
        rb_define_method(rb_cDialog, "on_key", s_RubyDialog_OnKey, -1);
@@ -2624,7 +2657,7 @@ RubyDialogInitClass(void)
                        *(sTable1[i]) = ID2SYM(rb_intern(sTable2[i]));
        }
        
-       /*  Global variable to hold open non-modal dialogs */
-       rb_define_variable("$non_modal_dialogs", &gRubyDialogList);
+       /*  Global variable to hold open dialogs */
+       rb_define_variable("$ruby_dialogs", &gRubyDialogList);
        gRubyDialogList = rb_ary_new();
 }
index 556fc2f..00ce7a9 100644 (file)
@@ -78,6 +78,7 @@ STUB void RubyDialogCallback_setRubyObject(RubyDialog *dref, RubyValue val);
 STUB void RubyDialogCallback_setWindowTitle(RubyDialog *dref, const char *title);
 STUB int RubyDialogCallback_runModal(RubyDialog *dref);
 STUB void RubyDialogCallback_endModal(RubyDialog *dref, int status);
+STUB void RubyDialogCallback_destroy(RubyDialog *dref);
 STUB void RubyDialogCallback_close(RubyDialog *dref);
 STUB void RubyDialogCallback_show(RubyDialog *dref);
 STUB void RubyDialogCallback_hide(RubyDialog *dref);