ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.3
Committed: Mon Oct 18 15:34:23 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.2: +107 -61 lines
Log Message:
first attempt to support maximising windows

File Contents

# Content
1 #include "deliantra/sender.h"
2
3 #include "dclient/input_handler.h"
4 #include "dclient/widgets.h"
5 #include "dclient/widgets/inventory.h"
6 #include "dclient/widgets/map.h"
7 #include "dclient/widgets/query.h"
8 #include "dclient/widgets/stats.h"
9
10 #include "adt/bind.h"
11
12 #include <ndk++/application.hh>
13
14 #include <curses.h>
15
16 #include <map>
17
18 typedef unsigned long flags_t;
19
20 enum class flags
21 : flags_t
22 {
23 none,
24 firing = 1 << 0,
25 running = 1 << 1,
26
27 COUNT
28 };
29
30 static flags &
31 operator += (flags &lhs, flags rhs)
32 {
33 return lhs = flags (flags_t (lhs) | flags_t (rhs));
34 }
35
36 static flags &
37 operator -= (flags &lhs, flags rhs)
38 {
39 return lhs = flags (flags_t (lhs) & ~flags_t (rhs));
40 }
41
42 static bool
43 operator & (flags lhs, flags rhs)
44 {
45 return flags_t (lhs) & flags_t (rhs);
46 }
47
48
49 enum class action
50 {
51 none,
52
53 north,
54 northeast,
55 east,
56 southeast,
57 south,
58 southwest,
59 west,
60 northwest,
61
62 run,
63 fire,
64 stay_fire,
65
66 quit,
67 redraw,
68 resize,
69 maximise,
70 input_mode,
71
72 apply,
73 take,
74
75 COUNT
76 };
77
78
79 struct input_handler::pimpl
80 : sender
81 {
82 pimpl ( interface::communicator &comm
83 , interface::service_manager &svs
84 , widgets &ui
85 );
86
87 void perform (ncurses::panel *sender, action cmd, action arg = action::none);
88
89 ndk::event::result on_kbd_common (ndk::keyboard const &ev);
90 ndk::event::result on_kbd_map (ndk::keyboard const &ev);
91
92 void on_command (std::string const &cmd);
93
94 interface::service_manager &svs;
95
96 widgets &ui;
97 std::string esc;
98 flags state;
99 };
100
101 input_handler::pimpl::pimpl ( interface::communicator &comm
102 , interface::service_manager &svs
103 , widgets &ui
104 )
105 : sender (comm)
106 , svs (svs)
107 , ui (ui)
108 , state (flags::none)
109 {
110 auto kbd_common = ndk::slot (&pimpl::on_kbd_common, this);
111
112 ui.map->events ()->on_keyboard (kbd_common);
113 ui.info->events ()->on_keyboard (kbd_common);
114 ui.stats->events ()->on_keyboard (kbd_common);
115 ui.inventory->events ()->on_keyboard (kbd_common);
116 ui.container->events ()->on_keyboard (kbd_common);
117 ui.invmenu->events ()->on_keyboard (kbd_common);
118 ui.query->events ()->on_keyboard (kbd_common);
119
120 ui.map->events ()->on_keyboard (ndk::slot (&pimpl::on_kbd_map, this));
121
122 ui.input->on_commit () = ndk::slot (&pimpl::on_command, this);
123 }
124
125 void
126 input_handler::pimpl::perform (ncurses::panel *sender, action cmd, action arg)
127 {
128 if (state & flags::running)
129 {
130 send ("command", "run_stop");
131 state -= flags::running;
132 }
133 if (state & flags::firing)
134 {
135 send ("command", "fire_stop");
136 state -= flags::firing;
137 }
138
139 switch (cmd)
140 {
141 case action::none:
142 break;
143
144 // direction commands
145 case action::north: send ("command", "north" ); break;
146 case action::northeast: send ("command", "northeast"); break;
147 case action::east: send ("command", "east" ); break;
148 case action::southeast: send ("command", "southeast"); break;
149 case action::south: send ("command", "south" ); break;
150 case action::southwest: send ("command", "southwest"); break;
151 case action::west: send ("command", "west" ); break;
152 case action::northwest: send ("command", "northwest"); break;
153
154 // running
155 case action::run:
156 send ("command", "run ", int (arg));
157 state += flags::running;
158 break;
159
160 // firing
161 case action::fire:
162 send ("command", "fire ", int (arg));
163 state += flags::firing;
164 break;
165
166 case action::stay_fire:
167 send ("command", "stay fire");
168 break;
169
170 // control commands
171 case action::quit:
172 svs.stop ();
173 break;
174
175 case action::redraw:
176 redrawwin (stdscr);
177 break;
178
179 case action::resize:
180 ui.resize ();
181 break;
182
183 case action::maximise:
184 if (ui.maximised)
185 ui.maximised = nullptr;
186 else
187 ui.maximised = sender;
188 perform (sender, action::resize);
189 break;
190
191 case action::input_mode:
192 ui.input->visualize ();
193 ui.input->focus ();
194 break;
195
196 // action commands
197 case action::apply:
198 send ("command", "apply");
199 break;
200
201 case action::take:
202 send ("command", "take");
203 break;
204
205 // never happens
206 case action::COUNT:
207 abort ();
208 }
209 }
210
211 ndk::event::result
212 input_handler::pimpl::on_kbd_common (ndk::keyboard const &ev)
213 {
214 switch (ev.code ())
215 {
216 case ndk::key::error:
217 throw "ERR";
218
219 // control actions
220 case ndk::key::ctrl_d:
221 case 'q':
222 perform (ev.sender (), action::quit);
223 return ndk::event::accepted;
224
225 case ndk::key::ctrl_l:
226 perform (ev.sender (), action::redraw);
227 return ndk::event::accepted;
228
229 case ndk::key::resize:
230 perform (ev.sender (), action::resize);
231 return ndk::event::accepted;
232
233 case ndk::key::F10:
234 perform (ev.sender (), action::maximise);
235 return ndk::event::accepted;
236
237 default:
238 return ndk::event::ignored;
239 }
240 }
241
242 ndk::event::result
243 input_handler::pimpl::on_kbd_map (ndk::keyboard const &ev)
244 {
245 switch (ev.code ())
246 {
247 // moving
248 case 'j':
249 case '2':
250 case ndk::key::down:
251 perform (ev.sender (), action::south);
252 return ndk::event::accepted;
253 case 'k':
254 case '8':
255 case ndk::key::up:
256 perform (ev.sender (), action::north);
257 return ndk::event::accepted;
258 case 'h':
259 case '4':
260 case ndk::key::left:
261 perform (ev.sender (), action::west);
262 return ndk::event::accepted;
263 case 'l':
264 case '6':
265 case ndk::key::right:
266 perform (ev.sender (), action::east);
267 return ndk::event::accepted;
268 case '7':
269 case ndk::key::home:
270 perform (ev.sender (), action::northwest);
271 return ndk::event::accepted;
272 case '9':
273 case ndk::key::pg_up:
274 perform (ev.sender (), action::northeast);
275 return ndk::event::accepted;
276 case '5':
277 case ndk::key::numpad_center:
278 perform (ev.sender (), action::stay_fire);
279 return ndk::event::accepted;
280 case '1':
281 case ndk::key::end:
282 perform (ev.sender (), action::southwest);
283 return ndk::event::accepted;
284 case '3':
285 case ndk::key::pg_dn:
286 perform (ev.sender (), action::southeast);
287 return ndk::event::accepted;
288
289 case ' ':
290 perform (ev.sender (), action::apply);
291 return ndk::event::accepted;
292 case ',':
293 perform (ev.sender (), action::take);
294 return ndk::event::accepted;
295 case ndk::key::enter:
296 case 'i':
297 perform (ev.sender (), action::input_mode);
298 return ndk::event::accepted;
299 case 'c':
300 ui.input->set_text ("chat ");
301 perform (ev.sender (), action::input_mode);
302 return ndk::event::accepted;
303 case '"':
304 ui.input->set_text ("say ");
305 perform (ev.sender (), action::input_mode);
306 return ndk::event::accepted;
307 case '\'':
308 ui.input->set_text ("tell ");
309 perform (ev.sender (), action::input_mode);
310 return ndk::event::accepted;
311
312 // firing
313 case 'J':
314 case ndk::key::shift_down:
315 perform (ev.sender (), action::fire, action::south);
316 return ndk::event::accepted;
317 case 'K':
318 case ndk::key::shift_up:
319 perform (ev.sender (), action::fire, action::north);
320 return ndk::event::accepted;
321 case 'H':
322 case ndk::key::shift_left:
323 perform (ev.sender (), action::fire, action::west);
324 return ndk::event::accepted;
325 case 'L':
326 case ndk::key::shift_right:
327 perform (ev.sender (), action::fire, action::east);
328 return ndk::event::accepted;
329 case ndk::key::shift_home:
330 perform (ev.sender (), action::fire, action::northwest);
331 return ndk::event::accepted;
332 case ndk::key::shift_pg_up:
333 perform (ev.sender (), action::fire, action::northeast);
334 return ndk::event::accepted;
335 case ndk::key::shift_end:
336 perform (ev.sender (), action::fire, action::southwest);
337 return ndk::event::accepted;
338 case ndk::key::shift_pg_dn:
339 perform (ev.sender (), action::fire, action::southeast);
340 return ndk::event::accepted;
341
342 // running
343 //case 'J':
344 case ndk::key::ctrl_down:
345 perform (ev.sender (), action::run, action::south);
346 return ndk::event::accepted;
347 //case 'K':
348 case ndk::key::ctrl_up:
349 perform (ev.sender (), action::run, action::north);
350 return ndk::event::accepted;
351 //case 'H':
352 case ndk::key::ctrl_left:
353 perform (ev.sender (), action::run, action::west);
354 return ndk::event::accepted;
355 //case 'L':
356 case ndk::key::ctrl_right:
357 perform (ev.sender (), action::run, action::east);
358 return ndk::event::accepted;
359 case ndk::key::ctrl_home:
360 perform (ev.sender (), action::run, action::northwest);
361 return ndk::event::accepted;
362 case ndk::key::ctrl_pg_up:
363 perform (ev.sender (), action::run, action::northeast);
364 return ndk::event::accepted;
365 case ndk::key::ctrl_end:
366 perform (ev.sender (), action::run, action::southwest);
367 return ndk::event::accepted;
368 case ndk::key::ctrl_pg_dn:
369 perform (ev.sender (), action::run, action::southeast);
370 return ndk::event::accepted;
371
372 case ndk::key::tab:
373 return ndk::event::ignored;
374
375 case ndk::key::unknown:
376 return ndk::event::ignored;
377
378 default:
379 if (getenv ("DCLIENT_FATAL"))
380 throw ev.code ();
381 else
382 {
383 ui.info->add_text ("unknown keycode: 0%03o\n", ev.code ());
384 ui.info->visualize ();
385 return ndk::event::ignored;
386 }
387 }
388 }
389
390 void
391 input_handler::pimpl::on_command (std::string const &cmd)
392 {
393 if (!cmd.empty ())
394 send ("command", cmd);
395
396 ui.map->focus ();
397 ui.input->set_text ("");
398 ui.input->hide ();
399 ndk::app ().cursor_off (); // FIXME: should be done automatically
400 }
401
402
403 input_handler::input_handler ( interface::communicator &comm
404 , interface::service_manager &svs
405 , widgets &ui
406 )
407 : impl (new pimpl (comm, svs, ui))
408 {
409 }
410
411 input_handler::~input_handler ()
412 {
413 delete impl;
414 }
415
416 void
417 input_handler::handle_read (boost::system::error_code const &error, size_t length)
418 {
419 ndk::app ().process (getch ());
420 }