diff --git a/docs/changelog.txt b/docs/changelog.txt index 2c000262b..eed11d6d6 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -38,6 +38,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Fixes ## Misc Improvements +- Scrollable widgets now react to mouse wheel events when the mouse is over the widget ## Documentation - `overlay-dev-guide`: added troubleshooting tips and common development workflows diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 80277960f..5a9784d24 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4316,7 +4316,6 @@ Attributes: If it returns false, the character is ignored. :on_change: Change notification callback; used as ``on_change(new_text,old_text)``. :on_submit: Enter key callback; if set the field will handle the key and call ``on_submit(text)``. -:on_submit2: Shift-Enter key callback; if set the field will handle the key and call ``on_submit2(text)``. :key: If specified, the field is disabled until this key is pressed. Must be given as a string. :key_sep: If specified, will be used to customize how the activation key is displayed. See ``token.key_sep`` in the ``Label`` documentation below. @@ -4346,8 +4345,8 @@ You can click where you want the cursor to move or you can use any of the following keyboard hotkeys: - Left/Right arrow: move the cursor one character to the left or right. -- Ctrl-Left/Right arrow: move the cursor one word to the left or right. -- Alt-Left/Right arrow: move the cursor to the beginning/end of the text. +- Ctrl-B/Ctrl-F: move the cursor one word back or forward. +- Ctrl-A/Ctrl-E: move the cursor to the beginning/end of the text. Scrollbar class --------------- @@ -4385,6 +4384,10 @@ direction. The amount of scrolling done in each case in determined by the associated widget, and after scrolling is complete, the associated widget must call ``scrollbar:update()`` with updated new display info. +If the mouse wheel is scrolled while the mouse is over the Scrollbar widget's +parent view, then the parent is scrolled accordingly. Holding :kbd:`Shift` +while scrolling will result in faster movement. + You can click and drag the scrollbar to scroll to a specific spot, or you can click and hold on the end arrows or in the unfilled portion of the scrollbar to scroll multiple times, just like in a normal browser scrollbar. The speed of @@ -4629,8 +4632,8 @@ It has the following attributes: with an empty list. :on_submit: Enter key or mouse click callback; if specified, the list reacts to the key/click and calls the callback as ``on_submit(index,choice)``. -:on_submit2: Shift-Enter key or shift-mouse click callback; if specified, the list - reacts to the key/click and calls it as ``on_submit2(index,choice)``. +:on_submit2: Shift-click callback; if specified, the list reacts to the click and + calls the callback as ``on_submit2(index,choice)``. :row_height: Height of every row in text lines. :icon_width: If not *nil*, the specified number of character columns are reserved to the left of the list item for the icons. diff --git a/library/lua/gui/buildings.lua b/library/lua/gui/buildings.lua index ae9219171..8871346f2 100644 --- a/library/lua/gui/buildings.lua +++ b/library/lua/gui/buildings.lua @@ -258,8 +258,8 @@ function BuildingDialog:onSubmitItem(idx, item) end function BuildingDialog:onInput(keys) - if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then - if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then + if keys.LEAVESCREEN then + if self.subviews.back.visible then self:onGoBack() else self:dismiss() @@ -267,9 +267,9 @@ function BuildingDialog:onInput(keys) self.on_cancel() end end - else - self:inputToSubviews(keys) + return true end + self:inputToSubviews(keys) end function showBuildingPrompt(title, prompt, on_select, on_cancel, build_filter) diff --git a/library/lua/gui/dialogs.lua b/library/lua/gui/dialogs.lua index 952e8f734..e5448986f 100644 --- a/library/lua/gui/dialogs.lua +++ b/library/lua/gui/dialogs.lua @@ -48,7 +48,7 @@ end function MessageBox:onRenderFrame(dc,rect) MessageBox.super.onRenderFrame(self,dc,rect) if self.on_accept then - dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('MENU_CONFIRM') + dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('SELECT') end end @@ -59,19 +59,16 @@ function MessageBox:onDestroy() end function MessageBox:onInput(keys) - if keys.MENU_CONFIRM then + if keys.SELECT or keys.LEAVESCREEN then self:dismiss() - if self.on_accept then + if keys.SELECT and self.on_accept then self.on_accept() - end - elseif keys.LEAVESCREEN or (keys.SELECT and not self.on_accept) then - self:dismiss() - if self.on_cancel then + elseif keys.LEAVESCREEN and self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showMessage(title, text, tcolor, on_close) @@ -132,14 +129,15 @@ function InputBox:onInput(keys) if self.on_input then self.on_input(self.subviews.edit.text) end + return true elseif keys.LEAVESCREEN then self:dismiss() if self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showInputPrompt(title, text, tcolor, input, on_input, on_cancel, min_width) @@ -238,9 +236,9 @@ function ListBox:onInput(keys) if self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showListPrompt(title, text, tcolor, choices, on_select, on_cancel, min_width, filter) diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index db80554cd..2686b597e 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -267,6 +267,10 @@ function Viewport:reveal(target,gap,max_scroll,scroll_gap,scroll_z) end MOVEMENT_KEYS = { + KEYBOARD_CURSOR_UP = { 0, -1, 0 }, KEYBOARD_CURSOR_DOWN = { 0, 1, 0 }, + KEYBOARD_CURSOR_LEFT = { -1, 0, 0 }, KEYBOARD_CURSOR_RIGHT = { 1, 0, 0 }, + KEYBOARD_CURSOR_UP_FAST = { 0, -1, 0, true }, KEYBOARD_CURSOR_DOWN_FAST = { 0, 1, 0, true }, + KEYBOARD_CURSOR_LEFT_FAST = { -1, 0, 0, true }, KEYBOARD_CURSOR_RIGHT_FAST = { 1, 0, 0, true }, CURSOR_UP = { 0, -1, 0 }, CURSOR_DOWN = { 0, 1, 0 }, CURSOR_LEFT = { -1, 0, 0 }, CURSOR_RIGHT = { 1, 0, 0 }, CURSOR_UPLEFT = { -1, -1, 0 }, CURSOR_UPRIGHT = { 1, -1, 0 }, @@ -553,66 +557,4 @@ function MenuOverlay:renderMapOverlay(get_overlay_char_fn, bounds_rect) end end ---fakes a "real" workshop sidebar menu, but on exactly selected workshop -WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay) -WorkshopOverlay.focus_path="WorkshopOverlay" -WorkshopOverlay.ATTRS={ - workshop=DEFAULT_NIL, -} -function WorkshopOverlay:onAboutToShow(below) - WorkshopOverlay.super.onAboutToShow(self,below) - - if df.global.world.selected_building ~= self.workshop then - error("The workshop overlay tried to show up for incorrect workshop") - end -end -function WorkshopOverlay:onInput(keys) - local allowedKeys={ --TODO add options: job management, profile, etc... - "CURSOR_RIGHT","CURSOR_RIGHT_FAST","CURSOR_LEFT","CURSOR_LEFT_FAST","CURSOR_UP","CURSOR_UP_FAST","CURSOR_DOWN","CURSOR_DOWN_FAST", - "CURSOR_UPRIGHT","CURSOR_UPRIGHT_FAST","CURSOR_UPLEFT","CURSOR_UPLEFT_FAST","CURSOR_DOWNRIGHT","CURSOR_DOWNRIGHT_FAST","CURSOR_DOWNLEFT","CURSOR_DOWNLEFT_FAST", - "CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB","SUSPENDBUILDING"} - - if keys.LEAVESCREEN then - self:dismiss() - self:sendInputToParent('LEAVESCREEN') - elseif keys.CHANGETAB then - self:sendInputToParent("CHANGETAB") - self:inputToSubviews(keys) - self:updateLayout() - else - for _,name in ipairs(allowedKeys) do - if keys[name] then - self:sendInputToParent(name) - break - end - end - self:inputToSubviews(keys) - end - if df.global.world.selected_building ~= self.workshop then - self:dismiss() - return - end -end -function WorkshopOverlay:onGetSelectedBuilding() - return self.workshop -end -local function is_slated_for_remove( bld ) - for i,v in ipairs(bld.jobs) do - if v.job_type==df.job_type.DestroyBuilding then - return true - end - end - return false -end -function WorkshopOverlay:render(dc) - self:renderParent() - if df.global.world.selected_building ~= self.workshop then - return - end - if is_slated_for_remove(self.workshop) then - return - end - - WorkshopOverlay.super.render(self, dc) -end return _ENV diff --git a/library/lua/gui/materials.lua b/library/lua/gui/materials.lua index 1fbce4377..eea881768 100644 --- a/library/lua/gui/materials.lua +++ b/library/lua/gui/materials.lua @@ -255,8 +255,8 @@ function MaterialDialog:onSubmitItem(idx, item) end function MaterialDialog:onInput(keys) - if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then - if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then + if keys.LEAVESCREEN then + if self.subviews.back.visible then self:onGoBack() else self:dismiss() @@ -264,9 +264,9 @@ function MaterialDialog:onInput(keys) self.on_cancel() end end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showMaterialPrompt(title, prompt, on_select, on_cancel, mat_filter) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index c8276750d..7c1c775ee 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -26,16 +26,13 @@ end STANDARDSCROLL = { STANDARDSCROLL_UP = -1, + KEYBOARD_CURSOR_UP = -1, STANDARDSCROLL_DOWN = 1, + KEYBOARD_CURSOR_DOWN = 1, STANDARDSCROLL_PAGEUP = '-page', + KEYBOARD_CURSOR_UP_FAST = '-page', STANDARDSCROLL_PAGEDOWN = '+page', -} - -SECONDSCROLL = { - SECONDSCROLL_UP = -1, - SECONDSCROLL_DOWN = 1, - SECONDSCROLL_PAGEUP = '-page', - SECONDSCROLL_PAGEDOWN = '+page', + KEYBOARD_CURSOR_DOWN_FAST = '+page', } ------------ @@ -366,8 +363,10 @@ function Panel:setKeyboardDragEnabled(enabled) return end if enabled then - local kbd_get_pos = function() return {x=0, y=0} end - Panel_begin_drag(self, kbd_get_pos()) + local kbd_get_pos = function() + return {x=self.frame_rect.x1, y=self.frame_rect.y1} + end + Panel_begin_drag(self) self.kbd_get_pos = kbd_get_pos else Panel_end_drag(self) @@ -680,22 +679,20 @@ function EditField:onInput(keys) return true end - if keys.SELECT then - if self.key then - self:setFocus(false) - end - if self.on_submit then - self.on_submit(self.text) - return true - end - return not not self.key - elseif keys.SEC_SELECT then + if keys.SELECT or keys.CUSTOM_SHIFT_ENTER then if self.key then self:setFocus(false) end - if self.on_submit2 then - self.on_submit2(self.text) - return true + if keys.CUSTOM_SHIFT_ENTER then + if self.on_submit2 then + self.on_submit2(self.text) + return true + end + else + if self.on_submit then + self.on_submit(self.text) + return true + end end return not not self.key elseif keys._MOUSE_L then @@ -726,25 +723,25 @@ function EditField:onInput(keys) self.on_change(self.text, old) end return true - elseif keys.CURSOR_LEFT then + elseif keys.KEYBOARD_CURSOR_LEFT then self:setCursor(self.cursor - 1) return true - elseif keys.A_MOVE_W_DOWN then -- Ctrl-Left (end of prev word) + elseif keys.CUSTOM_CTRL_B then -- back one word local _, prev_word_end = self.text:sub(1, self.cursor-1): - find('.*[%w_%-][^%w_%-]') + find('.*[%w_%-][^%w_%-]') self:setCursor(prev_word_end or 1) return true - elseif keys.A_CARE_MOVE_W then -- Alt-Left (home) + elseif keys.CUSTOM_CTRL_A then -- home self:setCursor(1) return true - elseif keys.CURSOR_RIGHT then + elseif keys.KEYBOARD_CURSOR_RIGHT then self:setCursor(self.cursor + 1) return true - elseif keys.A_MOVE_E_DOWN then -- Ctrl-Right (beginning of next word) + elseif keys.CUSTOM_CTRL_F then -- forward one word local _,next_word_start = self.text:find('[^%w_%-][%w_%-]', self.cursor) self:setCursor(next_word_start) return true - elseif keys.A_CARE_MOVE_E then -- Alt-Right (end) + elseif keys.CUSTOM_CTRL_E then -- end self:setCursor() return true end @@ -938,10 +935,26 @@ function Scrollbar:onRenderBody(dc) end function Scrollbar:onInput(keys) - if not keys._MOUSE_L_DOWN or not self.on_scroll - or not scrollbar_is_visible(self) then + if not self.on_scroll or not scrollbar_is_visible(self) then return false end + + if self.parent_view:getMousePos() then + if keys.CONTEXT_SCROLL_UP then + self.on_scroll('up_small') + return true + elseif keys.CONTEXT_SCROLL_DOWN then + self.on_scroll('down_small') + return true + elseif keys.CONTEXT_SCROLL_PAGEUP then + self.on_scroll('up_large') + return true + elseif keys.CONTEXT_SCROLL_PAGEDOWN then + self.on_scroll('down_large') + return true + end + end + if not keys._MOUSE_L_DOWN then return false end local _,y = self:getMousePos() if not y then return false end local scroll_spec = nil @@ -1683,12 +1696,14 @@ end function List:submit() if self.on_submit and #self.choices > 0 then self.on_submit(self:getSelected()) + return true end end function List:submit2() if self.on_submit2 and #self.choices > 0 then self.on_submit2(self:getSelected()) + return true end end @@ -1696,12 +1711,10 @@ function List:onInput(keys) if self:inputToSubviews(keys) then return true end - if self.on_submit and keys.SELECT then - self:submit() - return true - elseif self.on_submit2 and keys.SEC_SELECT then - self:submit2() - return true + if keys.SELECT then + return self:submit() + elseif keys.CUSTOM_SHIFT_ENTER then + return self:submit2() elseif keys._MOUSE_L_DOWN then local idx = self:getIdxUnderMouse() if idx then