| 1 |
//--------------------------------------------------------------------- |
|---|
| 2 |
/* |
|---|
| 3 |
Copyright: |
|---|
| 4 |
|
|---|
| 5 |
luigi/adapter/base.d -- input adaptor basics for the 'Luigi' user |
|---|
| 6 |
interface library. |
|---|
| 7 |
|
|---|
| 8 |
Copyright (C) 2006 William V. Baxter III |
|---|
| 9 |
|
|---|
| 10 |
This software is provided 'as-is', without any express or implied |
|---|
| 11 |
warranty. In no event will the authors be held liable for any |
|---|
| 12 |
damages arising from the use of this software. |
|---|
| 13 |
|
|---|
| 14 |
Permission is granted to anyone to use this software for any |
|---|
| 15 |
purpose, including commercial applications, and to alter it and |
|---|
| 16 |
redistribute it freely, subject to the following restrictions: |
|---|
| 17 |
|
|---|
| 18 |
1. The origin of this software must not be misrepresented; you must |
|---|
| 19 |
not claim that you wrote the original software. If you use this |
|---|
| 20 |
software in a product, an acknowledgment in the product |
|---|
| 21 |
documentation would be appreciated but is not required. |
|---|
| 22 |
2. Altered source versions must be plainly marked as such, and must |
|---|
| 23 |
not be misrepresented as being the original software. |
|---|
| 24 |
3. This notice may not be removed or altered from any source distribution. |
|---|
| 25 |
|
|---|
| 26 |
William Baxter wbaxter@gmail.com |
|---|
| 27 |
*/ |
|---|
| 28 |
module luigi.adapter; |
|---|
| 29 |
|
|---|
| 30 |
//import sslot.signal; |
|---|
| 31 |
import luigi.signalobj; |
|---|
| 32 |
import luigi.base; |
|---|
| 33 |
import luigi.event; |
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
/** The InputAdapter interface allows the GUI to connect to various windowing toolkits. |
|---|
| 37 |
Luigi wants to be able to get input from whatever source possible, be it GLFW, GLUT, SDL, |
|---|
| 38 |
native Win32, GTK, wxWidgets, or whatever. Implementations of the input adapter |
|---|
| 39 |
allow Luigi and applications to pretend that all toolkits work the same way, regardless |
|---|
| 40 |
of the back-end chosen. In particular Luigi puts a facade of a Signals-and-Slots type |
|---|
| 41 |
of delivery mechanism on top of whatever the underlying mechanism is. |
|---|
| 42 |
|
|---|
| 43 |
One common way simple toolkits like GLUT deliver input to applications is via callbacks. |
|---|
| 44 |
They usually allow one, and only one, function to be called. |
|---|
| 45 |
A concrete InputAdapter for one of these will override all callback methods and emit |
|---|
| 46 |
signals identifying all the events. |
|---|
| 47 |
|
|---|
| 48 |
To implement a new adapter, derive from the InputAdapter interface, and mixin the |
|---|
| 49 |
InputAdapterMix. This sets up the external interface and the signals. |
|---|
| 50 |
*/ |
|---|
| 51 |
interface InputAdapter |
|---|
| 52 |
{ |
|---|
| 53 |
/// Get the size of the specified window, using an opaque |
|---|
| 54 |
/// window handle. |
|---|
| 55 |
Size get_window_size(WindowHandle h); |
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
/** |
|---|
| 59 |
* These are standard user-level callbacks. |
|---|
| 60 |
* These get dispatched to your code only for |
|---|
| 61 |
* events that weren't handled by any widget |
|---|
| 62 |
* on the GUI overlay. |
|---|
| 63 |
*/ |
|---|
| 64 |
void addKeyCallback(KeyEventFn cb) ; |
|---|
| 65 |
void addMouseButtonCallback(MouseButtonEventFn cb) ; |
|---|
| 66 |
void addMouseMoveCallback(MouseMoveEventFn cb) ; |
|---|
| 67 |
void addMouseWheelCallback(MouseWheelEventFn cb) ; |
|---|
| 68 |
void addWindowSizeCallback(WindowSizeEventFn cb) ; |
|---|
| 69 |
void addWindowCloseCallback(WindowCloseEventFn cb) ; |
|---|
| 70 |
|
|---|
| 71 |
// And again for delegates... |
|---|
| 72 |
void addKeyCallback(KeyEventDg cb) ; |
|---|
| 73 |
void addMouseButtonCallback(MouseButtonEventDg cb) ; |
|---|
| 74 |
void addMouseMoveCallback(MouseMoveEventDg cb) ; |
|---|
| 75 |
void addMouseWheelCallback(MouseWheelEventDg cb) ; |
|---|
| 76 |
void addWindowSizeCallback(WindowSizeEventDg cb) ; |
|---|
| 77 |
void addWindowCloseCallback(WindowCloseEventDg cb) ; |
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
// remove raw system callback |
|---|
| 81 |
void removeKeyCallback(KeyEventFn cb) ; |
|---|
| 82 |
void removeMouseButtonCallback(MouseButtonEventFn cb) ; |
|---|
| 83 |
void removeMouseMoveCallback(MouseMoveEventFn cb) ; |
|---|
| 84 |
void removeMouseWheelCallback(MouseWheelEventFn cb) ; |
|---|
| 85 |
void removeWindowSizeCallback(WindowSizeEventFn cb) ; |
|---|
| 86 |
void removeWindowCloseCallback(WindowCloseEventFn cb) ; |
|---|
| 87 |
|
|---|
| 88 |
// And again for delegates... |
|---|
| 89 |
void removeKeyCallback(KeyEventDg cb) ; |
|---|
| 90 |
void removeMouseButtonCallback(MouseButtonEventDg cb) ; |
|---|
| 91 |
void removeMouseMoveCallback(MouseMoveEventDg cb) ; |
|---|
| 92 |
void removeMouseWheelCallback(MouseWheelEventDg cb) ; |
|---|
| 93 |
void removeWindowSizeCallback(WindowSizeEventDg cb) ; |
|---|
| 94 |
void removeWindowCloseCallback(WindowCloseEventDg cb) ; |
|---|
| 95 |
|
|---|
| 96 |
/** |
|---|
| 97 |
* These are "raw" system callbacks in that they haven't yet been |
|---|
| 98 |
* translated or dispatched to widgets. This is all the input |
|---|
| 99 |
* that comes in at the window level. Luigi uses these to get |
|---|
| 100 |
* input which is then dispatched to widgets based on current |
|---|
| 101 |
* focus item, location of the mouse, etc. See event.d for the |
|---|
| 102 |
* definitons of the function types. |
|---|
| 103 |
*/ |
|---|
| 104 |
void addSysKeyCallback(KeyEventFn cb) ; |
|---|
| 105 |
void addSysMouseButtonCallback(MouseButtonEventFn cb) ; |
|---|
| 106 |
|
|---|
| 107 |
// And again for delegates... |
|---|
| 108 |
void addSysKeyCallback(KeyEventDg cb) ; |
|---|
| 109 |
void addSysMouseButtonCallback(MouseButtonEventDg cb) ; |
|---|
| 110 |
|
|---|
| 111 |
// remove raw system callback |
|---|
| 112 |
void removeSysKeyCallback(KeyEventFn cb) ; |
|---|
| 113 |
void removeSysMouseButtonCallback(MouseButtonEventFn cb) ; |
|---|
| 114 |
|
|---|
| 115 |
// And again for delegates... |
|---|
| 116 |
void removeSysKeyCallback(KeyEventDg cb) ; |
|---|
| 117 |
void removeSysMouseButtonCallback(MouseButtonEventDg cb) ; |
|---|
| 118 |
|
|---|
| 119 |
// addRaw Paint |
|---|
| 120 |
// addRaw Idle |
|---|
| 121 |
|
|---|
| 122 |
// pollInput? |
|---|
| 123 |
// swapBuffers? |
|---|
| 124 |
|
|---|
| 125 |
// Other candidates: Create window, Move/Resize window, Set window title |
|---|
| 126 |
// maybe need a separate WindowSys adapter? |
|---|
| 127 |
// I don't want to be in the business of wrapping the OS, or becoming another GLUT. |
|---|
| 128 |
// Just the minimal things needed to run an on-screen UI. Let them use GLUT for |
|---|
| 129 |
// what GLUT does as much as possible. I really just need the inputs, and to know when my |
|---|
| 130 |
// window changes size, and perhaps goes away. |
|---|
| 131 |
} |
|---|
| 132 |
|
|---|
| 133 |
template InputAdapterMix() |
|---|
| 134 |
{ |
|---|
| 135 |
//------------------------------------------------------- |
|---|
| 136 |
// Use 'sig.*.emit' to emit signals from your InputAdapter implementation. |
|---|
| 137 |
// Use example: |
|---|
| 138 |
// KeyEvent ev; |
|---|
| 139 |
// [...build KeyEvent from native data...] |
|---|
| 140 |
// sig.key.emit(ev); |
|---|
| 141 |
|
|---|
| 142 |
// You MUST call this from your Adapter's constructor! |
|---|
| 143 |
void initInputAdapter() { |
|---|
| 144 |
with (_lsig) { |
|---|
| 145 |
key = new KeyEventSignal; |
|---|
| 146 |
mouseButton = new MouseButtonEventSignal; |
|---|
| 147 |
mouseMove = new MouseMoveEventSignal; |
|---|
| 148 |
mouseWheel = new MouseWheelEventSignal; |
|---|
| 149 |
windowSize = new WindowSizeEventSignal; |
|---|
| 150 |
windowClose = new WindowCloseEventSignal; |
|---|
| 151 |
|
|---|
| 152 |
sysKey = new KeyEventSignal; |
|---|
| 153 |
sysMouseButton = new MouseButtonEventSignal; |
|---|
| 154 |
} |
|---|
| 155 |
} |
|---|
| 156 |
|
|---|
| 157 |
//------------------------------------------------------- |
|---|
| 158 |
// The rest shouldn't concernt InputAdapter implementors |
|---|
| 159 |
private struct _LuigiSignals { |
|---|
| 160 |
KeyEventSignal key; |
|---|
| 161 |
MouseButtonEventSignal mouseButton; |
|---|
| 162 |
MouseMoveEventSignal mouseMove; |
|---|
| 163 |
MouseWheelEventSignal mouseWheel; |
|---|
| 164 |
WindowSizeEventSignal windowSize; |
|---|
| 165 |
WindowCloseEventSignal windowClose; |
|---|
| 166 |
|
|---|
| 167 |
KeyEventSignal sysKey; |
|---|
| 168 |
MouseButtonEventSignal sysMouseButton; |
|---|
| 169 |
} |
|---|
| 170 |
private _LuigiSignals _lsig; |
|---|
| 171 |
alias _lsig sig; |
|---|
| 172 |
|
|---|
| 173 |
// Implementation of InputAdapter |
|---|
| 174 |
void addKeyCallback(KeyEventFn cb) {_lsig.key.connect(cb);} |
|---|
| 175 |
void addMouseButtonCallback(MouseButtonEventFn cb) {_lsig.mouseButton.connect(cb);} |
|---|
| 176 |
void addMouseMoveCallback(MouseMoveEventFn cb) {_lsig.mouseMove.connect(cb);} |
|---|
| 177 |
void addMouseWheelCallback(MouseWheelEventFn cb) {_lsig.mouseWheel.connect(cb);} |
|---|
| 178 |
void addWindowSizeCallback(WindowSizeEventFn cb) {_lsig.windowSize.connect(cb);} |
|---|
| 179 |
void addWindowCloseCallback(WindowCloseEventFn cb) {_lsig.windowClose.connect(cb);} |
|---|
| 180 |
|
|---|
| 181 |
// And again for delegates... |
|---|
| 182 |
void addKeyCallback(KeyEventDg cb) {_lsig.key.connect(cb);} |
|---|
| 183 |
void addMouseButtonCallback(MouseButtonEventDg cb) {_lsig.mouseButton.connect(cb);} |
|---|
| 184 |
void addMouseMoveCallback(MouseMoveEventDg cb) {_lsig.mouseMove.connect(cb);} |
|---|
| 185 |
void addMouseWheelCallback(MouseWheelEventDg cb) {_lsig.mouseWheel.connect(cb);} |
|---|
| 186 |
void addWindowSizeCallback(WindowSizeEventDg cb) {_lsig.windowSize.connect(cb);} |
|---|
| 187 |
void addWindowCloseCallback(WindowCloseEventDg cb) {_lsig.windowClose.connect(cb);} |
|---|
| 188 |
|
|---|
| 189 |
// Implementation of InputAdapter |
|---|
| 190 |
void removeKeyCallback(KeyEventFn cb) {_lsig.key.disconnect(cb);} |
|---|
| 191 |
void removeMouseButtonCallback(MouseButtonEventFn cb) {_lsig.mouseButton.disconnect(cb);} |
|---|
| 192 |
void removeMouseMoveCallback(MouseMoveEventFn cb) {_lsig.mouseMove.disconnect(cb);} |
|---|
| 193 |
void removeMouseWheelCallback(MouseWheelEventFn cb) {_lsig.mouseWheel.disconnect(cb);} |
|---|
| 194 |
void removeWindowSizeCallback(WindowSizeEventFn cb) {_lsig.windowSize.disconnect(cb);} |
|---|
| 195 |
void removeWindowCloseCallback(WindowCloseEventFn cb) {_lsig.windowClose.disconnect(cb);} |
|---|
| 196 |
|
|---|
| 197 |
// And again for delegates... |
|---|
| 198 |
void removeKeyCallback(KeyEventDg cb) {_lsig.key.disconnect(cb);} |
|---|
| 199 |
void removeMouseButtonCallback(MouseButtonEventDg cb) {_lsig.mouseButton.disconnect(cb);} |
|---|
| 200 |
void removeMouseMoveCallback(MouseMoveEventDg cb) {_lsig.mouseMove.disconnect(cb);} |
|---|
| 201 |
void removeMouseWheelCallback(MouseWheelEventDg cb) {_lsig.mouseWheel.disconnect(cb);} |
|---|
| 202 |
void removeWindowSizeCallback(WindowSizeEventDg cb) {_lsig.windowSize.disconnect(cb);} |
|---|
| 203 |
void removeWindowCloseCallback(WindowCloseEventDg cb) {_lsig.windowClose.disconnect(cb);} |
|---|
| 204 |
|
|---|
| 205 |
|
|---|
| 206 |
// Implementation of InputAdapter |
|---|
| 207 |
void addSysKeyCallback(KeyEventFn cb) {_lsig.sysKey.connect(cb);} |
|---|
| 208 |
void addSysMouseButtonCallback(MouseButtonEventFn cb) {_lsig.sysMouseButton.connect(cb);} |
|---|
| 209 |
|
|---|
| 210 |
// And again for delegates... |
|---|
| 211 |
void addSysKeyCallback(KeyEventDg cb) {_lsig.sysKey.connect(cb);} |
|---|
| 212 |
void addSysMouseButtonCallback(MouseButtonEventDg cb) {_lsig.sysMouseButton.connect(cb);} |
|---|
| 213 |
|
|---|
| 214 |
// remove raw system callback |
|---|
| 215 |
void removeSysKeyCallback(KeyEventFn cb) {_lsig.sysKey.disconnect(cb);} |
|---|
| 216 |
void removeSysMouseButtonCallback(MouseButtonEventFn cb) {_lsig.sysMouseButton.disconnect(cb);}; |
|---|
| 217 |
|
|---|
| 218 |
// And again for delegates... |
|---|
| 219 |
void removeSysKeyCallback(KeyEventDg cb) {_lsig.sysKey.disconnect(cb);} |
|---|
| 220 |
void removeSysMouseButtonCallback(MouseButtonEventDg cb) {_lsig.sysMouseButton.disconnect(cb);}; |
|---|
| 221 |
|
|---|
| 222 |
|
|---|
| 223 |
|
|---|
| 224 |
} |
|---|
| 225 |
|
|---|
| 226 |
|
|---|
| 227 |
|
|---|
| 228 |
/** Gather input from multiple places */ |
|---|
| 229 |
/* |
|---|
| 230 |
class CompoundInputAdapter : InputAdapter |
|---|
| 231 |
{ |
|---|
| 232 |
InputAdapter[] adapters; |
|---|
| 233 |
} |
|---|
| 234 |
*/ |
|---|