diff --git a/lua/movewindow.lua b/lua/movewindow.lua index c4f58930..754aab20 100644 --- a/lua/movewindow.lua +++ b/lua/movewindow.lua @@ -6,13 +6,41 @@ Miniwindow drag-to-move functions. Author: Nick Gammon Date: 15th July 2009 +Modified: 16th November 2010 to add preprocessing This module is intended to make it easier to add drag handlers for miniwindows. It implements the following: - windowinfo = movewindow.install (win, default_position, flags) -- find previous location + -- find previous location + nocheck: if true, don't check if offscreen (boolean) + friends: other windows to move with this one (table) + preprocess: preprocessing for mousedown, mouseup etc. (table) + + Handler names for preprocess table: + + mousedown + mouseup + mouseover + cancelmouseover + cancelmousedown + dragmove + dragrelease + + If any preprocess handler returns true (that is, neither nil nor false) then the default handler + in this module is not used. (The miniwindow name is the third argument) + + function mousedown (flags, id, win) + if bit.band (flags, miniwin.hotspot_got_rh_mouse) then + -- do something different here + return true + end -- if + + return false -- take normal movewindow behaviour + end -- mousedown + + windowinfo = movewindow.install (win, default_position, default_flags, nocheck, friends, preprocess) movewindow.add_drag_handler (win, left, top, right, bottom, cursor) -- add a drag handler for the nominated rectangle @@ -20,7 +48,7 @@ It implements the following: It also installs a position-checker that moves the miniwindow into view after 5 seconds, in case you resize the main world window, and the window is no longer visible. The 5 seconds are to give -the main world window's position and size time to stabilize. +the main world window's position and size time to stabilize. (Unless nocheck is true) Example of use: @@ -32,7 +60,7 @@ Example of use: win = GetPluginID () -- miniwindow ID - windowinfo = movewindow.install (win, 7, 0) -- get position (default to right/middle) + windowinfo = movewindow.install (win, miniwin.pos_center_right, 0) -- default position / flags -- make miniwindow (use locations returned from last time we saved the state) -- note that the width and height are not part of the window position info, and can thus change as required @@ -52,8 +80,7 @@ Example of use: -- in this case we use 0,0,0,0 as the rectangle (ie. the whole window) -- typically the height would be the size of the title bar - movewindow.add_drag_handler (win, 0, 0, 0, 0, 10) -- both-ways arrow cursor (10) - + movewindow.add_drag_handler (win, 0, 0, 0, 0, miniwin.cursor_both_arrow) -- SAVE STATE in OnPluginSaveState @@ -95,8 +122,15 @@ movewindow = {} -- table to hold functions like movewindow.install local function make_mousedown_handler (mwi) return function (flags, hotspot_id) - + local win = mwi.win + + -- see if other action wanted + if mwi.preprocess.mousedown then + if mwi.preprocess.mousedown (flags, hotspot_id, win) then + return + end -- if handled already + end -- if handler -- find where mouse is so we can adjust window relative to mouse mwi.startx = WindowInfo (win, 14) @@ -107,9 +141,13 @@ local function make_mousedown_handler (mwi) 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} + for i, v in ipairs (mwi.window_friends) do + if v then + mwi.window_friend_deltas [i] = + { + WindowInfo (v, 10) - mwi.origx, + WindowInfo (v, 11) - mwi.origy + } end -- if end -- for @@ -125,17 +163,27 @@ local function make_dragmove_handler (mwi) local win = mwi.win + -- see if other action wanted + if mwi.preprocess.dragmove then + if mwi.preprocess.dragmove (flags, hotspot_id, win) then + return + end -- if handled already + end -- if handler + -- find where it is now local posx, posy = WindowInfo (win, 17) - mwi.startx, 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); + WindowPosition(win, posx, posy, 0, miniwin.create_absolute_location); -- 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)) + for i, v in ipairs(mwi.window_friends) do + if v 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 @@ -144,15 +192,15 @@ local function make_dragmove_handler (mwi) posx > GetInfo (281) - mwi.margin or posy < 0 or -- don't drag title out of view posy > GetInfo (280) - mwi.margin then - SetCursor (11) -- X cursor + SetCursor (miniwin.cursor_x) -- X cursor else - SetCursor (1) -- hand cursor + SetCursor (miniwin.cursor_hand) -- hand cursor end -- if mwi.window_left = posx -- remember for saving state mwi.window_top = posy mwi.window_mode = 0 - mwi.window_flags = 2 -- absolute position + mwi.window_flags = miniwin.create_absolute_location -- absolute position end -- dragmove @@ -166,6 +214,13 @@ local function make_dragrelease_handler (mwi) local win = mwi.win + -- see if other action wanted + if mwi.preprocess.dragrelease then + if mwi.preprocess.dragrelease (flags, hotspot_id, win) then + return + end -- if handled already + end -- if handler + Repaint () -- update window location -- find where window is now @@ -177,12 +232,12 @@ local function make_dragrelease_handler (mwi) newy < 0 or -- don't drag title out of view newy > GetInfo (280) - mwi.margin then -- put it back - WindowPosition(win, mwi.origx, mwi.origy, 0, 2) + WindowPosition(win, mwi.origx, mwi.origy, 0, miniwin.create_absolute_location) mwi.window_left = mwi.origx -- remember for saving state mwi.window_top = mwi.origy mwi.window_mode = 0 - mwi.window_flags = 2 -- absolute position + mwi.window_flags = miniwin.create_absolute_location -- absolute position return end -- if out of bounds @@ -192,6 +247,21 @@ local function make_dragrelease_handler (mwi) end -- make_dragrelease_handler +-- make other handler with the movement information as an upvalue + +local function make_other_handler (mwi, name) + + return function (flags, hotspot_id) + + -- send to supplied handler + if mwi.preprocess [name] then + mwi.preprocess [name] (flags, hotspot_id, mwi.win) + end -- if handler + + end -- other + +end -- make_other_handler + -- make a mouse position-checking function with the movement information as an upvalue local function make_check_map_position_handler (mwi) @@ -210,8 +280,8 @@ local function make_check_map_position_handler (mwi) mwi.window_left > GetInfo (281) - mwi.margin or mwi.window_top < 0 or -- don't drag title out of view mwi.window_top > GetInfo (280) - mwi.margin then - mwi.window_left, mwi.window_top = 0, 0 -- reset to top left - mwi.window_mode = 7 + mwi.window_left, mwi.window_top = 0, 0 -- reset to center right + mwi.window_mode = miniwin.pos_center_right mwi.window_flags = 0 end -- if not visible @@ -228,17 +298,14 @@ 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, default_friends) +function movewindow.install (win, default_position, default_flags, nocheck, friends, preprocess) 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_position = default_position or miniwin.pos_center_right -- 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 = { @@ -249,18 +316,28 @@ function movewindow.install (win, default_position, default_flags, nocheck, defa 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_friends = friends or {}, window_friend_deltas = {}, - margin = 20 -- how close we can put to the edge of the window + margin = 20, -- how close we can put to the edge of the window + preprocess = preprocess or {}, } + -- check valid + for k, v in pairs (movewindow_info.preprocess) do + assert (type (v) == "function", "Handler '" .. k .. "' is not a function") + end -- for + -- handler to reposition window movewindow_info.check_map_position = make_check_map_position_handler (movewindow_info) -- for startup -- mouse handlers - movewindow_info.mousedown = make_mousedown_handler (movewindow_info) - movewindow_info.dragmove = make_dragmove_handler (movewindow_info) - movewindow_info.dragrelease = make_dragrelease_handler (movewindow_info) + movewindow_info.mousedown = make_mousedown_handler (movewindow_info) + movewindow_info.mouseup = make_other_handler (movewindow_info, "mouseup") + movewindow_info.mouseover = make_other_handler (movewindow_info, "mouseover") + movewindow_info.cancelmouseover = make_other_handler (movewindow_info, "cancelmouseover") + movewindow_info.cancelmousedown = make_other_handler (movewindow_info, "cancelmousedown") + movewindow_info.dragmove = make_dragmove_handler (movewindow_info) + movewindow_info.dragrelease = make_dragrelease_handler (movewindow_info) -- save table in global namespace _G ["mw_" .. win .. "_movewindow_info"] = movewindow_info @@ -293,14 +370,14 @@ function movewindow.add_drag_handler (win, left, top, right, bottom, cursor) -- make a hotspot WindowAddHotspot(win, hotspot_id, - left or 0, top or 0, right or 0, bottom or 0, -- rectangle - "", -- MouseOver - "", -- CancelMouseOver - "mw_" .. win .. "_movewindow_info.mousedown", -- MouseDown - "", -- CancelMouseDown - "", -- MouseUp + left or 0, top or 0, right or 0, bottom or 0, -- rectangle + "mw_" .. win .. "_movewindow_info.mouseover", -- MouseOver + "mw_" .. win .. "_movewindow_info.cancelmouseover", -- CancelMouseOver + "mw_" .. win .. "_movewindow_info.mousedown", -- MouseDown + "mw_" .. win .. "_movewindow_info.cancelmousedown", -- CancelMouseDown + "mw_" .. win .. "_movewindow_info.mouseup", -- MouseUp "Drag to move window", -- tooltip text - cursor or 1, -- cursor + cursor or miniwin.cursor_hand, -- cursor 0) -- flags WindowDragHandler (win, hotspot_id,