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 | Top |
|