From 7726880387864bc9c9cdfad4b51eaf1583ffb63d Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Wed, 20 Feb 2019 20:35:16 -0500
Subject: [PATCH] add autopatching y offsets per fontsize and ability to change
 y-offset in prefs

---
 pd/nw/dialog_prefs.html           | 44 +++++++++++++++++++++++++++++--
 pd/nw/locales/de/translation.json |  3 +++
 pd/nw/locales/en/translation.json |  3 +++
 pd/nw/pdgui.js                    |  6 +++--
 pd/src/g_text.c                   | 26 ++++++++++++++++--
 pd/src/m_glob.c                   | 27 ++++++++++++-------
 pd/src/s_file.c                   |  7 ++++-
 7 files changed, 100 insertions(+), 16 deletions(-)

diff --git a/pd/nw/dialog_prefs.html b/pd/nw/dialog_prefs.html
index 245376117..63b18f488 100644
--- a/pd/nw/dialog_prefs.html
+++ b/pd/nw/dialog_prefs.html
@@ -385,6 +385,17 @@
               <input type="checkbox" id="save_zoom" name="save_zoom">
               <span data-i18n="prefs.gui.zoom.save_zoom"></span>
             </label>
+            <br/>
+            <label data-i18n="[title]prefs.gui.autopatch_yoffset_checkbox_tt">
+              <input type="checkbox" id="autopatch_yoffset"
+                     name="autopatch_yoffset"
+                     onchange="autopatch_yoffset_toggle(this.checked);">
+            <span data-i18n="prefs.gui.autopatch_yoffset"></span></span>:
+            </label>
+            <input type="text"
+                   id="autopatch_yoffset_value"
+                   name="autopatch_yoffset_value"
+                   data-i18n="[title]prefs.gui.autopatch_yoffset_tt">
             <br/><br/>
             <span data-i18n="prefs.gui.browser.browser_title"></span>
             <br/>
@@ -500,6 +511,14 @@ function get_bool_elem(elem) {
     return +document.getElementById(elem).checked;
 }
 
+function get_autopatch_yoffset() {
+    if (get_bool_elem("autopatch_yoffset")) {
+        return document.getElementById("autopatch_yoffset_value").value;
+    } else {
+        return "0";
+    }
+}
+
 // startup config data
 
 // XXXTODO: We should maybe include these in the dialog, but the startup tab
