OSDN Git Service

Resize of the Ruby Dialog is improved (still experimental). Antechamber can now be...
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Thu, 1 Aug 2013 15:45:02 +0000 (15:45 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Thu, 1 Aug 2013 15:45:02 +0000 (15:45 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@376 a2be9bc6-48de-4e38-9406-05402d4bc13c

13 files changed:
MolLib/Molecule.c
MolLib/Molecule.h
MolLib/Ruby_bind/Molby_extern.h
MolLib/Ruby_bind/ruby_bind.c
MolLib/Ruby_bind/ruby_dialog.c
MolLib/Ruby_bind/ruby_dialog.h
Scripts/md.rb
Scripts/uff.rb
wxSources/MoleculeView.cpp
wxSources/MyDocument.cpp
wxSources/MyDocument.h
wxSources/RubyDialogFrame.cpp
wxSources/RubyDialogFrame.h

index bde615e..f121dfe 100755 (executable)
@@ -876,6 +876,27 @@ MoleculeLoadMbsfFile(Molecule *mp, const char *fname, char **errbuf)
                                i++;
                        }
                        continue;
+               } else if (strcmp(buf, "!:uff_types") == 0) {
+                       i = 0;
+                       while (ReadLine(buf, sizeof buf, fp, &lineNumber) > 0) {
+                               if (buf[0] == '!')
+                                       continue;
+                               if (buf[0] == '\n')
+                                       break;
+                               /* idx uff_type */
+                               if (sscanf(buf, "%d %6s", &ibuf[0], cbuf[0]) < 2) {
+                                       s_append_asprintf(errbuf, "line %d: uff type info cannot be read for atom %d", lineNumber, i + 1);
+                                       goto err_exit;
+                               }
+                               if (i >= mp->natoms) {
+                                       s_append_asprintf(errbuf, "line %d: too many uff type info\n", lineNumber);
+                                       goto err_exit;
+                               }
+                               ap = ATOM_AT_INDEX(mp->atoms, i);
+                               strncpy(ap->uff_type, cbuf[0], 5);
+                               ap->uff_type[5] = 0;
+                               i++;
+                       }
                } else if (strcmp(buf, "!:mm_exclude") == 0) {
                        i = 0;
                        while (ReadLine(buf, sizeof buf, fp, &lineNumber) > 0) {
@@ -3763,7 +3784,7 @@ int
 MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf)
 {
        FILE *fp;
-       Int i, j, k, n1, n2, n3, n_aniso, nframes, nanchors;
+       Int i, j, k, n1, n2, n3, n_aniso, nframes, nanchors, n_uff;
        Atom *ap;
        char bufs[6][8];
 
@@ -3779,7 +3800,7 @@ MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf)
 
        fprintf(fp, "!:atoms\n");
        fprintf(fp, "! idx seg_name res_seq res_name name type charge weight element atomic_number occupancy temp_factor int_charge\n");
-       n1 = n2 = n3 = n_aniso = nanchors = 0;
+       n1 = n2 = n3 = n_aniso = nanchors = n_uff = 0;
        for (i = 0, ap = mp->atoms; i < mp->natoms; i++, ap = ATOM_NEXT(ap)) {
                strncpy(bufs[0], ap->segName, 4);
                bufs[0][4] = 0;
@@ -3813,10 +3834,22 @@ MoleculeWriteToMbsfFile(Molecule *mp, const char *fname, char **errbuf)
                        n_aniso++;
                if (ap->anchor != NULL)
                        nanchors++;
+               if (ap->uff_type[0] != 0)
+                       n_uff++;
                fprintf(fp, "%d %s %d %s %s %s %.5f %.5f %s %d %f %f %d\n", i, bufs[0], ap->resSeq, bufs[1], bufs[2], bufs[3], ap->charge, ap->weight, bufs[4], ap->atomicNumber, ap->occupancy, ap->tempFactor, ap->intCharge);
        }
        fprintf(fp, "\n");
        
+       if (n_uff > 0) {
+               fprintf(fp, "!:uff_type\n");
+               fprintf(fp, "! idx uff_type\n");
+               for (i = 0, ap = mp->atoms; i < mp->natoms; i++, ap = ATOM_NEXT(ap)) {
+                       int n;
+                       fprintf(fp, "%d %.5s\n", i, ap->uff_type);
+               }
+               fprintf(fp, "\n");
+       }
+       
        if (n1 > 0) {
                fprintf(fp, "!:atoms_symop\n");
                fprintf(fp, "! idx symop symbase\n");
index 7fe4133..050097a 100755 (executable)
@@ -116,6 +116,7 @@ typedef struct Atom {
        Vector fix_pos;
        Byte   mm_exclude;        /*  If nonzero, then this atom is excluded from MM/MD calculations  */
        Byte   periodic_exclude;  /*  If nonzero, then this atom is excluded from periodic calculations  */
+       char   uff_type[6]; /*  UFF type string  */
 } Atom;
 
 extern Int gSizeOfAtomRecord;
index 89862ad..acead96 100755 (executable)
@@ -25,6 +25,8 @@ extern "C" {
 
 /*  This definition is to work around 'VALUE' type in sources without "ruby.h"  */
 typedef void *RubyValue;
+
+#define RubyNil ((RubyValue)4)
        
 extern char *gRubyVersion;
 extern char *gRubyCopyright;
@@ -39,6 +41,11 @@ extern void Molby_showRubyValue(RubyValue value, char **outValueString);
 extern int Ruby_methodType(const char *className, const char *methodName);
 extern void Molby_buildARGV(int argc, const char **argv);
        
+/*  RubyValue version of Ruby_funcall2_protect()  */
+extern RubyValue Ruby_funcall2_protect_extern(RubyValue recv, int mid, int argc, RubyValue *argv, int *status);
+
+extern int g_RubyID_call;  /*  rb_intern("call") for extrenal use  */
+       
 STUB char *MyAppCallback_getGUIDescriptionString(void);
 STUB char *MyAppCallback_getGlobalSettings(const char *key);
 STUB void MyAppCallback_setGlobalSettings(const char *key, const char *value);
index 4b3552a..ce76a28 100644 (file)
@@ -58,7 +58,9 @@ int gMolbyIsCheckingInterrupt = 0;
 char *gRubyVersion, *gRubyCopyright;
 
 /*  For convenience  */
-static VALUE s_ID_equal;  /*  rb_intern("==")  */
+static ID s_ID_equal;  /*  rb_intern("==")  */
+
+int g_RubyID_call;
 
 /*  Symbols for atom attributes  */
 static VALUE
@@ -71,7 +73,7 @@ static VALUE
        s_VSym, s_FSym, s_OccupancySym, s_TempFactorSym,
        s_AnisoSym, s_SymopSym, s_IntChargeSym, s_FixForceSym,
        s_FixPosSym, s_ExclusionSym, s_MMExcludeSym, s_PeriodicExcludeSym,
-       s_HiddenSym, s_AnchorListSym;
+       s_HiddenSym, s_AnchorListSym, s_UFFTypeSym;
 
 /*  Symbols for parameter attributes  */
 static VALUE
@@ -811,6 +813,12 @@ Ruby_funcall2_protect(VALUE recv, ID mid, int argc, VALUE *argv, int *status)
        return rb_protect(s_Ruby_funcall2_sub, (VALUE)&rec, status);
 }
 
+RubyValue
+Ruby_funcall2_protect_extern(RubyValue recv, int mid, int argc, RubyValue *argv, int *status)
+{
+       return (RubyValue)Ruby_funcall2_protect((VALUE)recv, mid, argc, (VALUE *)argv, status);
+}
+
 #pragma mark ====== ParameterRef Class ======
 
 static UnionPar *
@@ -3638,6 +3646,11 @@ static VALUE s_AtomRef_GetAnchorList(VALUE self) {
        return retval;
 }
 
+static VALUE s_AtomRef_GetUFFType(VALUE self) {
+       char *p = s_AtomFromValue(self)->uff_type;
+       return rb_str_new(p, strlen_limit(p, 5));
+}
+
 static VALUE s_AtomRef_SetIndex(VALUE self, VALUE val) {
        rb_raise(rb_eMolbyError, "index cannot be directly set");
        return Qnil;
@@ -4174,6 +4187,16 @@ static VALUE s_AtomRef_SetAnchorList(VALUE self, VALUE val) {
        return val;
 }
 
+static VALUE s_AtomRef_SetUFFType(VALUE self, VALUE val) {
+       Atom *ap = s_AtomFromValue(self);
+       char *p = StringValuePtr(val);
+       VALUE oval = s_AtomRef_GetUFFType(self);
+       strncpy(ap->uff_type, p, 5);
+       ap->uff_type[5] = 0;
+       s_RegisterUndoForAtomAttrChange(self, s_UFFTypeSym, val, oval);
+       return val;
+}
+
 static struct s_AtomAttrDef {
        char *name;
        VALUE *symref;  /*  Address of s_IndexSymbol etc. */
@@ -4219,6 +4242,7 @@ static struct s_AtomAttrDef {
        {"periodic_exclude", &s_PeriodicExcludeSym, 0, s_AtomRef_GetPeriodicExclude, s_AtomRef_SetPeriodicExclude},
        {"hidden",       &s_HiddenSym,       0, s_AtomRef_GetHidden,       s_AtomRef_SetHidden},
        {"anchor_list",  &s_AnchorListSym,   0, s_AtomRef_GetAnchorList,   s_AtomRef_SetAnchorList},
+       {"uff_type",     &s_UFFTypeSym,      0, s_AtomRef_GetUFFType,      s_AtomRef_SetUFFType},
        {NULL} /* Sentinel */
 };
 
@@ -10387,6 +10411,7 @@ Init_Molby(void)
        rb_define_method(rb_mKernel, "hide_console_window", s_Kernel_HideConsoleWindow, 0);
        
        s_ID_equal = rb_intern("==");
+       g_RubyID_call = rb_intern("call");
 }
 
 #pragma mark ====== External functions ======
index d646aed..0f4350f 100644 (file)
@@ -40,7 +40,7 @@ static VALUE
        /*  Data source for Table (= MyListCtrl)  */
        sOnCountSymbol, sOnGetValueSymbol, sOnSetValueSymbol, sOnSelectionChangedSymbol,
        sOnSetColorSymbol, sIsItemEditableSymbol, sIsDragAndDropEnabledSymbol, sOnDragSelectionToRowSymbol,
-       sSelectionSymbol, sColumnsSymbol;
+       sSelectionSymbol, sColumnsSymbol, sRefreshSymbol;
 
 VALUE rb_cDialog = Qfalse;
 VALUE rb_cDialogItem = Qfalse;
@@ -221,35 +221,24 @@ s_RubyDialogItem_SetAttr(VALUE self, VALUE key, VALUE val)
                frame.size.height = NUM2DBL(rb_Float(Ruby_ObjectAtIndex(val, 3)));
                RubyDialogCallback_setFrameOfItem(view, frame);
        } else if (key == sFlexSymbol) {
-               /*  Glue to [left, top, right, bottom]
-                       An array of 4 integers or a string like "LTRB" (case insensitive)  */
-               int glue = 0;
+               /*  Flex flags: [left, top, right, bottom, width, height] (0: fixed, 1: flex)  */
+               int flex = 0;
                if (val == Qnil) {
                        rb_ivar_set(self, key_id, val);
                } else {
-                       if (rb_obj_is_kind_of(val, rb_cString)) {
-                               const char *sp = StringValuePtr(val);
-                               if (strchr(sp, 'l') || strchr(sp, 'L'))
-                                       glue |= 1;
-                               if (strchr(sp, 't') || strchr(sp, 'T'))
-                                       glue |= 2;
-                               if (strchr(sp, 'r') || strchr(sp, 'R'))
-                                       glue |= 4;
-                               if (strchr(sp, 'b') || strchr(sp, 'B'))
-                                       glue |= 8;
-                       } else if (rb_obj_is_kind_of(val, rb_mEnumerable)) {
+                       if (rb_obj_is_kind_of(val, rb_mEnumerable)) {
                                int i;
-                               for (i = 0; i < 4; i++) {
+                               for (i = 0; i < 6; i++) {
                                        VALUE gval = Ruby_ObjectAtIndex(val, i);
                                        if (RTEST(gval) && NUM2INT(rb_Integer(gval)) != 0)
-                                               glue |= (1 << i);
+                                               flex |= (1 << i);
                                }
                        } else if (rb_obj_is_kind_of(val, rb_cNumeric)) {
-                               glue = NUM2INT(rb_Integer(val));
+                               flex = NUM2INT(rb_Integer(val));
                        } else {
-                               rb_raise(rb_eMolbyError, "the 'glue' attribute should be either an integer, an array of 4 boolean/integers or a string");
+                               rb_raise(rb_eMolbyError, "the 'flex' attribute should be either an integer or an array of 4 boolean/integers");
                        }
-                       rb_ivar_set(self, key_id, INT2NUM(glue));
+                       rb_ivar_set(self, key_id, INT2NUM(flex));
                }
        } else if (key == sFontSymbol) {
                int size, family, style, weight, i;
@@ -286,7 +275,7 @@ s_RubyDialogItem_SetAttr(VALUE self, VALUE key, VALUE val)
                }
                RubyDialogCallback_setFontForItem(view, size, family, style, weight);
        } else if (key == sSelectionSymbol) {
-               /*  Selection (for Table == MyTextCtrl item)  */
+               /*  Selection (for Table == MyListCtrl item)  */
                if (type == sTableSymbol) {
                        IntGroup *ig = IntGroupFromValue(val);
                        int row, count;
@@ -297,7 +286,7 @@ s_RubyDialogItem_SetAttr(VALUE self, VALUE key, VALUE val)
                        }
                }
        } else if (key == sColumnsSymbol) {
-               /*  Columns (for Table == MyTextCtrl item)  */
+               /*  Columns (for Table == MyListCtrl item)  */
                if (type == sTableSymbol) {
                        /*  The value should be an array of [name, width, align (0: natural, 1: right, 2: center)] */
                        int col;
@@ -323,6 +312,13 @@ s_RubyDialogItem_SetAttr(VALUE self, VALUE key, VALUE val)
                                RubyDialogCallback_insertTableColumn((RDItem *)view, col, heading, format, width);
                        }
                }
+       } else if (key == sRefreshSymbol) {
+               /*  Refresh (for Table == MyListCtrl item)  */
+               if (type == sTableSymbol) {
+                       if (RTEST(val)) {
+                               RubyDialogCallback_refreshTable((RDItem *)view);
+                       }
+               }                       
        } else {
                if (key == sTagSymbol && rb_obj_is_kind_of(val, rb_cInteger))
                        rb_raise(rb_eMolbyError, "the dialog item tag must not be integers");                           
@@ -452,15 +448,14 @@ s_RubyDialogItem_Attr(VALUE self, VALUE key)
                val = rb_ary_new3(4, rb_float_new(frame.origin.x), rb_float_new(frame.origin.y), rb_float_new(frame.size.width), rb_float_new(frame.size.height));
                rb_obj_freeze(val);
        } else if (key == sFlexSymbol) {
-               int glue;
+               int i, flex;
                val = rb_ivar_get(self, key_id);
                if (val != Qnil) {
-                       glue = NUM2INT(rb_Integer(val));
+                       flex = NUM2INT(rb_Integer(val));
                        val = rb_ary_new();
-                       rb_ary_push(val, ((glue & 1) ? INT2FIX(1) : INT2FIX(0)));
-                       rb_ary_push(val, ((glue & 2) ? INT2FIX(1) : INT2FIX(0)));
-                       rb_ary_push(val, ((glue & 4) ? INT2FIX(1) : INT2FIX(0)));
-                       rb_ary_push(val, ((glue & 8) ? INT2FIX(1) : INT2FIX(0)));
+                       for (i = 0; i < 6; i++) {
+                               rb_ary_push(val, ((flex & (1 << i)) ? INT2FIX(1) : INT2FIX(0)));
+                       }
                }
        } else if (key == sFontSymbol) {
                int size, family, style, weight;
@@ -1007,13 +1002,21 @@ s_RubyDialog_Layout(int argc, VALUE *argv, VALUE self)
        /*  Index for the layout view  */
        itag = RARRAY_LEN(items);
 
-       /*  Create a new hash for the layout view and push to _items */
-       {
-               new_item = rb_class_new_instance(0, NULL, rb_cDialogItem);
-               rb_ivar_set(new_item, SYM2ID(sTypeSymbol), sViewSymbol);
-               rb_ivar_set(new_item, SYM2ID(sDialogSymbol), self);
-               rb_ivar_set(new_item, SYM2ID(sIndexSymbol), INT2NUM(itag));
-               rb_ary_push(items, new_item);
+       /*  Create a new item object for the layout view and push to _items */
+       new_item = rb_class_new_instance(0, NULL, rb_cDialogItem);
+       rb_ivar_set(new_item, SYM2ID(sTypeSymbol), sViewSymbol);
+       rb_ivar_set(new_item, SYM2ID(sDialogSymbol), self);
+       rb_ivar_set(new_item, SYM2ID(sIndexSymbol), INT2NUM(itag));
+       rb_ary_push(items, new_item);
+
+       if (oval != Qnil) {
+               /*  Set the attributes given in the option hash  */
+               VALUE keys = rb_funcall(oval, rb_intern("keys"), 0);
+               for (i = 0; i < RARRAY_LEN(keys); i++) {
+                       VALUE kval = RARRAY_PTR(keys)[i];
+                       if (TYPE(kval) == T_SYMBOL)
+                               s_RubyDialogItem_SetAttr(new_item, kval, rb_hash_aref(oval, kval));
+               }
        }
        
        RubyDialogCallback_setAutoResizeEnabled(dref, autoResizeFlag);
@@ -1453,6 +1456,51 @@ s_RubyDialog_SetMinSize(int argc, VALUE *argv, VALUE self)
 
 /*
  *  call-seq:
+ *     listen(obj, str, pr)
+ *
+ *  Listen to the event invoked by the object. str = the name of the event (dependent on the
+ *  object), pr = the callback procedure. The first argument to the callback procedure is
+ *  always obj. Other arguments are dependent on the event and the object.
+ */
+static VALUE
+s_RubyDialog_Listen(VALUE self, VALUE oval, VALUE sval, VALUE pval)
+{
+       int i;
+       const char *sptr;
+       if (sval == Qnil)
+               sptr = NULL;
+       else
+               sptr = StringValuePtr(sval);
+       if (rb_obj_is_kind_of(oval, rb_cMolecule)) {
+               Molecule *mol = MoleculeFromValue(oval);
+               i = RubyDialogCallback_Listen(s_RubyDialog_GetController(self), mol, "Molecule", sptr, (RubyValue)oval, (RubyValue)pval);
+               if (i < 0) {
+                       switch (i) {
+                               case -1: rb_raise(rb_eMolbyError, "This dialog cannot be listened to."); break;
+                               case -2: rb_raise(rb_eMolbyError, "This message is not supported"); break;
+                       }
+               } else {
+                       /*  Keep the objects in the internal array, to protect from GC  */
+                       ID id = rb_intern("listen");
+                       VALUE aval = rb_ivar_get(self, id);
+                       if (aval == Qnil) {
+                               aval = rb_ary_new();
+                               rb_ivar_set(self, id, aval);
+                       }
+                       if (pval == Qfalse || pval == Qnil) {
+                               rb_ary_delete_at(aval, i);
+                       } else {
+                               rb_ary_store(aval, i, rb_ary_new3(2, oval, pval));
+                       }
+               }
+       } else {
+               rb_raise(rb_eMolbyError, "Dialog#listen is presently only available for Molecule object");
+       }
+       return self;
+}
+
+/*
+ *  call-seq:
  *     save_panel(message = nil, directory = nil, default_filename = nil, wildcard = nil)
  *
  *  Display the "save as" dialog and returns the fullpath filename.
@@ -1648,12 +1696,9 @@ RubyDialog_GetTableItemText(RubyValue self, RDItem *ip, int row, int column, cha
        int status;
        void *vp[6] = { (void *)self, (void *)ip, (void *)sOnGetValueSymbol, (void *)row, (void *)column, NULL };
        VALUE val = rb_protect(s_RubyDialog_doTableAction, (VALUE)vp, &status);
-       if (status != 0) {
-               Molby_showError(status);
+       if (status != 0 || val == Qnil) {
                buf[0] = 0;
-       } else if (val == Qnil)
-               buf[0] = 0;
-       else {
+       } else {
                strncpy(buf, (char *)vp[5], buflen - 1);
                buf[buflen - 1] = 0;
        }
@@ -1893,19 +1938,39 @@ RubyDialog_doTimerAction(RubyValue self)
        }
 }
 
-int
-RubyDialog_getFlexFlags(RubyValue self, RDItem *ip)
+static VALUE
+s_RubyDialog_getFlexFlags(VALUE val)
 {
+       VALUE self = (VALUE)(((void **)val)[0]);
+       RDItem *ip = (RDItem *)(((void **)val)[1]);
        VALUE itval, pval;
-       RubyDialog *dref = s_RubyDialog_GetController((VALUE)self);
+       RubyDialog *dref = s_RubyDialog_GetController(self);
        int idx = RubyDialogCallback_indexOfItem(dref, ip);
        if (idx < 0)
-               return -1;  /*  No such item (this cannot happen)  */
-       itval = s_RubyDialog_ItemAtIndex((VALUE)self, INT2NUM(idx));
+               return Qnil;  /*  No such item (this cannot happen)  */
+       itval = s_RubyDialog_ItemAtIndex(self, INT2NUM(idx));
        pval = rb_ivar_get(itval, SYM2ID(sFlexSymbol));
        if (pval == Qnil)
-               return -1;  /*  Not set  */
-       else return NUM2INT(rb_Integer(pval));
+               return Qnil;  /*  Not set  */
+       else {
+               pval = rb_Integer(pval);
+               ((void **)val)[2] = (void *)(NUM2INT(pval));
+               return pval;
+       }
+}
+
+int
+RubyDialog_getFlexFlags(RubyValue self, RDItem *ip)
+{
+       int status;
+       VALUE rval;
+       void *args[3] = { (void *)self, (void *)ip, NULL };
+       rval = rb_protect(s_RubyDialog_getFlexFlags, (VALUE)args, &status);
+       if (status != 0)
+               return -1;
+       else if (rval == Qnil)
+               return -1;
+       else return (int)args[2];
 }
 
 #pragma mark ====== Initialize class ======
@@ -1940,6 +2005,7 @@ RubyDialogInitClass(void)
        rb_define_method(rb_cDialog, "size", s_RubyDialog_Size, 0);
        rb_define_method(rb_cDialog, "set_min_size", s_RubyDialog_SetMinSize, -1);
        rb_define_method(rb_cDialog, "min_size", s_RubyDialog_MinSize, 0);
+       rb_define_method(rb_cDialog, "listen", s_RubyDialog_Listen, 3);
        rb_define_singleton_method(rb_cDialog, "save_panel", s_RubyDialog_SavePanel, -1);
        rb_define_singleton_method(rb_cDialog, "open_panel", s_RubyDialog_OpenPanel, -1);
 
@@ -1969,7 +2035,7 @@ RubyDialogInitClass(void)
                        &sMediumSymbol, &sBoldSymbol, &sLightSymbol,
                        &sOnCountSymbol, &sOnGetValueSymbol, &sOnSetValueSymbol, &sOnSelectionChangedSymbol,
                        &sOnSetColorSymbol, &sIsItemEditableSymbol, &sIsDragAndDropEnabledSymbol, &sOnDragSelectionToRowSymbol,
-                       &sSelectionSymbol, &sColumnsSymbol
+                       &sSelectionSymbol, &sColumnsSymbol, &sRefreshSymbol
                };
                static const char *sTable2[] = {
                        "text", "textfield", "radio", "button",
@@ -1989,7 +2055,7 @@ RubyDialogInitClass(void)
                        "medium", "bold", "light",
                        "on_count", "on_get_value", "on_set_value", "on_selection_changed",
                        "on_set_color", "is_item_editable", "is_drag_and_drop_enabled", "on_drag_selection_to_row",
-                       "selection", "columns"
+                       "selection", "columns", "refresh"
                };
                int i;
                for (i = 0; i < sizeof(sTable1) / sizeof(sTable1[0]); i++)
index 5bd7bf7..d9cb6ad 100644 (file)
@@ -82,7 +82,9 @@ STUB void RubyDialogCallback_setWindowSize(RubyDialog *dref, RDSize size);
 
 STUB void RubyDialogCallback_setAutoResizeEnabled(RubyDialog *dref, int flag);
 STUB int RubyDialogCallback_isAutoResizeEnabled(RubyDialog *dref);
+STUB int RubyDialogCallback_Listen(RubyDialog *dref, void *obj, const char *objtype, const char *msg, RubyValue oval, RubyValue pval);
 
+       
 STUB void RubyDialogCallback_createStandardButtons(RubyDialog *dref, const char *oktitle, const char *canceltitle);
 STUB RDItem *RubyDialogCallback_createItem(RubyDialog *dref, const char *type, const char *title, RDRect frame);
 STUB RDItem *RubyDialogCallback_dialogItemAtIndex(RubyDialog *dref, int idx);
index 0a4645d..39ac415 100755 (executable)
@@ -372,9 +372,22 @@ class Molecule
                item(:textfield, :width=>"80", :tag=>"nc", :value=>(get_global_settings("antechamber.nc") || "0")),
                (tool == "resp" ?
                  -1 :
-                 item(:checkbox, :title=>"Optimize structure and calculate charges (may be slow)", :tag=>"calc_charge",
-                   :value=>(get_global_settings("antechamber.calc_charge") || 0),
-                   :action=>proc { |it| set_attr("nc", :enabled=>(it[:value] != 0)) } )),
+                 item(:checkbox, :title=>"Calculate partial charges", :tag=>"calc_charge",
+                   :action=>proc { |it|
+                         set_attr("optimize_structure", :enabled=>(it[:value] != 0)) } )),
+               -1,
+               (tool == "resp" ?
+                 -1 :
+                 layout(2,
+                   item(:view, :width=>"12"),
+                       item(:checkbox, :title=>"Optimize structure before calculating charges (may be slow)",
+                         :tag=>"optimize_structure",
+                         :value=>(get_global_settings("antechamber.optimize_structure") || 0)))),
+               -1,
+               (tool == "resp" ?
+                 -1 :
+                 item(:checkbox, :title=>"Guess atom types", :tag=>"guess_atom_types",
+                   :value=>(get_global_settings("antechamber.guess_atom_types") || 1))),
                -1,
                item(:checkbox, :title=>"Use the residue information for connection analysis", :tag=>"use_residue",
                  :value=>(get_global_settings("antechamber.use_residue") || 0),
@@ -408,6 +421,11 @@ class Molecule
                ),
                -1
          )
