From c1e44c178f437beb4489bc66fad20a02d6340514 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 9 May 2016 21:29:04 -0400 Subject: [PATCH] Add on_click/on_rclick handlers to widgets.Label Closes #919 --- NEWS.rst | 4 ++++ docs/Lua API.rst | 15 +++++++++------ library/lua/gui/widgets.lua | 20 ++++++++++++++++++-- scripts/gui/gm-editor.lua | 3 ++- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index f5bbeae5d..240e0ffc4 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -33,6 +33,10 @@ Changelog DFHack future ============= +Lua +--- +- Label widgets can now easily register handlers for mouse clicks + New Features ------------ - `gui/gm-editor` it's now possible to insert default types to containers. For primitive types leave the type entry empty, for references use ``*``. diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 000884b19..2db98abad 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -44,7 +44,7 @@ also broadly maps to the ``df`` namespace in the headers generated for C++. The wrapper provides almost raw access to the memory of the game, so mistakes in manipulating objects are as likely to crash the game as equivalent plain C++ code would be. - + eg. NULL pointer access is safely detected, but dangling pointers aren't. Objects managed by the wrapper can be broadly classified into the following groups: @@ -180,7 +180,7 @@ They implement the following features: In case of inheritance, *superclass* fields have precedence over the subclass, but fields shadowed in this way can still be accessed as ``ref['subclasstype.field']``. - + This shadowing order is necessary because vtable-based classes are automatically exposed in their exact type, and the reverse rule would make access to superclass fields unreliable. @@ -3051,10 +3051,13 @@ It has the following attributes: :text_pen: Specifies the pen for active text. :text_dpen: Specifies the pen for disabled text. +:text_hpen: Specifies the pen for text hovered over by the mouse, if a click handler is registered. :disabled: Boolean or a callback; if true, the label is disabled. :enabled: Boolean or a callback; if false, the label is disabled. :auto_height: Sets self.frame.h from the text height. :auto_width: Sets self.frame.w from the text width. +:on_click: A callback called when the label is clicked (optional) +:on_rclick: A callback called when the label is right-clicked (optional) The text itself is represented as a complex structure, and passed to the object via the ``text`` argument of the constructor, or via @@ -3499,7 +3502,7 @@ Functions :name: custom workshop id e.g. ``SOAPMAKER`` - + .. note:: this is the only mandatory field. :fix_impassible: @@ -3678,15 +3681,15 @@ Note that this function lets errors propagate to the caller. Run an Lua script and return its environment. This command allows you to use scripts like modules for increased portability. It is highly recommended that if you are a modder you put your custom modules in ``raw/scripts`` and use ``script_environment`` instead of ``require`` so that saves with your mod installed will be self-contained and can be transferred to people who do have DFHack but do not have your mod installed. - + You can say ``dfhack.script_environment('add-thought').addEmotionToUnit([arguments go here])`` and it will have the desired effect. It will call the script in question with the global ``moduleMode`` set to ``true`` so that the script can return early. This is useful because if the script is called from the console it should deal with its console arguments and if it is called by ``script_environment`` it should only create its global functions and return. You can also access global variables with, for example ``print(dfhack.script_environment('add-thought').validArgs)`` - + The function ``script_environment`` is fast enough that it is recommended that you not store its result in a nonlocal variable, because your script might need to load a different version of that script if the save is unloaded and a save with a different mod that overrides the same script with a slightly different functionality is loaded. This will not be an issue in most cases. - + This function also permits circular dependencies of scripts. * ``dfhack.reqscript(name)`` or ``reqscript(name)`` diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 6e789d35d..4bc48c1b5 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -330,15 +330,21 @@ Label = defclass(Label, Widget) Label.ATTRS{ text_pen = COLOR_WHITE, - text_dpen = COLOR_DARKGREY, + text_dpen = COLOR_DARKGREY, -- disabled + text_hpen = DEFAULT_NIL, -- highlight - default is text_pen with reversed brightness disabled = DEFAULT_NIL, enabled = DEFAULT_NIL, auto_height = true, auto_width = false, + on_click = DEFAULT_NIL, + on_rclick = DEFAULT_NIL, } function Label:init(args) self:setText(args.text) + if not self.text_hpen then + self.text_hpen = ((tonumber(self.text_pen) or tonumber(self.text_pen.fg) or 0) + 8) % 16 + end end function Label:setText(text) @@ -374,11 +380,21 @@ function Label:getTextWidth() end function Label:onRenderBody(dc) - render_text(self,dc,0,0,self.text_pen,self.text_dpen,is_disabled(self)) + local text_pen = self.text_pen + if self:getMousePos() and (self.on_click or self.on_rclick) then + text_pen = self.text_hpen + end + render_text(self,dc,0,0,text_pen,self.text_dpen,is_disabled(self)) end function Label:onInput(keys) if not is_disabled(self) then + if keys._MOUSE_L_DOWN and self:getMousePos() and self.on_click then + self:on_click() + end + if keys._MOUSE_R_DOWN and self:getMousePos() and self.on_rclick then + self:on_rclick() + end return check_text_keys(self, keys) end end diff --git a/scripts/gui/gm-editor.lua b/scripts/gui/gm-editor.lua index 9b03ba279..576649013 100644 --- a/scripts/gui/gm-editor.lua +++ b/scripts/gui/gm-editor.lua @@ -136,7 +136,8 @@ function GmEditorUi:init(args) subviews={ mainList, widgets.Label{text={{text="",id="name"},{gap=1,text="Help",key=keybindings.help.key,key_sep = '()'}}, view_id = 'lbl_current_item',frame = {l=1,t=1,yalign=0}}, - widgets.Label{text={{text="Search",key=keybindings.start_filter.key,key_sep = '()'},{text=": "}},frame={l=1,t=2}}, + widgets.Label{text={{text="Search",key=keybindings.start_filter.key,key_sep = '()'},{text=": "}},frame={l=1,t=2}, + on_click=function() self:enable_input(true) end}, widgets.EditField{frame={l=12,t=2},active=false,on_change=self:callback('text_input'),on_submit=self:callback("enable_input",false),view_id="filter_input"}, --widgets.Label{text="BLAH2"} }