widget.h

00001 // widget.h  -*-c++-*-
00002 //
00003 //   Copyright (C) 2000-2005 Daniel Burrows
00004 //
00005 //   This program is free software; you can redistribute it and/or
00006 //   modify it under the terms of the GNU General Public License as
00007 //   published by the Free Software Foundation; either version 2 of
00008 //   the License, or (at your option) any later version.
00009 //
00010 //   This program is distributed in the hope that it will be useful,
00011 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 //   General Public License for more details.
00014 //
00015 //   You should have received a copy of the GNU General Public License
00016 //   along with this program; see the file COPYING.  If not, write to
00017 //   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018 //   Boston, MA 02111-1307, USA.
00019 //
00020 // "widgets" are sort of what they sound like -- entities that get
00021 // drawn on the screen in some stacked order and can grab keyboard
00022 // input.  By default, the widget currently on the top of the stack
00023 // has keyboard "focus".  (overriding this may be an option eventually
00024 // but isn't right now) (the widget with keyboard focus gets to
00025 // determine cursor information)
00026 //
00027 //
00028 // Lifetime of a widget: a widget is potentially active and visible
00029 // until it is destroyed (via the destroy() method).  Once a widget
00030 // has been destroyed, you cannot un-destroy it, but further calls to
00031 // destroy() are allowed until the widget is deleted for good.
00032 // Widgets should generally be referred to using ref_ptr objects; to
00033 // enforce this, widgets can only be allocated via W::create(...).  Of
00034 // course, as with any refcounting scheme, it's the user's
00035 // responsibility to prevent cycles by using unsafe_get_ref()
00036 // appropriately.  For instance, pointers to the widget's parent have
00037 // to be created this way.
00038 
00039 #ifndef WIDGET_H
00040 #define WIDGET_H
00041 
00042 #include <list>
00043 #include <vector>
00044 
00045 #include <sigc++/signal.h>
00046 #include <sigc++/trackable.h>
00047 
00048 #include <cwidget/curses++.h>
00049 #include <cwidget/generic/util/ref_ptr.h>
00050 #include <cwidget/style.h>
00051 
00052 #include <cwidget/generic/util/eassert.h>
00053 
00054 namespace cwidget
00055 {
00056   namespace widgets
00057   {
00058     class widget;
00059   }
00060 
00061   namespace toplevel
00062   {
00063     bool poll();
00064     void mainloop(int);
00065     void redraw();
00066     util::ref_ptr<widgets::widget> settoplevel(const util::ref_ptr<widgets::widget> &);
00067     void suspend_without_signals();
00068     void resume();
00069     void updatecursornow();
00070     void handleresize();
00071   }
00072 
00073   namespace config
00074   {
00075     class key;
00076     class keybindings;
00077   }
00078 
00079   namespace widgets
00080   {
00081     class container;
00082 
00083     struct size
00084     {
00085       int w, h;
00086       size(int _w, int _h):w(_w), h(_h) {}
00087     };
00088 
00089     struct point
00090     {
00091       int x, y;
00092       point(int _x, int _y):x(_x), y(_y) {}
00093     };
00094 
00095     struct rect
00096     {
00097       int x, y, w, h;
00098       rect(int _x, int _y, int _w, int _h):x(_x), y(_y), w(_w), h(_h) {}
00099       void set_size(const size &s) {w=s.w; h=s.h;}
00100       size get_size() {return size(w, h);}
00101     };
00102 
00107     class widget:virtual public sigc::trackable
00108     {
00109       friend class container;
00110 
00111       // Too many friends..
00112       friend bool toplevel::poll();
00113       friend void toplevel::mainloop(int);
00114       friend void toplevel::redraw();
00115       friend util::ref_ptr<widget> toplevel::settoplevel(const util::ref_ptr<widget> &);
00116       friend void toplevel::suspend_without_signals();
00117       friend void toplevel::resume();
00118       friend void toplevel::updatecursornow();
00119       friend void toplevel::handleresize();
00120 
00121       // Used to store info on externally/explicitly set bindings.
00122       struct binding_connection
00123       {
00124         std::string keyname;
00125 
00126         config::keybindings *bindings;
00127 
00128         sigc::slot0<void> slot;
00129 
00130         binding_connection():bindings(NULL) {}
00131         binding_connection(const std::string &_keyname, config::keybindings *_bindings, const sigc::slot0<void> &_slot)
00132           :keyname(_keyname), bindings(_bindings), slot(_slot) {}
00133       };
00134 
00135       // Bindings set via connect_key() and connect_key_post()
00136       std::list<binding_connection> auxillary_bindings, auxillary_post_bindings;
00137 
00138       cwindow win;
00139 
00140       int timeout_value;
00141 
00142       container *owner;
00143 
00144       // Needed for recreating the window when the widget's window
00145       // gets switched.  This stores the CURRENT size of the widget.
00146       rect geom;
00147 
00149       style bg_style;
00150 
00156       mutable int refcount;
00157 
00158       // Whether the widget is visible (distinct from whether it has a window;
00159       // answers the question "should this widget have a window?")
00160       bool visible:1;
00161 
00162       // Tracks whether or not we have the focus.
00163       bool isfocussed:1;
00164 
00168       bool pre_display_erase:1;
00169 
00170       bool is_destroyed:1;
00171 
00172       // Used to set the owner-window without setting the owner.  Used only
00173       // to handle the toplevel widget (which has a window but no owner)
00174       // Like alloc_size
00175       void set_owner_window(cwindow _win, int x, int y, int w, int h);
00176 
00177       // Used to update the "focussed" state
00178       void set_isfocussed(bool _isfocussed);
00179     protected:
00180       cwindow get_win() {return win;}
00181 
00187       virtual void paint(const style &st)=0;
00188 
00196       virtual bool handle_key(const config::key &k);
00197 
00199       void cleanup();
00200     protected:
00201       widget();
00202 
00203     public:
00204       void incref()
00205       {
00206         eassert(refcount > 0);
00207 
00208         ++refcount;
00209       }
00210 
00211       void decref()
00212       {
00213         eassert(refcount > 0);
00214 
00215         --refcount;
00216         if(refcount == 0)
00217           cleanup();
00218       }
00219 
00220       static void handle_pending_deletes();
00221 
00222       // show() and hide() do the expected.  show_all() makes a container show
00223       // all of its "children".  (err..it doesn't make sense for menubars to show
00224       // their menus, but aside from that..)
00225       void show();
00226       virtual void show_all();
00227       void hide();
00228       void toggle_visible()
00229       {
00230         if(visible)
00231           hide();
00232         else
00233           show();
00234       }
00235       void set_visible(bool _visible)
00236       {
00237         if(visible!=_visible)
00238           {
00239             if(_visible)
00240               show();
00241             else
00242               hide();
00243           }
00244       }
00245 
00246       virtual ~widget();
00247 
00248       // This should be called when an arbitrary widget is to have a
00249       // keypress sent to it.
00250       bool dispatch_key(const config::key & k);
00251 
00252       // This should be called when an arbitrary widget is to have a mouse event
00253       // sent to it.  Override it to change mousing behavior.
00254       virtual void dispatch_mouse(short id, int x, int y, int z, mmask_t bstate);
00255 
00256 
00257 
00258       // The following methods deal with handling widget layout.  Widget
00259       // layout is a two-shot affair: first, all widgets are allocated
00260       // space in the X dimension; then, all widgets are allocated space
00261       // in the Y dimension.  Doing allocation in this asymmetrical way
00262       // allows widgets with complex interdependencies between their
00263       // dimensions to be handled (for instance: a widget that wraps the
00264       // text it displays, and will have to request more height if its
00265       // width decreases).
00266       //
00267       // You can assume that the widget's state is unchanged between a
00268       // call to width_request() and a call to height_request().
00269 
00271       virtual int width_request()=0;
00272 
00278       virtual int height_request(int width)=0;
00279 
00295       void alloc_size(int x, int y, int w, int h);
00296 
00297 
00298 
00299 
00300       virtual bool focus_me();
00301       // Returns true if this widet wants the keyboard focus (used in, eg, dialog
00302       // boxes)
00303 
00304       bool get_isfocussed() {return isfocussed;}
00305 
00306       void set_owner(container *w);
00307       // Makes this widget a child of the given widget (incidentally will delete
00308       // any allocated size; setting the owner to NULL hides the widget for now)
00309 
00317       void display(const style &st);
00318 
00319       int timeout(int msecs);
00320 
00324       virtual void destroy();
00325 
00326       util::ref_ptr<container> get_owner();
00327 
00328       virtual bool get_cursorvisible()=0;
00329       virtual point get_cursorloc()=0;
00330 
00331       int get_startx() {return geom.x;}
00332       int get_starty() {return geom.y;}
00333       int get_width() {return geom.w;}
00334       int get_height() {return geom.h;}
00335 
00336       bool get_visible() {return visible;}
00337 
00338       // Should NOT be overridden -- that was a thinko
00339       void sync() {if(win) {win.touch(); win.noutrefresh();}}
00340 
00341       int scroll(int n=1) {return win?win.scroll(n):0;}
00342 
00343       int addch(chtype ch) {return win?win.addch(ch):0;}
00344       int mvaddch(int y, int x, chtype ch) {return win?win.mvaddch(y,x,ch):0;}
00345 
00346       int add_wch(wchar_t wch)
00347       {
00348         return win?win.add_wch(wch):0;
00349       }
00350 
00351       int add_wch(const cchar_t *cch)
00352       {
00353         return win?win.add_wch(cch):0;
00354       }
00355 
00356       int mvadd_wch(int y, int x, wchar_t wch)
00357       {
00358         return win?win.mvadd_wch(y, x, wch):0;
00359       }
00360 
00361       int mvadd_wch(int y, int x, const cchar_t *cch)
00362       {
00363         return win?win.mvadd_wch(y, x, cch):0;
00364       }
00365 
00366       int addstr(const char *str) {return win?win.addstr(str):0;}
00367       int addnstr(const char *str, int n) {return win?win.addnstr(str, n):0;}
00368       int mvaddstr(int y, int x, const char *str) {return win?win.mvaddstr(y, x, str):0;}
00369       int mvaddnstr(int y, int x, const char *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
00370 
00371       int addstr(const wchar_t *str) {return win?win.addstr(str):0;}
00372       int addnstr(const wchar_t *str, int n) {return win?win.addnstr(str, n):0;}
00373       int mvaddstr(int y, int x, const wchar_t *str) {return win?win.mvaddstr(y, x, str):0;}
00374       int mvaddnstr(int y, int x, const wchar_t *str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
00375 
00376       int addstr(const std::wstring &str) {return win?win.addstr(str):0;}
00377       int addnstr(const std::wstring &str, int n) {return win?win.addnstr(str, n):0;}
00378       int mvaddstr(int y, int x, const std::wstring &str) {return win?win.mvaddstr(y, x, str):0;}
00379       int mvaddnstr(int y, int x, const std::wstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
00380 
00381       int addstr(const wchstring &str) {return win?win.addstr(str):0;}
00382       int addnstr(const wchstring &str, int n) {return win?win.addnstr(str, n):0;}
00383       int mvaddstr(int y, int x, const wchstring &str) {return win?win.mvaddstr(y, x, str):0;}
00384       int mvaddnstr(int y, int x, const wchstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
00385 
00386       int addstr(const chstring &str) {return win?win.addstr(str):0;}
00387       int addnstr(const chstring &str, int n) {return win?win.addnstr(str, n):0;}
00388       int mvaddstr(int y, int x, const chstring &str) {return win?win.mvaddstr(y, x, str):0;}
00389       int mvaddnstr(int y, int x, const chstring &str, int n) {return win?win.mvaddnstr(y, x, str, n):0;}
00390 
00391       int attroff(int attrs) {return win?win.attroff(attrs):0;}
00392       int attron(int attrs) {return win?win.attron(attrs):0;}
00393       int attrset(int attrs) {return win?win.attrset(attrs):0;}
00394 
00395       void bkgdset(const chtype ch) {if(win) win.bkgdset(ch);}
00396       int bkgd(const chtype ch) {return win?win.bkgd(ch):0;}
00397       chtype getbkgd() {return win?win.getbkgd():0;}
00398 
00399       int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
00400       {return win?win.border(ls,rs,ts,bs,tl,tr,bl,br):0;}
00401       int box(chtype verch, chtype horch) {return win?win.box(verch,horch):0;}
00402       int hline(chtype ch, int n) {return win?win.hline(ch,n):0;}
00403       int vline(chtype ch, int n) {return win?win.vline(ch,n):0;}
00404       int mvhline(int y, int x, chtype ch, int n) {return win?win.mvhline(y, x, ch, n):0;}
00405       int mvvline(int y, int x, chtype ch, int n) {return win?win.mvvline(y,x,ch,n):0;}
00406 
00407       int delch() {return win?win.delch():0;}
00408       int mvdelch(int y, int x) {return win?win.mvdelch(y, x):0;}
00409 
00410       int deleteln() {return win?win.deleteln():0;}
00411       int insdelln(int n) {return win?win.insdelln(n):0;}
00412       int insertln() {return win?win.insertln():0;}
00413 
00414       int echochar(chtype ch) {return win?win.echochar(ch):0;}
00415 
00416       int move(int y, int x) {return win?win.move(y,x):0;}
00417       void getyx(int &y, int &x) {if(win) win.getyx(y,x); else y=x=0;}
00418       void getbegyx(int &y, int &x) {if(win) win.getbegyx(y,x); else y=x=0;}
00419       void getmaxyx(int &y, int &x) {if(win) win.getmaxyx(y,x); else y=x=0;}
00420       int getmaxy() {return win?win.getmaxy():0;}
00421       int getmaxx() {return win?win.getmaxx():0;}
00422 
00423       void show_string_as_progbar(int x, int y, const std::wstring &s,
00424                                   const style &st1, const style &st2,
00425                                   int size1, int totalsize)
00426       {
00427         if(win)
00428           win.show_string_as_progbar(x, y, s,
00429                                      st1.get_attrs(),
00430                                      st2.get_attrs(),
00431                                      size1, totalsize);
00432       }
00433 
00434       void display_header(std::wstring s, const style &st) {if(win) win.display_header(s, st.get_attrs());}
00435       void display_status(std::wstring s, const style &st) {if(win) win.display_status(s, st.get_attrs());}
00436 
00437       int erase() {return win?win.erase():0;}
00438       int clear() {return win?win.clear():0;}
00439       int clrtobot() {return win?win.clrtobot():0;}
00440       int clrtoeol() {return win?win.clrtoeol():0;}
00441 
00442       // FIXME: we should preserve these settings ourselves and restore them on
00443       // set_win().  ?
00444       int keypad(bool bf) {return win?win.keypad(bf):0;}
00445       int meta(bool bf) {return win?win.meta(bf):0;}
00446 
00447       bool enclose(int y, int x)
00448       {
00449         if(win)
00450           return y>=geom.y && y<geom.y+geom.h && x>=geom.x && x<geom.x+geom.w;
00451         else
00452           return false;
00453       }
00454 
00462       void set_opaque(bool opaque)
00463       {
00464         pre_display_erase=opaque;
00465       }
00466 
00470       void set_bg_style(const style &new_style);
00471 
00476       void apply_style(const style &st);
00477 
00478       typedef std::list<binding_connection>::iterator key_connection;
00479       // This can be used to connect to a pseudo-signal for keypresses.
00480       // Most useful for stuff like setting up hotkeys and keyboard accelerators..
00481       key_connection connect_key(const std::string &key,
00482                                  config::keybindings *bindings,
00483                                  const sigc::slot0<void> &slot);
00484       // Same, but the key is tested for after all other possibilities are
00485       // exhausted.
00486       key_connection connect_key_post(const std::string &key,
00487                                       config::keybindings *bindings,
00488                                       const sigc::slot0<void> &slot);
00489 
00490       // The opposite..
00491       void disconnect_key(key_connection c);
00492       // Eww, do I really need two of these?
00493       void disconnect_key_post(key_connection c);
00494 
00495       // Signals:
00496       //
00497       // I use signals for events that an external object (eg,
00498       // a container) might want to act on.  For instance, when an object is
00499       // hidden, its parent might want to rearrange its children.
00500       //
00501       // In contrast, virtual methods are used for specific behaviors of this
00502       // class: for instance, displaying the widget itself.
00503 
00504       sigc::signal0<void> shown_sig;
00505       // Emitted when the object is shown.  (not to be confused with the obsolete
00506       // show_sig, which was a request by the object to be shown)
00507 
00508       sigc::signal0<void> hidden_sig;
00509       // similarly
00510 
00511       sigc::signal0<void> destroyed;
00512       // Sent before a widget is destroyed.
00513       // A widget is always hidden before being destroyed
00514 
00515       sigc::signal0<void> do_layout;
00516       // Sent when the widget's layout needs to be recalculated and child windows
00517       // need to be re-updated (mainly when the size is altered)
00518       // This should not be called directly by the user.  Use toplevel::queuelayout()
00519       // instead.
00520 
00521       sigc::signal0<void> focussed;
00522       sigc::signal0<void> unfocussed;
00523       // Sent when we gain or lose the keyboard focus.
00524     };
00525 
00526     typedef util::ref_ptr<widget> widget_ref;
00527   }
00528 }
00529 
00530 #endif

Generated on Mon Jul 7 11:11:55 2008 for cwidget by  doxygen 1.5.6