#include "diawxgtk.h" static int revlayout; // All /* All FORMBASE are using this function to note something has changed in their layout. So whenever something is added or removed, we can tell something has change, even if it is in a sub-sub-form. */ int formbase_getrevlayout() { return revlayout++; } PRIVATE void FORMBASE::init( FORMBASE *_f_parent, wxWindow *_wx_parent, const char *_id) { revlayout = formbase_getrevlayout(); tbc = (MFORM_C**) malloc (400 * sizeof(MFORM_C*)); maxtbc = 400; id = strdup(_id); nbc = 0; f_parent = _f_parent; wx_parent = _wx_parent; modified = true; stretch_mode = STRETCH_NONE; //setFont(new Font("Helvetica", Font.PLAIN, 14)); pref_width = pref_height = -1; logicaltop = false; fixed.x = rem_getvarval("x"); fixed.y = rem_getvarval("y"); fixed.w = rem_getvarval("w"); fixed.h = rem_getvarval("h"); max_width = 10000; max_height = 10000; doc_height = -1; doc_width = -1; voffset = 0; hoffset = 0; layout_once = false; vscroll = NULL; hscroll = NULL; background.brush = brush_back; background.pen = pen_back; } PUBLIC FORMBASE::FORMBASE( FORMBASE *_f_parent, wxWindow *_wx_parent, const char *_id) { init (_f_parent,_wx_parent,_id); } PUBLIC FORMBASE::FORMBASE(const char *_id) { init (NULL,NULL,_id); } PUBLIC wxFORMBASE::wxFORMBASE(wxFORMBASE *_parent, const char *_id) : wxPanel (_parent), FORMBASE (_parent,_parent,_id) { } PUBLIC wxFORMBASE::wxFORMBASE( FORMBASE *_f_parent, wxWindow *_wx_parent, const char *_id) : wxPanel (_wx_parent,-1,wxDefaultPosition,wxSize(400,100)) ,FORMBASE(_f_parent,_wx_parent,_id) { } PUBLIC wxFORMBASE::wxFORMBASE(const char *_id) :FORMBASE (_id) { } PUBLIC void FORMBASE::delall() { for (int i=0; itype == T_FORM || c->type == T_BOOK){ FORMBASE *f = c->getformbase(); int rev = f->getrevlayout(); if (rev > ret) ret = rev; } } return ret; } /* Perform a Fit in this form and then a Fit in the parent up to the top */ PUBLIC void wxFORMBASE::fit2top() { extern int layout_indent; layout_debug (id,"base fit2top start\n"); layout_indent++; wxWindow *p = GetParent(); while (p != NULL){ p->Fit(); p = p->GetParent(); } layout_indent--; layout_debug (id,"base fit2top end\n"); } /* Delete one sub-form */ PUBLIC VIRTUAL void FORMBASE::delform(wxWindow *fl) { pref_width = pref_height = -1; int pos = 0; for (int i=0; itype == T_FORM && c->c == fl){ revlayout = formbase_getrevlayout(); delete fl; delete c; }else{ tbc[pos] = tbc[i]; pos++; } } nbc = pos; } PUBLIC VIRTUAL FORMBASE::~FORMBASE() { delall(); free (tbc); free (id); delete hscroll; delete vscroll; } // Compute the path of a form, by appending the IDs of the parents void formbase_getabspath(FORMBASE *p, char *path) { if (!p->logicaltop && p->f_parent != NULL){ formbase_getabspath(p->f_parent,path); // Special intermediate form introduced by the toolkit have // an id starting with -. They are not shown here if (p->id[0] != '\0' && p->id[0] != '-'){ strcat (path,"."); strcat (path,p->id); } }else{ strcpy (path,p->id); } } PUBLIC VIRTUAL bool FORMBASE::may_stretch() { return stretch_mode != STRETCH_NONE; } PUBLIC VIRTUAL void FORMBASE::stretch ( int, // new_width int) // new_height { } PUBLIC bool FORMBASE::was_modified() { return modified; } PUBLIC VIRTUAL void FORMBASE::set_modified() { modified = true; if (f_parent != NULL) f_parent->set_modified(); } // Display the current value of each field of the dialog PUBLIC VIRTUAL void FORMBASE::dump() { for (int i=0; itype; if (type == T_FORM || type == T_SHEET || type == T_BOOK || type == T_TREE){ FORMBASE *m = c->getformbase(); m->dump(); }else if (type == T_TEXT){ wxTextCtrl *w = (wxTextCtrl*)c->c; char path[300]; formbase_getabspath(this,path); const char *pt = w->GetValue(); while (*pt != '\0'){ char line[1000]; char *dst = line; while (*pt != '\n' && *pt != '\0' && (unsigned)(dst-line)id,line); if (*pt == '\n') pt++; } }else if (type != T_UNKNOWN && type != T_BUTTON && type != T_BUTTONXPM && type != T_SKIP && type != T_ICON && type != T_NEWLINE && type != T_HLINE && type != T_VLINE && type != T_FILL && type != T_LABEL && type != T_RICHTEXT && type != T_CLIST && type != T_GAUGE && type != T_BUTTONFILL){ const char *val = ""; char tmp[100]; if (type == T_STRING){ val = ((wxText*)c->c)->GetValue(); }else if (type == T_CHECKBOX){ val = ((wxCheckBox*)c->c)->GetValue() ? "1" : "0"; }else if (type == T_SLIDER){ int numval = ((wxSlider*)c->c)->GetValue(); sprintf (tmp,"%d",numval); val = tmp; }else if (type == T_RADIO){ CHECKBOX_RADIO *radio = c->radio; if (radio->state){ sprintf (tmp,"%d",radio->instance); val = tmp; }else{ continue; } }else if (type == T_COMBO){ val = ((COMBO*)c->c)->getText(); }else if (type == T_LIST){ int sel = ((wxListBox*)c->c)->GetSelection(); val = ((wxListBox*)c->c)->GetString(sel); }else{ fprintf (stderr,"code dump %d\n",type); } char path[300]; formbase_getabspath(this,path); fprintf (mform_fout,"dump %s %s %s\n",path,c->id,val); } } } // Set the value of a field from its ID PUBLIC VIRTUAL void FORMBASE::setval( const char *id, const char *vals[], SETVAL_INFO &info) { for (int i=0; itype; if (type == T_FORM || type == T_SHEET || type == T_BOOK){ FORMBASE *m = c->getformbase(); m->setval(id,vals,info); }else if (strcmp(c->id,id)==0){ setvalid (i,c,vals,info); break; } } } PUBLIC VIRTUAL void FORMBASE::setvalid( int i, MFORM_C *c, const char *vals[], SETVAL_INFO &info) { // Do nothing by default } PUBLIC void wxFORMBASE::setvalid( int i, MFORM_C *c, const char *vals[], SETVAL_INFO &info) { int type = c->type; const char *val = vals[0]; if (type == T_CLIST){ CLIST *l = (CLIST*)c->c; l->Set_item (val,vals+1); }else if (type == T_TREE){ wxTREE *l = (wxTREE*)c->c; l->Set_item (val,vals+1); }else if (type == T_TEXT){ info.tarea = (wxTextCtrl*)c->c; if (strcmp(val,"reset")==0){ info.tarea->SetValue(""); } info.initbuf(); }else if (type == T_COMBO){ ((COMBO*)c->c)->setText ((char*)val); }else if (type == T_STRING){ ((wxText*)c->c)->SetValue((char*)val); }else if (type == T_CHECKBOX){ ((wxCheckBox*)c->c)->SetValue(strcmp(val,"1")==0 ? 1 : 0); }else if (type == T_SLIDER){ ((wxSlider*)c->c)->SetValue(atoi(val)); }else if (type == T_GAUGE){ ((wxGauge*)c->c)->SetValue(atoi(val)); }else if (type == T_RADIO){ CHECKBOX_RADIO *radio = c->radio; radio->state = radio->instance == atoi(val); drawitems (i,i+1,false); }else if (type == T_COMBO){ ((COMBO*)c->c)->setText(val); }else if (type == T_LABEL){ c->sets (val); DCNAME *dcn = defs_getvardc (); if (dcn != NULL) c->dcn = dcn; drawitems (i,i+1,true); }else if (type == T_LIST){ wxListBox *l = (wxListBox*)c->c; for (int j=0; jGetCount(); j++){ const char *s = l->GetString(j); if (strcmp(s,val)==0){ l->SetSelection(j); break; } } }else if (type == T_BUTTON){ wxButton *b = (wxButton*)c->c; b->SetLabel ((char*)val); }else if (type == T_BUTTONXPM){ wxBitmapButton *b = (wxBitmapButton*)c->c; wxBitmap *bitmap = icon_xpm_locate(val); if (bitmap != NULL){ b->SetBitmapLabel (*bitmap); b->SetBitmapFocus (*bitmap); b->SetBitmapSelected (*bitmap); } }else{ fprintf (stderr,"setval unknown type %d\n",type); } } PUBLIC wxFrame *FORMBASE::getframe() { return gettop()->getframe(); } /* Return the parent of a form */ PUBLIC wxWindow *FORMBASE::getwxparent() const { return wx_parent; } /* Return the parent of a form */ PUBLIC FORMBASE *FORMBASE::getparent() const { return f_parent; } /* Return the TOP MAINFORM owning this FORM */ PUBLIC MAINFORM *FORMBASE::gettop() { MAINFORM *ret = NULL; if (istop()){ ret = (MAINFORM*)this; }else{ ret = f_parent->gettop(); } return ret; } /* Return true if this form is the top level (is a MAINFORM in fact) */ PUBLIC bool FORMBASE::istop() { return f_parent == NULL; } /* Return the logical TOP FORM owning this FORM */ PUBLIC FORMBASE *FORMBASE::getlogicaltop() { FORMBASE *ret = NULL; if (f_parent == NULL || logicaltop){ ret = this; }else{ ret = f_parent->getlogicaltop(); } return ret; } PUBLIC VIRTUAL void FORMBASE::resizeitems (int, int) { } PUBLIC VIRTUAL void FORMBASE::getweight (int &w, int &h) { w = 0; h = 0; } PUBLIC VIRTUAL bool FORMBASE::doalllayout() { return false; } PUBLIC void FORMBASE::resetlayout() { pref_width = -1; } /* Locate a sub-form or notebook object in a form using its ID Return -1 if not found */ PUBLIC int FORMBASE::locate(const char *id, MFORM *&form, wxBOOK *&book) { int ret = -1; int nb = nbc; form = NULL; book = NULL; for (int i=0; itype; if (type == T_FORM || type == T_BOOK || type == T_CLIST){ FORMBASE *b = c->getformbase(); if (strcmp(b->id,id)==0){ if (type == T_FORM || type == T_CLIST){ form = (MFORM*)b; }else{ book = (wxBOOK*)b; } ret = 0; break; } } } return ret; } PUBLIC MFORM_C *FORMBASE::alloc_mf(const char *_id) { revlayout = formbase_getrevlayout(); set_modified(); MFORM_C *m = new MFORM_C(_id); if (nbc == maxtbc){ maxtbc += 400; tbc = (MFORM_C**)realloc(tbc,maxtbc*sizeof(MFORM_C*)); } tbc[nbc++] = m; return m; } PUBLIC MFORM_C *FORMBASE::alloc_mf() { return alloc_mf(""); } /* Give focus to a specific field of this form. Return -1 if the form did not contain the proper field */ PUBLIC VIRTUAL int FORMBASE::setcurfield ( const char *, wxWindow *[], int &) { return -1; } /* Give focus to a specific field of this form. Return -1 if the form did not contain the proper field */ PUBLIC int MFORM::setcurfield ( const char *id_suffix, wxWindow *tbfocus[], int &nbfocus) { /* #Specification: setcurfield / strategy The setcurfield assume that the ID of field which may accept focus has this form # A single letter following by a suffix. Generally the suffix is the internal field number used by Linuxconf. For a text field (New_string()), this is S20 for example. When remadmin receive a Curfield command, it identify the proper MAINFORM and then lookup the proper ID in the various fields and sub-form. One the field is identify, proper action is done to make it visible if needed. */ int ret = -1; #if 0 fprintf (stderr,"MFORM %s curfield %d :%s:\n",id,nbc,id_suffix); #endif for (int i=0; ic; const char *id = c->id; // fprintf (stderr,"cmp id :%s: %d %p\n",id,c->type,cc); if ((c->type == T_BUTTONFILL || cc != NULL) && c->type != T_BUTTON && c->type != T_BUTTONXPM && id != NULL && id[0] != '\0' && strcmp(id,id_suffix)==0){ #if 0 fprintf (stderr,"%s %s\n",id,id_suffix); #endif if (cc != NULL) tbfocus[nbfocus++] = cc; ret = 0; }else if (c->type == T_FORM || c->type == T_BOOK || c->type == T_CLIST){ FORMBASE *b = c->getformbase(); ret = b->setcurfield (id_suffix,tbfocus,nbfocus); } if (ret == 0){ int ww,wh; GetSize (&ww,&wh); int fx,fy,fw,fh; if (cc != NULL){ cc->GetPosition (&fx,&fy); cc->GetSize (&fw,&fh); }else{ fx = c->x; fy = c->y; fw = c->pref_width; fh = c->pref_height; } if (fy < 0 || fy + fh > wh){ vmoveitems(voffset + fy); } break; } } if (ret == 0) tbfocus[nbfocus++] = this; return ret; } /* Give focus to a specific field of this form. Return -1 if the form did not contain the proper field */ PUBLIC int BOOK::setcurfield ( const char *id_suffix, wxWindow *tbfocus[], int &nbfocus) { int ret = -1; #if 0 extern FILE *ftty; fprintf (ftty,"BOOK %s curfield %d %s\n",id,nbc,id_suffix); fflush (ftty); #endif for (int i=0; ic; #if 0 fprintf (ftty,"book %d m=%p\n",i,m); fflush (ftty); #endif ret = m->setcurfield (id_suffix,tbfocus,nbfocus); #if 0 fprintf (ftty,"book %d m=%p ret=%d\n",i,m,ret); fflush (ftty); #endif if (ret == 0){ selpage (i,NULL); break; } } if (ret == 0) tbfocus[nbfocus++] = this; return ret; } /* We walk recursivly to change the state of all CHECKBOX_RADIO sharing the same id. Only one will be left "on". */ PUBLIC void FORMBASE::processradio (MFORM_C *csel) { for (int i=0; itype == T_FORM || c->type == T_BOOK){ FORMBASE *b = c->getformbase(); b->processradio (csel); }else if (c->type == T_RADIO){ if (strcmp(csel->id,c->id)==0){ bool newstate = csel == c; #if 0 c->c->SetValue (newstate); #else c->radio->state = newstate; // Only a wxFORMBASE (not a wxBOOK) can contain radios wxFORMBASE *f = (wxFORMBASE*)this; f->drawradio_but (c); #endif } } } } /* Draw only the button part of the radio button */ PUBLIC void wxFORMBASE::drawradio_but (MFORM_C *c) { int x= c->x; int y= c->y; bool state = c->radio->state; const int nbpix=5; int x0 = x+1; int x1 = x+1+nbpix; int x2 = x+1+2*nbpix; int y0 = y+4; int y1 = y+4+nbpix; int y2 = y+4+2*nbpix; wxClientDC dc(this); dc.SetPen (state ? *pen_black : *pen_white); dc.DrawLine (x0,y1,x1,y0); dc.DrawLine (x0+1,y1,x1,y0+1); dc.DrawLine (x1,y0,x2,y1); dc.DrawLine (x1,y0+1,x2-1,y1); dc.SetPen (state ? *pen_white : *pen_black); y1++; dc.DrawLine (x0,y1,x1,y2); dc.DrawLine (x0+1,y1,x1,y2-1); dc.DrawLine (x1,y2,x2,y1); dc.DrawLine (x1,y2-1,x2-1,y1); } /* Delete all the childs of this form */ PUBLIC void FORMBASE::delchild() { revlayout = formbase_getrevlayout(); for (int i=0; itype == T_FORM || c->type == T_BOOK){ FORMBASE *b = c->getformbase(); delete b; } delete c; } nbc = 0; } // We override this function because wx won't do anything unless // there is at least some childs widget in the form. We have some // form with "homemade" widget and they do not count PUBLIC void wxFORMBASE::Fit() { if (max_height == 10000 && max_width == 10000){ // Figure out auto-scroll triggers bool autolimit = true; for (int i=0; itype == T_FORM || c->type == T_TEXT || c->type == T_CLIST || c->type == T_SHEET || c->type == T_BOOK){ autolimit = false; break; } } if (autolimit){ max_height = 300; max_width = 600; } } SetClientSize(DoGetBestSize()); }