From f01bb163c9264741984ffe45ba46d665c203c64c Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Mon, 21 Dec 2015 22:43:29 -0500
Subject: [PATCH] second draft of iemgui handles--- still some bugs when
 switching between canvas gop rect and iemguis

---
 pd/nw/pd_canvas.js  |  56 +++++++++++++++++++++-
 pd/nw/pdgui.js      | 114 ++++++++++++++++++++++++++++++++------------
 pd/src/g_all_guis.c |  37 ++++++++++----
 pd/src/g_bang.c     |  24 +++-------
 pd/src/g_canvas.c   |  62 +++++++++++++++++-------
 pd/src/g_editor.c   |  31 ++++++++++++
 pd/src/g_mycanvas.c |  36 ++------------
 pd/src/g_numbox.c   |  71 +++++++++++----------------
 pd/src/g_radio.c    |  29 ++---------
 pd/src/g_slider.c   |  27 ++---------
 pd/src/g_toggle.c   |  23 ++-------
 pd/src/g_vumeter.c  |  26 ++--------
 12 files changed, 301 insertions(+), 235 deletions(-)

diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index f0f399424..a6d5dc94e 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -83,7 +83,7 @@ var canvas_events = (function() {
     var name,
         state,
         scalar_draggables = {}, // elements of a scalar which have the "drag" event enabled
-        draggable_elem,         // the current scalar element being dragged
+        draggable_elem,         // last scalar we dragged
         last_draggable_x,       // last x coord for the element we're dragging
         last_draggable_y,       // last y 
         previous_state = "none", /* last state, excluding explicit 'none' */
@@ -118,8 +118,20 @@ var canvas_events = (function() {
                 return false;
             },
             mousedown: function(evt) {
+                var target_id;
                 if (target_is_scrollbar(evt)) {
                     return;
+                } else if (evt.target.id === "clickable_resize_handle") {
+                    // get id ("x123456etcgobj" without the "x" or "gobj")
+                    target_id = "_h" +
+                        evt.target.parentNode.id.slice(0,-4).slice(1);
+                    last_draggable_x = evt.pageX + svg_view.x;
+                    last_draggable_y = evt.pageY + svg_view.y;
+                    pdgui.pdsend(target_id, "_click", 1,
+                        (evt.pageX + svg_view.x),
+                        (evt.pageY + svg_view.y));
+                    canvas_events.iemgui_label_drag();
+                    return;
                 }
                 // tk events (and, therefore, Pd evnets) are one greater
                 // than html5...
@@ -373,6 +385,35 @@ var canvas_events = (function() {
             },
             scalar_draggable_mouseup: function(evt) {
                 canvas_events.normal();
+            },
+            iemgui_label_mousemove: function(evt) {
+                var dx = (evt.pageX + svg_view.x) - last_draggable_x,
+                    dy = (evt.pageY + svg_view.y) - last_draggable_y,
+                    handle_elem =
+                        document.getElementById("clickable_resize_handle"),
+                    target_id = "_h" +
+                        handle_elem.parentNode.id.slice(0,-4).slice(1),
+                    is_canvas_gop_rect = document.
+                        getElementsByClassName("gop_drag_handle").length ?
+                        true : false;
+
+                last_draggable_x = evt.pageX + svg_view.x;
+                last_draggable_y = evt.pageY + svg_view.y;
+
+                if (!is_canvas_gop_rect) {
+                    handle_elem.x.baseVal.value += dx;
+                    handle_elem.y.baseVal.value += dy;
+                }
+
+                pdgui.pdsend(target_id, "_motion",
+                    (evt.pageX + svg_view.x),
+                    (evt.pageY + svg_view.y));
+            },
+            iemgui_label_mouseup: function(evt) {
+                pdgui.post("lifting the mousebutton on an iemgui label");
+                // Set last state (none doesn't count as a state)
+                pdgui.post("previous state is " + canvas_events.get_previous_state());
+                canvas_events[canvas_events.get_previous_state()]();
             }
         },
         utils = {
@@ -497,6 +538,16 @@ var canvas_events = (function() {
             document.addEventListener("mousemove", events.scalar_draggable_mousemove, false);
             document.addEventListener("mouseup", events.scalar_draggable_mouseup, false);
         },
+        iemgui_label_drag: function() {
+            // This is a workaround for dragging iemgui labels. Resizing iemguis
+            // currently happens in Pd (canvas_doclick and canvas_motion). (Look
+            // for MA_RESIZE.)
+            this.none();
+            document.addEventListener("mousemove",
+                events.iemgui_label_mousemove, false);
+            document.addEventListener("mouseup",
+                events.iemgui_label_mouseup, false);
+        },
         text: function() {
             this.none();
 
@@ -558,7 +609,8 @@ var canvas_events = (function() {
             if (scalar_draggables[id]) {
                 scalar_draggables[id] = null;
             }
-        }
+        },
+        clickable_resize_handle: false // this can be removed...
     }
 }());
 
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index ec7d0fb4e..7b6078d6b 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -1826,23 +1826,29 @@ function gui_toggle_update(cid, tag, state, color) {
     }
 }
 
+function numbox_data_string(w, h) {
+    return ["M", 0, 0,
+            "L", w - 4, 0,
+                 w, 4,
+                 w, h,
+                 0, h,
+            "z",
+            "L", 0, 0,
+                 (h / 2)|0, (h / 2)|0, // |0 to force int
+                 0, h]
+    .join(" ");
+}
+
 // Todo: send fewer parameters from c
-function gui_create_numbox(width,cid,tag,bgcolor,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,basex,basey,half, is_toplevel) {
-    // numbox doesn't have a standard iemgui border, so we must create its gobj manually
-    var g = gui_text_create_gobj(cid, tag, "iemgui", basex, basey, is_toplevel),
-        data_array,
+function gui_create_numbox(cid, tag, bgcolor, x, y, w, h, is_toplevel) {
+    // numbox doesn't have a standard iemgui border,
+    // so we must create its gobj manually
+    var g = gui_text_create_gobj(cid, tag, "iemgui", x, y, is_toplevel),
+        data,
         border;
-    data_array = ["M", p1 - basex, p2 - basey,
-                  "L", p3 - basex, p4 - basey,
-                       p5 - basex, p6 - basey,
-                       p7 - basex, p8 - basey,
-                       p9 - basex, p10 - basey,
-                  "z",
-                  "L", basex - basex, basey - basey,
-                       half, half,
-                       p9 - basex, p10 - basey];
+    data = numbox_data_string(w, h);
     border = create_item(cid, "path", {
-        d: data_array.join(" "),
+        d: data,
         fill: bgcolor,
         stroke: "black",
         "stroke-width": 1,
@@ -1852,12 +1858,21 @@ function gui_create_numbox(width,cid,tag,bgcolor,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,
     g.appendChild(border);
 }
 
+function gui_numbox_coords(cid, tag, w, h) {
+    var b = get_item(cid, tag + "border");
+    configure_item(b, {
+        d: numbox_data_string(w, h)
+    });
+}
+
 function gui_numbox_drawtext(cid,tag,text,font_size,color,xpos,ypos,basex,basey) {
+    // kludge alert -- I'm not sure why I need to add half to the ypos
+    // below. But it works for most font sizes.
     var g = get_gobj(cid, tag),
         svg_text = create_item(cid, "text", {
             transform: "translate(" +
                         (xpos - basex) + "," +
-                        (ypos - basey + 5) + ")",
+                        ((ypos - basey + (ypos - basey) * 0.5)|0) + ")",
             "font-size": font_size,
             fill: color,
             id: tag + "text"
@@ -1869,9 +1884,21 @@ function gui_numbox_drawtext(cid,tag,text,font_size,color,xpos,ypos,basex,basey)
 
 function gui_update_numbox(cid, tag, fcolor, bgcolor, font_name, font_size, font_weight) {
     var b = get_item(cid, tag + "border"),
-        text = get_item(cid, tag + "text");
+        text = get_item(cid, tag + "text"),
+        label = get_item(cid, tag + "label");
     configure_item(b, { fill: bgcolor });
     configure_item(text, { fill: fcolor, "font-size": font_size });
+    // Update the label if one exists
+    if (label) {
+        gui_iemgui_label_font(cid, tag, font_name, font_weight, font_size);
+    }
+}
+
+function gui_update_numbox_text_position(cid, tag, x, y) {
+    var text = get_item(cid, tag + "text");
+    configure_item(text, {
+        transform: "translate( " + x + "," + ((y + y*0.5)|0) + ")"
+    });
 }
 
 function gui_create_slider(cid,tag,color,p1,p2,p3,p4,basex, basey) {
@@ -2065,7 +2092,11 @@ function gui_update_vumeter_rect(cid, tag, color) {
 // of this?
 function gui_vumeter_border_coords(cid, tag, width, height) {
     var r = get_item(cid, tag + "border");
-    configure_item(r, { width: width, height: height });
+    // also need to check for existence-- apparently the iemgui
+    // dialog will delete the vu and try to set this before recreating it...
+    if (r) {
+        configure_item(r, { width: width, height: height });
+    }
 }
 
 function gui_update_vumeter_peak(cid, tag, width) {
@@ -2260,17 +2291,25 @@ function gui_iemgui_label_show_drag_handle(cid, tag, state, x, y) {
     if (state !== 0) {
 post("did thisbranch with cid as " + cid);
         rect = create_item(cid, "rect", {
-            x: x,
-            y: y,
-            width: 10,
-            height: 10,
-            id: "iemgui_label_handle"
+            x: x - 4,
+            y: y + 3,
+            width: 7,
+            height: 7,
+            id: "clickable_resize_handle",
+            class: (cid === tag) ? "gop_drag_handle" : "label_drag_handle"
         });
         gobj.appendChild(rect);
+        patchwin[cid].window.canvas_events.clickable_resize_handle = true;
     } else {
 post("did delete branch with cid as " + cid);
-        rect = get_item(cid, "iemgui_label_handle");
-        rect.parentNode.removeChild(rect);
+        rect = get_item(cid, "clickable_resize_handle");
+        // Need to check for null here...
+        if (rect) {
+            rect.parentNode.removeChild(rect);
+            patchwin[cid].window.canvas_events.clickable_resize_handle = false;
+        } else {
+post("couldnt delete the thing!");
+        }
     }
 }
 
@@ -2279,6 +2318,9 @@ post("did delete branch with cid as " + cid);
 // going between the GUI and Pd (as opposed to doing it completely in the GUI).
 function gui_add_iemgui_label_resize_listener(cid, tag) {
     post("received a message to add a binding for an iemgui handle...");
+    var handle = get_item(cid, "clickable_resize_handle");
+
+    patchwin[cid].window.canvas_events.clickable_resize_handle = true;
 }
 
 function gui_create_mycanvas(cid,tag,color,x1,y1,x2_vis,y2_vis,x2,y2) {
@@ -2879,19 +2921,19 @@ function gui_graph_tick_label(cid, tag, x, y, text, font, font_size, font_weight
 
 function gui_canvas_drawredrect(cid, x1, y1, x2, y2) {
     var svgelem = get_item(cid, "patchsvg"),
-        b;
-    b = create_item(cid, "rect", {
-        x: x1 + 0.5, // align to pixel grid
-        y: y1 + 0.5, // align to pixel grid
+        g = gui_text_create_gobj(cid, cid, "gop_rect", x1, y1, 1),
+        r;
+    r = create_item(cid, "rect", {
         width: x2 - x1,
         height: y2 - y1,
-        id: "gop_rect" // Note: the old tk tag was "GOP"
+        id: "gop_rect"
     });
-    svgelem.appendChild(b);
+    g.appendChild(r);
+    svgelem.appendChild(g);
 }
 
 function gui_canvas_deleteredrect(cid) {
-    var r = get_item(cid, "gop_rect");
+    var r = get_gobj(cid, cid);
     // We need to check for existence here, because the first
     // time setting GOP in properties, there is no red rect yet.
     // But setting properties when the subpatch's window is
@@ -2906,6 +2948,16 @@ function gui_canvas_deleteredrect(cid) {
     }
 }
 
+function gui_canvas_redrect_coords(cid, x1, y1, x2, y2) {
+    var g = get_gobj(cid, cid),
+        r = get_item(cid, "gop_rect");
+    elem_move(g, x1, y1);
+    configure_item(r, {
+        width: x2 - x1,
+        height: y2 - y1
+    });
+}
+
 //  Cord Inspector (a.k.a. Magic Glass)
 
 // For clarity, this probably shouldn't be a gobj.  Also, it might be easier to
diff --git a/pd/src/g_all_guis.c b/pd/src/g_all_guis.c
index d2d25961d..6d2207236 100644
--- a/pd/src/g_all_guis.c
+++ b/pd/src/g_all_guis.c
@@ -806,8 +806,8 @@ void scalehandle_draw_erase(t_scalehandle *h) {
     sys_vgui("destroy %s\n", h->h_pathname);
     sys_vgui(".x%lx.c delete %lx%s\n", canvas, h->h_master,
         h->h_scale ? "SCALE" : pd_class((t_pd *)h->h_master)==canvas_class?"MOVE":"LABELH");
-    gui_vmess("gui_iemgui_label_show_drag_handle", "xsiii",
-        h->h_glist, "dummy_tag", 0, 0, 0);
+    gui_vmess("gui_iemgui_label_show_drag_handle", "xxiii",
+        h->h_glist, h->h_master, 0, 0, 0);
     h->h_vis = 0;
 }
 
@@ -830,13 +830,16 @@ t_scalehandle *scalehandle_new(t_object *x, t_glist *glist, int scale, t_clickha
     char buf[19]; // 3 + max size of %lx
     h->h_master = x;
     h->h_glist = glist;
-    sprintf(buf, "_h%lx", (t_int)h);
-    pd_bind((t_pd *)h, h->h_bindsym = gensym(buf));
+    if (!scale) /* Only bind for labels-- scaling uses pd_vmess in g_editor.c */
+    {
+        sprintf(buf, "_h%lx", (t_int)x);
+        pd_bind((t_pd *)h, h->h_bindsym = gensym(buf));
+    }
     sprintf(h->h_outlinetag, "h%lx", (t_int)h);
     h->h_dragon = 0;
     h->h_scale = scale;
-    //h->h_offset_x = 0; // unused (maybe keep for later)
-    //h->h_offset_y = 0; // unused (maybe keep for later)
+    h->h_offset_x = 0;
+    h->h_offset_y = 0;
     h->h_vis = 0;
     sprintf(h->h_pathname, ".x%lx.h%lx", (t_int)h->h_glist, (t_int)h);
     h->h_clickfn = chf;
@@ -845,7 +848,9 @@ t_scalehandle *scalehandle_new(t_object *x, t_glist *glist, int scale, t_clickha
 }
 
 void scalehandle_free(t_scalehandle *h) {
-    pd_unbind((t_pd *)h, h->h_bindsym);
+    if (!h->h_scale) { /* only binding handles labels, not for scaling guis */
+        pd_unbind((t_pd *)h, h->h_bindsym);
+    }
     pd_free((t_pd *)h);
 }
 
@@ -854,13 +859,16 @@ void properties_set_field_int(long props, const char *gui_field, int value) {
     sys_vgui(".gfxstub%lx.%s insert 0 %d\n", props, gui_field, value);
 };
 
-void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2) {
+void scalehandle_dragon_label(t_scalehandle *h, float mouse_x, float mouse_y) {
     if (h->h_dragon && !h->h_scale)
     {
         t_iemgui *x = (t_iemgui *)(h->h_master);
-        int dx = (int)f1, dy = (int)f2;
+        int dx = (int)mouse_x - (int)h->h_offset_x,
+            dy = (int)mouse_y - (int)h->h_offset_y;
         h->h_dragx = dx;
         h->h_dragy = dy;
+
+
         int properties = gfxstub_haveproperties((void *)x);
         if (properties)
         {
@@ -869,6 +877,12 @@ void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2) {
             properties_set_field_int(properties,"label.xy.x_entry",new_x);
             properties_set_field_int(properties,"label.xy.y_entry",new_y);
         }
+
+        x->x_ldx += dx;
+        x->x_ldy += dy;
+
+
+
         if (glist_isvisible(x->x_glist))
         {
             int xpos=text_xpix(&x->x_obj, x->x_glist);
@@ -878,6 +892,11 @@ void scalehandle_dragon_label(t_scalehandle *h, float f1, float f2) {
             sys_vgui(".x%lx.c coords %lxLABEL %d %d\n", canvas, x,
                 xpos+x->x_ldx + h->h_dragx,
                 ypos+x->x_ldy + h->h_dragy);
+            gui_vmess("gui_iemgui_label_coords", "xxii",
+                canvas,
+                x,
+                x->x_ldx,
+                x->x_ldy);
         }
     }
 }
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index f097e70f0..7210556ae 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -140,26 +140,14 @@ static void bng__clickhook_old(t_scalehandle *sh, int newstate)
 static void bng__clickhook(t_scalehandle *sh, int newstate)
 {
     t_bng *x = (t_bng *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale) /* click on a label handle */
+            scalehandle_click_label(sh);
     }
-    /* not sure we need this anymore... */
-    else if (newstate == 0 && sh->h_scale)
-    {
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_w += sh->h_dragx;
-            x->x_gui.x_h += sh->h_dragy;
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            bng_draw_move(x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+//    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void bng__motionhook(t_scalehandle *sh,
@@ -215,7 +203,7 @@ static void bng__motionhook(t_scalehandle *sh,
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x, mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void bng_draw(t_bng *x, t_glist *glist, int mode)
diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index 40806943a..9ff38c28f 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -775,12 +775,18 @@ void canvas_draw_gop_resize_hooks(t_canvas* x)
         sprintf(sh->h_pathname, ".x%lx.h%lx", (t_int)x, (t_int)sh);
         sprintf(mh->h_pathname, ".x%lx.h%lx", (t_int)x, (t_int)mh);
 
-        scalehandle_draw_select(sh,
-            -1-x->gl_obj.te_xpix+x->gl_xmargin + x->gl_pixwidth,
-            -1-x->gl_obj.te_ypix+x->gl_ymargin + x->gl_pixheight/*,GOP_resblob*/);
+//        scalehandle_draw_select(sh,
+//            -1-x->gl_obj.te_xpix+x->gl_xmargin + x->gl_pixwidth,
+//            -1-x->gl_obj.te_ypix+x->gl_ymargin + x->gl_pixheight/*,GOP_resblob*/);
+//        scalehandle_draw_select(mh,
+//            2+SCALEHANDLE_WIDTH -x->gl_obj.te_xpix+x->gl_xmargin,
+//            2+SCALEHANDLE_HEIGHT-x->gl_obj.te_ypix+x->gl_ymargin /*,"GOP_movblob"*/);
+
+        /* these constants don't actually reflect the actual size of the
+           click rectangle-- we should probably change them... */
+
         scalehandle_draw_select(mh,
-            2+SCALEHANDLE_WIDTH -x->gl_obj.te_xpix+x->gl_xmargin,
-            2+SCALEHANDLE_HEIGHT-x->gl_obj.te_ypix+x->gl_ymargin /*,"GOP_movblob"*/);
+            SCALEHANDLE_WIDTH - 4, SCALEHANDLE_HEIGHT - 11);
     }
     else
     {
@@ -2160,6 +2166,9 @@ void canvasgop__clickhook(t_scalehandle *sh, int newstate)
     }
     else if (!sh->h_dragon && newstate)
     {
+        /* set undo */
+        canvas_undo_add(x, 8, "apply", canvas_undo_set_canvas(x));
+
         if(sh->h_scale) //enter if resize_gop hook
         {
             sys_vgui("lower %s\n", sh->h_pathname);
@@ -2184,17 +2193,18 @@ void canvasgop__clickhook(t_scalehandle *sh, int newstate)
     sh->h_dragon = newstate;
 }
 
-void canvasgop__motionhook(t_scalehandle *sh,t_floatarg f1, t_floatarg f2)
+void canvasgop__motionhook(t_scalehandle *sh,t_floatarg mouse_x, t_floatarg mouse_y)
 {
     t_canvas *x = (t_canvas *)(sh->h_master);
-    int dx = (int)f1, dy = (int)f2;
+    int dx = (int)mouse_x - sh->h_offset_x,
+        dy = (int)mouse_y - sh->h_offset_y;
     
     if (sh->h_dragon)
     {
         if(sh->h_scale) //enter if resize_gop hook
         {
-            int sx = maxi(SCALE_GOP_MINWIDTH ,x->gl_pixwidth +dx);
-            int sy = maxi(SCALE_GOP_MINHEIGHT,x->gl_pixheight+dy);
+            int sx = maxi(SCALE_GOP_MINWIDTH ,x->gl_pixwidth + dx);
+            int sy = maxi(SCALE_GOP_MINHEIGHT,x->gl_pixheight + dy);
             //int x1=0, y1=0, x2=0, y2=0;
             // if text is not hidden, use it as min height & width.
             /*if (!x->gl_hidetext)
@@ -2206,11 +2216,21 @@ void canvasgop__motionhook(t_scalehandle *sh,t_floatarg f1, t_floatarg f2)
                 sx = maxi(sx,x2-x1);
                 sy = maxi(sy,y2-y1);
             }*/ // does not work, needs a gobj_getrect that does not use pixwidth & pixheight
-            int newx = x->gl_xmargin + sx;
-            int newy = x->gl_ymargin + sy;
 
-            sys_vgui(".x%x.c coords %s %d %d %d %d\n",
-                x, sh->h_outlinetag, x->gl_xmargin, x->gl_ymargin, newx, newy);
+            x->gl_pixwidth = sx;
+            x->gl_pixheight= sy;
+
+            int newx = sx;
+            int newy = sy;
+
+            //sys_vgui(".x%x.c coords %s %d %d %d %d\n",
+            //    x, sh->h_outlinetag, x->gl_xmargin, x->gl_ymargin, newx, newy);
+            gui_vmess("gui_canvas_redrect_coords", "xiiii",
+                x,
+                x->gl_xmargin,
+                x->gl_ymargin,
+                x->gl_xmargin + newx,
+                x->gl_ymargin + newy);
 
             sh->h_dragx = sx-x->gl_pixwidth;
             sh->h_dragy = sy-x->gl_pixheight;
@@ -2234,10 +2254,18 @@ void canvasgop__motionhook(t_scalehandle *sh,t_floatarg f1, t_floatarg f2)
                 properties_set_field_int(properties,
                     "n.canvasdialog.y.f2.entry4",x->gl_ymargin + dy);
             }
-            int x1 = x->gl_xmargin+dx, x2 = x1+x->gl_pixwidth;
-            int y1 = x->gl_ymargin+dy, y2 = y1+x->gl_pixheight;
-            sys_vgui(".x%x.c coords GOP %d %d %d %d %d %d %d %d %d %d\n",
-                        x, x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
+
+            x->gl_xmargin += dx;
+            x->gl_ymargin += dy;
+
+            int x1 = x->gl_xmargin, x2 = x1+x->gl_pixwidth;
+            int y1 = x->gl_ymargin, y2 = y1+x->gl_pixheight;
+
+
+            //sys_vgui(".x%x.c coords GOP %d %d %d %d %d %d %d %d %d %d\n",
+            //            x, x1, y1, x2, y1, x2, y2, x1, y2, x1, y1);
+            gui_vmess("gui_canvas_redrect_coords", "xiiii",
+                x, x1, y1, x2, y2);
             sh->h_dragx = dx;
             sh->h_dragy = dy;            
         }
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 6f68d64ef..5a2639288 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -3679,6 +3679,31 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
             // end jsarlo
         }
         return;
+    } else if (x->gl_isgraph && x->gl_goprect &&
+               xpos <= x->gl_xmargin + x->gl_pixwidth + 4 &&
+               xpos >= x->gl_xmargin + x->gl_pixwidth - 2 &&
+               ypos <= x->gl_ymargin + x->gl_pixheight + 4 &&
+               ypos > x->gl_ymargin + x->gl_pixheight - 2)
+    {
+// refactor the if into a function call...
+        if (doit)
+        {
+            x->gl_editor->e_onmotion = MA_RESIZE;
+            x->gl_editor->e_xwas = x1;
+            x->gl_editor->e_ywas = y1;
+            x->gl_editor->e_xnew = xpos;
+            x->gl_editor->e_ynew = ypos;
+            t_pd *sh = (t_pd *)x->x_handle; // scale handle
+            pd_vmess(sh, gensym("_click"), "fff",
+                (t_float)1, (t_float)xpos, (t_float)ypos);
+        }
+        else
+        {
+            canvas_setcursor(x,
+                CURSOR_EDITMODE_RESIZE_BOTTOM_RIGHT);
+        }
+        canvas_check_nlet_highlights(x);
+        return;
     }
         /* if right click doesn't hit any boxes, call rightclick
             routine anyway */
@@ -5416,6 +5441,12 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
             }
             else post("not resizable");
         }
+        else // resizing a gop rectangle
+        {
+            t_pd *sh = (t_pd *)x->x_handle;
+            pd_vmess(sh, gensym("_motion"), "ff", (t_float)xpos, (t_float)ypos);
+            post("moving a gop rect");
+        }
     }
     else if (x->gl_editor->e_onmotion == MA_SCROLL || mod == -1)
     {
diff --git a/pd/src/g_mycanvas.c b/pd/src/g_mycanvas.c
index d6e59829a..a550c15b2 100644
--- a/pd/src/g_mycanvas.c
+++ b/pd/src/g_mycanvas.c
@@ -92,39 +92,13 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist)
 static void my_canvas__clickhook(t_scalehandle *sh, int newstate)
 {
     t_my_canvas *x = (t_my_canvas *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
-    /* the rest is unused */
-    if (sh->h_dragon && newstate == 0 && sh->h_scale)
-    {
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_vis_w += sh->h_dragx;
-            x->x_vis_h += sh->h_dragy;
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        // if select area is larger tahn the visible arae
-        // make select area match that of the dragged one
-        // so that we don't have to go into properties to 
-        // manually adjust this
-        if (x->x_vis_w < x->x_gui.x_w)
-            x->x_gui.x_w = x->x_vis_w;
-        if (x->x_vis_h < x->x_gui.x_h)
-            x->x_gui.x_h = x->x_vis_h;
-        if (x->x_gui.x_w < x->x_gui.x_h)
-            x->x_gui.x_h = x->x_gui.x_w;
-        else
-            x->x_gui.x_w = x->x_gui.x_h;
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            my_canvas_draw_move(x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void my_canvas__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
@@ -164,7 +138,7 @@ static void my_canvas__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_float
             }
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x,mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void my_canvas_draw(t_my_canvas *x, t_glist *glist, int mode)
diff --git a/pd/src/g_numbox.c b/pd/src/g_numbox.c
index e5da3ca5f..e0728a583 100644
--- a/pd/src/g_numbox.c
+++ b/pd/src/g_numbox.c
@@ -176,9 +176,14 @@ static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
     //    canvas, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2,
     //    x->x_hide_frame <= 1 ? "$pd_colors(iemgui_border)" : bcol,
     //    bcol, x, x);
-    gui_vmess("gui_create_numbox", "ixxsiiiiiiiiiiiiii", x->x_numwidth,
-        canvas, x,
-        bcol, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2, x1, y1, half,
+    gui_vmess("gui_create_numbox", "xxsiiiii",
+        canvas,
+        x,
+        bcol,
+        x1,
+        y1,
+        x2 - x1,
+        y2 - y1,
         glist_istoplevel(canvas));
     /* Not sure when it is necessary to hide the frame... */
     if (!x->x_hide_frame || x->x_hide_frame == 2)
@@ -218,6 +223,18 @@ static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist)
         //sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n",
         //    canvas, x, x1, y1, x1 + half, y1 + half, x1, y2);
     }
+
+    gui_vmess("gui_numbox_coords", "xxii",
+        canvas,
+        x,
+        x2 - x1,
+        y2 - y1);
+
+    gui_vmess("gui_update_numbox_text_position", "xxii",
+        canvas,
+        x,
+        half + 2,
+        half + d);
     //sys_vgui(".x%lx.c coords %lxNUMBER %d %d\n",
     //    canvas, x, x1+half+2, y1+half+d);
 }
@@ -271,45 +288,13 @@ static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
 static void my_numbox__clickhook(t_scalehandle *sh, int newstate)
 {
     t_my_numbox *x = (t_my_numbox *)(sh->h_master);
-    if (newstate && sh->h_scale)
-    {
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-    }
-    /* the rest is no longer used */
-    else if (sh->h_dragon && newstate == 0 && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_fontsize = x->x_tmpfontsize;
-            x->x_gui.x_w = x->x_scalewidth;
-            x->x_gui.x_h = x->x_scaleheight;
-            x->x_numwidth = my_numbox_calc_fontwidth(x);
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            my_numbox_draw_move(x, x->x_gui.x_glist);
-            my_numbox_draw_config(x, x->x_gui.x_glist);
-            my_numbox_draw_update((t_gobj*)x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    else if (!sh->h_dragon && newstate && sh->h_scale)
-    {
-        scalehandle_click_scale(sh);
-        x->x_scalewidth = x->x_gui.x_w;
-        x->x_scaleheight = x->x_gui.x_h;
-        x->x_tmpfontsize = x->x_gui.x_fontsize;
-    }
-    else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
-    {
-        scalehandle_unclick_label(sh);
-    }
-    else if (!sh->h_dragon && newstate && !sh->h_scale)
-    {
-        scalehandle_click_label(sh);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
+    /* not sure if we need this */
     sh->h_dragon = newstate;
 }
 
@@ -367,13 +352,15 @@ static void my_numbox__motionhook(t_scalehandle *sh,
 
         if (glist_isvisible(x->x_gui.x_glist))
         {
-            /*
+            
             my_numbox_draw_move(x, x->x_gui.x_glist);
             my_numbox_draw_config(x, x->x_gui.x_glist);
             my_numbox_draw_update((t_gobj*)x, x->x_gui.x_glist);
-            */
+            
+/*
             gobj_vis(x, x->x_gui.x_glist, 0);
             gobj_vis(x, x->x_gui.x_glist, 1);
+*/
             scalehandle_unclick_scale(sh);
         }
 
@@ -387,7 +374,7 @@ static void my_numbox__motionhook(t_scalehandle *sh,
             properties_set_field_int(properties,"label.fontsize_entry",x->x_tmpfontsize);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x, mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void my_numbox_draw(t_my_numbox *x, t_glist *glist, int mode)
diff --git a/pd/src/g_radio.c b/pd/src/g_radio.c
index bd878de64..0262ee1c3 100644
--- a/pd/src/g_radio.c
+++ b/pd/src/g_radio.c
@@ -150,32 +150,13 @@ void radio_draw_config(t_radio *x, t_glist *glist)
 static void radio__clickhook(t_scalehandle *sh, int newstate)
 {
     t_radio *x = (t_radio *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
-    /* this part isn't needed */
-    else if (sh->h_dragon && newstate == 0 && sh->h_scale)
-    {
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            if (x->x_orient) {
-                x->x_gui.x_w += sh->h_dragx;
-                x->x_gui.x_h += sh->h_dragx;
-            } else {
-                x->x_gui.x_w += sh->h_dragy;
-                x->x_gui.x_h += sh->h_dragy;
-            }
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            radio_draw_move(x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void radio__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
@@ -214,7 +195,7 @@ static void radio__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg
                 x->x_gui.x_w + sh->h_dragx);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x,mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void radio_draw(t_radio *x, t_glist *glist, int mode)
diff --git a/pd/src/g_slider.c b/pd/src/g_slider.c
index d98e653f0..abe3a350e 100644
--- a/pd/src/g_slider.c
+++ b/pd/src/g_slider.c
@@ -151,29 +151,13 @@ static void vslider__clickhook2(t_scalehandle *sh, t_slider *x) {
 static void slider__clickhook(t_scalehandle *sh, int newstate)
 {
     t_slider *x = (t_slider *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
-    /* the rest is no longer used and can be trashed once all iemguis
-       are working */
-    else if (sh->h_dragon && newstate == 0 && sh->h_scale)
-    {
-        t_slider *x = (t_slider *)(sh->h_master);
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            if (x->x_orient) vslider__clickhook2(sh,x);
-            else             hslider__clickhook2(sh,x);
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            slider_draw_move(x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void slider__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
@@ -210,8 +194,7 @@ static void slider__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg
             properties_set_field_int(properties,"dim.h_ent",new_h);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x,
-        mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void slider_draw(t_slider *x, t_glist *glist, int mode)
diff --git a/pd/src/g_toggle.c b/pd/src/g_toggle.c
index c866c9a51..36a4aa97f 100644
--- a/pd/src/g_toggle.c
+++ b/pd/src/g_toggle.c
@@ -101,26 +101,13 @@ void toggle_draw_config(t_toggle* x, t_glist* glist)
 static void toggle__clickhook(t_scalehandle *sh, int newstate)
 {
     t_toggle *x = (t_toggle *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
-    else if (newstate == 0 && sh->h_scale)
-    {
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_w += sh->h_dragx;
-            x->x_gui.x_h += sh->h_dragy;
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            toggle_draw_move(x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void toggle__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
@@ -175,7 +162,7 @@ static void toggle__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg
             properties_set_field_int(properties,"dim.w_ent",new_w);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x, mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 
diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c
index f053f25be..d09301570 100644
--- a/pd/src/g_vumeter.c
+++ b/pd/src/g_vumeter.c
@@ -314,29 +314,13 @@ static void vu_draw_select(t_vu* x,t_glist* glist)
 static void vu__clickhook(t_scalehandle *sh, int newstate)
 {
     t_vu *x = (t_vu *)(sh->h_master);
-    if (newstate && sh->h_scale)
+    if (newstate)
     {
         canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
+        if (!sh->h_scale)
+            scalehandle_click_label(sh);
     }
-    else if (sh->h_dragon && newstate == 0  && sh->h_scale)
-    {
-        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
-        if (sh->h_dragx || sh->h_dragy)
-        {
-            x->x_gui.x_w += sh->h_dragx;
-            x->x_gui.x_h += sh->h_dragy;
-            canvas_dirty(x->x_gui.x_glist, 1);
-        }
-        if (glist_isvisible(x->x_gui.x_glist))
-        {
-            vu_check_height(x, x->x_gui.x_h);
-            vu_draw_move(x, x->x_gui.x_glist);
-            vu_draw_config(x, x->x_gui.x_glist);
-            vu_draw_update((t_gobj *)x, x->x_gui.x_glist);
-            scalehandle_unclick_scale(sh);
-        }
-    }
-    iemgui__clickhook3(sh,newstate);
+    sh->h_dragon = newstate;
 }
 
 static void vu__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
@@ -374,7 +358,7 @@ static void vu__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mou
             properties_set_field_int(properties,"dim.h_ent",new_h);
         }
     }
-    scalehandle_dragon_label(sh,mouse_x - sh->h_offset_x, mouse_y - sh->h_offset_y);
+    scalehandle_dragon_label(sh,mouse_x, mouse_y);
 }
 
 void vu_draw(t_vu *x, t_glist *glist, int mode)
-- 
GitLab