+         it = item_with_tag("calc_charge")
+         if it
+           it[:value] = (get_global_settings("antechamber.calc_charge") || 0)
+               it[:action].call(it)
+         end
     }
        hash.each_pair { |key, value|
          next if key == :status
@@ -613,18 +631,22 @@ class Molecule
        
   end
   
-  def import_ac(acfile)
+  def import_ac(acfile, read_charge, read_type)
     open(acfile, "r") { |fp|
          while (s = fp.gets)
            next if s !~ /^ATOM/
                s.chomp!
                idx = Integer(s[4..11]) - 1
-               charge = Float(s[54..63])
-               type = s[72..-1]
-               type.gsub!(/ /, "")
                ap = atoms[idx]
-               ap.charge = charge
-               ap.atom_type = type
+               if read_charge != 0
+                 charge = Float(s[54..63])
+                 ap.charge = charge
+               end
+               if read_type != 0
+                 type = s[72..-1]
+                 type.gsub!(/ /, "")
+                 ap.atom_type = type
+               end
          end
        }
        return 0
index 00daa9c..7d7804b 100644 (file)
@@ -195,6 +195,7 @@ def guess_uff_parameter_dialog(current_value, indices)
   }
   names = indices.map { |i| sprintf("%d:%s", atoms[i].res_seq, atoms[i].name) }
   types = indices.map { |i| atoms[i].atom_type }
