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 
53 namespace 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();
115  friend void toplevel::suspend_without_signals();
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: 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
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 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