[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Miniwindows
. . -> [Subject]  New module to simplify moving miniwindows around by dragging them

New module to simplify moving miniwindows around by dragging them

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Thu 16 Jul 2009 02:34 AM (UTC)

Amended on Thu 16 Jul 2009 02:40 AM (UTC) by Nick Gammon

Message
After the new functionality of dragging was introduced in MUSHclient version 4.40, I have been adding dragging functionality to some of my plugins. However getting it right is fiddlier than it looks for various reasons. Thus I have now made a separate module (which is distributed with MUSHclient version 4.42 onwards) that simplifies adding dragging. It only requires adding four lines to an existing plugin, as described in the comments at the start of the module.

As an example of how you might use the module, I'll show parts of my Aardwolf campaign tracker, adding in the bits to make the window moveable.


First, looking at OnPluginInstall, this is the original:


function OnPluginInstall ()
  
  win = GetPluginID ()
  font_id = "fn"
  
  font_name = "Comic Sans MS"    -- the actual font
  
  -- make window so I can grab the font info
  WindowCreate (win, 
                 0, 0, 1, 1,  
                 1,   -- irrelevant
                 0, 
                 background_colour) 

 WindowFont (win, font_id, font_name, 8, false, false, false, false, 0, 0)  -- normal  
 font_height = WindowFontInfo (win, font_id, 1)  -- height

end -- OnPluginInstall


Now we need to "require" the module, and tell it to get the position of the window from last time the plugin was used:


function OnPluginInstall ()
  
  win = GetPluginID ()
  font_id = "fn"
  
  font_name = "Comic Sans MS"    -- the actual font
  
  require "movewindow"  -- load the movewindow.lua module

  -- install the window movement handler, get back the window position
  windowinfo = movewindow.install (win, 7)  -- default to 7 (on right, center top/bottom)
   
  -- make window so I can grab the font info
  WindowCreate (win, 
                 windowinfo.window_left, 
                 windowinfo.window_top, 
                 1, 1,              -- width, height
                 windowinfo.window_mode,   
                 windowinfo.window_flags,
                 background_colour) 

  WindowFont (win, font_id, font_name, 8, false, false, false, false, 0, 0)  -- normal  
  font_height = WindowFontInfo (win, font_id, 1)  -- height
  
end -- OnPluginInstall


The call to movewindow.install prepares for window dragging, and returns in the windowinfo table the location the window was at last time, so we can plug these into the WindowCreate call.

The next thing to do is to save the window's position when the plugin saves its state. The original OnPluginSaveState function (which may not even exist) would look like this:


function OnPluginSaveState ()
end -- function OnPluginSaveState


So we need to add one line to remember the window position:


function OnPluginSaveState ()
  -- save window current location for next time  
  movewindow.save_state (win)
end -- function OnPluginSaveState


Finally we need to add a drag handler after deleting hotspots, or after creating or re-creating the window.

My old function which showed the list of mobs to kill was this:


function show_campaign_text ()

  -- do nothing if no campaign
  if #campaign_info == 0 or when_required == nil then
    return
  end -- if

  -- recreate the window the correct size
  WindowCreate (win, 
                 0, 0,   -- left, top (auto-positions)
                 max_width + 10,     -- width
                 (#campaign_info + 2)   * font_height + 5,  -- height
                 7,       -- auto-position: top middle
                 0,  -- flags
                 0xE7FFFF) 
 
  -- heading
  local text = "Current campaign. You need to kill:"
  max_width = math.max (max_width, WindowTextWidth (win, font_id, text))
  Display_Line (1, text, font_id, heading_colour)

  -- list of mobs
  for i, v in ipairs (campaign_info) do
    Display_Line (i + 1, v, font_id, text_colour)
  end -- for
  
  -- how long to go
  local time_to_go = when_required - os.time ()
  
  if time_to_go < 0 then
    return
  end -- if
  
  text = string.format ("Time to go: %s", convert_time (time_to_go))
  max_width = math.max (max_width, WindowTextWidth (win, font_id, text))
  Display_Line (#campaign_info + 2, text, font_id, time_colour)
    
  WindowShow (win, true)  
end -- show_campaign_text


Now instead of auto-positioning the window, we need to use the coordinates saved in the windowinfo table, like this:


function show_campaign_text ()

  -- do nothing if no campaign
  if #campaign_info == 0 or when_required == nil then
    return
  end -- if

  -- recreate the window the correct size and position
  WindowCreate (win, 
                 windowinfo.window_left, 
                 windowinfo.window_top, 
                 max_width + 10,     -- width
                 (#campaign_info + 2)   * font_height + 5,  -- height
                 windowinfo.window_mode,   -- whatever
                 windowinfo.window_flags,
                 0xE7FFFF) 
 
  -- draw drag bar rectangle
  WindowRectOp (win, 2, 0, 0, 0, font_height, 0x8CE6F0)
  
  -- heading
  local text = "Current campaign. You need to kill:"
  max_width = math.max (max_width, WindowTextWidth (win, font_id, text))
  Display_Line (1, text, font_id, heading_colour)

  -- add the drag handler so they can move the window around
  movewindow.add_drag_handler (win, 0, 0, 0, font_height)
  
  -- list of mobs
  for i, v in ipairs (campaign_info) do
    Display_Line (i + 1, v, font_id, text_colour)
  end -- for
  
  -- how long to go
  local time_to_go = when_required - os.time ()
  
  if time_to_go < 0 then
    return
  end -- if
  
  text = string.format ("Time to go: %s", convert_time (time_to_go))
  max_width = math.max (max_width, WindowTextWidth (win, font_id, text))
  Display_Line (#campaign_info + 2, text, font_id, time_colour)
    
  WindowShow (win, true)  
end -- show_campaign_text


I also added a WindowRectOp call to make the "title bar" a different colour, to make it more obvious this was where you clicked to drag. Finally the call to movewindow.add_drag_handler sets up the dragging hotspot. In this case I made it go from 0,0 (top left) to line down (vertically, font_height down).




One of the complexities in the movewindow module was that I wanted to support multiple windows in a single plugin. Thus each window is allocated its own table in the global namespace, based on the miniwindow ID. That way it is possible to have multiple windows and drag them around independently. An example of that might be an inventory window, with a separate window for the contents of your bags. This is why you have to pass down the miniwindow ID to the drag handler functions, so they can associate themselves with the correct window.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #1 on Wed 07 Apr 2010 12:05 AM (UTC)
Message
I'd like to lobby for an amendment to .install that takes another parameter to optionally disable the call to
DoAfterSpecial (5, "mw_" .. win .. "_movewindow_info.check_map_position ()" , sendto.script)


I like the simplicity of the drag module, but that line seems to do more harm than good for me.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #2 on Wed 07 Apr 2010 12:25 AM (UTC)
Message
Also, the ability to pass in a list of other miniwindows to be synchronously moved by the same amount would be awesome.

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Wed 07 Apr 2010 01:06 AM (UTC)
Message
Fiendish said:

I'd like to lobby for an amendment to .install that takes another parameter to optionally disable the call to
DoAfterSpecial (5, "mw_" .. win .. "_movewindow_info.check_map_position ()" , sendto.script)


I like the simplicity of the drag module, but that line seems to do more harm than good for me.


Added a parameter to do that. New commit 9e32881.

http://github.com/nickgammon/mushclient/blob/master/lua/movewindow.lua

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #4 on Wed 07 Apr 2010 02:13 AM (UTC)
Message
Oh for crying out loud...4th try at posting this. :)

Nick, I'd like your opinion on...

@@ -104,10 +104,17 @@
     
     -- find where window is in case we drag it offscreen
     mwi.origx = WindowInfo (win, 10) 
     mwi.origy = WindowInfo (win, 11)
     
+    -- find where the friends are relative to the window
+    for j,v in ipairs(mwi.window_friends) do
+        if (v ~= nil) then
+            mwi.window_friend_deltas[j] = {WindowInfo(v, 10) - mwi.origx, WindowInfo(v, 11) - mwi.origy}
+        end -- if
+    end -- for
+        
   end -- mousedown
 
 end -- make_mousedown_handler
 
 -- make a mouse drag-move handler with the movement information as an upvalue
@@ -123,10 +130,17 @@
                        WindowInfo (win, 18) - mwi.starty
   
     -- move the window to the new location - offset by how far mouse was into window
     WindowPosition(win, posx, posy, 0, 2);
     
+    -- move the friends if they still exist
+    for j,v in ipairs(mwi.window_friends) do
+        if (v ~= nil) then
+            WindowPosition(v, posx+mwi.window_friend_deltas[j][1], posy+mwi.window_friend_deltas[j][2], 0, 2)
+        end -- if
+    end -- for
+
     -- change the mouse cursor shape appropriately
     if posx < mwi.margin - WindowInfo (win, 3) or 
        posx > GetInfo (281) - mwi.margin or
        posy < 0 or   -- don't drag title out of view
        posy > GetInfo (280) - mwi.margin then
@@ -212,29 +226,33 @@
 end -- make_check_map_position_handler
 
 -- call movewindow.install in OnPluginInstall to find the position of the window, before creating it
 --  - it also creates the handler functions ready for use later
 
-function movewindow.install (win, default_position, default_flags, nocheck)
+function movewindow.install (win, default_position, default_flags, nocheck, default_friends)
 
   win = win or GetPluginID ()  -- default to current plugin ID
   
   assert (not string.match (win, "[^A-Za-z0-9_]"), "Invalid window name in movewindow.install: " .. win)
   
   default_position = default_position or 7 -- on right, center top/bottom
   default_flags = default_flags or 0
+  if (default_friends == nil) then
+    default_friends = {}
+  end
   
   -- set up handlers and where window should be shown (from saved state, if any)
   local movewindow_info = {
      win = win,   -- save window ID
      
      -- save current position in table (obtained from state file)
      window_left  = tonumber (GetVariable ("mw_" .. win .. "_windowx")) or 0,
      window_top   = tonumber (GetVariable ("mw_" .. win .. "_windowy")) or 0,
      window_mode  = tonumber (GetVariable ("mw_" .. win .. "_windowmode")) or default_position,
      window_flags = tonumber (GetVariable ("mw_" .. win .. "_windowflags")) or default_flags,
-     
+     window_friends = default_friends,
+     window_friend_deltas = {},
      margin = 20  -- how close we can put to the edge of the window
     }
 
     -- handler to reposition window
     movewindow_info.check_map_position = make_check_map_position_handler (movewindow_info)  -- for startup

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Wed 07 Apr 2010 02:33 AM (UTC)
Message
Looks OK. Personally I prefer:


 if v then


to:


 if (v ~= nil) then


Can you repost with forum codes escaped?

Template:post=9691 Please see the forum thread: http://gammon.com.au/forum/?id=9691.


If you don't there is a chance backslashes or things like [i] won't come out as you expect.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Wed 07 Apr 2010 02:33 AM (UTC)
Message
And does the code seem to work?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #7 on Wed 07 Apr 2010 02:36 AM (UTC)
Message
It seems to work. Except I changed.


WindowPosition(v, posx+mwi.window_friend_deltas[j][1], posy+mwi.window_friend_deltas[j][2], 0, 2)


to


WindowPosition(v, posx+mwi.window_friend_deltas[j][1], posy+mwi.window_friend_deltas[j][2], 0, WindowInfo(v, 8))

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Wed 07 Apr 2010 02:37 AM (UTC)
Message
OK can you repost with the square brackets escaped as I described (use MUSHclient to do that) and I'll merge it in.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #9 on Wed 07 Apr 2010 02:39 AM (UTC)
Message
The whole module or just the diff?

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #10 on Wed 07 Apr 2010 02:43 AM (UTC)
Message
Here, how about this. :)

http://ilikepants.pastebin.com/deyK9YXn

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Wed 07 Apr 2010 02:56 AM (UTC)

Amended on Wed 07 Apr 2010 02:57 AM (UTC) by Nick Gammon

Message
My diffs aren't working properly.

Can you post the diffs, but before putting them into the code tags, just go to MUSHclient's Edit menu -> Convert Clipboard Forum Codes. That will fix up the clipboard to be correct to paste here.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Fiendish   USA  (2,522 posts)  [Biography] bio   Global Moderator
Date Reply #12 on Wed 07 Apr 2010 03:02 AM (UTC)
Message

@@ -104,10 +104,17 @@
     
     -- find where window is in case we drag it offscreen
     mwi.origx = WindowInfo (win, 10) 
     mwi.origy = WindowInfo (win, 11)
     
+    -- find where the friends are relative to the window
+    for i,v in ipairs(mwi.window_friends) do
+        if (v ~= nil) then
+            mwi.window_friend_deltas[i] = {WindowInfo(v, 10) - mwi.origx, WindowInfo(v, 11) - mwi.origy}
+        end -- if
+    end -- for
+        
   end -- mousedown
 
 end -- make_mousedown_handler
 
 -- make a mouse drag-move handler with the movement information as an upvalue
@@ -123,10 +130,17 @@
                        WindowInfo (win, 18) - mwi.starty
   
     -- move the window to the new location - offset by how far mouse was into window
     WindowPosition(win, posx, posy, 0, 2);
     
+    -- move the friends if they still exist
+    for i,v in ipairs(mwi.window_friends) do
+        if (v ~= nil) then
+            WindowPosition(v, posx+mwi.window_friend_deltas[i][1], posy+mwi.window_friend_deltas[i][2], 0, WindowInfo(v, 8))
+        end -- if
+    end -- for
+
     -- change the mouse cursor shape appropriately
     if posx < mwi.margin - WindowInfo (win, 3) or 
        posx > GetInfo (281) - mwi.margin or
        posy < 0 or   -- don't drag title out of view
        posy > GetInfo (280) - mwi.margin then
@@ -212,29 +226,33 @@
 end -- make_check_map_position_handler
 
 -- call movewindow.install in OnPluginInstall to find the position of the window, before creating it
 --  - it also creates the handler functions ready for use later
 
-function movewindow.install (win, default_position, default_flags, nocheck)
+function movewindow.install (win, default_position, default_flags, nocheck, default_friends)
 
   win = win or GetPluginID ()  -- default to current plugin ID
   
   assert (not string.match (win, "[^A-Za-z0-9_]"), "Invalid window name in movewindow.install: " .. win)
   
   default_position = default_position or 7 -- on right, center top/bottom
   default_flags = default_flags or 0
+  if (default_friends == nil) then
+    default_friends = {}
+  end
   
   -- set up handlers and where window should be shown (from saved state, if any)
   local movewindow_info = {
      win = win,   -- save window ID
      
      -- save current position in table (obtained from state file)
      window_left  = tonumber (GetVariable ("mw_" .. win .. "_windowx")) or 0,
      window_top   = tonumber (GetVariable ("mw_" .. win .. "_windowy")) or 0,
      window_mode  = tonumber (GetVariable ("mw_" .. win .. "_windowmode")) or default_position,
      window_flags = tonumber (GetVariable ("mw_" .. win .. "_windowflags")) or default_flags,
-     
+     window_friends = default_friends,
+     window_friend_deltas = {},
      margin = 20  -- how close we can put to the edge of the window
     }
 
     -- handler to reposition window
     movewindow_info.check_map_position = make_check_map_position_handler (movewindow_info)  -- for startup

https://github.com/fiendish/aardwolfclientpackage
[Go to top] top

Posted by Nick Gammon   Australia  (23,006 posts)  [Biography] bio   Forum Administrator
Date Reply #13 on Wed 07 Apr 2010 03:33 AM (UTC)
Message
Added to next release, commit e3bebba.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Tiredchris   (17 posts)  [Biography] bio
Date Reply #14 on Mon 03 May 2010 11:11 PM (UTC)
Message
I'm at a complete loss as to how to use this to move a miniwindow. Well where to put any of the code really. I'm just getting into mini-windows and some of this just looks...well hard. Could someone do youtoube video on how to set this up beginning to end with the inventory mini-window thread? I just got that one down, so a demonstration would go a long way for helping me :)
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


47,498 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]