Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/data/gui/scripts/GUISheet.lua @ 7925

Last change on this file since 7925 was 7925, checked in by landauf, 13 years ago

if a menu sheet was opened with the keyboard, preselect the first button

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1-- GUISheet.lua
2
3local P = {}
4_G[_REQUIREDNAME or "GUISheet"] = P
5P.__index = P
6
7-- Don't use directly --> use HUDSheet.new or MenuSheet.new
8function P.new(_name)
9    local newSheet = { name = _name }
10    setmetatable(newSheet, P)
11    return newSheet
12end
13
14-- Override this function if you need to do work on load
15function P:onLoad()
16end
17
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
30-- show function for the GUI
31function P:show()
32    self.window:show()
33    self.bVisible = true
34
35    -- set the selected button's state
36    if self.buttons and self:hasSelection() then
37        self:setButtonStateSelected()
38    end
39
40    self:onShow()
41end
42
43-- hide function for the GUI
44function P:hide()
45    self.window:hide()
46    self.bVisible = false
47
48    self:onHide()
49end
50
51function P:afterHide()
52    -- reset the selected button
53    if self.buttons then
54        self:resetSelection()
55    end
56
57    self:onAfterHide()
58end
59
60function P:load()
61    -- Load the layout that describes the sheet
62    self.window = winMgr:loadWindowLayout(self.name .. ".layout")
63    if self.window == nil then
64        error("Could not load layout file for GUI sheet '"..self.name.."'")
65    end
66    -- Hide it at first
67    self:hide()
68    -- Allow sheets to do some work upon loading
69    self:onLoad()
70
71    -- Also load additional sheets to avoid display lags
72    if self.loadAlong then
73        for k, sheet in pairs(self.loadAlong) do
74            loadSheet(sheet)
75        end
76    end
77    return self
78end
79
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.pressedEnter = true
143        self:getSelectedButton().callback()
144        self.pressedEnter = false
145    end
146end
147
148-- Sets the selection to a given row and column. The upper-left button is at position (1, 1)
149function P:setSelection(row, column)
150    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 .. ")")
151
152    if self:hasSelection() then
153        self:setButtonStateNormal()
154    end
155
156    self.selectedRow = row
157    self.selectedColumn = column
158
159    self:setButtonStateSelected()
160end
161
162-- Moves the selection by a given number of rows and columns (positive values mean increasing row/column, negative values mean decreasing row/column)
163function P:moveSelection(relRow, relColumn)
164    -- if there's no selection yet, prepare it such that the selection enters the table from the desired side
165    if self:hasSelection() == false then
166        -- note: we assume either relRow or relColumn is 0, thus no diagonal movement. therefore the following checks can be separated
167        if relRow > 0 then
168            self.selectedRow = 0
169            self.selectedColumn = 1
170        elseif relRow < 0 then
171            self.selectedRow = self.rows + 1
172            self.selectedColumn = 1
173        end
174
175        if relColumn > 0 then
176            self.selectedRow = 1
177            self.selectedColumn = 0
178        elseif relColumn < 0 then
179            self.selectedRow = 1
180            self.selectedColumn = self.columns + 1
181        end
182    else
183        self:setButtonStateNormal()
184    end
185
186    -- move the selection according to the parameters
187    self.selectedRow = self.selectedRow + relRow
188    self.selectedColumn = self.selectedColumn + relColumn
189
190    -- wrap around on overflow
191    while self.selectedRow > self.rows do
192        self.selectedRow = self.selectedRow - self.rows
193    end
194    while self.selectedColumn > self.columns do
195        self.selectedColumn = self.selectedColumn - self.columns
196    end
197
198    -- wrap around on underflow
199    while self.selectedRow <= 0 do
200        self.selectedRow = self.selectedRow + self.rows
201    end
202    while self.selectedColumn <= 0 do
203        self.selectedColumn = self.selectedColumn + self.columns
204    end
205
206    -- if the button is deactivated, call this function again
207    if self:getSelectedButton() == nil then
208        self:moveSelection(relRow, relColumn)
209    else
210        self:setButtonStateSelected()
211    end
212end
213
214-- Resets the selection
215function P:resetSelection()
216    if self:hasSelection() then
217        self:setButtonStateNormal()
218    end
219
220    self.selectedRow = 0
221    self.selectedColumn = 0
222end
223
224-- Determines if a button is selected
225function P:hasSelection()
226    if self.selectedRow == 0 or self.selectedColumn == 0 then
227        return false
228    else
229        return true
230    end
231end
232
233-- Sets the selected button's state to normal
234function P:setButtonStateNormal()
235    self:setButtonState("Normal")
236end
237
238-- Sets the selected button's state to selected
239function P:setButtonStateSelected()
240    self:setButtonState("Selected")
241end
242
243-- Sets the selected button's state to pushed
244function P:setButtonStatePushed()
245    self:setButtonState("Pushed")
246end
247
248-- Sets the selected button's state
249function P:setButtonState(state)
250    if self:getSelectedButton() then
251        local element = self:getSelectedButton().button
252        local offset = getElementStateOffset(element)
253
254        if offset then
255            element:setProperty("NormalImageRightEdge",  string.sub(element:getProperty("NormalImageRightEdge"),  1, offset) .. state)
256            element:setProperty("NormalImageLeftEdge",   string.sub(element:getProperty("NormalImageLeftEdge"),   1, offset) .. state)
257            element:setProperty("NormalImageBackground", string.sub(element:getProperty("NormalImageBackground"), 1, offset) .. state)
258        end
259    end
260end
261
262-- Gets the offset of the button's current state
263function getElementStateOffset(element)
264    local property = element:getProperty("NormalImageRightEdge")
265
266    if string.sub(property, string.len(property) - 5, string.len(property)) == "Normal" then
267        return -7
268    elseif string.sub(property, string.len(property) - 7, string.len(property)) == "Selected" then
269        return -9
270    elseif string.sub(property, string.len(property) - 5, string.len(property)) == "Pushed" then
271        return -7
272    else
273        return nil
274    end
275end
276
277return P
Note: See TracBrowser for help on using the repository browser.