cwidget 0.5.18
widget.h
1// widget.h -*-c++-*-
2//
3// Copyright (C) 2000-2005 Daniel Burrows
4//
5// This program is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License as
7// published by the Free Software Foundation; either version 2 of
8// the License, or (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; see the file COPYING. If not, write to
17// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18// Boston, MA 02111-1307, USA.
19//
20// "widgets" are sort of what they sound like -- entities that get
21// drawn on the screen in some stacked order and can grab keyboard
22// input. By default, the widget currently on the top of the stack
23// has keyboard "focus". (overriding this may be an option eventually
24// but isn't right now) (the widget with keyboard focus gets to
25// determine cursor information)
26//
27//
28// Lifetime of a widget: a widget is potentially active and visible
29// until it is destroyed (via the destroy() method). Once a widget
30// has been destroyed, you cannot un-destroy it, but further calls to
31// destroy() are allowed until the widget is deleted for good.
32// Widgets should generally be referred to using ref_ptr objects; to
33// enforce this, widgets can only be allocated via W::create(...). Of
34// course, as with any refcounting scheme, it's the user's
35// responsibility to prevent cycles by using unsafe_get_ref()
36// appropriately. For instance, pointers to the widget's parent have
37// to be created this way.
38
39#ifndef WIDGET_H
40#define WIDGET_H
41
42#include <list>
43
44#include <sigc++/signal.h>
45#include <sigc++/trackable.h>
46
47#include <cwidget/curses++.h>
48#include <cwidget/generic/util/ref_ptr.h>
49#include <cwidget/style.h>
50
51#include <cwidget/generic/util/eassert.h>
52
53namespace cwidget
54{
55 namespace widgets
56 {
57 class widget;
58 }
59
60 namespace toplevel
61 {
62 bool poll();
63 void mainloop(int);
64 void redraw();
65 util::ref_ptr<widgets::widget> settoplevel(const util::ref_ptr<widgets::widget> &);
67 void resume();
68 void updatecursornow();
69 void handleresize();
70 }
71
72 namespace config
73 {
74 class key;
75 class keybindings;
76 }
77
78 namespace widgets
79 {
80 class container;
81
82 struct size
83 {
84 int w, h;
85 size(int _w, int _h):w(_w), h(_h) {}
86 };
87
88 struct point
89 {
90 int x, y;
91 point(int _x, int _y):x(_x), y(_y) {}
92 };
93
94 struct rect
95 {
96 int x, y, w, h;
97 rect(int _x, int _y, int _w, int _h):x(_x), y(_y), w(_w), h(_h) {}
98 void set_size(const size &s) {w=s.w; h=s.h;}
99 size get_size() {return size(w, h);}
100 };
101
106 class widget:virtual public sigc::trackable
107 {
108 friend class container;
109
110 // Too many friends..
111 friend bool toplevel::poll();
112 friend void toplevel::mainloop(int);
113 friend void toplevel::redraw();
114 friend util::ref_ptr<widget> toplevel::settoplevel(const util::ref_ptr<widget> &);
116 friend void toplevel::resume();
117 friend void toplevel::updatecursornow();
118 friend void toplevel::handleresize();
119
120 // Used to store info on externally/explicitly set bindings.
121 struct binding_connection
122 {
123 std::string keyname;
124
125 config::keybindings *bindings;
126
127 sigc::slot0<void> slot;
128
129 binding_connection():bindings(NULL) {}
130 binding_connection(const std::string &_keyname, config::keybindings *_bindings, const sigc::slot0<void> &_slot)
131 :keyname(_keyname), bindings(_bindings), slot(_slot) {}
132 };
133
134 // Bindings set via connect_key() and connect_key_post()
135 std::list<binding_connection> auxillary_bindings, auxillary_post_bindings;
136
137 cwindow win;
138
139 int timeout_value;
140
141 container *owner;
142
143 // Needed for recreating the window when the widget's window
144 // gets switched. This stores the CURRENT size of the widget.
145 rect geom;
146
148 style bg_style;
149
155 mutable int refcount;
156
157 // Whether the widget is visible (distinct from whether it has a window;
158 // answers the question "should this widget have a window?")
159 bool visible:1;
160
161 // Tracks whether or not we have the focus.
162 bool isfocussed:1;
163
167 bool pre_display_erase:1;
168
169 bool is_destroyed:1;
170
171 // Used to set the owner-window without setting the owner. Used only
172 // to handle the toplevel widget (which has a window but no owner)
173 // Like alloc_size
174 void set_owner_window(cwindow _win, int x, int y, int w, int h);
175
176 // Used to update the "focussed" state
177 void set_isfocussed(bool _isfocussed);
178 protected:
179 cwindow get_win() {return win;}
180
186 virtual void paint(const style &st)=0;
187
195 virtual bool handle_key(const config::key &k);
196
198 void cleanup();
199 protected:
200 widget();
201
202 public:
203 void incref()
204 {
205 eassert(refcount > 0);
206
207 ++refcount;
208 }
209
210 void decref()
211 {
212 eassert(refcount > 0);
213
214 --refcount;
215 if(refcount == 0)
216 cleanup();
217 }
218
219 static void handle_pending_deletes();
220
221 // show() and hide() do the expected. show_all() makes a container show
222 // all of its "children". (err..it doesn't make sense for menubars to show
223 // their menus, but aside from that..)
224 void show();
225 virtual void show_all();
226 void hide();
227 void toggle_visible()
228 {
229 if(visible)
230 hide();
231 else
232 show();
233 }
234 void set_visible(bool _visible)
235 {
236 if(visible!=_visible)
237 {
238 if(_visible)
239 show();
240 else
241 hide();
242 }
243 }
244
245 virtual ~widget();
246
247 // This should be called when an arbitrary widget is to have a
248 // keypress sent to it.
249 bool dispatch_key(const config::key & k);
250
251 // This should be called when an arbitrary widget is to have a mouse event
252 // sent to it. Override it to change mousing behavior.
253 virtual void dispatch_mouse(short id, int x, int y, int z, mmask_t bstate);
254
255
256
257 // The following methods deal with handling widget layout. Widget
258 // layout is a two-shot affair: first, all widgets are allocated
259 // space in the X dimension; then, all widgets are allocated space
260 // in the Y dimension. Doing allocation in this asymmetrical way
261 // allows widgets with complex interdependencies between their
262 // dimensions to be handled (for instance: a widget that wraps the
263 // text it displays, and will have to request more height if its
264 // width decreases).
265 //
266 // You can assume that the widget's state is unchanged between a
267 // call to width_request() and a call to height_request().
268
270 virtual int width_request()=0;
271
277 virtual int height_request(int width)=0;
278
294 void alloc_size(int x, int y, int w, int h);
295
296
297
298
299 virtual bool focus_me();
300 // Returns true if this widet wants the keyboard focus (used in, eg, dialog
301 // boxes)
302
303 bool get_isfocussed() {return isfocussed;}
304
305 void set_owner(container *w);
306 // Makes this widget a child of the given widget (incidentally will delete
307 // any allocated size; setting the owner to NULL hides the widget for now)
308
316 void display(const style &st);
317
318 int timeout(int msecs);
319
323 virtual void destroy();
324
325 util::ref_ptr<container> get_owner();
326
327 virtual bool get_cursorvisible()=0;
328 virtual point get_cursorloc()=0;
329
330 int get_startx() {return geom.x;}
331 int get_starty() {return geom.y;}
332 int get_width() {return geom.w;}
333 int get_height() {return geom.h;}
334
335 bool get_visible() {return visible;}
336
337 // Should NOT be overridden -- that was a thinko
338 void sync() {if(win) {win.touch(); win.noutrefresh();}}
339
340 int scroll(int n=1) {return win?win.scroll(n):0;}
341
342 int addch(chtype ch) {return win?win.addch(ch):0;}
343 int mvaddch(int y, int x, chtype ch) {return win?win.mvaddch(y,x,ch):0;}
344
345 int add_wch(wchar_t wch)
346 {
347 return win?win.add_wch(wch):0;
348 }
349
350 int add_wch(const cchar_t *cch)
351 {
352 return win?win.add_wch(cch):0;
353 }
354
355 int mvadd_wch(int y, int x, wchar_t wch)
356 {
357 return win?win.mvadd_wch(y, x, wch):0;
358 }
359
360 int mvadd_wch(int y, int x, const cchar_t *cch)
361 {
362 return win?win.mvadd_wch(y, x, cch):0;
363 }
364
365 int addstr(const char *str) {return win?win.addstr(str):0;}
366 int addnstr(const char *str, int n) {return win?win.addnstr(str, n):0;}
367 int mvaddstr(int y, int x, const char *str) {return win?win.mvaddstr(y, x, str):0;}
368 int mvaddnstr(int y, int x, const char *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
369
370 int addstr(const wchar_t *str) {return win?win.addstr(str):0;}
371 int addnstr(const wchar_t *str, int n) {return win?win.addnstr(str, n):0;}
372 int mvaddstr(int y, int x, const wchar_t *str) {return win?win.mvaddstr(y, x, str):0;}
373 int mvaddnstr(int y, int x, const wchar_t *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
374
375 int addstr(const std::wstring &str) {return win?win.addstr(str):0;}
376 int addnstr(const std::wstring &str, int n) {return win?win.addnstr(str, n):0;}
377 int mvaddstr(int y, int x, const std::wstring &str) {return win?win.mvaddstr(y, x, str):0;}
378 int mvaddnstr(int y, int x, const std::wstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
379
380 int addstr(const wchstring &str) {return win?win.addstr(str):0;}
381 int addnstr(const wchstring &str, int n) {return win?win.addnstr(str, n):0;}
382 int mvaddstr(int y, int x, const wchstring &str) {return win?win.mvaddstr(y, x, str):0;}
383 int mvaddnstr(int y, int x, const wchstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
384
385 int addstr(const chstring &str) {return win?win.addstr(str):0;}
386 int addnstr(const chstring &str, int n) {return win?win.addnstr(str, n):0;}
387 int mvaddstr(int y, int x, const chstring &str) {return win?win.mvaddstr(y, x, str):0;}
388 int mvaddnstr(int y, int x, const chstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
389
390 int attroff(int attrs) {return win?win.attroff(attrs):0;}
391 int attron(int attrs) {return win?win.attron(attrs):0;}
392 int attrset(int attrs) {return win?win.attrset(attrs):0;}
393
394 void bkgdset(const chtype ch) {if(win) win.bkgdset(ch);}
395 int bkgd(const chtype ch) {return win?win.bkgd(ch):0;}
396 chtype getbkgd() {return win?win.getbkgd():0;}
397
398 int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
399 {return win?win.border(ls,rs,ts,bs,tl,tr,bl,br):0;}
400 int box(chtype verch, chtype horch) {return win?win.box(verch,horch):0;}
401 int hline(chtype ch, int n) {return win?win.hline(ch,n):0;}
402 int vline(chtype ch, int n) {return win?win.vline(ch,n):0;}
403 int mvhline(int y, int x, chtype ch, int n) {return win?win.mvhline(y, x, ch, n):0;}
404 int mvvline(int y, int x, chtype ch, int n) {return win?win.mvvline(y,x,ch,n):0;}
405
406 int delch() {return win?win.delch():0;}
407 int mvdelch(int y, int x) {return win?win.mvdelch(y, x):0;}
408
409 int deleteln() {return win?win.deleteln():0;}
410 int insdelln(int n) {return win?win.insdelln(n):0;}
411 int insertln() {return win?win.insertln():0;}
412
413 int echochar(chtype ch) {return win?win.echochar(ch):0;}
414
415 int move(int y, int x) {return win?win.move(y,x):0;}
416 void getyx(int &y, int &x) {if(win) win.getyx(y,x); else y=x=0;}
417 void getbegyx(int &y, int &x) {if(win) win.getbegyx(y,x); else y=x=0;}
418 void getmaxyx(int &y, int &x) {if(win) win.getmaxyx(y,x); else y=x=0;}
419 int getmaxy() {return win?win.getmaxy():0;}
420 int getmaxx() {return win?win.getmaxx():0;}
421
422 void show_string_as_progbar(int x, int y, const std::wstring &s,
423 const style &st1, const style &st2,
424 int size1, int totalsize)
425 {
426 if(win)
427 win.show_string_as_progbar(x, y, s,
428 st1.get_attrs(),
429 st2.get_attrs(),
430 size1, totalsize);
431 }
432
433 void display_header(std::wstring s, const style &st) {if(win) win.display_header(s, st.get_attrs());}
434 void display_status(std::wstring s, const style &st) {if(win) win.display_status(s, st.get_attrs());}
435
436 int erase() {return win?win.erase():0;}
437 int clear() {return win?win.clear():0;}
438 int clrtobot() {return win?win.clrtobot():0;}
439 int clrtoeol() {return win?win.clrtoeol():0;}
440
441 // FIXME: we should preserve these settings ourselves and restore them on
442 // set_win(). ?
443 int keypad(bool bf) {return win?win.keypad(bf):0;}
444 int meta(bool bf) {return win?win.meta(bf):0;}
445
446 bool enclose(int y, int x)
447 {
448 if(win)
449 return y>=geom.y && y<geom.y+geom.h && x>=geom.x && x<geom.x+geom.w;
450 else
451 return false;
452 }
453
461 void set_opaque(bool opaque)
462 {
463 pre_display_erase=opaque;
464 }
465
469 void set_bg_style(const style &new_style);
470
475 void apply_style(const style &st);
476
477 typedef std::list<binding_connection>::iterator key_connection;
478 // This can be used to connect to a pseudo-signal for keypresses.
479 // Most useful for stuff like setting up hotkeys and keyboard accelerators..
480 key_connection connect_key(const std::string &key,
481 config::keybindings *bindings,
482 const sigc::slot0<void> &slot);
483 // Same, but the key is tested for after all other possibilities are
484 // exhausted.
485 key_connection connect_key_post(const std::string &key,
486 config::keybindings *bindings,
487 const sigc::slot0<void> &slot);
488
489 // The opposite..
490 void disconnect_key(key_connection c);
491 // Eww, do I really need two of these?
492 void disconnect_key_post(key_connection c);
493
494 // Signals:
495 //
496 // I use signals for events that an external object (eg,
497 // a container) might want to act on. For instance, when an object is
498 // hidden, its parent might want to rearrange its children.
499 //
500 // In contrast, virtual methods are used for specific behaviors of this
501 // class: for instance, displaying the widget itself.
502
503 sigc::signal0<void> shown_sig;
504 // Emitted when the object is shown. (not to be confused with the obsolete
505 // show_sig, which was a request by the object to be shown)
506
507 sigc::signal0<void> hidden_sig;
508 // similarly
509
510 sigc::signal0<void> destroyed;
511 // Sent before a widget is destroyed.
512 // A widget is always hidden before being destroyed
513
514 sigc::signal0<void> do_layout;
515 // Sent when the widget's layout needs to be recalculated and child windows
516 // need to be re-updated (mainly when the size is altered)
517 // This should not be called directly by the user. Use toplevel::queuelayout()
518 // instead.
519
520 sigc::signal0<void> focussed;
521 sigc::signal0<void> unfocussed;
522 // Sent when we gain or lose the keyboard focus.
523 };
524
526 }
527}
528
529#endif
Stores the keys bound to various functions.
Definition keybindings.h:88
Definition curses++.h:369
A "style" is a setting to be applied to a display element (widget, text, etc).
Definition style.h:52
Definition ref_ptr.h:20
Definition container.h:33
The basic widget interface.
Definition widget.h:107
virtual bool handle_key(const config::key &k)
Handles a keypress in this widget.
Definition widget.cc:228
void set_opaque(bool opaque)
Enable or disable clearing the background before displaying the widget.
Definition widget.h:461
virtual void paint(const style &st)=0
Display this widget.
virtual void destroy()
Destroys the visible representation of this widget and disconnects it from any children that it may h...
Definition widget.cc:129
void set_bg_style(const style &new_style)
Update this widget's basic style to the given value.
Definition widget.cc:53
virtual int width_request()=0
void alloc_size(int x, int y, int w, int h)
Set the size and location in the parent of this widget.
Definition widget.cc:100
void cleanup()
Handle cleanup when the reference count goes to 0.
Definition widget.cc:123
void apply_style(const style &st)
Set the display attributes of our associated window directly from the given style.
Definition widget.cc:58
void display(const style &st)
Display this widget in the given style environment.
Definition widget.cc:198
virtual int height_request(int width)=0
Calculate the desired height of the widget, given its width.
wstring keyname(const key &k)
Convert a keystroke to its string definition.
Definition keybindings.cc:424
void redraw()
Redraws the screen completely from scratch.
Definition toplevel.cc:1274
void mainloop()
Start the main event loop.
Definition toplevel.cc:1155
bool poll()
Dispatch any events in the event queue.
Definition toplevel.cc:1135
void resume()
Returns to Curses mode after a suspend*, restoring any signal handlers that were modified by the susp...
Definition toplevel.cc:1247
void suspend_without_signals()
Hides all widgets and suspends Curses operation until resume() is called, but does NOT reset the SIGC...
Definition toplevel.cc:1193
The namespace containing everything defined by cwidget.
Definition columnify.cc:28
Represents a keystroke as seen by curses.
Definition keybindings.h:43
Definition widget.h:89
Definition widget.h:95
Definition widget.h:83