+  utypes = indices.map { |i| atoms[i].uff_type }
   names_str = names.join("-")
   types_str = types.join("-")
   recalc = proc { |i1, i2, i3, b1, b2|
@@ -224,7 +225,9 @@ def guess_uff_parameter_dialog(current_value, indices)
       if p.length == 1
         type_selects.push(item(:text, :title=>UFFParams[p[0]][0]))
       else
-        type_selects.push(item(:popup, :subitems=>p.map { |pp| UFFParams[pp][0] }, :tag=>"uff_type_#{i}", :action=>action_proc))
+           subitems = p.map { |pp| UFFParams[pp][0] }
+               uff_idx = subitems.index(utypes[i]) || 0
+        type_selects.push(item(:popup, :subitems=>p.map { |pp| UFFParams[pp][0] }, :tag=>"uff_type_#{i}", :action=>action_proc, :value=>uff_idx))
       end
     }
     bond_orders = []
@@ -252,6 +255,15 @@ def guess_uff_parameter_dialog(current_value, indices)
     )
   }
   if hash[:status] == 0
+    3.times { |i|
+         idx = indices[i]
+         next unless idx
+         ii = uff_types[i][hash["uff_type_#{i}"].to_i]
+         puts "i = #{i}, idx = #{idx}, ii = #{ii}, UFFParams[ii][0] = #{UFFParams[ii][0].inspect}"
+         if ii
+        atoms[idx].uff_type = UFFParams[ii][0]
+      end
+       }
     return hash["guessed"], current_value
   else
     return nil
