Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Feb 20, 2011, 12:47:57 AM (13 years ago)
Author:
landauf
Message:

implemented new keyboard control of menu buttons with these new features:

  • more intuitive placement of buttons in table (row/column format instead of linear index)
  • no need to overwrite onShow() and onKeyPressed() functions, no need for P.buttonList
  • highlights the selected button in a different layout than mouse hovering
  • remembers the selection while moving through the menu hierarchy, but resets it if the menu is closed
  • allows preselected button (for example "Yes" in decision popup)
  • when opening a menu, the first selected button is not always the upper left, but instead depends on the pressed key (e.g. the 'up' key selects the button at the bottom, while the 'down' key selects the button at the top. once a button is selected, the keys behave as usual)

+ fixed wrong callback function in ingame menu

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/usability/data/gui/scripts/GUISheet.lua

    r7689 r7922  
    1616end
    1717
     18-- Override this function if you need to do work on show
     19function P:onShow()
     20end
     21
     22-- Override this function if you need to do work on hide
     23function P:onHide()
     24end
     25
     26-- Override this function if you need to do work just after the sheet has been hidden
     27function P:onAfterHide()
     28end
     29
    1830-- show function for the GUI
    1931function P:show()
     
    2133    self.bVisible = true
    2234
     35    -- set the selected button's state
     36    if self.buttons and self:hasSelection() then
     37        self:setButtonStateSelected()
     38    end
     39
    2340    self:onShow()
    24 end
    25 
    26 -- Override this function if you need to do work on show
    27 function P:onShow()
    2841end
    2942
     
    3649end
    3750
    38 -- Override this function if you need to do work on hide
    39 function P:onHide()
    40 end
    41 
    42 -- Override this function if you need to do work just after the sheet has been hidden
    4351function P:afterHide()
     52    -- reset the selected button
     53    if self.buttons then
     54        self:resetSelection()
     55    end
     56
     57    self:onAfterHide()
    4458end
    4559
     
    6478end
    6579
    66 function P:onKeyPressed(e)
     80-- Handles key pressed while the gui sheed is displayed
     81function P:keyPressed()
     82    if self.buttons then
     83        if code == "208" then     -- key down
     84            self:moveSelection(1, 0)
     85        elseif code == "200" then -- key up
     86            self:moveSelection(-1, 0)
     87        elseif code == "205" then -- key right
     88            self:moveSelection(0, 1)
     89        elseif code == "203" then -- key left
     90            self:moveSelection(0, -1)
     91        elseif code == "28"  then -- key enter
     92            self:pressSelectedButton()
     93        end
     94    end
     95
     96    self.onKeyPressed()
     97end
     98
     99-- Override this function if you want to ract on keystrokes
     100function P:onKeyPressed()
     101end
     102
     103
     104-------------------------------------------------------------------------------
     105-- Keyboard control -----------------------------------------------------------
     106-------------------------------------------------------------------------------
     107
     108-- Initializes the buttons table, used to control the menu with the keyboard
     109function P:initButtons(rows, columns)
     110    self.rows = rows
     111    self.columns = columns
     112    self.buttons = {}
     113    self.selectedRow = 0
     114    self.selectedColumn = 0
     115end
     116
     117-- Defines the button for a given position in the table. The upper-left button is at position (1, 1)
     118function P:setButton(row, column, button)
     119    assert(self.rows ~= nil and self.columns ~= nil and self.buttons ~= nil, "You have to call initButtons() before using setButton()")
     120    assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
     121
     122    self.buttons[(row - 1) * self.columns + (column - 1)] = button
     123end
     124
     125-- Returns the button at a given position in the table. The upper-left button is at position (1, 1)
     126function P:getButton(row, column)
     127    assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
     128
     129    return self.buttons[(row - 1) * self.columns + (column - 1)]
     130end
     131
     132-- Returns the selected button
     133function P:getSelectedButton()
     134    assert(self.selectedRow > 0 and self.selectedColumn > 0, "no button selected")
     135
     136    return self:getButton(self.selectedRow, self.selectedColumn)
     137end
     138
     139-- Presses the selected button if any
     140function P:pressSelectedButton()
     141    if self:hasSelection() then
     142        self:getSelectedButton().callback()
     143    end
     144end
     145
     146-- Sets the selection to a given row and column. The upper-left button is at position (1, 1)
     147function P:setSelection(row, column)
     148    assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
     149
     150    if self:hasSelection() then
     151        self:setButtonStateNormal()
     152    end
     153
     154    self.selectedRow = row
     155    self.selectedColumn = column
     156
     157    self:setButtonStateSelected()
     158end
     159
     160-- Moves the selection by a given number of rows and columns (positive values mean increasing row/column, negative values mean decreasing row/column)
     161function P:moveSelection(relRow, relColumn)
     162    -- if there's no selection yet, prepare it such that the selection enters the table from the desired side
     163    if self:hasSelection() == false then
     164        -- note: we assume either relRow or relColumn is 0, thus no diagonal movement. therefore the following checks can be separated
     165        if relRow > 0 then
     166            self.selectedRow = 0
     167            self.selectedColumn = 1
     168        elseif relRow < 0 then
     169            self.selectedRow = self.rows + 1
     170            self.selectedColumn = 1
     171        end
     172
     173        if relColumn > 0 then
     174            self.selectedRow = 1
     175            self.selectedColumn = 0
     176        elseif relColumn < 0 then
     177            self.selectedRow = 1
     178            self.selectedColumn = self.columns + 1
     179        end
     180    else
     181        self:setButtonStateNormal()
     182    end
     183
     184    -- move the selection according to the parameters
     185    self.selectedRow = self.selectedRow + relRow
     186    self.selectedColumn = self.selectedColumn + relColumn
     187
     188    -- wrap around on overflow
     189    while self.selectedRow > self.rows do
     190        self.selectedRow = self.selectedRow - self.rows
     191    end
     192    while self.selectedColumn > self.columns do
     193        self.selectedColumn = self.selectedColumn - self.columns
     194    end
     195
     196    -- wrap around on underflow
     197    while self.selectedRow <= 0 do
     198        self.selectedRow = self.selectedRow + self.rows
     199    end
     200    while self.selectedColumn <= 0 do
     201        self.selectedColumn = self.selectedColumn + self.columns
     202    end
     203
     204    -- if the button is deactivated, call this function again
     205    if self:getSelectedButton() == nil then
     206        self:moveSelection(relRow, relColumn)
     207    else
     208        self:setButtonStateSelected()
     209    end
     210end
     211
     212-- Resets the selection
     213function P:resetSelection()
     214    if self:hasSelection() then
     215        self:setButtonStateNormal()
     216    end
     217
     218    self.selectedRow = 0
     219    self.selectedColumn = 0
     220end
     221
     222-- Determines if a button is selected
     223function P:hasSelection()
     224    if self.selectedRow == 0 or self.selectedColumn == 0 then
     225        return false
     226    else
     227        return true
     228    end
     229end
     230
     231-- Sets the selected button's state to normal
     232function P:setButtonStateNormal()
     233    self:setButtonState("Normal")
     234end
     235
     236-- Sets the selected button's state to selected
     237function P:setButtonStateSelected()
     238    self:setButtonState("Selected")
     239end
     240
     241-- Sets the selected button's state to pushed
     242function P:setButtonStatePushed()
     243    self:setButtonState("Pushed")
     244end
     245
     246-- Sets the selected button's state
     247function P:setButtonState(state)
     248    if self:getSelectedButton() then
     249        local element = self:getSelectedButton().button
     250        local offset = getElementStateOffset(element)
     251
     252        if offset then
     253            element:setProperty("NormalImageRightEdge",  string.sub(element:getProperty("NormalImageRightEdge"),  1, offset) .. state)
     254            element:setProperty("NormalImageLeftEdge",   string.sub(element:getProperty("NormalImageLeftEdge"),   1, offset) .. state)
     255            element:setProperty("NormalImageBackground", string.sub(element:getProperty("NormalImageBackground"), 1, offset) .. state)
     256        end
     257    end
     258end
     259
     260-- Gets the offset of the button's current state
     261function getElementStateOffset(element)
     262    local property = element:getProperty("NormalImageRightEdge")
     263
     264    if string.sub(property, string.len(property) - 5, string.len(property)) == "Normal" then
     265        return -7
     266    elseif string.sub(property, string.len(property) - 7, string.len(property)) == "Selected" then
     267        return -9
     268    elseif string.sub(property, string.len(property) - 5, string.len(property)) == "Pushed" then
     269        return -7
     270    else
     271        return nil
     272    end
    67273end
    68274
Note: See TracChangeset for help on using the changeset viewer.