00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "ndk++.h"
00035
00036 using namespace std;
00037
00038 namespace NDK_XX{
00039
00040 ofstream logfile("NDK_debug");
00041 ofstream &get_logfile(){return logfile;}
00042
00043 string DialogBox::lblOk=" OK ";
00044 string DialogBox::lblCancel="Cancel";
00045 string DialogBox::lblYes=" Yes ";
00046 string DialogBox::lblNo=" No ";
00047 string DialogBox::titDataChgd="Data changed!";
00048 string DialogBox::msgAskToSave="Save before we exit?";
00049 string DialogBox:: lblApply=" Apply";
00050
00051
00052
00053
00054
00055
00056 BEGIN_FIRST_BINDINGS(Control)
00057 END_BINDINGS()
00058
00059
00060 ofstream &Control::send_to_log(const string &what)
00061 {
00062 logfile << what;
00063 return logfile;
00064 }
00065
00066
00067
00068 bool Control::process_message(Control *pTarget,int what
00069 , int ctrl_id, void* pExtra)
00070 {
00071 if(!pTarget)
00072 return false;
00073 const BINDING_MAP* binding_map;
00074 const BINDING* pEntry;
00075
00076 for (binding_map = pTarget->get_binding_map(); binding_map != 0;
00077 binding_map = binding_map->base_map)
00078 {
00079 assert(bindings_map != binding_map->base_map);
00080
00081 pEntry = get_binding(binding_map->pEntries, what, ctrl_id);
00082 if (pEntry)
00083 {
00084 if(what==0)
00085 (pTarget->*pEntry->p_cmd_fn)();
00086 else
00087 (pTarget->*pEntry->p_notif_fn)(ctrl_id);
00088 return true;
00089 }
00090 }
00091 return false;
00092 }
00093
00094
00095
00096 const BINDING* Control::get_binding(const BINDING* pEntry,int what, int ctrl_id)
00097 {
00098
00099 while (pEntry->pfn())
00100 {
00101 if (pEntry->what == what &&
00102 ctrl_id >= pEntry->ctrl_id && ctrl_id <= pEntry->last_ctrl_id){
00103 return pEntry;
00104 }
00105 pEntry++;
00106 }
00107 return 0;
00108 }
00109
00110
00111
00112 Control::styles
00113 Control::set_styles(Control::styles s)
00114 {
00115 int old_style=field_style;
00116 field_style=s;
00117 return styles(old_style);
00118 }
00119
00120
00121
00122 Control::styles
00123 Control::set_style(Control::styles s,bool on)
00124 {
00125 int old_style=field_style;
00126 if (on) field_style|=s;
00127 else field_style&=~s;
00128 return styles(old_style);
00129 }
00130
00131
00132
00133 Control::states
00134 Control::set_states(Control::states s)
00135 {
00136 int old_state=field_state;
00137 field_state=s;
00138 return states(old_state);
00139 }
00140
00141
00142
00143 Control::states
00144 Control::set_state(Control::states s,bool on)
00145 {
00146 int old_state=field_state;
00147 if (on) field_state|=s;
00148 else field_state&=~s;
00149 return states(old_state);
00150 }
00151
00152
00153
00154 int Control::mvwin(int y, int x)
00155 {
00156 if(!is_moveable())
00157 return E_REQUEST_DENIED;
00158
00159 int result=0;
00160 int new_x=begx()+x;
00161 int new_y=begy()+y;
00162
00163 if( new_x > pParent->begx()
00164 && new_x+ width() <= pParent->begx()+pParent->maxx()
00165 && new_y > pParent->begy()
00166 && new_y+ height() <= pParent->begy()+pParent->maxy()
00167 ){
00168 result = NCursesPanel::mvwin(new_y,new_x);
00169 if(result==OK){
00170 w->_begx = new_x;
00171 w->_begy = new_y;
00172 refresh();
00173 }
00174 }
00175 return result;
00176 }
00177
00178
00179
00180
00181 int Control::move_left()
00182 {
00183 int result = false;
00184 if(!arrow_is_tab())
00185 result = true;
00186 beep();
00187 return result;
00188 }
00189
00190
00191
00192 int Control::move_right()
00193 {
00194 int result=false;
00195 if(!arrow_is_tab())
00196 result = true;
00197 beep();
00198 return result;
00199 }
00200
00201
00202
00203 void Control::activate()
00204 {
00205 if(is_hidden())
00206 return;
00207 top();
00208 set_state(active);
00209 if(has_frame()){
00210 attron(A_BOLD);
00211 box();
00212 attroff(A_BOLD);
00213 refresh();
00214 }
00215 }
00216
00217
00218
00219 void Control::deactivate()
00220 {
00221 if(is_hidden())
00222 return;
00223 top();
00224 set_state(active,false);
00225 if(has_frame()){
00226 attroff(A_BOLD);
00227 box();
00228 refresh();
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237 Label::Label( Control *parent
00238 ,int id, const string &title
00239 ,int lines,int cols,int y, int x
00240 ,int style)
00241 : Control(parent,id,lines,cols,y,x,style)
00242 ,text(title)
00243 ,pos_x(0),pos_y(0)
00244 ,viewport(this)
00245 ,cur_x(0),cur_y(0),x_start(0)
00246 {
00247 enable_notify(false);
00248 if(has_frame()){
00249 viewport = new NCursesWindow(*this);
00250 pos_x++;
00251 pos_y++;
00252 }
00253 max_length = viewport->width();
00254 set_text(title);
00255 enable_notify();
00256 }
00257
00258
00259
00260 Label::Label( int id, const string &title
00261 ,int lines,int cols,int y, int x
00262 ,int style)
00263 : Control(id,lines,cols,y,x,style)
00264 ,text(title)
00265 ,pos_x(0),pos_y(0)
00266 ,viewport(this)
00267 ,cur_x(0),cur_y(0)
00268 {
00269 enable_notify(false);
00270 if(has_frame()){
00271 viewport = new NCursesWindow(*this);
00272 pos_x++;
00273 pos_y++;
00274 }
00275 set_text(title);
00276 enable_notify();
00277 }
00278
00279
00280
00281 void Label::set_text(const string &v)
00282 {
00283 string old_text= text;
00284 text = v;
00285 x_start=0;
00286 cur_x=0;
00287 refresh_text();
00288 refresh_viewport();
00289 if(old_text!=text && notify_enabled()){
00290 process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00291 }
00292 }
00293
00294
00295
00296 int Control::driver(int key)
00297 {
00298 switch(key) {
00299 case KEY_RIGHT:
00300 return move_right();
00301 case KEY_LEFT:
00302 return move_left();
00303 default: break;
00304 }
00305 return FALSE;
00306 }
00307
00308
00309
00310 void Label::activate()
00311 {
00312 if(is_hidden())
00313 return;
00314 Control::activate();
00315 if(!has_frame()){
00316 refresh_viewport();
00317 }
00318 }
00319
00320
00321
00322 void Label::deactivate()
00323 {
00324 if(is_hidden())
00325 return;
00326 Control::deactivate();
00327 if(!has_frame()){
00328 refresh_viewport();
00329 }
00330 }
00331
00332
00333
00334
00335
00336
00337 Button::Button( Control *parent
00338 ,int id,const string &title
00339 ,int lines,int cols,int y, int x
00340 ,int style)
00341 :Label(parent,id,title,lines,cols,y,x,style)
00342 {
00343 }
00344
00345
00346
00347 int Button::driver(int key)
00348 {
00349 int result= FALSE;
00350 switch(key) {
00351 case KEY_ENTER: result = action(); break;
00352 #ifdef NCURSES_MOUSE_VERSION
00353 case KEY_MOUSE:
00354 {
00355 MEVENT event;
00356 getmouse(&event);
00357 int ry = event.y, rx = event.x;
00358 if (mouse_trafo(&ry,&rx,FALSE)){
00359 if((event.bstate & ( BUTTON1_CLICKED|
00360 BUTTON1_DOUBLE_CLICKED|
00361 BUTTON1_TRIPLE_CLICKED))
00362 && clicked_inside(ry, rx)){
00363
00364
00365 result=action();
00366 }
00367 }
00368 break;
00369 }
00370 #endif
00371 default: result = Label::driver(key); break;
00372 }
00373 return result;
00374 }
00375
00376
00377
00378 void Button::activate()
00379 {
00380 Control::activate();
00381 attron(A_BOLD);
00382 set_text(text);
00383 refresh();
00384
00385 }
00386
00387
00388
00389 void Button::deactivate()
00390 {
00391 Control::deactivate();
00392 attroff(A_BOLD);
00393 set_text(text);
00394 }
00395
00396
00397
00398
00399
00400
00401 PushButton::PushButton( Control *parent
00402 ,int id, const string &title
00403 ,int lines,int cols,int y, int x
00404 ,int style)
00405 :Button(parent,id, title,lines,cols,y,x,(style&=~framed))
00406 {
00407 enable_notify(false);
00408 set_style(framed,true);
00409 set_text(text);
00410 enable_notify();
00411 }
00412
00413
00414
00415 PushButton::PushButton( Control *parent
00416 ,int id, const string &title
00417 ,int y, int x)
00418 :Button(parent,id,title,1,title.size()+3,y,x,tabstop|notify)
00419 {
00420 enable_notify(false);
00421 set_style(framed,true);
00422 set_text(text);
00423 enable_notify();
00424 }
00425
00426
00427
00428 void PushButton::set_text(const string &v)
00429 {
00430 int max_len = width()-pos_x-has_frame();
00431 string new_text= v.substr(0, max_len);
00432 text = new_text;
00433 clrtoeol();
00434 centertext(0,text.c_str());
00435 if(has_frame()){
00436 addch(0,0, '[');
00437 addch(0,maxx(), ']');
00438 }
00439 move(0,0);
00440 refresh();
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 ListItemData &
00457 ListItemData::operator=(const ListItem &rha)
00458 {
00459 set_styles(rha.get_style());
00460 set_states(rha.get_state());
00461 set_default(rha.is_default());
00462 return *this;
00463 }
00464
00465
00466
00467 ListItemData &
00468 ListItemData::operator=(const ListItemData &rha)
00469 {
00470 set_text(rha.get_text());
00471 set_ctrl_id(rha.get_ctrl_id());
00472 set_styles(rha.get_style());
00473 set_states(rha.get_state());
00474 set_default(rha.is_default());
00475 set_user_data(rha.get_user_data());
00476 return *this;
00477 }
00478
00479
00480
00481 int
00482 ListItemData::set_state(int s,bool on)
00483 {
00484 int old_state=field_state;
00485 if (on) field_state|=s;
00486 else field_state&=~s;
00487 return old_state;
00488 }
00489
00490
00491
00492
00493
00494
00495 ListItem::ListItem( Control *parent
00496 ,int id, const string &title
00497 ,int lines,int cols,int y, int x
00498 ,int style)
00499 :Button(parent,id, title,lines,cols,y,x,style),user_data(0)
00500 {
00501 }
00502
00503
00504
00505 int ListItem::driver(int key)
00506 {
00507 int result= FALSE;
00508 switch(key) {
00509 case ' ':
00510 set_check(!is_checked());
00511 result=TRUE;
00512 break;
00513 #ifdef NCURSES_MOUSE_VERSION
00514 case KEY_MOUSE:
00515 {
00516 MEVENT event;
00517 getmouse(&event);
00518 if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
00519 && wenclose(w,event.y, event.x))
00520 {
00521
00522 set_check(!is_checked());
00523 result=TRUE;
00524 }
00525 }
00526 #endif
00527 default:
00528 break;
00529 }
00530 return result;
00531 }
00532
00533
00534
00535 void ListItem::set_text(const string &v)
00536 {
00537 string new_text= v;
00538 text = new_text;
00539 refresh_text();
00540 move(0,0);
00541 refresh();
00542 }
00543
00544
00545
00546 ListItem &ListItem::operator=(const ListItemData &rha)
00547 {
00548 set_text(rha.get_text());
00549 set_ctrl_id(rha.get_ctrl_id());
00550 set_styles(styles(rha.get_style()));
00551 set_states(states(rha.get_state()));
00552 set_default(rha.is_default());
00553 set_user_data(rha.get_user_data());
00554 return *this;
00555 }
00556
00557
00558
00559
00560
00561
00562 RadioButton::RadioButton( Control *parent
00563 ,int id,const string &title
00564 ,int lines,int cols
00565 ,int y, int x,int style)
00566 :ListItem(parent,id,title,lines,cols,y,x,style)
00567 {
00568 enable_notify(false);
00569 set_text(text);
00570 enable_notify();
00571 }
00572
00573
00574
00575 RadioButton::RadioButton( Control *parent
00576 ,int id, const string &title
00577 ,int y, int x)
00578 :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
00579 {
00580 enable_notify(false);
00581 set_text(text);
00582 enable_notify();
00583 }
00584
00585
00586
00587
00588
00589
00590 CheckButton::CheckButton( Control *parent
00591 ,int id,const string &title
00592 ,int lines,int cols
00593 ,int y, int x,int style)
00594 :ListItem(parent,id,title,lines,cols,y,x,style)
00595 {
00596 enable_notify(false);
00597 set_text(text);
00598 enable_notify();
00599 }
00600
00601
00602
00603 CheckButton::CheckButton( Control *parent
00604 ,int id,const string &title
00605 ,int y, int x)
00606 :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
00607 {
00608 enable_notify(false);
00609 set_text(text);
00610 enable_notify();
00611 }
00612
00613
00614
00615
00616
00617
00618 Edit::Edit( Control *parent
00619 ,int id,const string &title
00620 ,int lines,int cols,int y, int x
00621 ,int style)
00622 :Label(parent,id,title,lines,cols,y,x,style)
00623 {
00624 }
00625
00626
00627
00628 Edit::~Edit()
00629 {
00630 if(has_frame())
00631 delete viewport;
00632 }
00633
00634
00635
00636 int Edit::driver(int key)
00637 {
00638 if(key==KEY_MOUSE)
00639 return false;
00640 return edit(key);
00641 }
00642
00643
00644
00645 void Edit::add_char(int key)
00646 {
00647 if(cur_x < text.size())
00648 text[cur_x]=key;
00649 else
00650 text+=key;
00651 }
00652
00653
00654
00655 void Edit::insert_char(int key)
00656 {
00657 if(text.size()+1 <= max_len()){
00658 text.insert(cur_x,1,(char)key);
00659 }
00660 }
00661
00662
00663
00664 int Edit::add_or_insert_char(int key)
00665 {
00666 if(!isprint(key))
00667 return FALSE;
00668
00669 if(cur_x > -1 && cur_x < max_len()){
00670 if(overwrite())add_char(key);
00671 else{
00672 if(text.size()==max_len()){
00673 beep();
00674 return TRUE;
00675 }
00676 insert_char(key);
00677 }
00678 refresh_text();
00679 if(++cur_x >= viewport->width())
00680 x_start++;
00681
00682 refresh_viewport();
00683 if(notify_enabled())
00684 process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00685 }
00686 else beep();
00687 return TRUE;
00688 }
00689
00690
00691
00692 int Edit::edit(int key)
00693 {
00694 switch(key) {
00695 case KEY_BACKSPACE:
00696 case KEY_DC:
00697 if(!text.empty()){
00698 if(cur_x) cur_x--;
00699 if(x_start) x_start--;
00700 text.erase(cur_x,1);
00701 refresh_text();
00702 refresh_viewport();
00703 if(notify_enabled())
00704 process_message(pParent,TXT_CHANGED,get_ctrl_id(),0);
00705 }
00706 else beep();
00707 return TRUE;
00708 case KEY_LEFT: return move_left();
00709 case KEY_RIGHT: return move_right();
00710 case KEY_ENTER: beep(); return KEY_TAB;
00711 default:
00712 if(add_or_insert_char(key))
00713 return TRUE;
00714 }
00715 return FALSE;
00716 }
00717
00718
00719
00720 int Edit::move_right()
00721 {
00722 int result=TRUE;
00723 if(text.size() && cur_x < text.size() && cur_x < max_len()-1){
00724 if(++cur_x >= viewport->width()){
00725 x_start++;
00726 refresh_text();
00727 }
00728 refresh_viewport();
00729 }
00730 else
00731 result = Label::move_right();
00732 return result;
00733 }
00734
00735
00736
00737 int Edit::move_left()
00738 {
00739 int result = TRUE;
00740 if(cur_x){
00741 if(--cur_x == x_start){
00742 if(x_start)
00743 x_start--;
00744 refresh_text();
00745 }
00746 refresh_viewport();
00747 }
00748 else
00749 result = Label::move_left();
00750 return result;
00751 }
00752
00753
00754
00755
00756
00757
00758 int EditNumber::edit(int key)
00759 {
00760 switch(key) {
00761 case KEY_BACKSPACE:
00762 case KEY_DC:
00763 case KEY_LEFT:
00764 case KEY_RIGHT:
00765 case KEY_ENTER:
00766 return Edit::edit(key);
00767 default:
00768 if(isdigit(key))
00769 return Edit::edit(key);
00770 else
00771 beep();
00772 break;
00773 }
00774 return FALSE;
00775 }
00776
00777
00778
00779
00780
00781
00782 EditDate::EditDate( Control *parent,int id,const string &msk
00783 ,int lines,int cols,int y, int x
00784 ,int style)
00785 :EditNumber(parent,id,msk,lines,cols,y,x,style)
00786 ,mask(msk)
00787 {
00788 enable_notify(false);
00789 set_overwrite();
00790 set_text(mask);
00791 enable_notify();
00792 }
00793
00794
00795
00796 EditDate::EditDate( Control *parent
00797 ,int id, const string &msk
00798 ,int y, int x,int style)
00799 :EditNumber(parent,id,msk
00800 ,1+((style&framed==framed)*2)
00801 ,msk.size()+((style&framed==framed)*2)
00802 ,y,x,style)
00803 ,mask(msk)
00804 {
00805 enable_notify(false);
00806 set_overwrite();
00807 set_text(mask);
00808 enable_notify();
00809 }
00810
00811
00812
00813 int EditDate::edit(int key)
00814 {
00815 int result = FALSE;
00816 switch(key) {
00817 case KEY_LEFT:
00818 result = Edit::edit(key);
00819 if(text[cur_x]=='/' || text[cur_x]=='-'){
00820 result = Edit::edit(key);
00821 }
00822 break;
00823 case KEY_BACKSPACE:
00824 case KEY_DC:
00825 if(cur_x==0)
00826 beep();
00827 else{
00828 if(text[cur_x-1]=='/' || text[cur_x-1]=='-'){
00829 cur_x--;
00830 refresh_viewport();
00831 }
00832 result = Edit::edit(key);
00833 text.insert(cur_x,1,mask[cur_x]);
00834 refresh_text();
00835 refresh_viewport();
00836 }
00837 break;
00838 case '0':
00839 case '1':
00840 case '2':
00841 case '3':
00842 case '4':
00843 case '5':
00844 case '6':
00845 case '7':
00846 case '8':
00847 case '9':
00848 case KEY_ENTER:
00849 case KEY_RIGHT:
00850 result = Edit::edit(key);
00851 if(text[cur_x]=='/' || text[cur_x]=='-'){
00852 result = Edit::edit(KEY_RIGHT);
00853 }
00854 break;
00855 default:
00856 beep();
00857 break;
00858 }
00859 return result;
00860 }
00861
00862
00863
00864
00865
00866
00867 int EditDouble::edit(int key)
00868 {
00869 switch(key) {
00870 case '.':
00871 return Edit::edit(key);
00872 default:
00873 return EditNumber::edit(key);
00874 break;
00875 }
00876 return FALSE;
00877 }
00878
00879
00880
00881
00882
00883
00884
00885 ListBox::ListBox( Control *parent
00886 ,int id,const string &title
00887 ,int lines,int cols,int y, int x
00888 ,int style)
00889 :Control( parent,id,lines,cols,y,x,style)
00890 ,pos_x(0), pos_y(0)
00891 ,curr_item(-1)
00892 ,first_visible(-1)
00893 ,last_visible(-1)
00894 ,cur_sel(-1)
00895 {
00896 enable_notify(false);
00897 if(has_frame()){
00898 pos_x++;
00899 pos_y++;
00900 }
00901 set_text(title);
00902 draw_scrollbar();
00903 enable_notify();
00904 }
00905
00906
00907 ListBox::ListBox(int id,const string &title
00908 ,int lines,int cols,int y, int x
00909 ,int style)
00910 :Control( id,lines,cols,y,x,style)
00911 ,pos_x(0), pos_y(0)
00912 ,curr_item(-1)
00913 ,first_visible(-1)
00914 ,last_visible(-1)
00915 ,cur_sel(-1)
00916 {
00917 enable_notify(false);
00918 if(has_frame()){
00919 pos_x++;
00920 pos_y++;
00921 }
00922 set_text(title);
00923 draw_scrollbar();
00924 enable_notify();
00925 }
00926
00927
00928
00929 BEGIN_BINDINGS(ListBox,Control)
00930 ON_NOTIFY_RANGE(LI_SEL_CHANGE,0,0xffff,ListBox::on_sel_change)
00931 END_BINDINGS()
00932
00933
00934
00935
00936 ListBox::~ListBox()
00937 {
00938 hide();
00939 VisibleItems::iterator it;
00940 for(it=items.begin();it!=items.end();it++){
00941 delete *it;
00942 }
00943
00944 delete_data();
00945 }
00946
00947
00948
00949 void ListBox::delete_data()
00950 {
00951 ListItems::iterator d;
00952 for(d=data.begin();d!=data.end();d++){
00953 delete *d;
00954 }
00955 }
00956
00957
00958
00959 void ListBox::clear()
00960 {
00961 delete_data();
00962 data.clear();
00963 curr_item=first_visible=last_visible=0;
00964 refresh_items();
00965 show_empty();
00966 draw_scrollbar();
00967 refresh();
00968 }
00969
00970
00971
00972 void ListBox::show_empty()
00973 {
00974 if(data.empty()){
00975 cur_sel=-1;
00976 items[0]->set_text("Empty");
00977 items[0]->enable(false);
00978 }
00979
00980 }
00981
00982
00983
00984 void ListBox::draw_scrollbar()
00985 {
00986 if(!has_vscrollbar())
00987 return;
00988 int i, row, col, h_len, v_len;
00989 int winheight=items.size();
00990 int dataheight = data.size();
00991 int top = ((first_visible==-1)? 0:first_visible);
00992
00993 if(dataheight==0)
00994 dataheight = 1;
00995
00996 v_len = (winheight*winheight + dataheight - 1)/dataheight;
00997 if (v_len==0)
00998 v_len = 1;
00999 if (v_len > winheight)
01000 v_len = winheight;
01001
01002
01003 row = (top * winheight + dataheight - 1) / dataheight;
01004 if (row + v_len > winheight)
01005 row = winheight - v_len;
01006
01007 vline(1,maxx(),winheight);
01008 attron(A_REVERSE);
01009 if (v_len>=2) {
01010 addch(row+1,maxx(),ACS_UARROW);
01011 for(i=2;i<v_len;i++)
01012 addch(row+i,maxx(),' ');
01013 addch(row+v_len,maxx(),ACS_DARROW);
01014 }
01015 else {
01016 for(i=1;i<=v_len;i++)
01017 addch(row+i,maxx(),' ');
01018 }
01019 attroff(A_REVERSE);
01020 }
01021
01022
01023 int ListBox::add_item(const string &new_item,int pos
01024 ,bool is_default= false,bool make_visible)
01025 {
01026 ListItemData *item=new ListItemData(new_item,data.size());
01027 item->set_default(is_default);
01028 add_item(item,pos,make_visible);
01029 }
01030
01031
01032
01033
01034 int ListBox::add_item(ListItemData *new_item,int pos
01035 ,bool make_visible)
01036 {
01037 int old_current = curr_item;
01038
01039 ListItems::iterator where=data.end();
01040
01041 if(pos!=-1 ){
01042 if(pos >-1 && pos < data.size()){
01043 where=data.begin()+pos;
01044 if(make_visible){
01045 curr_item=pos;
01046 }
01047 }
01048 else
01049 throw
01050 Exception<ListBox>(this
01051 ,"Position out of range in add_item");
01052 }
01053 else{
01054 if(data.empty()==false){
01055 if(make_visible){
01056 curr_item++;
01057 }
01058 }
01059 }
01060 data.insert(where,new_item);
01061 adjust_visible_items();
01062 draw_scrollbar();
01063 refresh();
01064 }
01065
01066
01067
01068
01069 int ListBox::remove_item(int pos)
01070 {
01071 if(pos>=0 && pos < data.size()){
01072 data.erase(data.begin()+pos);
01073 if(pos<= curr_item && curr_item)
01074 curr_item--;
01075 if(cur_sel == pos){
01076 if(is_multisel()){
01077 cur_sel = -1;
01078 adjust_visible_items();
01079 draw_scrollbar();
01080 show_empty();
01081 refresh();
01082 }
01083 else if(cur_sel!=-1)
01084 set_cur_sel(curr_item);
01085 }
01086 }
01087 };
01088
01089
01090
01091 int ListBox::refresh()
01092 {
01093 for( int idx=first_visible;idx <= last_visible; idx++){
01094 if(idx!=curr_item)
01095 deactivate_item(idx);
01096 }
01097 activate_item(curr_item);
01098 }
01099
01100
01101
01102 void ListBox::refresh_items()
01103 {
01104 for( int idx=first_visible;idx <= last_visible; idx++){
01105 update_item(idx);
01106 }
01107 clear_items();
01108
01109 }
01110
01111
01112
01113 void ListBox::clear_items()
01114 {
01115 for( int idx=data.size()-first_visible;idx <items.size(); idx++){
01116 items[idx]->set_text("");
01117 }
01118 }
01119
01120
01121
01122
01123 int ListBox::driver (int key)
01124 {
01125 if( data.size()
01126 && curr_item!=-1
01127
01128 && visible_item(curr_item)->driver(key)==TRUE)
01129 return TRUE;
01130 switch(key) {
01131 case KEY_UP:
01132 return move_up();
01133 case KEY_DOWN:
01134 return move_down();
01135 case KEY_RIGHT:
01136 return move_right();
01137 case KEY_LEFT:
01138 return move_left();
01139 #ifdef NCURSES_MOUSE_VERSION
01140 case KEY_MOUSE:
01141 {
01142 MEVENT event;
01143 getmouse(&event);
01144 if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
01145 && wenclose(w,event.y, event.x))
01146 {
01147
01148 int ry = event.y, rx = event.x;
01149
01150 if (mouse_trafo(&ry,&rx,FALSE)){
01151 set_cur_pos(first_visible + (ry-begy()-1));
01152 if (event.bstate & BUTTON1_DOUBLE_CLICKED)
01153 set_cur_sel(curr_item);
01154 return true;
01155 }
01156 }
01157 break;
01158 }
01159 #endif
01160 default:
01161 break;
01162 }
01163 return FALSE;
01164 }
01165
01166
01167
01168 void ListBox::adjust_visible_items()
01169 {
01170
01171 if(curr_item < first_visible){
01172 first_visible = curr_item;
01173 last_visible = first_visible + (items.size()-1);
01174 }
01175 if(curr_item > last_visible){
01176 last_visible = curr_item;
01177 first_visible = last_visible - (items.size()-1);
01178 if(first_visible < 0)
01179 first_visible =0;
01180 }
01181
01182 if(first_visible > data.size()) first_visible = (data.size()-1);
01183 if(last_visible > data.size() || items.size() >= data.size())
01184 last_visible = (data.size()-1);
01185
01186 if(first_visible < 0) first_visible =0;
01187 if(last_visible < 0) last_visible =0;
01188
01189 refresh_items();
01190 }
01191
01192
01193
01194
01195 void ListBox::activate()
01196 {
01197 Control::activate();
01198 attron(A_BOLD);
01199 set_text(_title);
01200 attroff(A_BOLD);
01201 draw_scrollbar();
01202 refresh();
01203 }
01204
01205
01206
01207
01208 void ListBox::deactivate()
01209 {
01210 Control::deactivate();
01211 attron(A_BOLD);
01212 set_text(_title);
01213 attroff(A_BOLD);
01214 deactivate_item(curr_item);
01215 draw_scrollbar();
01216 refresh();
01217 }
01218
01219
01220
01221
01222 void ListBox::show_text(const string &t,char where)
01223 {
01224 if (!t.empty()){
01225 switch(where){
01226 case 'l': lefttext(0,t.c_str()); break;
01227 case 'c': centertext(0,t.c_str()); break;
01228 case 'r': righttext(0,t.c_str()); break;
01229 default: centertext(0,t.c_str()); break;
01230 }
01231 }
01232 }
01233
01234
01235
01236
01237 void ListBox::lefttext(int row,const char *label) {
01238 if (label) {
01239 OnError(addstr(row, 1, label, width()));
01240 }
01241 }
01242
01243
01244
01245
01246 void ListBox::righttext(int row,const char *label) {
01247 if (label) {
01248 int x = maxx() - strlen(label)-1;
01249 if (x<0)
01250 x=0;
01251 OnError(addstr(row, x, label, width()));
01252 }
01253 }
01254
01255
01256
01257
01258 void ListBox::activate_item(int item_idx)
01259 {
01260 update_item(item_idx);
01261 visible_item(item_idx)->activate();
01262 }
01263
01264
01265
01266
01267 void ListBox::deactivate_item(int item_idx)
01268 {
01269 visible_item(item_idx)->deactivate();
01270 update_data(item_idx);
01271 }
01272
01273
01274
01275
01276 void ListBox::update_data(int item_idx)
01277 {
01278 if(data.empty()||item_idx<0||item_idx >= data.size() )
01279 return;
01280 ListItem &itm= *(visible_item(item_idx));
01281 ListItemData &dat = *(data[item_idx]);
01282 dat = itm;
01283
01284 }
01285
01286
01287
01288
01289 void ListBox::update_item(int item_idx)
01290 {
01291 if(data.empty()||item_idx<0||item_idx >= data.size() )
01292 return;
01293 ListItem &itm= *(visible_item(item_idx));
01294 ListItemData &dat = *(data[item_idx]);
01295 itm = dat;
01296 }
01297
01298
01299
01300
01301 int ListBox::move_up()
01302 {
01303 if(curr_item){
01304 curr_item--;
01305 adjust_visible_items();
01306 draw_scrollbar();
01307 refresh();
01308 if(!is_multisel() && cur_sel!=-1)
01309 visible_item(curr_item)->set_check();
01310 if(notify_enabled()){
01311 process_message(pParent,LI_POS_CHANGE,get_ctrl_id(),0);
01312 }
01313 }
01314 return true;
01315 }
01316
01317
01318
01319
01320 int ListBox::move_down()
01321 {
01322 if(data.size() && curr_item < data.size()-1){
01323 curr_item++;
01324 adjust_visible_items();
01325 draw_scrollbar();
01326 refresh();
01327 if(!is_multisel()&& cur_sel!=-1)
01328 visible_item(curr_item)->set_check();
01329 if(notify_enabled()){
01330 process_message(pParent,LI_POS_CHANGE,get_ctrl_id(),0);
01331 }
01332 }
01333 return true;
01334 }
01335
01336
01337
01338 string ListBox::get_item_text(int pos){
01339 string result;
01340 if(pos>-1 && pos < data.size())
01341 result = data[pos]->get_text();
01342
01343 return result;
01344 }
01345
01346
01347
01348 void ListBox::set_item_text(int pos,const string &txt)
01349 {
01350 if(pos>-1 && pos < data.size())
01351 data[pos]->set_text(txt);
01352 }
01353
01354
01355
01356 int ListBox::sel_string(int pos,const string &txt)
01357 {
01358 ListItems::iterator it;
01359 for(int i=pos;i<data.size();i++){
01360 if(data[i]->text.find(txt)!=string::npos){
01361 set_cur_sel(i);
01362 return i;
01363 }
01364 }
01365 return string::npos;
01366 }
01367
01368
01369
01370 void *ListBox::get_item_data(int pos)
01371 {
01372 void *result=0;
01373 if(pos>-1 && pos < data.size())
01374 result = data[pos]->get_user_data();
01375
01376 return result;
01377 }
01378
01379
01380
01381 void ListBox::set_item_data(int pos,void *usr_data)
01382 {
01383 if(pos>-1 && pos < data.size())
01384 data[pos]->set_user_data(usr_data);
01385 }
01386
01387
01388
01389 ListItemData *ListBox::get_item(int pos)
01390 {
01391 ListItemData *result=0;
01392 if(pos>-1 && pos < data.size())
01393 result = data[pos];
01394
01395 return result;
01396 }
01397
01398
01399
01400 void ListBox::set_item(int pos,ListItemData *item)
01401 {
01402 if(pos>-1 && pos < data.size()){
01403 delete data[pos];
01404 data[pos]=item;
01405 refresh_items();
01406 refresh();
01407 }
01408 }
01409
01410
01411
01412 int ListBox::get_cur_pos()
01413 {
01414 return curr_item;
01415 }
01416
01417
01418
01419 void ListBox::set_cur_pos(int pos)
01420 {
01421 if(pos>-1 && pos < data.size()){
01422 curr_item = pos;
01423 adjust_visible_items();
01424 draw_scrollbar();
01425 refresh();
01426 }
01427 }
01428
01429
01430
01431 void ListBox::set_cur_sel(int pos)
01432 {
01433 if(pos>-1 && pos < data.size()){
01434 curr_item = pos;
01435 adjust_visible_items();
01436 draw_scrollbar();
01437 visible_item(pos)->set_check(true);
01438 check_multisel(pos, true);
01439 refresh();
01440 }
01441 }
01442
01443
01444
01445 int ListBox::get_cur_sel()
01446 {
01447 if(is_multisel())
01448 throw Exception<ListBox>(this,"Calling get_selected and is_multisel==true");
01449
01450 return cur_sel;
01451 }
01452
01453
01454
01455 void ListBox::get_sel_items(IndexList &list)
01456 {
01457 list.clear();
01458 if(is_multisel()){
01459 for(int i=0;i<data.size();i++){
01460 if(data[i]->is_checked())
01461 list.push_back(i);
01462 }
01463 }
01464 else
01465 list.push_back(cur_sel);
01466
01467 }
01468
01469
01470
01471 void ListBox::set_sel_items(const IndexList &list, bool t_or_f)
01472 {
01473 if(is_multisel()){
01474 for(int i=0;i<list.size();i++){
01475 data[list[i]]->set_check(t_or_f);
01476 }
01477 }
01478 refresh_items();
01479 refresh();
01480 }
01481
01482
01483
01484 void ListBox::check_multisel(int pos, bool t_or_f)
01485 {
01486 if(!is_multisel()){
01487 if(t_or_f==true){
01488 cur_sel = pos;
01489 for(int i=0;i<data.size();i++){
01490 if(i != pos){
01491 data[i]->set_check(false);
01492 if(i>=first_visible && i<=last_visible){
01493 update_item(i);
01494 }
01495 }
01496 }
01497 }
01498 else
01499 cur_sel=-1;
01500 }
01501 }
01502
01503
01504
01505 void ListBox::on_sel_change(int id)
01506 {
01507 update_data(curr_item);
01508 check_multisel(curr_item,data[curr_item]->is_checked());
01509 refresh();
01510 if(notify_enabled())
01511 process_message(pParent,LI_SEL_CHANGE,get_ctrl_id(),0);
01512 }
01513
01514
01515
01516 int ListBox::largest_name_len()const{
01517 unsigned MaximumNameLength = 0;
01518 ListItems::const_iterator it;
01519 for(it = data.begin(); it !=data.end();it++){
01520 string name((*it)->get_text());
01521
01522 if (name.size() > MaximumNameLength ){
01523 MaximumNameLength = name.size();
01524 }
01525 }
01526 return MaximumNameLength;
01527 }
01528
01529
01530
01531
01532
01533
01534 void SelectionBox::initialize_items()
01535 {
01536 curr_item=first_visible=last_visible=0;
01537 for(int i=pos_y;i<maxy();i++){
01538 items.push_back(new ListItem(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01539 }
01540 show_empty();
01541 }
01542
01543
01544
01545
01546
01547
01548 void CheckListBox::initialize_items()
01549 {
01550 curr_item=first_visible=last_visible=0;
01551 for(int i=pos_y;i<maxy();i++){
01552 items.push_back(new CheckButton(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01553 }
01554 show_empty();
01555 }
01556
01557
01558
01559
01560
01561
01562 void ChoiceBox::initialize_items()
01563 {
01564 curr_item=first_visible=last_visible=0;
01565 for(int i=pos_y;i<maxy();i++){
01566 items.push_back(new RadioButton(this,-1,"",1,width()-pos_x-has_frame() ,i,pos_x));
01567 }
01568 show_empty();
01569 }
01570
01571
01572
01573
01574
01575
01576 MenuItem::MenuItem( Control *parent
01577 ,int id,const string &title
01578 ,int lines,int cols
01579 ,int y, int x,int style)
01580 :ListItem(parent,id,title,lines,cols,y,x,style)
01581 {
01582 enable_notify(false);
01583 set_text(text);
01584 enable_notify();
01585 }
01586
01587
01588
01589 MenuItem::MenuItem( Control *parent
01590 ,int id,const string &title
01591 ,int y, int x)
01592 :ListItem(parent,id,title,1,title.size()+4,y,x,tabstop|notify)
01593 {
01594 enable_notify(false);
01595 set_text(text);
01596 enable_notify();
01597 }
01598
01599
01600
01601 int MenuItem::driver(int key)
01602 {
01603 int result =false;
01604 switch(key){
01605 case KEY_ENTER:
01606 result = pData->action();
01607 break;
01608 #ifdef NCURSES_MOUSE_VERSION
01609 case KEY_MOUSE:
01610 {
01611 MEVENT event;
01612 getmouse(&event);
01613 if ((event.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED|BUTTON1_TRIPLE_CLICKED))
01614 && wenclose(w,event.y, event.x))
01615 {
01616
01617 result = pData->action();
01618 }
01619 break;
01620 }
01621 #endif
01622 default:
01623 result = false;
01624 break;
01625 }
01626 return result;
01627 }
01628
01629
01630
01631
01632
01633
01634 int MenuBar::execute()
01635 {
01636 show();
01637 refresh();
01638 bool bBreakLoop=false;
01639 do{
01640 bBreakLoop=driver(getch());
01641
01642 } while( bBreakLoop==false);
01643 hide();
01644 refresh();
01645 return bBreakLoop;
01646 }
01647
01648
01649
01650 int MenuBar::driver (int key)
01651 {
01652 int result = false;
01653 switch(key) {
01654 case EXIT_APP:
01655 {
01656 string prompt(get_param("exit app","prompt","Esta seguro que quiere salir de la aplicacion?"));
01657 YesNoBox mb(Application::get_application()->get_title(),prompt);
01658 int req =mb.do_modal();
01659 refresh();
01660 if(req==IDYES){
01661 result=true;
01662 }
01663 break;
01664 }
01665 case KEY_ESC:
01666 if(is_main_menu)
01667 result = driver(EXIT_APP);
01668 else result =true;
01669 break;
01670 case KEY_ENTER:
01671 result = execute_current_item(key);
01672 switch(result) {
01673 case EXIT_APP:
01674 case KEY_ESC:
01675 case KEY_LEFT:
01676 case KEY_RIGHT:
01677 return driver(result);
01678 default:
01679 break;
01680 }
01681 break;
01682 #ifdef NCURSES_MOUSE_VERSION
01683 case KEY_MOUSE:
01684 {
01685 MEVENT event;
01686 getmouse(&event);
01687 if (event.bstate & (BUTTON1_CLICKED)){
01688 if( wenclose(w,event.y, event.x))
01689 {
01690
01691 find_clicked();
01692 result = execute_current_item(key);
01693 switch(result) {
01694 case EXIT_APP:
01695 case KEY_ESC:
01696 case KEY_LEFT:
01697 case KEY_RIGHT:
01698 return driver(result);
01699 default:
01700 break;
01701 }
01702 }
01703 else result = true;
01704 }
01705 break;
01706 }
01707 #endif
01708 default:
01709 result = ListBox::driver(key);
01710 break;
01711 }
01712 return result;
01713 }
01714
01715
01716
01717 int MenuBar::execute_current_item(int key)
01718 {
01719 int result=false;
01720 if(curr_item > -1 && curr_item < data.size()){
01721 MenuItem *pItem = dynamic_cast<MenuItem *>(visible_item(curr_item));
01722 if(pItem){
01723 result = pItem->driver(key);
01724 }
01725 refresh();
01726 }
01727 return result;
01728 }
01729
01730
01731
01732 int MenuBar::get_next_item_x()
01733 {
01734 int result = 0;
01735 if(orientation=='v'){
01736 result = pos_x;
01737 }
01738 else{
01739 VisibleItems::iterator it;
01740 for(it=items.begin();it!=items.end();it++){
01741 result += (*it)->width();
01742 }
01743 }
01744 return result;
01745
01746 }
01747
01748
01749
01750 int MenuBar::get_next_item_y()
01751 {
01752 int result = 0;
01753 if(orientation=='h'){
01754 result = pos_y;
01755 }
01756 else{
01757 result = items.size();
01758 }
01759 return result+has_frame();
01760
01761 }
01762
01763
01764
01765 void MenuBar::find_clicked()
01766 {
01767 MEVENT event;
01768 getmouse(&event);
01769 int ry = event.y, rx = event.x;
01770
01771 if (mouse_trafo(&ry,&rx,FALSE)){
01772 if(clicked_inside(ry,rx)){
01773 for(int i=0;i<items.size();i++){
01774 if(items[i]->clicked_inside(ry,rx))
01775 set_cur_pos(first_visible + i );
01776 }
01777 }
01778 }
01779 }
01780
01781
01782
01783
01784
01785
01786 int PopUpMenu::action()
01787 {
01788 int result = false;
01789 S = new SubMenu(-1,sub_menu_label
01790 ,items.size(),largest_name_len()
01791 ,pMenuItem->begy(),pMenuItem->begx(),'v');
01792 S->items_owner(false);
01793 ListItems::iterator it;
01794 for(it=items.begin();it!=items.end();it++){
01795 S->add_item((MenuItemData *)*it);
01796 }
01797 S->set_cur_pos(cur_sel);
01798 result = S->execute();
01799 cur_sel = S->get_cur_pos();
01800 refresh();
01801 delete S;
01802
01803 return false;
01804 }
01805
01806
01807
01808 int PopUpMenu::largest_name_len()const{
01809 unsigned MaximumNameLength = 0;
01810 ListItems::const_iterator it;
01811 for(it = items.begin(); it !=items.end();it++){
01812 string name((*it)->get_text());
01813
01814 if (name.size() > MaximumNameLength ){
01815 MaximumNameLength = name.size();
01816 }
01817 }
01818 if(sub_menu_label.size() > MaximumNameLength)
01819 MaximumNameLength = sub_menu_label.size();
01820 return MaximumNameLength;
01821 }
01822
01823
01824
01825
01826 PopUpMenu::~PopUpMenu()
01827 {
01828 delete S;
01829
01830
01831
01832
01833 }
01834
01835
01836
01837
01838
01839
01840 DialogBox::DialogBox(int id,const string &title
01841 ,int lines, int cols,int y, int x,int d_style, int c_style)
01842 : Control(id,lines,cols,y,x,c_style)
01843 ,_title(title)
01844 ,curr_child(0),
01845 dlg_style(d_style),
01846 changed(false),
01847 pBtnYes(0),
01848 pBtnNo(0),
01849 pBtnCancel(0),
01850 pBtnOk(0)
01851 {
01852 leaveok(FALSE);
01853 if(has_frame()){
01854 frame();
01855 }
01856 if(has_show_title()){
01857 show_text(_title,'c');
01858 }
01859 }
01860
01861
01862
01863 DialogBox::DialogBox(Control *parent,int id,const string &title
01864 ,int lines, int cols,int y, int x,int d_style, int c_style)
01865 : Control(parent,id,lines,cols,y,x,c_style)
01866 ,_title(title)
01867 ,curr_child(0),
01868 dlg_style(d_style),
01869 changed(false),
01870 pBtnYes(0),
01871 pBtnNo(0),
01872 pBtnCancel(0),
01873 pBtnOk(0)
01874 {
01875 leaveok(FALSE);
01876 if(has_frame()){
01877 frame();
01878 }
01879 if(has_show_title()){
01880 show_text(_title,'c');
01881 }
01882 }
01883
01884
01885
01886 BEGIN_BINDINGS(DialogBox,Control)
01887 ON_COMMAND(IDOK,DialogBox::on_dlg_ok)
01888 ON_COMMAND(IDYES,DialogBox::on_dlg_yes)
01889 ON_COMMAND(IDNO,DialogBox::on_dlg_no)
01890 ON_COMMAND(IDCANCEL,DialogBox::on_dlg_cancel)
01891 END_BINDINGS()
01892
01893
01894 DialogBox::~DialogBox()
01895 {
01896 hide();
01897 ListOfChildren::iterator it;
01898 for(it=children.begin();it!=children.end();it++){
01899 (*it)->hide();
01900 delete *it;
01901 }
01902 }
01903
01904
01905
01906 int DialogBox::do_modal()
01907 {
01908 on_dlg_init();
01909 bContinueModal=true;
01910 int req=REQ_DLG_EXIT;
01911 do{
01912 req=driver(getch());
01913 switch(req){
01914 case REQ_DLG_EXIT:
01915 on_dlg_cancel();
01916 break;
01917
01918 case REQ_DLG_LEFT:
01919 case REQ_DLG_PREV:
01920 prev_control();
01921 break;
01922
01923 case REQ_DLG_RIGHT:
01924 case REQ_DLG_NEXT:
01925 next_control();
01926 break;
01927
01928 default: on_cmd(req); break;
01929 }
01930 } while( bContinueModal);
01931 hide();
01932 return user_request;
01933 }
01934
01935
01936
01937 void DialogBox::hide()
01938 {
01939 ListOfChildren::iterator it;
01940 for(it=children.begin();it!=children.end();it++){
01941 (*it)->hide();
01942 }
01943 Control::hide();
01944 }
01945
01946
01947
01948 void DialogBox::show()
01949 {
01950 ListOfChildren::iterator it;
01951 for(it=children.begin();it!=children.end();it++){
01952 (*it)->show();
01953 }
01954 Control::show();
01955 }
01956
01957
01958
01959 void DialogBox::show_text(const string &t,char where)
01960 {
01961 if (!t.empty()){
01962 switch(where){
01963 case 'l': lefttext(0,t.c_str()); break;
01964 case 'c': centertext(0,t.c_str()); break;
01965 case 'r': righttext(0,t.c_str()); break;
01966 default: centertext(0,t.c_str()); break;
01967 }
01968 }
01969 }
01970
01971
01972
01973 int DialogBox::driver (int key)
01974 {
01975
01976 #ifdef NCURSES_MOUSE_VERSION
01977 if(key == KEY_MOUSE){
01978 find_clicked();
01979 }
01980 #endif
01981
01982 int result;
01983 if(!children.empty() && curr_child > -1) {
01984 result=children[curr_child]->driver(key);
01985 switch(result){
01986 case TRUE: return REQ_DLG_PROCESSED;
01987 case KEY_TAB: return REQ_DLG_NEXT;
01988 case KEY_SHIFT_TAB: return REQ_DLG_PREV;
01989 case KEY_ESC: key = result;
01990 default: break;
01991 }
01992 }
01993
01994 switch(key) {
01995 case KEY_UP: return REQ_DLG_UP;
01996 case KEY_DOWN: return REQ_DLG_DOWN;
01997 case KEY_LEFT: return REQ_DLG_LEFT;
01998 case KEY_RIGHT: return REQ_DLG_RIGHT;
01999 case KEY_EXIT:
02000 case CTRL('X'):
02001 case KEY_ESC:
02002
02003 user_request=IDCANCEL;
02004 return REQ_DLG_EXIT;
02005 case KEY_TAB +0x2f: return REQ_DLG_PREV;
02006 case KEY_TAB: return REQ_DLG_NEXT;
02007 default: return(key);
02008 }
02009 }
02010
02011
02012
02013 void DialogBox:: add_child(int pos,Control *new_child)
02014 {
02015 ListOfChildren::iterator where=children.end();
02016 if(pos >-1 && pos < children.size()){
02017 where=children.begin()+pos;
02018 }
02019
02020 if(where==children.end())
02021 add_child(new_child);
02022 else{
02023 where++;
02024 children.insert(where,new_child);
02025 }
02026 }
02027
02028
02029
02030 void DialogBox::find_clicked()
02031 {
02032 MEVENT event;
02033 getmouse(&event);
02034 int ry = event.y, rx = event.x;
02035
02036 if (mouse_trafo(&ry,&rx,FALSE)){
02037 if(clicked_inside(ry,rx)){
02038 for(int i=0;i<children.size();i++){
02039 if(children[i]->clicked_inside(ry,rx))
02040 set_focus_to(i);
02041 }
02042 }
02043 }
02044 }
02045
02046
02047
02048 void DialogBox:: add_child(Control *after,Control *new_child)
02049 {
02050 ListOfChildren::iterator where;
02051 for(where=children.begin();after && where!=children.end();where++){
02052 if(*where==after){
02053
02054 break;
02055 }
02056 }
02057 if(where==children.end())
02058 add_child(new_child);
02059 else{
02060 where++;
02061 children.insert(where,new_child);
02062 }
02063 }
02064
02065
02066 void DialogBox::next_control()
02067 {
02068 if(children.size()>1 && on_ctrl_term(*(children[curr_child]))){
02069 int start_point=curr_child;
02070 for(curr_child++;start_point!=curr_child;curr_child++){
02071 if(curr_child==children.size())
02072 curr_child=0;
02073
02074 if(children[curr_child]->is_enabled())
02075 break;
02076 }
02077 on_ctrl_init(*(children[curr_child]));
02078 }
02079 }
02080
02081
02082
02083 void DialogBox::prev_control()
02084 {
02085 if(children.size()>1 && on_ctrl_term(*(children[curr_child]))){
02086 int start_point=curr_child;
02087 for(curr_child--;start_point!=curr_child;curr_child--){
02088 if(curr_child<0)
02089 curr_child=children.size()-1;
02090
02091 if(children[curr_child]->is_enabled())
02092 break;
02093 }
02094 on_ctrl_init(*(children[curr_child]));
02095 }
02096 }
02097
02098
02099
02100 void DialogBox::set_focus_to(int child_idx)
02101 {
02102 if(children.empty()||curr_child < 0)
02103 return;
02104 if(!children[child_idx]->is_enabled())
02105 return;
02106
02107 if(on_ctrl_term(*(children[curr_child]))){
02108 curr_child = child_idx;
02109 on_ctrl_init(*(children[curr_child]));
02110 }
02111 }
02112
02113
02114
02115 void DialogBox::set_focus_to(Control *p_child)
02116 {
02117 for(int i=0;p_child && i<children.size();i++){
02118 if(children[i] == p_child){
02119 set_focus_to(i);
02120 break;
02121 }
02122 }
02123 }
02124
02125
02126
02127 bool DialogBox::can_close()
02128 {
02129 int result = true;
02130 if(changed){
02131 YesNoCancelBox dlg(titDataChgd,msgAskToSave);
02132 int usr_choice = dlg.do_modal();
02133 switch(usr_choice){
02134 case IDCANCEL: result = false;
02135 case IDYES:
02136 case IDNO:
02137 default:
02138 break;
02139 }
02140 }
02141 refresh();
02142 return result;
02143 }
02144
02145
02146
02147 void DialogBox::lefttext(int row,const char *label) {
02148 if (label) {
02149 OnError(addstr(row, 0, label, width()));
02150 }
02151 }
02152
02153
02154
02155 void DialogBox::righttext(int row,const char *label) {
02156 if (label) {
02157 int x = maxx() - strlen(label);
02158 if (x<0)
02159 x=0;
02160 OnError(addstr(row, x, label, width()));
02161 }
02162 }
02163
02164
02165
02166 int DialogBox::my_w = 0;
02167 int DialogBox::btn_w= 0;
02168 int DialogBox::btns=0;
02169 int DialogBox::used_width=0;
02170 int DialogBox::spc=0;
02171 int DialogBox::X_POS(int pos)
02172 {
02173 return (((my_w-used_width)/btns)+((btn_w+spc)*pos));
02174 }
02175
02176
02177
02178 void DialogBox::create_buttons()
02179 {
02180 switch((dlg_style & 0x00ff)){
02181 case okCancel: add_ok_cancel(); break;
02182 case yesNo: add_yes_no(); break;
02183 case yesNoCancel:add_yes_no_cancel(); break;
02184 default: add_ok(); break;
02185 }
02186 }
02187
02188
02189 void DialogBox::add_ok()
02190 {
02191 pBtnOk=new PushButton(this,IDOK,lblOk, maxy()-1,(maxx()-9)/2);
02192 add_child(pBtnOk);
02193
02194 if(!children.empty())
02195 set_focus_to(children.size()-1);
02196 }
02197
02198
02199 void DialogBox::add_ok_cancel()
02200 {
02201 Control *pCtrl=0;
02202 my_w = width()-2;
02203 btn_w= 9;
02204 btns=2;
02205 used_width=btn_w*btns;
02206 spc=2;
02207 pBtnOk=new PushButton(this,IDOK,lblOk,maxy()-1,X_POS(0));
02208 add_child(pBtnOk);
02209 pBtnOk->enable(false);
02210 pBtnCancel=new PushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(1));
02211 add_child(pBtnCancel);
02212 }
02213
02214
02215
02216 void DialogBox::add_yes_no_cancel()
02217 {
02218 my_w = width()-2;
02219 btn_w= 9;
02220 btns=3;
02221 used_width=btn_w*btns;
02222 spc=2;
02223 pBtnYes=new PushButton(this,IDYES,lblYes,maxy()-1,X_POS(0));
02224 add_child(pBtnYes);
02225 pBtnNo=new PushButton(this,IDNO,lblNo,maxy()-1,X_POS(1));
02226 add_child(pBtnNo);
02227 pBtnCancel=new PushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(2));
02228 add_child(pBtnCancel);
02229 }
02230
02231
02232
02233 void DialogBox::add_yes_no()
02234 {
02235 Control *pCtrl=0;
02236 my_w = width()-2;
02237 btn_w= 9;
02238 btns=2;
02239 used_width=btn_w*btns;
02240 spc=2;
02241 pBtnYes=new PushButton(this,IDYES,lblYes,maxy()-1,X_POS(0));
02242 add_child(pBtnYes);
02243 pBtnNo=new PushButton(this,IDNO,lblNo,maxy()-1,X_POS(1));
02244 add_child(pBtnNo);
02245 }
02246
02247
02248
02249
02250
02251
02252 PropertyDialog::PropertyDialog(int id,const string &title,int lines, int cols,int y, int x)
02253 : DialogBox(id,title,lines,cols,y,x,0,Control::title),pBtnApply(pBtnNo)
02254 {
02255 }
02256
02257
02258
02259 BEGIN_BINDINGS(PropertyDialog,DialogBox)
02260 ON_COMMAND(IDAPPLY,PropertyDialog::on_apply)
02261 ON_COMMAND(RETURN_TO_PAGE,PropertyDialog::on_return_to_page)
02262 ON_COMMAND(CANCEL_TO_CLOSE,PropertyDialog::cancel_to_close)
02263 ON_COMMAND(FOCUS_TO_BUTTONS,PropertyDialog::on_focus_to_buttons)
02264 ON_NOTIFY_RANGE(PAGE_MODIFIED,0,0xffff,PropertyDialog::on_page_modified)
02265 ON_NOTIFY_RANGE(PAGE_SELECTED,0,0xffff,PropertyDialog::on_page_selected)
02266 END_BINDINGS()
02267
02268
02269
02270 PropertyDialog::~PropertyDialog()
02271 {
02272 }
02273
02274
02275
02276 void PropertyDialog::on_dlg_init()
02277 {
02278 create_buttons();
02279 set_focus_to(pBtnCancel);
02280 }
02281
02282
02283
02284 void PropertyDialog::create_buttons()
02285 {
02286 Label *pFrame = new Label(this,-1,"",3,width(),maxy()-2,0,framed);
02287 pFrame->enable(false);
02288 add_child(pFrame);
02289 my_w = width()-2;
02290 btn_w= 9;
02291 btns=3;
02292 used_width=btn_w*btns;
02293 spc=2;
02294 pBtnOk=new PropDlgPushButton(this,IDOK,lblOk,maxy()-1,X_POS(0));
02295 pBtnOk->enable(false);
02296 add_child(pBtnOk);
02297 pBtnApply=new PropDlgPushButton(this,IDAPPLY,lblApply,maxy()-1,X_POS(1));
02298 pBtnApply->enable(false);
02299 add_child(pBtnApply);
02300 pBtnCancel=new PropDlgPushButton(this,IDCANCEL,lblCancel,maxy()-1,X_POS(2));
02301 add_child(pBtnCancel);
02302 }
02303
02304
02305
02306 int PropertyDialog::get_next_tab_pos()
02307 {
02308 int result = 0;
02309 ListOfPages::iterator it;
02310 for(it=pages.begin();it!=pages.end();it++){
02311 result += (*it)->width()-1;
02312 }
02313 if(result)
02314 result--;
02315
02316 return result;
02317
02318 }
02319
02320
02321
02322 void PropertyDialog::set_selected_page(int page)
02323 {
02324 if(valid_page_number(page))
02325 set_focus_to(pages[page]);
02326 }
02327
02328
02329
02330 PropertyPage *PropertyDialog::get_page(int page)
02331 {
02332 if(valid_page_number(page))
02333 return pages[page]->get_page();
02334
02335 throw Exception<PropertyDialog>(this,"Invalid page number!",-1);
02336 }
02337
02338
02339
02340 void PropertyDialog::add_page(PropertyPage *new_page)
02341 {
02342 Tab *pTab = new Tab(this,new_page->get_ctrl_id(),new_page->get_text(),0,get_next_tab_pos());
02343 pages.push_back(pTab);
02344 pTab->set_page(new_page);
02345 add_child(pTab);
02346 }
02347
02348
02349
02350 void PropertyDialog::reorder_pages()
02351 {
02352 int pos=0;
02353 ListOfPages::iterator it;
02354 for(it = pages.begin();it!=pages.end();it++){
02355 Tab *pTab = *it;
02356 pTab->mvwin(begy(),begx()+pos);
02357 pos += pTab->width()-1;
02358 }
02359 }
02360
02361
02362
02363 void PropertyDialog::cancel_to_close()
02364 {
02365 changed = false;
02366 pBtnOk->enable(false);
02367 pBtnApply->enable(false);
02368 pBtnCancel->set_text(" Close ");
02369 }
02370
02371
02372
02373
02374
02375
02376 Tab::Tab( Control *parent
02377 ,int id, const string &title
02378 ,int lines,int cols,int y, int x
02379 ,int style)
02380 :Button(parent,id, title,lines,cols,y,x,style|=framed)
02381 ,pPage(0)
02382 {
02383 enable_notify(false);
02384 set_text(text);
02385 enable_notify();
02386 }
02387
02388
02389
02390 Tab::Tab( Control *parent
02391 ,int id, const string &title
02392 ,int y, int x)
02393 :Button(parent,id,title,3,title.size()+3,y,x,tabstop|notify|framed)
02394 ,pPage(0)
02395 {
02396 enable_notify(false);
02397 set_text(text);
02398 enable_notify();
02399 }
02400
02401
02402
02403 Tab::~Tab()
02404 {
02405 delete pPage;
02406 }
02407
02408
02409
02410 void Tab::activate()
02411 {
02412 if(is_hidden())
02413 return;
02414
02415 if(pPage){
02416 pPage->activate();
02417 pPage->refresh();
02418 }
02419 Control::activate();
02420 attron(A_BOLD);
02421 set_text(text);
02422 if(notify_enabled())
02423 process_message(pParent,PAGE_SELECTED,get_ctrl_id(),this);
02424 }
02425
02426
02427
02428 void Tab::deactivate()
02429 {
02430 if(is_hidden())
02431 return;
02432 if(pPage){
02433 pPage->deactivate();
02434 }
02435 Control::deactivate();
02436 attroff(A_BOLD);
02437 set_text(text);
02438 }
02439
02440
02441
02442 void Tab::set_text(const string &v)
02443 {
02444 int max_len = width()-pos_x-has_frame();
02445 string new_text= v.substr(0, max_len);
02446 text = new_text;
02447 clrtoeol();
02448 centertext(1,text.c_str());
02449 delch(0,maxx());
02450 delch(0,maxx()-1);
02451 addch(1,maxx()-1, '\\');
02452 move(1,1);
02453 refresh();
02454 }
02455
02456
02457
02458 int Tab::driver(int key)
02459 { int val=0;
02460 switch(key) {
02461 #ifdef NCURSES_MOUSE_VERSION
02462 case KEY_MOUSE:
02463 {
02464 MEVENT event;
02465 getmouse(&event);
02466 int ry = event.y, rx = event.x;
02467 if (!mouse_trafo(&ry,&rx,FALSE))
02468 return false;
02469 if(!(event.bstate & ( BUTTON1_CLICKED|
02470 BUTTON1_DOUBLE_CLICKED|
02471 BUTTON1_TRIPLE_CLICKED))
02472 ||!pPage->clicked_inside(ry, rx)){
02473 return false;
02474 }
02475 }
02476 #endif
02477 case KEY_TAB:
02478 case KEY_DOWN:
02479 case KEY_ENTER:
02480 val = pPage->process_key(key);
02481 if(val == DialogBox::REQ_DLG_DOWN){
02482 process_message(pParent,0,(int)FOCUS_TO_BUTTONS,0);
02483 return TRUE;
02484 }
02485 else if(val== DialogBox::REQ_DLG_EXIT)
02486 return KEY_ESC;
02487 else if(key==KEY_MOUSE)
02488 return key;
02489 else
02490 activate();
02491 break;
02492 default:
02493 return Button::driver(key);
02494 break;
02495 }
02496 return FALSE;
02497 }
02498
02499
02500
02501
02502
02503
02504 int PropertyPage::process_key(int key)
02505 {
02506 refresh();
02507 bContinueModal=true;
02508 int req=REQ_DLG_EXIT;
02509 do{
02510 #ifdef NCURSES_MOUSE_VERSION
02511 if(key == KEY_MOUSE){
02512 req=driver(key);
02513 key=0;
02514 }
02515 else
02516 #endif
02517
02518 req=driver(getch());
02519 switch(req){
02520 case REQ_DLG_EXIT:
02521 case REQ_DLG_UP:
02522 case REQ_DLG_DOWN:
02523 bContinueModal=false;break;
02524 case REQ_DLG_RIGHT:
02525 case REQ_DLG_NEXT: next_control(); break;
02526
02527 case REQ_DLG_LEFT:
02528 case REQ_DLG_PREV: prev_control(); break;
02529 default: on_cmd(req); break;
02530 }
02531 } while( bContinueModal);
02532 return req;
02533 }
02534
02535
02536
02537 void PropertyPage::on_cmd(int key)
02538 {
02539 switch(key) {
02540 #ifdef NCURSES_MOUSE_VERSION
02541 case KEY_MOUSE:
02542 {
02543 MEVENT event;
02544 getmouse(&event);
02545 int ry = event.y, rx = event.x;
02546 if (mouse_trafo(&ry,&rx,FALSE)){
02547 if((event.bstate & ( BUTTON1_CLICKED|
02548 BUTTON1_DOUBLE_CLICKED|
02549 BUTTON1_TRIPLE_CLICKED))
02550 && !clicked_inside(ry, rx)){
02551
02552
02553 bContinueModal=false;
02554 }
02555 }
02556 break;
02557 }
02558 #endif
02559 default: break;
02560 }
02561 }
02562
02563
02564
02565
02566
02567 MessageBox::MessageBox( const string &title,const string &message,int style)
02568 : DialogBox(10000,title,LINES-15,COLS-30,7,15,style),msg(message)
02569 {
02570 }
02571
02572
02573
02574 void MessageBox::on_dlg_init()
02575 {
02576 set_style(styles(title|framed));
02577 DialogBox::on_dlg_init();
02578 show_message();
02579 create_buttons();
02580 if(pBtnCancel)
02581 set_focus_to(pBtnCancel);
02582 else if(pBtnNo)
02583 set_focus_to(pBtnNo);
02584 }
02585
02586
02587
02588 void MessageBox::show_message()
02589 {
02590 int max_row_size = width()-4;
02591 int rows = msg.size()/max_row_size;
02592 if(msg.size()%max_row_size)
02593 rows++;
02594
02595 for(int i=0;i<rows && i< maxy()-3;i++){
02596 string what(msg.substr(max_row_size*i,max_row_size));
02597 centertext(i+2,what.c_str());
02598 }
02599 }
02600
02601
02602
02603
02604
02605
02606 void Application::activateStatusBar()
02607 {
02608 pStatusBar = new StatusBar(1,COLS,LINES-1,0);
02609
02610 }
02611
02612
02613
02614 bool Application::section_exists(ifstream ¶m_file,const string §ion_name)
02615 {
02616 string tag("[" + section_name + "]");
02617 string line;
02618 char line_read[255]={0};
02619 for( param_file.getline(line_read,sizeof(line_read));
02620 param_file.good();
02621 param_file.getline(line_read,sizeof(line_read))){
02622 if(line_read[0] == '['){
02623 line = line_read;
02624 if(line.find(tag)!= string::npos){
02625 return true;
02626 }
02627 }
02628 }
02629 return false;
02630 }
02631
02632
02633
02634 long Application::find_key(ifstream ¶m_file,const string §ion_name,
02635 const string &key_name,string &value)
02636 {
02637 long line_beg =0;
02638 if(section_exists(param_file,section_name)){
02639 string line;
02640 string found_key;
02641 char line_read[255]={0};
02642 for( param_file.getline(line_read,sizeof(line_read));
02643 param_file.good();
02644 param_file.getline(line_read,sizeof(line_read))){
02645 line = line_read;
02646 line_beg = param_file.tellg();
02647 line_beg -= line.size();
02648 if(line.empty() || line[0]=='#')
02649 continue;
02650 if(line_read[0] == '[')
02651 break;
02652 int from= line.find_first_not_of(" \t");
02653 if(from == string::npos)
02654 continue;
02655 int to= line.rfind("#");
02656 if(to!=string::npos){
02657 line = line.substr(from,to-from);
02658 }
02659 to= line.find_last_not_of(" \t");
02660 line = line.substr(from,to-from+1);
02661 int eq_sign = line.find('=');
02662 found_key= line.substr(0,eq_sign);
02663 if(found_key == key_name){
02664 if(to!=eq_sign && eq_sign!=string::npos){
02665 value= line.substr(eq_sign+1);
02666 }
02667 break;
02668 }
02669 }
02670 }
02671 return line_beg;
02672 }
02673
02674
02675
02676 string Application::get_param(const string §ion_name,
02677 const string &key_name,const string &val)
02678 {
02679 long pos=0;
02680 string value=val;
02681 if(!param_file_name.empty()){
02682 ifstream param_file(param_file_name.c_str());
02683 pos = find_key(param_file,section_name,key_name,value);
02684 if(pos && value.empty())
02685 value=val;
02686 }
02687
02688 return value;
02689 }
02690
02691
02692
02693 long Application::get_param(const string §ion_name,
02694 const string &key_name,long val)
02695 {
02696 char txt[255]={0};
02697 ostrstream str_val(txt,sizeof(txt));
02698 str_val << val << ends;
02699 string result = get_param(section_name,key_name, str_val.str());
02700 return atol(result.c_str());
02701 ;
02702 }
02703
02704 }