cwidget 0.5.16
|
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