@@ -721,7 +740,14 @@ function apply(save_prefs) {
     // Send the gui prefs (currently just the name of the gui preset, the
     // status of the save-zoom toggle and various options related to the help
     // browser) to Pd
-    pdgui.pdsend("pd gui-prefs", get_gui_preset(), get_bool_elem("save_zoom"), get_bool_elem("browser_doc"), get_bool_elem("browser_path"), get_bool_elem("browser_init"));
+    pdgui.pdsend("pd gui-prefs",
+        get_gui_preset(),
+        get_bool_elem("save_zoom"),
+        get_bool_elem("browser_doc"),
+        get_bool_elem("browser_path"),
+        get_bool_elem("browser_init"),
+        get_autopatch_yoffset()
+    );
 
     // Send the startup config data to Pd
     pdgui.pdsend.apply(null, ["pd path-dialog", startup_use_stdpath, startup_verbose].concat(get_path_array()));
@@ -960,7 +986,13 @@ function midi_prefs_callback(attrs) {
     pdgui.resize_window(pd_object_callback);
 }
 
-function gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init) {
+function autopatch_yoffset_toggle(checked) {
+    document.getElementById("autopatch_yoffset_value").disabled = !checked;
+    document.getElementById("autopatch_yoffset").checked = checked;
+}
+
+function gui_prefs_callback(name, save_zoom, browser_doc, browser_path,
+    browser_init, autopatch_yoffset) {
     var s = document.getElementById("gui_preset"),
         i;
     for (i = 0; i < s.options.length; i++) {
@@ -973,6 +1005,14 @@ function gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_
     document.getElementById("browser_doc").checked = !!browser_doc;
     document.getElementById("browser_path").checked = !!browser_path;
     document.getElementById("browser_init").checked = !!browser_init;
+
+    if (+autopatch_yoffset !== 0) {
+        document.getElementById("autopatch_yoffset_value").value =
+            autopatch_yoffset;
+        autopatch_yoffset_toggle(true);
+    } else {
+        autopatch_yoffset_toggle(false);
+    }
 }
 
 // startup settings
diff --git a/pd/nw/locales/de/translation.json b/pd/nw/locales/de/translation.json
index 9eb94414e..216b0d328 100644
--- a/pd/nw/locales/de/translation.json
+++ b/pd/nw/locales/de/translation.json
@@ -389,6 +389,9 @@
       "del_tt": "Lösche das ausgewählte Element"
     },
     "gui": {
+      "autopatch_yoffset_tt": "specify a distance in pixels from the bottom of the object to which the new object will be connected",
+      "autopatch_yoffset": "custom autopatching y-offset",
+      "autopatch_yoffset_checkbox_tt": "check to enable a custom autopatching y-offset",
       "presets": {
         "gui_preset": "GUI-Preset",
         "gui_preset_tt": "Kollektion von Patch-Farben und -Stilen",
diff --git a/pd/nw/locales/en/translation.json b/pd/nw/locales/en/translation.json
index 57f658c22..e7a851019 100644
--- a/pd/nw/locales/en/translation.json
+++ b/pd/nw/locales/en/translation.json
@@ -390,6 +390,9 @@
       "del_tt": "Delete the selected item"
     },
     "gui": {
+      "autopatch_yoffset_tt": "specify a distance in pixels from the bottom of the object to which the new object will be connected",
+      "autopatch_yoffset": "custom autopatching y-offset",
+      "autopatch_yoffset_checkbox_tt": "check to enable a custom autopatching y-offset",
       "presets": {
         "gui_preset": "GUI preset",
         "gui_preset_tt": "Collection of patch colors and styles",
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index e4ae68a11..ddb88b2e7 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -5401,9 +5401,11 @@ function gui_midi_properties(gfxstub, sys_indevs, sys_outdevs,
     }
 }
 
-function gui_gui_properties(dummy, name, save_zoom, browser_doc, browser_path, browser_init) {
+function gui_gui_properties(dummy, name, save_zoom, browser_doc, browser_path,
+    browser_init, autopatch_yoffset) {
     if (dialogwin["prefs"] !== null) {
-        dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init);
+        dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom,
+            browser_doc, browser_path, browser_init, autopatch_yoffset);
     }
 }
 
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index 30affd0b9..45b1db4df 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -262,6 +262,28 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix,
     }
 }
 
+
+extern int sys_autopatch_yoffset;
+static int get_autopatch_yoffset(t_canvas *x)
+{
+    if (sys_autopatch_yoffset)
+        return sys_autopatch_yoffset;
+    else
+    {
+        int fontsize = glist_getfont(x);
+        switch (fontsize)
+        {
+        case 8: return 8;
+        case 10: return 8;
+        case 12: return 9;
+        case 16: return 10;
+        case 24: return 13;
+        case 36: return 18;
+        }
+        return 10;
+    }
+}
+
 extern int sys_noautopatch;
 extern t_gobj *glist_nth(t_glist *x, int n);
 extern int glist_getindex(t_glist *x, t_gobj *y);
@@ -302,7 +324,7 @@ void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
                 gobj_getrect(g, x, &x1, &y1, &x2, &y2);
                 indx = nobj;
                 *xpixp = x1;
-                *ypixp = y2 + 5;
+                *ypixp = y2 + get_autopatch_yoffset(x);
             }
         }
         glist_noselect(x);
