#include "diawxxt.h" class CELLDISP{ public: MFORM_C *item; int used; // Une cellule multi-colonne ou multi-ligne // occupe l'espace, voir USED_XXX int width,height; CELLDISP(){ used = 0; item = NULL; width = height = -1; } }; #define USED_TOP 1 // On est sur la première ligne d'un multi-ligne #define USED_LEFT 2 // On est sur la première colonne d'un multi-colonne #define USED_MULTICOL 4 // Ce champs occupe plusieurs colonnes #define USED_MULTILINE 8 // Ce champs occupe plusieurs lignes // private int preferredWidth,preferredHeight; // private int minWidth = 0, minHeight = 0; // private boolean sizeUnknown = true; // private boolean DEBUG = false; // mform fl; PUBLIC void MFORM::vmoveitems (int newpos) { if (vscroll != NULL){ if (newpos == voffset + 1){ newpos = voffset + 15; }else if (newpos == voffset - 1){ newpos = voffset - 15; } int viewstart,viewlength,objlength,pagelength; vscroll->GetValues(&viewstart, &viewlength, &objlength, &pagelength); if (newpos < 0) newpos = 0; int limit = objlength - viewlength; if (newpos > limit) newpos = limit; int diffy = newpos - voffset; if (diffy != 0){ bool somelabels = false; for (int i=0; ic; if (c != NULL){ int px,py; c->GetPosition(&px,&py); py -= diffy; c->SetSize (px,py,-1,-1,wxSIZE_USE_NEGATIVE); }else if (item->homemade){ somelabels = true; item->y -= diffy; } } voffset = newpos; if (somelabels) Clear(); OnPaint(); } if (vscroll->GetValue() != newpos) vscroll->SetValue (newpos); } } PUBLIC VIRTUAL void MFORM::hmoveitems (int newpos) { int viewstart,viewlength,objlength,pagelength; hscroll->GetValues(&viewstart, &viewlength, &objlength, &pagelength); if (newpos < 0) newpos = 0; int limit = objlength - viewlength; if (newpos > limit) newpos = limit; int curpos = hscroll->GetValue(); int diffx = newpos - hoffset; if (diffx != 0){ bool somelabels = false; for (int i=0; ic; if (c != NULL){ int px,py; c->GetPosition(&px,&py); px -= diffx; c->SetSize (px,py,-1,-1,wxSIZE_USE_NEGATIVE); }else if (item->homemade){ somelabels = true; item->x -= diffx; } } hoffset = newpos; if (somelabels) Clear(); OnPaint(); } if (curpos != newpos) hscroll->SetValue (newpos); } static void vscroll_func (wxObject &o, wxCommandEvent &) { wxScrollBar *b = (wxScrollBar*)&o; int newpos = b->GetValue(); MFORM *p = (MFORM*)b->GetParent(); p->vmoveitems (newpos); } /* Make sure the vertical scroll bar is created */ PUBLIC void FORMBASE::setvscroll() { if (vscroll == NULL){ vscroll = new wxScrollBar (this,vscroll_func,-1,-1,-1,-1 ,wxVERTICAL); voffset = 0; vscroll->SetValue (0); } } static void hscroll_func (wxObject &o, wxCommandEvent &) { wxScrollBar *b = (wxScrollBar*)&o; int newpos = b->GetValue(); MFORM *p = (MFORM*)b->GetParent(); p->hmoveitems (newpos); } /* Make sure the horizontal scroll bar is created */ PUBLIC void FORMBASE::sethscroll() { if (hscroll == NULL){ hscroll = new wxScrollBar (this,hscroll_func,-1,-1,-1,-1 ,wxHORIZONTAL); hoffset = 0; hscroll->SetValue (0); } } PROTECTED void MFORM::FitStrategie_marge( int gauche, int droit, // Right margin int haut, // Top margin int bas, // Bottom margin bool use_cur_size, int maxw, // Maximum width allowed int maxh, // Maximum height allowed bool force) // Extend the dimension to use the maxw and maxh { maxw -= (droit+4+marge_droite); maxh -= (bas+4+marge_bas); // SetClientSize reserves 2 pixels (I think) around //if (f_parent == NULL) fprintf (stderr,"fit start\n"); int nb = nbc; gauche += marge_gauche; droit += marge_droite; haut += marge_haut; bas += marge_bas; dc->SetFont (font_normal); // int has_fill = 0; // Map all the fields in the proper tbcell entry int i; int noline = 0; for (i=0; itype == T_NEWLINE) noline++; } CELLDISP tbcell[noline+1][MAX_COL]; int nocol = 0; noline = 0; for (i=0; itype == T_NEWLINE){ noline++; nocol = 0; }else if (item->type == T_SKIP){ int used = USED_LEFT | USED_TOP; tbcell[noline][nocol].item = item; for (int sk=0; skh_cells; sk++,nocol++){ tbcell[noline][nocol].used = used; used &= ~USED_LEFT; } }else if (item->type == T_FILL){ if (stretch_mode == STRETCH_NONE){ stretch_mode = STRETCH_LOOK; } tbcell[noline][nocol].item = item; tbcell[noline][nocol].used = USED_LEFT | USED_TOP; nocol++; }else{ tbcell[noline][nocol].item = item; int used = USED_LEFT | USED_TOP; if (item->is_hcontrib){ int nbcol = item->h_cells; if (nbcol > 1) used |= USED_MULTICOL; if (item->v_cells > 1) used |= USED_MULTILINE; for (; nbcol>0; nbcol--,nocol++){ int nol = noline; used |= USED_TOP; for (int l=0; lv_cells; l++,nol++){ tbcell[nol][nocol].item = item; tbcell[nol][nocol].used = used; used &= ~USED_TOP; } used &= ~USED_LEFT; } }else{ tbcell[noline][nocol].used = used; nocol++; } } } int lineheight[noline+1]; memset (colwidth,0,sizeof(colwidth)); memset (lineheight,0,sizeof(lineheight)); // Dans un premier temps, on calcule la largeur de chaque // colonne et la hauteur de chaque ligne en ne tenant compte // que des items simple (non multi-ligne ou non-multicolonne) // Pour chaque colonne, on trouve l'item le plus large. // Pour chaque ligne, on trouve l'item le plus haut. wxDC *dc = GetDC(); int charheight = (int)dc->GetCharHeight(); for (i=0; i<=noline; i++){ for (int c=0; citem; if (item != NULL && item->is_hcontrib){ int nbcol = item->h_cells; int nbline = item->v_cells; if (item->c != NULL){ if (use_cur_size){ item->c->GetSize(&ptcell->width,&ptcell->height); }else{ if (item->pref_width == -1){ item->c->GetSize(&item->pref_width ,&item->pref_height); } ptcell->width = item->pref_width; ptcell->height = item->pref_height; } }else if (item->type == T_LABEL || item->type == T_BUTTONFILL){ float w,h; defs_setdc (item->dcn,dc); dc->GetTextExtent (item->s,&w,&h); if (item->pref_width > w) w = item->pref_width; if (item->pref_height > h) h = item->pref_height; ptcell->width = (int)w+6; ptcell->height = (int)h; if (item->type == T_BUTTONFILL){ if (item->options & MFORM_OPTFLAT){ ptcell->height += charheight/2; }else{ ptcell->height += charheight; } }else{ ptcell->height += 6; } item->height = ptcell->height; }else if (item->type == T_ICON){ int w = item->bitmap->GetWidth(); int h = item->bitmap->GetHeight(); item->width = ptcell->width = w; item->height = ptcell->height = h; }else if (item->type == T_RICHTEXT){ int w,h; richtext_extent (item->s,w,h); ptcell->width = w; ptcell->height = h; }else if (item->type == T_RADIO){ float w,h; dc->GetTextExtent (item->s,&w,&h); item->width = ptcell->width = (int)w + 14; item->height = ptcell->height = charheight + 6; } if (nbcol == 1){ if (colwidth[c] < ptcell->width) colwidth[c] = ptcell->width; } if (nbline == 1){ if (lineheight[i] < ptcell->height) lineheight[i] = ptcell->height; } } } } // On recommence le processus, mais ce coup ci, en ne tenant // compte que des items multi-colonnes et multi-ligne. // Ce qui nous interesse, c'est la largeur totale des X colonnes // occupé par l'item vs sa propre largeur. Si sa largeur excede // alors, on augmentera artificiellement la largeur de la dernière // colonne. On pourrait aussi repartir l'excédant entre les colonnes // On fait la même chose pour les multi-lignes for (i=0; i<=noline; i++){ for (int c=0; citem; if (item != NULL && item->is_hcontrib){ int used = ptcell->used; int nbcol = item->h_cells; int nbline = item->v_cells; if (ptcell->width != -1){ if (nbcol > 1 && (used & USED_LEFT) != 0){ int total = 0; for (int x=0; xwidth){ colwidth[c+nbcol-1] += ptcell->width-total; } } if (nbline > 1 && (used & USED_TOP) != 0){ int total = 0; for (int x=0; xheight) lineheight[i+nbline-1] += ptcell->height-total; } } } } } // We ajust the width according to parent specification for (i=0; i colwidth[i]) colwidth[i] = minw; } // On connait maintenant les spécifications de chaque colonnes // et chaque ligne, donc la taille maximum de chaque cellule. // On va repasser au travers du design une fois de plus et // demander à tous les items extensibles de bien vouloirs // s'étirer pour occuper leur cellule complètement. for (i=0; i<=noline; i++){ for (int c=0; cused & (USED_TOP | USED_LEFT)) == (USED_TOP | USED_LEFT)){ MFORM_C *item = ptcell->item; if (item != NULL && (item->type == T_FORM || item->type == T_BOOK)){ FORMBASE *b = (FORMBASE*)item->c; if (b->may_stretch()){ int nbcol = item->h_cells; int nbline = item->v_cells; int cwidth = 0; int cheight = 0; int ci; for (ci=0; ci item->pref_width || cheight > item->pref_height){ b->stretch (cwidth,cheight); } if (stretch_mode == STRETCH_NONE){ stretch_mode = STRETCH_LOOK; } } } } } } // On peut maitenant disposer les items int v_pos = haut; int h_pos = gauche; for (i=0; i<=noline; i++){ h_pos = gauche; const char *disp = dispstr; for (int c=0; citem; if (item != NULL){ int used = ptcell->used; if((used & USED_LEFT) != 0 && (used & USED_TOP) != 0 && ptcell->width != -1){ int nbcol = item->h_cells; int nbline = item->v_cells; char dhori = item->h_align; char dverti = item->v_align; #if 0 if (item->c != NULL){ d = item->c.size(); if (d.width == 0) d = item->c.preferredSize(); } #endif int total_width = 0; for (int x=0; xwidth; }else if (dhori == 'c'){ xpos += (total_width - ptcell->width)/2; } if (dverti == 'b'){ ypos += total_height - ptcell->height; }else if (dverti == 'c'){ ypos += (total_height - ptcell->height)/2; } int ypos_scrolled = ypos - voffset; if (item->homemade){ item->x = xpos; item->y = ypos_scrolled; item->width = total_width; }else if (item->type == T_HLINE){ item->c->SetSize(xpos,ypos_scrolled,total_width,ptcell->height); }else{ item->c->SetSize (xpos,ypos_scrolled,-1,-1); } //if (item->is_vline()) item->setspec(-1,-1,-1,total_height); } } h_pos += colwidth[c]; } v_pos += lineheight[i]; } //stretch_last(h_pos); // fprintf (stderr,"id=:%s: h_pos %d maxw %d v_pos %d maxh %d\n",id,h_pos,maxw,v_pos,maxh); // fprintf (stderr,"layout vpos %d doc_height %d h_pos %d doc_width %d\n",v_pos,doc_height,h_pos,doc_width); if (doc_height > v_pos) v_pos = doc_height; if (doc_width > h_pos) h_pos = doc_width; bool need_vscroll = vscroll != NULL || ((nbc > 5 || doc_height != -1) && v_pos > maxh); if (force && maxh > v_pos) v_pos = maxh; int document_height = v_pos; int document_width = h_pos; int new_height = v_pos > maxh ? maxh : v_pos; if (need_vscroll){ setvscroll(); maxw -= 20; v_pos = new_height; } bool need_hscroll = !istop() && (h_pos > maxw || hscroll != NULL); if (force && maxw > h_pos) h_pos = maxw; int new_width = h_pos > maxw ? maxw : h_pos; if (need_hscroll){ // fprintf (stderr,"need_hscroll %p force %d h_pos %d maxw %d\n",hscroll,force,h_pos,maxw); sethscroll(); hscroll->SetViewLength(new_width); hscroll->SetObjectLength(document_width); hscroll->SetPageLength(200); h_pos = new_width; hscroll->SetSize (0,v_pos-20,new_width,20); new_height -= 20; } if (vscroll != NULL){ // fprintf (stderr,"v set %d %d %d %d\n",h_pos,haut,20,new_height); int v_height = new_height; if (v_height == 0) v_height = 10; vscroll->SetSize (h_pos,haut,20,v_height); h_pos += (int)20; vscroll->SetViewLength(v_height); vscroll->SetObjectLength(document_height); vscroll->SetPageLength(200); } if (fixed.x != -1){ SetSize (fixed.x,fixed.y,-1,-1); } if (fixed.w != -1){ SetClientSize (fixed.w,fixed.h); }else{ SetClientSize (h_pos+droit,v_pos+bas); } modified = false; layout_once = true; } PUBLIC VIRTUAL void MFORM::dolayout(int maxw, int maxh, bool force) { FitStrategie_marge(sidetitle != NULL ? 20 : 0,0,0,0,true,maxw,maxh, force); }