From 8b98ba5042f7ee33d92ad8f2b284c5e771a6820f Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 23 Jan 2023 17:40:16 -0800 Subject: [PATCH 1/6] allow windows to be defocused instead of pinned --- docs/changelog.txt | 1 + docs/dev/Lua API.rst | 108 +++++++++++++++++++++------------ library/lua/gui.lua | 117 ++++++++++++++++++++++-------------- library/lua/gui/widgets.lua | 13 ++-- plugins/lua/hotkeys.lua | 1 + 5 files changed, 146 insertions(+), 94 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 073837eff..daba5b791 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -42,6 +42,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `hotkeys`: clicking on the DFHack logo no longer closes the popup menu - `gui/launcher`: sped up initialization time for faster load of the UI - `orders`: orders plugin functionality is now offered via an overlay widget when the manager orders screen is open +- Many DFHack windows can now be unfocused by clicking somewhere not over the tool window. This has the same effect as pinning previously did, but without the extra clicking. ## Documentation diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 63b533d61..a832639e6 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4117,32 +4117,28 @@ It adds the following methods: ZScreen class ------------- -A screen subclass that allows the underlying viewscreens to be interacted with. -For example, a DFHack GUI tool implemented as a ZScreen can allow the player to -interact with the underlying map. That is, even when the DFHack tool window is -visible, players will be able to use vanilla designation tools, select units, or -scan/drag the map around. - -If multiple ZScreens are on the stack and the player clicks on a visible element -of a non-top ZScreen, that ZScreen will be raised to the top of the viewscreen -stack. This allows multiple DFHack gui tools to be usable at the same time. -Clicks that are not over any visible ZScreen element, of course, are passed -through to the underlying viewscreen. - -If :kbd:`Esc` or the right mouse button is pressed, and the ZScreen widgets -don't otherwise handle them, then the top ZScreen is dismissed. If the ZScreen -is "pinned", then the screen is not dismissed and the input is passed on to the -underlying DF viewscreen. :kbd:`Alt`:kbd:`L` toggles the pinned status if the -ZScreen widgets don't otherwise handle that key sequence. If you have a -``Panel`` with the ``pinnable`` attribute set and a frame that has pens defined -for the pin icon (like ``Window`` widgets have by default), then a pin icon -will appear in the upper right corner of the frame. Clicking on this icon will -toggle the ZScreen ``pinned`` status just as if :kbd:`Alt`:kbd:`L` had been -pressed. - -Keyboard input goes to the top ZScreen, as usual. If the subviews of the top -ZScreen don't handle the input (i.e. they all return something falsey), the -input is passed directly to the first underlying non-ZScreen. +A screen subclass that allows multi-layer interactivity. For example, a DFHack +GUI tool implemented as a ZScreen can allow the player to interact with the +underlying map, or even other DFHack ZScreen windows! That is, even when the +DFHack tool window is visible, players will be able to use vanilla designation +tools, select units, and scan/drag the map around. + +At most one ZScreen can have keyboard focus at a time. That ZScreen's widgets +will have a chance to handle the input before anything else. If unhandled, the +input skips all unfocused ZScreens under that ZScreen and is passed directly to +the first non-ZScreen viewscreen. There are class attributes that can be set to +control what kind of unhandled input is passed to the lower layers. + +If multiple ZScreens are visible and the player left or right clicks on a +visible element of a non-focused ZScreen, that ZScreen will be given focus. This +allows multiple DFHack GUI tools to be usable at the same time. If the mouse is +clicked away from the ZScreen widgets, that ZScreen loses focus. If no ZScreen +has focus, all input is passed directly through to the first underlying +non-ZScreen viewscreen. + +For a ZScreen with keyboard focus, if :kbd:`Esc` or the right mouse button is +pressed, and the ZScreen widgets don't otherwise handle them, then the ZScreen +is dismissed. All this behavior is implemented in ``ZScreen:onInput()``, which subclasses **must not override**. Instead, ZScreen subclasses should delegate all input @@ -4152,24 +4148,23 @@ level input processor. When rendering, the parent viewscreen is automatically rendered first, so subclasses do not have to call ``self:renderParent()``. Calls to ``logic()`` (a world "tick" when playing the game) are also passed through, so the game -progresses normally and can be paused/unpaused as normal by the player. -ZScreens that handle the :kbd:`Space` key may want to provide an alternate way -to pause. Note that passing ``logic()`` calls through to the underlying map is -required for allowing the player to drag the map with the mouse. +progresses normally and can be paused/unpaused as normal by the player. Note +that passing ``logic()`` calls through to the underlying map is required for +allowing the player to drag the map with the mouse. ZScreen subclasses can set +attributes that control whether the game is paused when the ZScreen is shown and +whether the game is forced to continue being paused while the ZScreen is shown. +If pausing is forced, child ``Window`` widgets will show a force-pause icon to +indicate which tool is forcing the pausing. ZScreen provides the following functions: * ``zscreen:raise()`` - Raises the ZScreen to the top of the viewscreen stack and returns a reference - to ``self``. A common pattern is to check if a tool dialog is already active - when the tool command is run and raise the existing dialog if it exists or - show a new dialog if it doesn't. See the sample code below for an example. - -* ``zscreen:togglePinned()`` - - Toggles whether the window closes on :kbd:`ESC` or r-click (unpinned) or not - (pinned). + Raises the ZScreen to the top of the viewscreen stack, gives it keyboard + focus, and returns a reference to ``self``. A common pattern is to check if a + tool dialog is already active when the tool command is run and raise the + existing dialog if it exists or show a new dialog if it doesn't. See the + sample code below for an example. * ``zscreen:isMouseOver()`` @@ -4177,6 +4172,37 @@ ZScreen provides the following functions: subclass and sees if ``getMouseFramePos()`` returns a position for any of them. Subclasses can override this function if that logic is not appropriate. +* ``zscreen:hasFocus()`` + + Whether the ZScreen has keyboard focus. Subclasses will generally not need to + check this because they can assume if they are getting input, then they have + focus. + +ZScreen subclasses can set the following attributes: + +* ``initial_pause`` (default: ``true``) + + Whether to pause the game when the ZScreen is shown. + +* ``force_pause`` (default: ``false``) + + Whether to ensure the game *stays* paused while the ZScreen is shown. + +* ``pass_pause`` (default: ``true``) + + Whether to pass the pause key to the lower viewscreens if it is not handled + by this ZScreen. + +* ``pass_movement_keys`` (default: ``false``) + + Whether to pass the map movement keys to the lower viewscreens if they ar not + handled by this ZScreen. + +* ``pass_mouse_clicks`` (default: ``true``) + + Whether to pass mouse clicks to the lower viewscreens if they are not handled + by this ZScreen. + Here is an example skeleton for a ZScreen tool dialog:: local gui = require('gui') @@ -4187,11 +4213,12 @@ Here is an example skeleton for a ZScreen tool dialog:: frame_title='My Window', frame={w=50, h=45}, resizable=true, -- if resizing makes sense for your dialog + resize_min={w=50, h=20}, -- try to allow users to shrink your windows } function MyWindow:init() self:addviews{ - -- add subviews here + -- add subview widgets here } end @@ -4202,6 +4229,7 @@ Here is an example skeleton for a ZScreen tool dialog:: MyScreen = defclass(MyScreen, gui.ZScreen) MyScreen.ATTRS { focus_path='myscreen', + -- set pause and passthrough attributes as appropriate } function MyScreen:init() diff --git a/library/lua/gui.lua b/library/lua/gui.lua index 524978baf..af9d68870 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -13,16 +13,18 @@ CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0, write_to_lower=true} TRANSPARENT_PEN = to_pen{tile=0, ch=0} KEEP_LOWER_PEN = to_pen{ch=32, fg=0, bg=0, keep_lower=true} -local FAKE_INPUT_KEYS = { +local MOUSE_KEYS = { _MOUSE_L = true, _MOUSE_R = true, _MOUSE_M = true, _MOUSE_L_DOWN = true, _MOUSE_R_DOWN = true, _MOUSE_M_DOWN = true, - _STRING = true, } +local FAKE_INPUT_KEYS = copyall(MOUSE_KEYS) +FAKE_INPUT_KEYS._STRING = true + function simulateInput(screen,...) local keys = {} local function push_key(arg) @@ -692,8 +694,34 @@ end ----------------------------- ZScreen = defclass(ZScreen, Screen) +ZScreen.ATTRS{ + initial_pause=true, + force_pause=false, + pass_pause=true, + pass_movement_keys=false, + pass_mouse_clicks=true, +} + +function ZScreen:init() + self.saved_pause_state = df.global.pause_state + if self.initial_pause then + df.global.pause_state = true + end + self.defocused = false +end + +function ZScreen:onDestroy() + if self.force_pause or self.initial_pause then + -- never go from unpaused to paused, just from paused to unpaused + df.global.pause_state = df.global.pause_state or self.saved_pause_state + end +end +-- this is necessary for middle-click map scrolling to function function ZScreen:onIdle() + if self.force_pause then + df.global.pause_state = true + end if self._native and self._native.parent then self._native.parent:logic() end @@ -704,17 +732,15 @@ function ZScreen:render(dc) ZScreen.super.render(self, dc) end -function ZScreen:isOnTop() - return dfhack.gui.getCurViewscreen(true) == self._native -end - -function ZScreen:togglePinned() - self.pinned = not self.pinned +function ZScreen:hasFocus() + return not self.defocused + and dfhack.gui.getCurViewscreen(true) == self._native end function ZScreen:onInput(keys) - if not self:isOnTop() then - if keys._MOUSE_L_DOWN and self:isMouseOver() then + local has_mouse = self:isMouseOver() + if not self:hasFocus() then + if (keys._MOUSE_L_DOWN or keys._MOUSE_R_DOWN) and has_mouse then self:raise() else self:sendInputToParent(keys) @@ -734,30 +760,42 @@ function ZScreen:onInput(keys) return end - if keys.CUSTOM_ALT_L then - self:togglePinned() + if keys._MOUSE_L_DOWN and not has_mouse then + self.defocused = true + self:sendInputToParent(keys) return - end - - if (self:isMouseOver() or not self.pinned) - and (keys.LEAVESCREEN or keys._MOUSE_R_DOWN) then + elseif keys.LEAVESCREEN or keys._MOUSE_R_DOWN then self:dismiss() - -- ensure underlying DF screens don't also react to the click + -- ensure underlying DF screens don't also react to the rclick df.global.enabler.mouse_rbut_down = 0 df.global.enabler.mouse_rbut = 0 return - end - - if not keys._MOUSE_L or not self:isMouseOver() then - self:sendInputToParent(keys) + else + local passit = self.pass_pause and keys.D_PAUSE + if not passit and self.pass_mouse_clicks then + for key in pairs(MOUSE_KEYS) do + if keys[key] then + passit = true + break + end + end + end + if not passit and self.pass_movement_keys then + passit = require('gui.dwarfmode').getMapKey(keys) + end + if passit then + self:sendInputToParent(keys) + end + return end end function ZScreen:raise() - if self:isDismissed() or self:isOnTop() then + if self:isDismissed() or self:hasFocus() then return self end dscreen.raise(self) + self.defocused = false return self end @@ -809,8 +847,7 @@ local BASE_FRAME = { title_pen = to_pen{ fg=COLOR_BLACK, bg=COLOR_GREY }, inactive_title_pen = to_pen{ fg=COLOR_GREY, bg=COLOR_BLACK }, signature_pen = to_pen{ fg=COLOR_GREY, bg=COLOR_BLACK }, - pinned_pen = to_pen{tile=779, ch=216, fg=COLOR_GREY, bg=COLOR_GREEN}, - unpinned_pen = to_pen{tile=782, ch=216, fg=COLOR_GREY, bg=COLOR_BLACK}, + paused_pen = to_pen{tile=782, ch=216, fg=COLOR_GREY, bg=COLOR_BLACK}, } local function make_frame(name, double_line) @@ -840,7 +877,7 @@ THIN_FRAME = make_frame('Thin', false) -- for compatibility with pre-steam code GREY_LINE_FRAME = WINDOW_FRAME -function paint_frame(dc,rect,style,title,show_pin,pinned,inactive) +function paint_frame(dc,rect,style,title,inactive, pause_forced) local pen = style.frame_pen local x1,y1,x2,y2 = dc.x1+rect.x1, dc.y1+rect.y1, dc.x1+rect.x2, dc.y1+rect.y2 dscreen.paintTile(style.lt_frame_pen or pen, x1, y1) @@ -865,27 +902,15 @@ function paint_frame(dc,rect,style,title,show_pin,pinned,inactive) x, y1, tstr) end - if show_pin then - if pinned and style.pinned_pen then - local pin_texpos = dfhack.textures.getGreenPinTexposStart() - if pin_texpos == -1 then - dscreen.paintTile(style.pinned_pen, x2-1, y1) - else - dscreen.paintTile(style.pinned_pen, x2-2, y1-1, nil, pin_texpos+0) - dscreen.paintTile(style.pinned_pen, x2-1, y1-1, nil, pin_texpos+1) - dscreen.paintTile(style.pinned_pen, x2-2, y1, nil, pin_texpos+2) - dscreen.paintTile(style.pinned_pen, x2-1, y1, nil, pin_texpos+3) - end - elseif not pinned and style.unpinned_pen then - local pin_texpos = dfhack.textures.getRedPinTexposStart() - if pin_texpos == -1 then - dscreen.paintTile(style.unpinned_pen, x2-1, y1) - else - dscreen.paintTile(style.unpinned_pen, x2-2, y1-1, nil, pin_texpos+0) - dscreen.paintTile(style.unpinned_pen, x2-1, y1-1, nil, pin_texpos+1) - dscreen.paintTile(style.unpinned_pen, x2-2, y1, nil, pin_texpos+2) - dscreen.paintTile(style.unpinned_pen, x2-1, y1, nil, pin_texpos+3) - end + if pause_forced then + local pause_texpos = dfhack.textures.getRedPinTexposStart() + if pause_texpos == -1 then + dscreen.paintTile(style.paused_pen, x2-1, y1) + else + dscreen.paintTile(style.paused_pen, x2-2, y1-1, nil, pause_texpos+0) + dscreen.paintTile(style.paused_pen, x2-1, y1-1, nil, pause_texpos+1) + dscreen.paintTile(style.paused_pen, x2-2, y1, nil, pause_texpos+2) + dscreen.paintTile(style.paused_pen, x2-1, y1, nil, pause_texpos+3) end end end diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 4538c39df..21f79c0ef 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -505,14 +505,11 @@ end function Panel:onRenderFrame(dc, rect) Panel.super.onRenderFrame(self, dc, rect) if not self.frame_style then return end - local pinned = nil - if self.pinnable then - pinned = self.parent_view and self.parent_view.pinned - end - local inactive = self.parent_view and self.parent_view.isOnTop - and not self.parent_view:isOnTop() - gui.paint_frame(dc, rect, self.frame_style, self.frame_title, - self.pinnable, pinned, inactive) + local inactive = self.parent_view and self.parent_view.hasFocus + and not self.parent_view:hasFocus() + local pause_forced = self.parent_view and self.parent_view.force_pause + gui.paint_frame(dc, rect, self.frame_style, self.frame_title, inactive, + pause_forced) if self.kbd_get_pos then local pos = self.kbd_get_pos() local pen = to_pen{fg=COLOR_GREEN, bg=COLOR_BLACK} diff --git a/plugins/lua/hotkeys.lua b/plugins/lua/hotkeys.lua index 99ba08a05..c377666c2 100644 --- a/plugins/lua/hotkeys.lua +++ b/plugins/lua/hotkeys.lua @@ -297,6 +297,7 @@ end MenuScreen = defclass(MenuScreen, gui.ZScreen) MenuScreen.ATTRS { focus_path='hotkeys/menu', + initial_pause=false, hotspot=DEFAULT_NIL, } From 4377065081a91d344ab49c91ca3ce243c7eb9e19 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 23 Jan 2023 17:46:03 -0800 Subject: [PATCH 2/6] move pause restore to dismiss and fix the condition --- library/lua/gui.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/lua/gui.lua b/library/lua/gui.lua index af9d68870..a1671a230 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -710,10 +710,11 @@ function ZScreen:init() self.defocused = false end -function ZScreen:onDestroy() +function ZScreen:dismiss() + ZScreen.super.dismiss(self) if self.force_pause or self.initial_pause then -- never go from unpaused to paused, just from paused to unpaused - df.global.pause_state = df.global.pause_state or self.saved_pause_state + df.global.pause_state = df.global.pause_state and self.saved_pause_state end end From 0905943ecf0a4a10c49381b56d530873b9de6018 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 23 Jan 2023 18:05:03 -0800 Subject: [PATCH 3/6] don't unfocus if mouse is not being passed through --- library/lua/gui.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui.lua b/library/lua/gui.lua index a1671a230..da26692ba 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -761,7 +761,7 @@ function ZScreen:onInput(keys) return end - if keys._MOUSE_L_DOWN and not has_mouse then + if self.pass_mouse_clicks and keys._MOUSE_L_DOWN and not has_mouse then self.defocused = true self:sendInputToParent(keys) return From 1c2f8eccbf22a67220bc1d3e9ff904f7d26d8119 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 23 Jan 2023 19:02:26 -0800 Subject: [PATCH 4/6] paint pause symbol for force-pause windows --- library/lua/gui.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/lua/gui.lua b/library/lua/gui.lua index da26692ba..2274c8794 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -904,14 +904,18 @@ function paint_frame(dc,rect,style,title,inactive, pause_forced) end if pause_forced then - local pause_texpos = dfhack.textures.getRedPinTexposStart() - if pause_texpos == -1 then + -- get the tiles for the activated pause symbol + local pause_texpos_ul = dfhack.screen.findGraphicsTile('INTERFACE_BITS', 18, 28) + local pause_texpos_ur = dfhack.screen.findGraphicsTile('INTERFACE_BITS', 19, 28) + local pause_texpos_ll = dfhack.screen.findGraphicsTile('INTERFACE_BITS', 18, 29) + local pause_texpos_lr = dfhack.screen.findGraphicsTile('INTERFACE_BITS', 19, 29) + if not pause_texpos_ul then dscreen.paintTile(style.paused_pen, x2-1, y1) else - dscreen.paintTile(style.paused_pen, x2-2, y1-1, nil, pause_texpos+0) - dscreen.paintTile(style.paused_pen, x2-1, y1-1, nil, pause_texpos+1) - dscreen.paintTile(style.paused_pen, x2-2, y1, nil, pause_texpos+2) - dscreen.paintTile(style.paused_pen, x2-1, y1, nil, pause_texpos+3) + dscreen.paintTile(style.paused_pen, x2-2, y1-1, nil, pause_texpos_ul) + dscreen.paintTile(style.paused_pen, x2-1, y1-1, nil, pause_texpos_ur) + dscreen.paintTile(style.paused_pen, x2-2, y1, nil, pause_texpos_ll) + dscreen.paintTile(style.paused_pen, x2-1, y1, nil, pause_texpos_lr) end end end From 1fa71c0d9237ba177e1adc8a12d0050a29974a1e Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 23 Jan 2023 19:24:37 -0800 Subject: [PATCH 5/6] update quickstart guide with new ZScreen semantics --- docs/Quickstart.rst | 57 +++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/docs/Quickstart.rst b/docs/Quickstart.rst index f6f8920c2..81415e3a9 100644 --- a/docs/Quickstart.rst +++ b/docs/Quickstart.rst @@ -99,37 +99,33 @@ How do DFHack in-game windows work? Many DFHack tools have graphical interfaces that appear in-game. You can tell which windows belong to DFHack tools because they will have the word "DFHack" -printed across their bottom frame edge. DFHack provides a custom windowing system -that gives the player a lot of control over where the windows appear and whether -they capture keyboard and mouse input. - -The DFHack windowing system allows you to use DFHack tools without interrupting -the game. That is, if the game is unpaused, it will continue to run while a -DFHack window is open. You can also interact with the map, scrolling it with the -keyboard or mouse and selecting units, buildings, and items. Some tools will -capture all keyboard input, such as tools with editable text fields, and some will -force-pause the game if it makes sense to, like `gui/quickfort`, since you cannot -interact with the map normally while trying to apply a blueprint. +printed across their bottom frame edge. DFHack provides an advanced windowing +system that gives the player a lot of control over where the windows appear and +whether they capture keyboard and mouse input. + +The DFHack windowing system allows multiple overlapping windows to be active at +once. The one with the highlighted title bar has focus and will receive anything +you type at the keyboard. Hit Esc or right click to close the window or cancel +the current operation. You can click anywhere on the screen that is not a +DFHack window to unfocus the window and let it just sit in the background. It won't +respond to key presses or mouse clicks until you click on it again to give it +focus. You can right click directly on an unfocused window to close it without +left clicking to activate it first. DFHack windows are draggable from the title bar or from anywhere on the window that doesn't have a mouse-clickable widget on it. Many are resizable as well (if the tool window has components that can reasonably be resized). -DFHack windows close with a right mouse click or keyboard Esc, but if you -want to keep a DFHack tool open while you interact with the game, you can click the -pin in the upper right corner of the DFHack window or hit Alt-L so -that the pin turns green. The DFHack window will then ignore right clicks and -Esc key presses that would otherwise close the window. This is especially -useful for the configuration tool windows for the automation tools. For example, -you can pin the `gui/autochop` window, set it to minimal mode, and let it sit -there monitoring your logging industry as you play, using it as a live status -window. Note that you can still right click *on* the DFHack tool window to close -it, even when it is pinned. - -You can have multiple DFHack tool windows on the screen at the same time. The -one that is receiving keyboard input has a highlighted title bar and will appear -over other windows if dragged across them. Clicking on a DFHack window that is not -currently active will bring it to the foreground and make it the active window. +You can generally use DFHack tools without interrupting the game. That is, if the +game is unpaused, it can continue to run while a DFHack window is open. Many tools +will initially pause the game to let you focus on the task at hand, but you can +unpause like normal if you want. You can also interact with the map, scrolling it +with the keyboard or mouse and selecting units, buildings, and items. Some tools +will capture all keyboard input, such as tools with editable text fields, and some +will force-pause the game if it makes sense to, like `gui/quickfort`, since you +cannot interact with the map normally while trying to apply a blueprint. Windows +for tools that force-pause the game will have a pause icon in their upper right +corner to indicate which tool is responsible for the pausing. Where do I go next? ------------------- @@ -161,10 +157,11 @@ You can enable it from the GUI, so you don't need to run `enable autochop Date: Mon, 23 Jan 2023 19:34:48 -0800 Subject: [PATCH 6/6] remove references to pinnable --- docs/dev/Lua API.rst | 7 +------ library/lua/gui/widgets.lua | 16 ++++------------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index a832639e6..eb05db0a1 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4392,11 +4392,6 @@ Has attributes: hitting :kbd:`Esc` (while resizing with the mouse or keyboard), or by calling ``Panel:setKeyboardResizeEnabled(false)`` (while resizing with the keyboard). -* ``pinnable = bool`` (default: ``false``) - - Determines whether the panel will draw a pin icon in its frame. See - `ZScreen class`_ for details. - * ``autoarrange_subviews = bool`` (default: ``false``) * ``autoarrange_gap = int`` (default: ``0``) @@ -4458,7 +4453,7 @@ Window class ------------ Subclass of Panel; sets Panel attributes to useful defaults for a top-level -framed, pinnable, draggable window. +framed, draggable window. ResizingPanel class ------------------- diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 21f79c0ef..ab4dad88e 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -81,7 +81,6 @@ Panel.ATTRS { resize_min = DEFAULT_NIL, on_resize_begin = DEFAULT_NIL, on_resize_end = DEFAULT_NIL, - pinnable = false, autoarrange_subviews = false, -- whether to automatically lay out subviews autoarrange_gap = 0, -- how many blank lines to insert between widgets } @@ -272,21 +271,21 @@ local function Panel_on_double_click(self) Panel_update_frame(self, frame, true) end -local function panel_is_on_pin(self) +local function panel_mouse_is_on_pause_icon(self) local frame_rect = self.frame_rect local x,y = dscreen.getMousePos() return (x == frame_rect.x2-2 or x == frame_rect.x2-1) and (y == frame_rect.y1-1 or y == frame_rect.y1) end -local function panel_is_pinnable(self) - return self.pinnable and self.parent_view and self.parent_view.togglePinned +local function panel_has_pause_icon(self) + return self.parent_view and self.parent_view.force_pause end function Panel:getMouseFramePos() local x,y = Panel.super.getMouseFramePos(self) if x then return x, y end - if panel_is_pinnable(self) and panel_is_on_pin(self) then + if panel_has_pause_icon(self) and panel_mouse_is_on_pause_icon(self) then local frame_rect = self.frame_rect return frame_rect.width - 3, 0 end @@ -320,12 +319,6 @@ function Panel:onInput(keys) end return true end - if panel_is_pinnable(self) and keys._MOUSE_L_DOWN then - if panel_is_on_pin(self) then - self.parent_view:togglePinned() - return true - end - end if Panel.super.onInput(self, keys) then return true end @@ -532,7 +525,6 @@ Window.ATTRS { frame_background = gui.CLEAR_PEN, frame_inset = 1, draggable = true, - pinnable = true, } -------------------