@@ -358,7 +380,7 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         post("unable to create stub object in closed canvas!");
     else
     {
-            /* interactively create new obect */
+            /* interactively create new object */
         t_binbuf *b = binbuf_new();
         int connectme, xpix, ypix, indx, nobj;
         canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index 42e135d0d..b3ed14c9f 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -75,21 +75,30 @@ static void glob_perf(t_pd *dummy, float f)
     sys_perf = (f != 0);
 }
 
-extern int sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init;
+extern int sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init,
+    sys_autopatch_yoffset;
 extern t_symbol *sys_gui_preset;
-static void glob_gui_prefs(t_pd *dummy, t_symbol *s, float f, float f2, float f3, float f4)
+static void glob_gui_prefs(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
 {
-    sys_gui_preset = s;
-    sys_zoom = !!(int)f;
-    sys_browser_doc = !!(int)f2;
-    sys_browser_path = !!(int)f3;
-    sys_browser_init = !!(int)f4;
+    sys_gui_preset = atom_getsymbolarg(0, argc--, argv++);
+    sys_zoom = !!atom_getintarg(0, argc--, argv++);
+    sys_browser_doc = !!atom_getintarg(0, argc--, argv++);
+    sys_browser_path = !!atom_getintarg(0, argc--, argv++);
+    sys_browser_init = !!atom_getintarg(0, argc--, argv++);
+    sys_autopatch_yoffset = atom_getintarg(0, argc--, argv++);
 }
 
 /* just the gui-preset, the save-zoom toggle and various help browser options for now */
 static void glob_gui_properties(t_pd *dummy)
 {
-    gui_vmess("gui_gui_properties", "xsiiii", 0, sys_gui_preset->s_name, sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init);
+    gui_vmess("gui_gui_properties", "xsiiiii",
+        dummy,
+        sys_gui_preset->s_name,
+        sys_zoom,
+        sys_browser_doc,
+        sys_browser_path,
+        sys_browser_init,
+        sys_autopatch_yoffset);
 }
 
 // ths one lives inside g_editor so that it can access the clipboard
@@ -175,7 +184,7 @@ void glob_init(void)
     class_addmethod(glob_pdobject, (t_method)glob_clipboard_text,
         gensym("clipboardtext"), A_FLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_gui_prefs,
-        gensym("gui-prefs"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+        gensym("gui-prefs"), A_GIMME, 0);
     class_addmethod(glob_pdobject, (t_method)glob_gui_properties,
         gensym("gui-properties"), 0);
     class_addmethod(glob_pdobject, (t_method)glob_recent_files,
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index 30a39d61a..acc8fa447 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -40,7 +40,8 @@
 #define snprintf sprintf_s
 #endif
 
-int sys_defeatrt, sys_zoom, sys_browser_doc = 1, sys_browser_path, sys_browser_init;
+int sys_defeatrt, sys_autopatch_yoffset, sys_zoom, sys_browser_doc = 1,
+    sys_browser_path, sys_browser_init;
 t_symbol *sys_flags = &s_;
 void sys_doflags( void);
 
@@ -675,6 +676,8 @@ void sys_loadpreferences( void)
         sscanf(prefbuf, "%d", &sys_browser_path);
     if (sys_getpreference("browser_init", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &sys_browser_init);
+    if (sys_getpreference("autopatch_yoffset", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &sys_autopatch_yoffset);
     if (sys_getpreference("guipreset", prefbuf, MAXPDSTRING))
     {
         char preset_buf[MAXPDSTRING];
@@ -820,6 +823,8 @@ void glob_savepreferences(t_pd *dummy)
     sys_putpreference("browser_path", buf1);
     sprintf(buf1, "%d", sys_browser_init);
     sys_putpreference("browser_init", buf1);
+    sprintf(buf1, "%d", sys_autopatch_yoffset);
+    sys_putpreference("autopatch_yoffset", buf1);
     sys_putpreference("guipreset", sys_gui_preset->s_name);
     sys_putpreference("flags", 
         (sys_flags ? sys_flags->s_name : ""));
-- 
GitLab