index 84a55f4..c565d8d 100755 (executable)
@@ -668,7 +668,7 @@ void
 MoleculeView::OnLeftDClickInListCtrl(wxMouseEvent &event)
 {
        listctrl->OnLeftDClick(event);
-       if (mview->tableIndex >= kMainViewBondTableIndex && mview->tableIndex <= kMainViewImproperTableIndex && mview->mol->par != NULL) {
+       if (mview->tableIndex >= kMainViewBondTableIndex && mview->tableIndex <= kMainViewImproperTableIndex /* && mview->mol->par != NULL */ ) {
                int row, col, i;
                char indices[64], names[64], types[64], value[20], partypes[64], params[3][20];
                char *ptype, *parstr;
index 2f739a6..dfbb3e2 100755 (executable)
@@ -485,7 +485,13 @@ MyDocument::Close()
                MyAppCallback_errorMessageBox("%s is running: please stop it before closing", msg);
                return false;
        }
-       return wxDocument::Close();
+       if (wxDocument::Close()) {
+               /*  Send a message that this document will close  */
+               wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_documentWillClose);
+               myEvent.SetEventObject(this);
+               ProcessEvent(myEvent);
+               return true;
+       } else return false;            
 }
 
 void
@@ -1386,7 +1392,7 @@ void
 MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
 {
        char *ante_dir, buf[256];
-       Int net_charge, i, n, calc_charge, use_residue;
+       Int net_charge, i, n, calc_charge, optimize_structure, use_residue, guess_atom_types;
        int status;
 
        /*  Find the ambertool directory  */
@@ -1401,6 +1407,8 @@ MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
 
        if ((status = MyAppCallback_getGlobalSettingsWithType("antechamber.nc", 'i', &net_charge))
                || (status = MyAppCallback_getGlobalSettingsWithType("antechamber.calc_charge", 'i', &calc_charge))
+               || (status = MyAppCallback_getGlobalSettingsWithType("antechamber.optimize_structure", 'i', &optimize_structure))
+               || (status = MyAppCallback_getGlobalSettingsWithType("antechamber.guess_atom_types", 'i', &guess_atom_types))
                || (status = MyAppCallback_getGlobalSettingsWithType("antechamber.use_residue", 'i', &use_residue))) {
                Molby_showError(status);
                return;
@@ -1456,6 +1464,7 @@ MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
        {
                /*  Run antechamber and parmck  */
                char *p;
+               int j_option = 4;
 
                /*  Set AMBERHOME environment variable if necessary  */
                n = strlen(ante_dir);
@@ -1473,15 +1482,20 @@ MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
                }
                
                if (calc_charge) {
-                       snprintf(buf, sizeof buf, "-nc %d -c bcc", net_charge);
+                       snprintf(buf, sizeof buf, "-nc %d -c bcc %s", net_charge,
+                                        (optimize_structure ? "" : " -ek 'maxcyc=0'"));
                } else buf[0] = 0;
 
-               asprintf(&p, "\"%s/antechamber\" -i mol.pdb -fi pdb -o mol.ac -fo ac %s", ante_dir, buf);
+               if (!guess_atom_types) {
+                       j_option = 0;
+               }
+               
+               asprintf(&p, "\"%s/antechamber\" -i mol.pdb -fi pdb -o mol.ac -fo ac -j %d %s", ante_dir, j_option, buf);
 
                status = MyAppCallback_callSubProcess(p, "antechamber", NULL, NULL);
                if (status != 0) {
                        MyAppCallback_errorMessageBox("Antechamber failed: status = %d.", status);
-               } else {
+               } else if (guess_atom_types) {
                        asprintf(&p, "\"%s/parmchk\" -i mol.ac -f ac -o frcmod", ante_dir);
                        status = MyAppCallback_callSubProcess(p, "parmchk", NULL, NULL);
                        if (status != 0)
@@ -1491,7 +1505,7 @@ MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
 
        if (status == 0) {
                wxString acfile = tdir + wxFileName::GetPathSeparator() + _T("mol.ac");
-               status = MolActionCreateAndPerform(mol, SCRIPT_ACTION("s"), "import_ac", (const char *)acfile.mb_str(wxConvFile));
+               status = MolActionCreateAndPerform(mol, SCRIPT_ACTION("sii"), "import_ac", (const char *)acfile.mb_str(wxConvFile), calc_charge, guess_atom_types);
                if (status != 0) {
                        MyAppCallback_errorMessageBox("Cannot import antechamber output.");
                }
@@ -1507,7 +1521,7 @@ MyDocument::OnInvokeAntechamber(wxCommandEvent &event)
                }
        }
 
-       if (status == 0) {
+       if (guess_atom_types && status == 0) {
                wxString frcmodfile = tdir + wxFileName::GetPathSeparator() + _T("frcmod");
                status = MolActionCreateAndPerform(mol, SCRIPT_ACTION("s"), "import_frcmod", (const char *)frcmodfile.mb_str(wxConvFile));
                if (status != 0) {
@@ -1737,6 +1751,7 @@ MoleculeCallback_notifyModification(Molecule *mp, int now_flag)
        if (doc && !doc->isModifyNotificationSent) {
                doc->isModifyNotificationSent = true;
                wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_documentModified);
+               myEvent.SetEventObject(doc);
                if (now_flag)
                        doc->ProcessEvent(myEvent);
                else
index a27f375..1b1f56d 100755 (executable)
@@ -37,7 +37,8 @@ enum {
        MyDocumentEvent_updateDisplay,
        MyDocumentEvent_insertFrameFromMD,
        MyDocumentEvent_threadTerminated,
-       MyDocumentEvent_openFilesByIPC
+       MyDocumentEvent_openFilesByIPC,
+       MyDocumentEvent_documentWillClose
 };
 
 class MyDocument: public wxDocument
index fa411a0..d6feda9 100644 (file)
@@ -32,6 +32,7 @@
 #include "RubyDialogFrame.h"
 #include "MyApp.h"
 #include "MyMBConv.h"
+#include "MyDocument.h"
 
 BEGIN_EVENT_TABLE(RubyDialogFrame, wxDialog)
   EVT_TIMER(-1, RubyDialogFrame::OnTimerEvent)
@@ -48,7 +49,9 @@ RubyDialogFrame::RubyDialogFrame(wxWindow* parent, wxWindowID wid, const wxStrin
        dval = NULL;
        mySize = gZeroSize;
        autoResizeEnabled = true;
-
+       messageData = NULL;
+       countMessageData = 0;
+       
        //  Create a vertical box sizer that contains a panel containing all controls and a sizer containing
        //  OK/Cancel buttons
        contentSizer = new wxBoxSizer(wxVERTICAL);
@@ -64,10 +67,16 @@ RubyDialogFrame::RubyDialogFrame(wxWindow* parent, wxWindowID wid, const wxStrin
 
 RubyDialogFrame::~RubyDialogFrame()
 {
+       int i;
        if (myTimer != NULL)
                delete myTimer;
        if (ditems != NULL)
                free(ditems);
+       for (i = 0; i < countMessageData; i++) {
+               if (messageData[i * 5] != NULL) {
+                       ((wxEvtHandler *)messageData[i * 5])->Disconnect((int)messageData[i * 5 + 1], (wxEventType)messageData[i * 5 + 2], wxCommandEventHandler(RubyDialogFrame::HandleDocumentEvent));
+               }
+       }       
 }
 
 int
@@ -209,82 +218,177 @@ RubyDialogFrame::OnTimerEvent(wxTimerEvent &event)
        RubyDialog_doTimerAction((RubyValue)dval);
 }
 
+static void
+sResizeSubWindows(RubyValue dval, wxWindow *win, int dx, int dy)
+{
+       wxWindowList & children = win->GetChildren();
+       wxWindowList::Node *node;
+       for (node = children.GetFirst(); node; node = node->GetNext()) {
+               int i, d, f, d1, d2, d3, ddx, ddy;
+               wxWindow *current = (wxWindow *)node->GetData();
+               wxRect frame = current->GetRect();
+               int flex = RubyDialog_getFlexFlags(dval, (RDItem *)current);
+               if (flex < 0)
+                       continue;               
+               for (i = 0, f = flex; i < 2; i++, f /= 2) {
+                       if (i == 0)
+                               d = dx;
+                       else
+                               d = dy;
+                       switch (f & 21) {  /*  left, right, width (or top, bottom, height) */
+                               case 21:  /*  all flex  */
+                                       d1 = d2 = d / 3;
+                                       d3 = d - d1 - d2;
+                                       break;
+                               case 5:   /*  left & right  */
+                                       d1 = d / 2;
+                                       d2 = 0;
+                                       d3 = d - d1;
+                                       break;
+                               case 17:  /*  left & width  */
+                                       d1 = d / 2;
+                                       d2 = d - d1;
+                                       d3 = 0;
+                                       break;
+                               case 20:  /*  right & width  */
+                                       d1 = 0;
+                                       d2 = d / 2;
+                                       d3 = d - d2;
+                                       break;
+                               case 1:   /*  left  */
+                                       d1 = d;
+                                       d2 = d3 = 0;
+                                       break;
+                               case 4:   /*  right */
+                                       d3 = d;
+                                       d1 = d2 = 0;
+                                       break;
+                               case 16:  /*  width  */
+                                       d2 = d;
+                                       d1 = d3 = 0;
+                                       break;
+                       }
+                       if (i == 0) {
+                               frame.x += d1;
+                               frame.width += d2;
+                               ddx = d2;
+                       } else {
+                               frame.y += d1;
+                               frame.height += d2;
+                               ddy = d2;
+                       }
+               }
+               if (ddx != 0 || ddy != 0)
+                       sResizeSubWindows(dval, current, ddx, ddy);
+               current->SetSize(frame);
+       }
+}
+
 void
 RubyDialogFrame::OnSize(wxSizeEvent &event)
 {
        wxSize size = GetClientSize();
        if (mySize.width != 0 && mySize.height != 0 && /*(mySize.width != size.x || mySize.height != size.y) &&*/ autoResizeEnabled) {
                /*  Resize the subviews  */
-               int i;
-               for (i = 2; i < nditems; i++) {
-                       RDItem *item = ditems[i];
-                       int glue = RubyDialog_getFlexFlags((RubyValue)dval, item);
-                       if (glue >= 0) {
-                               RDRect frame = RubyDialogCallback_frameOfItem(item);
-                               switch (glue & 5) {
-                                       case 5: /* left & right */
-                                               frame.size.width += size.x - mySize.width;
-                                               break;
-                                       case 4: /* right */
-                                               frame.origin.x += size.x - mySize.width;
-                                               break;
-                               }
-                               switch (glue & 10) {
-                                       case 10: /* top & bottom */
-                                               frame.size.height += size.y - mySize.height;
-                                               break;
-                                       case 8: /* bottom */
-                                               frame.origin.y += size.y - mySize.height;
-                                               break;
-                               }
-                               RubyDialogCallback_setFrameOfItem(item, frame);
-                       } else if (wxDynamicCast((wxWindow *)item, wxPanel) != NULL) {
-                               wxWindowList & children = ((wxWindow *)item)->GetChildren();
-                               wxWindowList::Node *node;
-                               wxRect thisRect, origRect, thatRect;
-                               int count = 0, dx, dy;
-                               origRect = ((wxWindow *)item)->GetRect();
-                               for (node = children.GetFirst(); node; node = node->GetNext(), count++) {
-                                       wxWindow *current = (wxWindow *)node->GetData();
-                                       thatRect = current->GetRect();
-                                       if (count == 0) {
-                                               thisRect = thatRect;
-                                               continue;
-                                       }
-                                       if (thisRect.x > thatRect.x) {
-                                               thisRect.width += thisRect.x - thatRect.x;
-                                               thisRect.x = thatRect.x;
-                                       }
-                                       if (thisRect.y > thatRect.y) {
-                                               thisRect.height += thisRect.y - thatRect.y;
-                                               thisRect.y = thatRect.y;
-                                       }
-                                       if (thatRect.x + thatRect.width > thisRect.x + thisRect.width)
-                                               thisRect.width = thatRect.x + thatRect.width - thisRect.x;
-                                       if (thatRect.y + thatRect.height > thisRect.y + thisRect.height)
-                                               thisRect.height = thatRect.y + thatRect.height - thisRect.y;
-                               }
-                               /*  Resize the view, while keeping the subviews at the same window position */
-                               dx = thisRect.x;
-                               dy = thisRect.y;
-                               for (node = children.GetFirst(); node; node = node->GetNext()) {
-                                       wxWindow *current = (wxWindow *)node->GetData();
-                                       thatRect = current->GetRect();
-                                       current->Move(thatRect.x - dx, thatRect.y - dy);
-                               }
-                               origRect.x += dx;
-                               origRect.y += dy;
-                               origRect.width = thisRect.width;
-                               origRect.height = thisRect.height;
-                               ((wxWindow *)item)->SetSize(origRect);
-                       }
-               }
+               sResizeSubWindows((RubyValue)dval, this, size.x - mySize.width, size.y - mySize.height);
        }
        mySize.width = size.x;
        mySize.height = size.y;
        event.Skip();
 }
 
+int
+RubyDialogFrame::ListenToObject(void *obj, const char *objtype, const char *msg, RubyValue oval, RubyValue pval)
+{
+       int i, j, eventId;
+       wxEventType eventType;
+       wxEvtHandler *handler;
+       if (strcmp(objtype, "Molecule") == 0) {
+               eventType = MyDocumentEvent;
+               handler = MyDocumentFromMolecule((Molecule *)obj);
+               if (handler == NULL)
+                       return -1;  /*  obj is not an event handler  */
+               if (msg == NULL)
+                       eventId = -1;
+               else if (strcmp(msg, "documentModified") == 0)
+                       eventId = MyDocumentEvent_documentModified;
+               else if (strcmp(msg, "documentWillClose") == 0)
+                       eventId = MyDocumentEvent_documentWillClose;
+               else return -2; /*  this event type is not supported  */
+       } else return -1;
+       
+       if (pval == NULL || pval == RubyNil) {
+               /*  Remove the registration  */
+               for (i = 0; i < countMessageData; i++) {
+                       if (messageData[i * 5] == (void *)handler && 
+                               messageData[i * 5 + 1] == (void *)eventId &&
+                               messageData[i * 5 + 2] == (void *)eventType) {
+                               handler->Disconnect(eventId, eventType, wxCommandEventHandler(RubyDialogFrame::HandleDocumentEvent));
+                               break;
+                       }
+               }
+               if (i == countMessageData)
+                       return -3;  /*  No such message  */
+               messageData[i * 5] = NULL;
+               return i;
+       } else {
+               /*  Check the duplicate  */
+               j = countMessageData;  /*  The position to store info if it is new  */
+               for (i = 0; i < countMessageData; i++) {
+                       if (messageData[i * 5] == (void *)handler && 
+                               messageData[i * 5 + 1] == (void *)eventId &&
+                               messageData[i * 5 + 2] == (void *)eventType) {
+                               /*  Just replace the arguments  */
+                               messageData[i * 5 + 3] = (void *)oval;
+                               messageData[i * 5 + 4] = (void *)pval;
+                               break;
+                       }
+                       if (messageData[i * 5] == NULL)
+                               j = i;
+               }
+               if (i == countMessageData) {
+                       /*  Register the data and establish a new connection  */
+                       if (j == countMessageData) {
+                               /*  Create a new entry  */
+                               InsertArray(&messageData, &countMessageData, sizeof(void *) * 5, i, 1, NULL);
+                       }
+                       messageData[j * 5] = (void *)handler;
+                       messageData[j * 5 + 1] = (void *)eventId;
+                       messageData[j * 5 + 2] = (void *)eventType;
+                       messageData[j * 5 + 3] = (void *)oval;
+                       messageData[j * 5 + 4] = (void *)pval;
+                       handler->Connect(eventId, eventType, wxCommandEventHandler(RubyDialogFrame::HandleDocumentEvent), NULL, this);
+                       i = j;
+               }
+               return i;
+       }
+}
+
+void
+RubyDialogFrame::HandleDocumentEvent(wxCommandEvent &event)
+{
+       int i;
+       int eventId = event.GetId();
+       int eventType = event.GetEventType();
+       wxObject *eventObject = event.GetEventObject();
+               
+       /*  Look up the message table  */
+       for (i = 0; i < countMessageData; i++) {
+               if (messageData[i * 5] == (void *)eventObject && 
+                       messageData[i * 5 + 1] == (void *)eventId &&
+                       messageData[i * 5 + 2] == (void *)eventType) {
+                       int status;
+                       RubyValue oval = (RubyValue)messageData[i * 5 + 3];
+                       RubyValue pval = (RubyValue)messageData[i * 5 + 4];
+                       Ruby_funcall2_protect_extern(pval, g_RubyID_call, 1, &oval, &status);
+/*                     if (status != 0) {
+                               Molby_showError(status);
+                       } */
+               }
+       }
+       event.Skip();
+}
+
 #pragma mark ====== MyListCtrlDataSource methods ======
 
 int
@@ -488,6 +592,12 @@ RubyDialogCallback_isAutoResizeEnabled(RubyDialog *dref)
        return ((RubyDialogFrame *)dref)->IsAutoResizeEnabled();
 }
 
+int
+RubyDialogCallback_Listen(RubyDialog *dref, void *obj, const char *objtype, const char *msg, RubyValue oval, RubyValue pval)
+{
+       return ((RubyDialogFrame *)dref)->ListenToObject(obj, objtype, msg, oval, pval);
+}
+
 void
 RubyDialogCallback_createStandardButtons(RubyDialog *dref, const char *oktitle, const char *canceltitle)
 {
index 0bb554e..fdb8c42 100644 (file)
@@ -41,12 +41,19 @@ public:
        RDSize mySize;  /*  Previous size  */
        bool autoResizeEnabled;  /*  true if auto resizing is enabled  */
        
+       /*  Message bridge (with Ruby world); obj, objtype, msg, pval  */
+       void **messageData;
+       Int countMessageData;
+       
        RubyDialogFrame(wxWindow* parent, wxWindowID wid, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE);
        virtual ~RubyDialogFrame();
 
        void SetAutoResizeEnabled(int flag) { autoResizeEnabled = (flag != 0); }
        bool IsAutoResizeEnabled() { return autoResizeEnabled; }
        
+       int ListenToObject(void *obj, const char *objtype, const char *msg, RubyValue oval, RubyValue pval);
+       void HandleDocumentEvent(wxCommandEvent &event);
+       
        int AddDialogItem(RDItem *item);
        RDItem *DialogItemAtIndex(int index);
        int SearchDialogItem(RDItem *item);