1-- Copyright (C) 2012 Jared Krinke.
2--
3-- This is free software; you can redistribute it and/or
4-- modify it under the terms of the GNU General Public License
5-- as published by the Free Software Foundation; either version 2
6-- of the License, or (at your option) any later version.
7--
8-- This program is distributed in the hope that it will be useful,
9-- but WITHOUT ANY WARRANTY; without even the implied warranty of
10-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11-- GNU General Public License for more details.
12--
13-- You should have received a copy of the GNU General Public License
14-- along with this program; if not, write to the Free Software
15-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17require("UI/Input.lua")
18require("UI/Label.lua")
19require("UI/Button.lua")
20require("UI/Form.lua")
21
22-- Helper layer for setting a new control
23local rawEventCaptureLayer = Layer.new(-1)
24
25rawEventCaptureLayer:addChild(Entity.new(0, 0, 0, Form.defaultTextWidth, Form.defaultTextHeight, 0, Color.new(1, 1, 1), ElementList.new(Element.Text.new("Press any key", 0, 0, 0, 1, 1, 0, Color.new(1, 1, 1), "center"))))
26
27-- TODO: Add some UI for binding (preferably without hiding lower layers)
28function rawEventCaptureLayer.rawEventReceived(self, rawEvent, pressed)
29    if isString(rawEvent) then
30        if pressed then
31            self.rawEvent = rawEvent
32        elseif not pressed and not isNil(self.rawEvent) then
33            Layers.pop()
34
35            if isFunction(self.rawEventCaptured) then
36                self.rawEventCaptured()
37            end
38        end
39    end
40end
41
42function rawEventCaptureLayer.keyPressed(self, key, pressed, character)
43    self:rawEventReceived(key, pressed)
44end
45
46function rawEventCaptureLayer.mouseButtonPressed(self, button, pressed, x, y)
47    self:rawEventReceived(button, pressed)
48end
49
50function rawEventCaptureLayer.joystickButtonPressed(self, joystick, button, pressed)
51    self:rawEventReceived(Input.translateJoystickButtonToRawEvent(joystick, button), pressed)
52end
53
54function rawEventCaptureLayer.joystickAxisMoved(self, joystick, axis, value)
55    local rawEventPressed
56    local rawEventReleased
57
58    rawEventPressed, rawEventReleased = Input.translateJoystickAxisMoveToRawEvent(self, joystick, axis, value)
59
60    self:rawEventReceived(rawEventPressed, true)
61    self:rawEventReceived(rawEventReleased, false)
62end
63
64function rawEventCaptureLayer.capture(self, rawEventCaptured)
65    self.rawEvent = nil
66    self.rawEventCaptured = rawEventCaptured
67    Layers.push(self)
68end
69
70function rawEventCaptureLayer.getRawEvent(self)
71    return self.rawEvent
72end
73
74local function writeRawEventsToStringBuffer(rawEvents, stringBuffer)
75    local first = true
76
77    stringBuffer:clear()
78
79    if isTable(rawEvents) then
80        rawEvents:forEach(function(rawEvent)
81            if first then
82                first = false
83            else
84                stringBuffer:append(" ")
85            end
86
87            stringBuffer:append(rawEvent)
88        end)
89    end
90end
91
92-- The actual control component
93Control = { }
94
95function Control.new(input, logicalEvent, name)
96    local labelText = logicalEvent
97
98    if isString(name) then
99        labelText = name
100    end
101
102    local rawEvents = Label.new("", "right")
103    local control = Form.newNestedBox({ left = Button.new(labelText), center = rawEvents })
104
105    control.input = input
106    control.logicalEvent = logicalEvent
107    control.rawEvents = rawEvents
108    control.buffer = StringBuffer.new()
109
110    function control.notified(self)
111        writeRawEventsToStringBuffer(self.input:getRawEvents(self.logicalEvent), self.buffer)
112        self.rawEvents:setText(self.buffer.text)
113        self:layout()
114    end
115
116    function control.activated(self)
117        rawEventCaptureLayer:capture(function()
118            self.input:bind(rawEventCaptureLayer:getRawEvent(), self.logicalEvent)
119        end)
120    end
121
122    -- Treat as one component
123    control.mouseMoved = nil
124
125    -- Override inputReceived
126    control.inputReceivedBase = control.inputReceived
127
128    function control.inputReceived(self, event, pressed)
129        local handled = false
130
131        if event == "delete" and pressed then
132            -- Remove oldest binding
133            local rawEvents = self.input:getRawEvents(self.logicalEvent)
134
135            if rawEvents:getCount() > 0 then
136                self.input:unbind(rawEvents:get(1), self.logicalEvent)
137            end
138
139            handled = true
140        end
141
142        if not handled then
143            handled = self:inputReceivedBase(event, pressed)
144        end
145
146        return handled
147    end
148
149    input:addListener(function() control:notified() end)
150    control:notified()
151
152    return control
153end
154
155