
Insert dragable and resizeable subgraphs into a graph window

This code provides a hook function which makes it possible to drag and resize subwindows in a graph with the mouse. To see how this works create a graph and execute the following:
TestAppendSubGraph(mainGraphName, plotThisWave)
This will insert a subpanel with a subgraph into the designated graph window, which can then be interacted with via the mouse. You can add as many subgraphs as you want. The subwindows are also prevented from disappearing outside the main graph area upon resizing the main graph. A minimum subwindow size is set by the subMinSize constant. The detection range for subwindow edge (i.e., where the dragging mode switches to resizing close to window edges) is controlled via the edgeDetect constant.
If you want to remove the hook and associated user data again, use:
TestRemoveHook(GraphName)
Here is the full code:
#pragma TextEncoding = "UTF-8" #pragma rtGlobals=3 #pragma DefaultTab={3,20,4} function TestAppendSubGraph(string mainGName, wave plotThis) GetWindow $mainGName, expand variable gExpand = V_value; gExpand = gExpand == 0 ? 1 : gExpand // pixel conversion and expansion factor variable pixConv = ScreenResolution/72*gExpand GetWindow $mainGName psizeDC // define an initial size variable size = max(min((V_bottom-V_top)/4,(V_right-V_left)/5),subMinSize)/pixConv variable wL = (V_left+20)/pixConv, wT = (V_top+20)/pixConv, wR = wL+size*1.2, wB = wT+size NewPanel/HOST=$mainGName/N=floatPanel/W=(wL,wT,wR,wB) Display/HOST=#/FG=(FL,FT,FR,FB) plotThis ModifyGraph frameStyle=1 // edges are easier to see with a frame SetActiveSubwindow $mainGName SetWindow $mainGName hook(DragUpdate)=DragHookFunction end function TestRemoveHook(string gName) string subWinList = ChildWindowList(gName) int i for (i=0; i<ItemsInList(subWinList); i++) SetWindow $gName userdata($StringFromList(i,subWinList))="" // remove user data from graph endfor SetWindow $gName userdata(dragInfo)="" SetWindow $gName hook(DragUpdate)=$"" end // ################## static Constant subMinSize = 100 static Constant edgeDetect = 15 function DragHookFunction(STRUCT WMWinHookStruct &s) string gName = StringFromList(0,s.winName,"#") string sName = StringFromList(1,s.winName,"#") string dragInfo = "", floatStruct = "" int i, hookTakeOver = 0 GetWindow $gName, expand variable gExpand = V_value; gExpand = gExpand == 0 ? 1 : gExpand // pixel conversion and expansion factor variable pixConv = ScreenResolution/72*gExpand variable winEdge = 0, dragEdge = 0 STRUCT DragStruct d STRUCT rect tempRect if (WhichListItem(s.eventName, "mousedown;mousemoved;mouseup;")>-1 && CmpStr(s.winName, gName)) // mouse events on the sub-graph GetWindow $s.winName psizeDC tempRect.top = v_top tempRect.left = v_left tempRect.right = v_right tempRect.bottom = v_bottom if (!CheckPointInRect(s.mouseLoc,tempRect)) // mouse is not in plot area GetWindow $s.winName gsizeDC; winEdge = 1 // encode sub-window mouse edge detection into winEdge winEdge = abs(s.mouseloc.h-v_left) <edgeDetect && abs(s.mouseloc.v-v_top) <edgeDetect ? 2 : winEdge // LT winEdge = abs(s.mouseloc.h-v_right)<edgeDetect && abs(s.mouseloc.v-v_top) <edgeDetect ? 3 : winEdge // RT winEdge = abs(s.mouseloc.h-v_left) <edgeDetect && abs(s.mouseloc.v-v_bottom)<edgeDetect ? 4 : winEdge // LB winEdge = abs(s.mouseloc.h-v_right)<edgeDetect && abs(s.mouseloc.v-v_bottom)<edgeDetect ? 5 : winEdge // RB endif endif StrSwitch(s.eventName) case "mousedown": if (CmpStr(s.winName, gName) && s.eventMod==1) if (CheckPointInRect(s.mouseLoc,tempRect)) break endif GetWindow $gName gsizeDC d.graphRect.top = v_top d.graphRect.left = v_left d.graphRect.bottom = v_bottom d.graphRect.right = v_right d.mouse_init = s.mouseloc d.subwinRect = s.winrect StructPut/S d, floatStruct SetWindow $gName userdata($sName)=floatStruct // save info for the current subwindow SetWindow $gName userdata(dragInfo)=num2str(winEdge)+";"+sName+";" // a list of the edge to drag and the dragged subwindow name hookTakeOver = 1 endif break case "mouseup": if (str2num(GetUserData(gName, "", "dragInfo"))) SetActiveSubwindow $gName SetWindow $gName userdata(dragInfo)="" endif break case "mousemoved": if (winEdge) s.cursorCode = str2num(StringFromList(winEdge,"0;8;4;11;10;7;")) s.doSetCursor = 1 // change mouse cursor endif dragInfo = GetUserData(gName, "", "dragInfo") dragEdge = str2num(StringFromList(0,dragInfo)) dragEdge = numtype(dragEdge) != 0 ? 0 : dragEdge if (dragEdge) GetMouse/W=$gName if (!(V_flag & 1)) // mouse button released? => maybe we missed a mouse-up event? SetWindow $gName userdata(dragInfo)="" dragEdge = 0 endif else break endif sName = StringFromList(1,dragInfo) StructGet/S d, GetUserData(gName, "", sName) variable deltah = s.mouseloc.h - d.mouse_init.h variable deltav = s.mouseloc.v - d.mouse_init.v tempRect = d.subwinRect tempRect.top += deltav * (dragEdge == 1 || dragEdge == 2 || dragEdge == 3) tempRect.left += deltah * (dragEdge == 1 || dragEdge == 2 || dragEdge == 4) tempRect.right += deltah * (dragEdge == 1 || dragEdge == 5 || dragEdge == 3) tempRect.bottom += deltav * (dragEdge == 1 || dragEdge == 5 || dragEdge == 4) string subWin = gName + "#" + sName if (CheckRectPosAndSize(tempRect, d.graphRect) && WinType(subWin)) MoveSubwindow/W=$subWin fnum=(tempRect.left/pixConv, tempRect.top/pixConv, tempRect.right/pixConv, tempRect.bottom/pixConv) d.subwinRect = tempRect endif d.mouse_init = s.mouseloc StructPut/S d, floatStruct SetWindow $gName userdata($sName)=floatStruct break case "resize": string subWinList = ChildWindowList(gName) if (!ItemsInList(subWinList)) break endif GetWindow $gName wsizeDC int isHostMinW = abs(v_right-v_left) <= subMinSize int isHostMinH = abs(v_bottom-v_top) <= subMinSize for (i=0; i<ItemsInList(subWinList); i++) sName = StringFromList(i, subWinList) GetWindow $(gName+"#"+sName) wsizeDC variable subW = abs(v_right-v_left) variable subH = abs(v_bottom-v_top) variable dW = isHostMinW ? 0 : subMinSize - subW // check if the panel width is smaller than the minimum variable dH = isHostMinH ? 0 : subMinSize - subH if (dW <= 0 && dH <= 0) continue endif dragInfo = GetUserData(gName, "", sName) if (strlen(dragInfo)) StructGet/S d, dragInfo subW = abs(d.subwinRect.right -d.subwinRect.left) subH = abs(d.subwinRect.bottom-d.subwinRect.top) endif tempRect.top = v_top - dH*(dH>0) tempRect.bottom = v_top - dH*(dH>0) + subH tempRect.left = v_left - dW*(dW>0) tempRect.right = v_left - dW*(dW>0) + subW MoveSubwindow/W=$(gName+"#"+sName) fnum=(tempRect.left/pixConv, tempRect.top/pixConv, tempRect.right/pixConv, tempRect.bottom/pixConv) endfor break endswitch return hookTakeOver end // ++++++++++++ static structure DragStruct STRUCT point mouse_init STRUCT Rect subwinRect STRUCT Rect graphRect endstructure static function CheckRectPosAndSize(STRUCT rect &in, STRUCT rect &ref) int isInside = (in.left>ref.left && in.top>ref.top && in.right<ref.right && in.bottom<ref.bottom) int isMinSize = abs(in.right-in.left) >= subMinSize && abs(in.bottom-in.top) >= subMinSize return isInside && isMinSize end static function CheckPointInRect(STRUCT point &pnt, STRUCT rect &ref) return ( pnt.h>ref.left && pnt.h<ref.right && pnt.v>ref.top && pnt.v<ref.bottom ) end


Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More