cwidget  0.5.17
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 #include <vector>
44 
45 #include <sigc++/signal.h>
46 #include <sigc++/trackable.h>
47 
48 #include <cwidget/curses++.h>
49 #include <cwidget/generic/util/ref_ptr.h>
50 #include <cwidget/style.h>
51 
52 #include <cwidget/generic/util/eassert.h>
53 
54 namespace cwidget
55 {
56  namespace widgets
57  {
58  class widget;
59  }
60 
61  namespace toplevel
62  {
63  bool poll();
64  void mainloop(int);
65  void redraw();
66  util::ref_ptr<widgets::widget> settoplevel(const util::ref_ptr<widgets::widget> &);
68  void resume();
69  void updatecursornow();
70  void handleresize();
71  }
72 
73  namespace config
74  {
75  class key;
76  class keybindings;
77  }
78 
79  namespace widgets
80  {
81  class container;
82 
83  struct size
84  {
85  int w, h;
86  size(int _w, int _h):w(_w), h(_h) {}
87  };
88 
89  struct point
90  {
91  int x, y;
92  point(int _x, int _y):x(_x), y(_y) {}
93  };
94 
95  struct rect
96  {
97  int x, y, w, h;
98  rect(int _x, int _y, int _w, int _h):x(_x), y(_y), w(_w), h(_h) {}
99  void set_size(const size &s) {w=s.w; h=s.h;}
100  size get_size() {return size(w, h);}
101  };
102 
107  class widget:virtual public sigc::trackable
108  {
109  friend class container;
110 
111  // Too many friends..
112  friend bool toplevel::poll();
113  friend void toplevel::mainloop(int);
114  friend void toplevel::redraw();
116  friend void toplevel::suspend_without_signals();
117  friend void toplevel::resume();
118  friend void toplevel::updatecursornow();
119  friend void toplevel::handleresize();
120 
121  // Used to store info on externally/explicitly set bindings.
122  struct binding_connection
123  {
124  std::string keyname;
125 
126  config::keybindings *bindings;
127 
128  sigc::slot0<void> slot;
129 
130  binding_connection():bindings(NULL) {}
131  binding_connection(const std::string &_keyname, config::keybindings *_bindings, const sigc::slot0<void> &_slot)
132  :keyname(_keyname), bindings(_bindings), slot(_slot) {}
133  };
134 
135  // Bindings set via connect_key() and connect_key_post()
136  std::list<binding_connection> auxillary_bindings, auxillary_post_bindings;
137 
138  cwindow win;
139 
140  int timeout_value;
141 
142  container *owner;
143 
144  // Needed for recreating the window when the widget's window
145  // gets switched. This stores the CURRENT size of the widget.
146  rect geom;
147 
149  style bg_style;
150 
156  mutable int refcount;
157 
158  // Whether the widget is visible (distinct from whether it has a window;
159  // answers the question "should this widget have a window?")
160  bool visible:1;
161 
162  // Tracks whether or not we have the focus.
163  bool isfocussed:1;
164 
168  bool pre_display_erase:1;
169 
170  bool is_destroyed:1;
171 
172  // Used to set the owner-window without setting the owner. Used only
173  // to handle the toplevel widget (which has a window but no owner)
174  // Like alloc_size
175  void set_owner_window(cwindow _win, int x, int y, int w, int h);
176 
177  // Used to update the "focussed" state
178  void set_isfocussed(bool _isfocussed);
179  protected:
180  cwindow get_win() {return win;}
181 
187  virtual void paint(const style &st)=0;
188 
196  virtual bool handle_key(const config::key &k);
197 
199  void cleanup();
200  protected:
201  widget();
202 
203  public:
204  void incref()
205  {
206  eassert(refcount > 0);
207 
208  ++refcount;
209  }
210 
211  void decref()
212  {
213  eassert(refcount > 0);
214 
215  --refcount;
216  if(refcount == 0)
217  cleanup();
218  }
219 
220  static void handle_pending_deletes();
221 
222  // show() and hide() do the expected. show_all() makes a container show
223  // all of its "children". (err..it doesn't make sense for menubars to show
224  // their menus, but aside from that..)
225  void show();
226  virtual void show_all();
227  void hide();
228  void toggle_visible()
229  {
230  if(visible)
231  hide();
232  else
233  show();
234  }
235  void set_visible(bool _visible)
236  {
237  if(visible!=_visible)
238  {
239  if(_visible)
240  show();
241  else
242  hide();
243  }
244  }
245 
246  virtual ~widget();
247 
248  // This should be called when an arbitrary widget is to have a
249  // keypress sent to it.
250  bool dispatch_key(const config::key & k);
251 
252  // This should be called when an arbitrary widget is to have a mouse event
253  // sent to it. Override it to change mousing behavior.
254  virtual void dispatch_mouse(short id, int x, int y, int z, mmask_t bstate);
255 
256 
257 
258  // The following methods deal with handling widget layout. Widget
259  // layout is a two-shot affair: first, all widgets are allocated
260  // space in the X dimension; then, all widgets are allocated space
261  // in the Y dimension. Doing allocation in this asymmetrical way
262  // allows widgets with complex interdependencies between their
263  // dimensions to be handled (for instance: a widget that wraps the
264  // text it displays, and will have to request more height if its
265  // width decreases).
266  //
267  // You can assume that the widget's state is unchanged between a
268  // call to width_request() and a call to height_request().
269 
271  virtual int width_request()=0;
272 
278  virtual int height_request(int width)=0;
279 
295  void alloc_size(int x, int y, int w, int h);
296 
297 
298 
299 
300  virtual bool focus_me();
301  // Returns true if this widet wants the keyboard focus (used in, eg, dialog
302  // boxes)
303 
304  bool get_isfocussed() {return isfocussed;}
305 
306  void set_owner(container *w);
307  // Makes this widget a child of the given widget (incidentally will delete
308  // any allocated size; setting the owner to NULL hides the widget for now)
309 
317  void display(const style &st);
318 
319  int timeout(int msecs);
320 
324  virtual void destroy();
325 
326  util::ref_ptr<container> get_owner();
327 
328  virtual bool get_cursorvisible()=0;
329  virtual point get_cursorloc()=0;
330 
331  int get_startx() {return geom.x;}
332  int get_starty() {return geom.y;}
333  int get_width() {return geom.w;}
334  int get_height() {return geom.h;}
335 
336  bool get_visible() {return visible;}
337 
338  // Should NOT be overridden -- that was a thinko
339  void sync() {if(win) {win.touch(); win.noutrefresh();}}
340 
341  int scroll(int n=1) {return win?win.scroll(n):0;}
342 
343  int addch(chtype ch) {return win?win.addch(ch):0;}
344  int mvaddch(int y, int x, chtype ch) {return win?win.mvaddch(y,x,ch):0;}
345 
346  int add_wch(wchar_t wch)
347  {
348  return win?win.add_wch(wch):0;
349  }
350 
351  int add_wch(const cchar_t *cch)
352  {
353  return win?win.add_wch(cch):0;
354  }
355 
356  int mvadd_wch(int y, int x, wchar_t wch)
357  {
358  return win?win.mvadd_wch(y, x, wch):0;
359  }
360 
361  int mvadd_wch(int y, int x, const cchar_t *cch)
362  {
363  return win?win.mvadd_wch(y, x, cch):0;
364  }
365 
366  int addstr(const char *str) {return win?win.addstr(str):0;}
367  int addnstr(const char *str, int n) {return win?win.addnstr(str, n):0;}
368  int mvaddstr(int y, int x, const char *str) {return win?win.mvaddstr(y, x, str):0;}
369  int mvaddnstr(int y, int x, const char *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
370 
371  int addstr(const wchar_t *str) {return win?win.addstr(str):0;}
372  int addnstr(const wchar_t *str, int n) {return win?win.addnstr(str, n):0;}
373  int mvaddstr(int y, int x, const wchar_t *str) {return win?win.mvaddstr(y, x, str):0;}
374  int mvaddnstr(int y, int x, const wchar_t *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
375 
376  int addstr(const std::wstring &str) {return win?win.addstr(str):0;}
377  int addnstr(const std::wstring &str, int n) {return win?win.addnstr(str, n):0;}
378  int mvaddstr(int y, int x, const std::wstring &str) {return win?win.mvaddstr(y, x, str):0;}
379  int mvaddnstr(int y, int x, const std::wstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
380 
381  int addstr(const wchstring &str) {return win?win.addstr(str):0;}
382  int addnstr(const wchstring &str, int n) {return win?win.addnstr(str, n):0;}
383  int mvaddstr(int y, int x, const wchstring &str) {return win?win.mvaddstr(y, x, str):0;}
384  int mvaddnstr(int y, int x, const wchstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
385 
386  int addstr(const chstring &str) {return win?win.addstr(str):0;}
387  int addnstr(const chstring &str, int n) {return win?win.addnstr(str, n):0;}
388  int mvaddstr(int y, int x, const chstring &str) {return win?win.mvaddstr(y, x, str):0;}
389  int mvaddnstr(int y, int x, const chstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
390 
391  int attroff(int attrs) {return win?win.attroff(attrs):0;}
392  int attron(int attrs) {return win?win.attron(attrs):0;}
393  int attrset(int attrs) {return win?win.attrset(attrs):0;}
394 
395  void bkgdset(const chtype ch) {if(win) win.bkgdset(ch);}
396  int bkgd(const chtype ch) {return win?win.bkgd(ch):0;}
397  chtype getbkgd() {return win?win.getbkgd():0;}
398 
399  int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
400  {return win?win.border(ls,rs,ts,bs,tl,tr,bl,br):0;}
401  int box(chtype verch, chtype horch) {return win?win.box(verch,horch):0;}
402  int hline(chtype ch, int n) {return win?win.hline(ch,n):0;}
403  int vline(chtype ch, int n) {return win?win.vline(ch,n):0;}
404  int mvhline(int y, int x, chtype ch, int n) {return win?win.mvhline(y, x, ch, n):0;}
405  int mvvline(int y, int x, chtype ch, int n) {return win?win.mvvline(y,x,ch,n):0;}
406 
407  int delch() {return win?win.delch():0;}
408  int mvdelch(int y, int x) {return win?win.mvdelch(y, x):0;}
409 
410  int deleteln() {return win?win.deleteln():0;}
411  int insdelln(int n) {return win?win.insdelln(n):0;}
412  int insertln() {return win?win.insertln():0;}
413 
414  int echochar(chtype ch) {return win?win.echochar(ch):0;}
415 
416  int move(int y, int x) {return win?win.move(y,x):0;}
417  void getyx(int &y, int &x) {if(win) win.getyx(y,x); else y=x=0;}
418  void getbegyx(int &y, int &x) {if(win) win.getbegyx(y,x); else y=x=0;}
419  void getmaxyx(int &y, int &x) {if(win) win.getmaxyx(y,x); else y=x=0;}
420  int getmaxy() {return win?win.getmaxy():0;}
421  int getmaxx() {return win?win.getmaxx():0;}
422 
423  void show_string_as_progbar(int x, int y, const std::wstring &s,
424  const style &st1, const style &st2,
425  int size1, int totalsize)
426  {
427  if(win)
428  win.show_string_as_progbar(x, y, s,
429  st1.get_attrs(),
430  st2.get_attrs(),
431  size1, totalsize);
432  }
433 
434  void display_header(std::wstring s, const style &st) {if(win) win.display_header(s, st.get_attrs());}
435  void display_status(std::wstring s, const style &st) {if(win) win.display_status(s, st.get_attrs());}
436 
437  int erase() {return win?win.erase():0;}
438  int clear() {return win?win.clear():0;}
439  int clrtobot() {return win?win.clrtobot():0;}
440  int clrtoeol() {return win?win.clrtoeol():0;}
441 
442  // FIXME: we should preserve these settings ourselves and restore them on
443  // set_win(). ?
444  int keypad(bool bf) {return win?win.keypad(bf):0;}
445  int meta(bool bf) {return win?win.meta(bf):0;}
446 
447  bool enclose(int y, int x)
448  {
449  if(win)
450  return y>=geom.y && y<geom.y+geom.h && x>=geom.x && x<geom.x+geom.w;
451  else
452  return false;
453  }
454 
462  void set_opaque(bool opaque)
463  {
464  pre_display_erase=opaque;
465  }
466 
470  void set_bg_style(const style &new_style);
471 
476  void apply_style(const style &st);
477 
478  typedef std::list<binding_connection>::iterator key_connection;
479  // This can be used to connect to a pseudo-signal for keypresses.
480  // Most useful for stuff like setting up hotkeys and keyboard accelerators..
481  key_connection connect_key(const std::string &key,
482  config::keybindings *bindings,
483  const sigc::slot0<void> &slot);
484  // Same, but the key is tested for after all other possibilities are
485  // exhausted.
486  key_connection connect_key_post(const std::string &key,
487  config::keybindings *bindings,
488  const sigc::slot0<void> &slot);
489 
490  // The opposite..
491  void disconnect_key(key_connection c);
492  // Eww, do I really need two of these?
493  void disconnect_key_post(key_connection c);
494 
495  // Signals:
496  //
497  // I use signals for events that an external object (eg,
498  // a container) might want to act on. For instance, when an object is
499  // hidden, its parent might want to rearrange its children.
500  //
501  // In contrast, virtual methods are used for specific behaviors of this
502  // class: for instance, displaying the widget itself.
503 
504  sigc::signal0<void> shown_sig;
505  // Emitted when the object is shown. (not to be confused with the obsolete
506  // show_sig, which was a request by the object to be shown)
507 
508  sigc::signal0<void> hidden_sig;
509  // similarly
510 
511  sigc::signal0<void> destroyed;
512  // Sent before a widget is destroyed.
513  // A widget is always hidden before being destroyed
514 
515  sigc::signal0<void> do_layout;
516  // Sent when the widget's layout needs to be recalculated and child windows
517  // need to be re-updated (mainly when the size is altered)
518  // This should not be called directly by the user. Use toplevel::queuelayout()
519  // instead.
520 
521  sigc::signal0<void> focussed;
522  sigc::signal0<void> unfocussed;
523  // Sent when we gain or lose the keyboard focus.
524  };
525 
527  }
528 }
529 
530 #endif
A "style" is a setting to be applied to a display element (widget, text, etc).
Definition: style.h:51
Stores the keys bound to various functions.
Definition: keybindings.h:87
Definition: widget.h:89
Definition: curses++.h:199
attr_t get_attrs() const
Definition: style.h:158
void mainloop(int synch)
Start the main event loop.
Definition: toplevel.cc:1155
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:26
Definition: widget.h:95
Definition: widget.h:83
Definition: container.h:32
The basic widget interface.
Definition: widget.h:107
Represents a keystroke as seen by curses.
Definition: keybindings.h:42
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
wstring keyname(const key &k)
Convert a keystroke to its string definition.
Definition: keybindings.cc:423
util::ref_ptr< widgets::widget > settoplevel(const util::ref_ptr< widgets::widget > &widget)
Sets the top-level widget to the new value, returning the old top-level widget.
void set_opaque(bool opaque)
Enable or disable clearing the background before displaying the widget.
Definition: widget.h:462
Definition: curses++.h:369
A string class which stores attributes along with characters.
Definition: curses++.h:170