Back to index

plt-scheme  4.2.1
Layout.cc
Go to the documentation of this file.
00001 /*                                                      -*- C++ -*-
00002  *
00003  * Purpose: layout classes
00004  *
00005  * Authors: Markus Holzem and Julian Smart
00006  *
00007  * Copyright: (C) 2004-2009 PLT Scheme Inc.
00008  * Copyright: (C) 1995, AIAI, University of Edinburgh (Julian)
00009  * Copyright: (C) 1995, GNU (Markus)
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00027 #ifdef __GNUG__
00028 #pragma implementation "Layout.h"
00029 #endif
00030 
00031 #define  Uses_wxLayout
00032 #define  Uses_wxWindow
00033 #define  Uses_wxPanel
00034 #define  Uses_wxFrame
00035 #define  Uses_wxTypeTree
00036 #include "wx.h"
00037 
00038 //-----------------------------------------------------------------------------
00039 // wxLayoutConstraint
00040 //-----------------------------------------------------------------------------
00041 
00042 wxLayoutConstraints::wxLayoutConstraints(void)
00043 : wxObject(FALSE)
00044 {
00045     __type = wxTYPE_CONSTRAINTS;
00046 
00047 #ifdef MZ_PRECISE_GC
00048     left = new wxIndividualLayoutConstraint;
00049     top = new wxIndividualLayoutConstraint;
00050     right = new wxIndividualLayoutConstraint;
00051     bottom = new wxIndividualLayoutConstraint;
00052     centreX = new wxIndividualLayoutConstraint;
00053     centreY = new wxIndividualLayoutConstraint;
00054     width = new wxIndividualLayoutConstraint;
00055     height = new wxIndividualLayoutConstraint;
00056 #endif
00057 
00058     wxLC_MEM(left, myEdge)    = wxLeft;
00059     wxLC_MEM(top, myEdge)     = wxTop;
00060     wxLC_MEM(right, myEdge)   = wxRight;
00061     wxLC_MEM(bottom, myEdge)  = wxBottom;
00062     wxLC_MEM(centreX, myEdge) = wxCentreX;
00063     wxLC_MEM(centreY, myEdge) = wxCentreY;
00064     wxLC_MEM(width, myEdge)   = wxWidth;
00065     wxLC_MEM(height, myEdge)  = wxHeight;
00066 }
00067 
00068 Bool wxLayoutConstraints::SatisfyConstraints(wxWindow *child)
00069 {
00070     Bool changes = FALSE;
00071 
00072     if (!wxLC_MEM(width, done))
00073        changes |= wxLC_MEM(width, SatisfyConstraint(this, child));
00074     if (!wxLC_MEM(height, done))
00075        changes |= wxLC_MEM(height, SatisfyConstraint(this, child));
00076     if (!wxLC_MEM(left, done))
00077        changes |= wxLC_MEM(left, SatisfyConstraint(this, child));
00078     if (!wxLC_MEM(top, done))
00079        changes |= wxLC_MEM(top, SatisfyConstraint(this, child));
00080     if (!wxLC_MEM(right, done))
00081        changes |= wxLC_MEM(right, SatisfyConstraint(this, child));
00082     if (!wxLC_MEM(bottom, done))
00083        changes |= wxLC_MEM(bottom, SatisfyConstraint(this, child));
00084     if (!wxLC_MEM(centreX, done))
00085        changes |= wxLC_MEM(centreX, SatisfyConstraint(this, child));
00086     if (!wxLC_MEM(centreY, done))
00087        changes |= wxLC_MEM(centreY, SatisfyConstraint(this, child));
00088 
00089     return changes;
00090 }
00091 
00092 void wxLayoutConstraints::UnDone(void)
00093 {
00094     wxLC_MEM(left, done)    = FALSE;
00095     wxLC_MEM(top, done)     = FALSE;
00096     wxLC_MEM(right, done)   = FALSE;
00097     wxLC_MEM(bottom, done)  = FALSE;
00098     wxLC_MEM(centreX, done) = FALSE;
00099     wxLC_MEM(centreY, done) = FALSE;
00100     wxLC_MEM(width, done)   = FALSE;
00101     wxLC_MEM(height, done)  = FALSE;
00102 }
00103 
00104 //-----------------------------------------------------------------------------
00105 // wxIndividualLayoutConstraint
00106 //-----------------------------------------------------------------------------
00107 
00108 wxIndividualLayoutConstraint::wxIndividualLayoutConstraint(void)
00109   : wxObject(FALSE)
00110 {
00111     otherWinSR        = NULL;
00112     otherEdge  = wxTop;
00113     myEdge     = wxTop;
00114     relationship = wxUnconstrained;
00115     margin = value = percent = 0;
00116     done       = FALSE;
00117 }
00118 
00119 void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindow **otherW,
00120                                    wxEdge otherE, int val, int marg)
00121 {
00122     relationship = rel;
00123     otherWinSR   = otherW;
00124     otherEdge    = otherE;
00125     value        = val;
00126     margin       = marg;
00127 }
00128 
00129 void wxIndividualLayoutConstraint::PercentOf(wxWindow **otherW, wxEdge wh, int per)
00130 {
00131     otherWinSR = otherW;
00132     relationship = wxPercentOf;
00133     percent = per;
00134     otherEdge = wh;
00135 }
00136 
00137 //-----------------------------------------------------------------------------
00138 // wxIndividualLayoutConstraint: Try to satisfy constraint
00139 //-----------------------------------------------------------------------------
00140 
00141 Bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints,
00142                                                wxWindow *win)
00143 {
00144     int edge_pos;
00145     wxWindow *otherWin;
00146 
00147     if (relationship == wxAbsolute || done == TRUE) {
00148        return (done = TRUE);
00149     }
00150 
00151     otherWin = (otherWinSR ? (wxWindow *)GET_SAFEREF(otherWinSR) : NULL);
00152 
00153     edge_pos = (win && otherWin) ? GetEdge(otherEdge, win, otherWin) : -1;
00154     switch (myEdge) {
00155     case wxLeft:
00156        switch (relationship) {
00157         case wxLeftOf:
00158            if (edge_pos != -1) { // otherWin has satisfying edge
00159               value = edge_pos - margin;
00160               done = TRUE;
00161            }
00162            break;
00163         case wxRightOf:
00164            if (edge_pos != -1) { // otherWin has satisfying edge
00165               value = edge_pos + margin;
00166               done = TRUE;
00167            }
00168            break;
00169         case wxPercentOf:
00170            if (edge_pos != -1) { // otherWin has satisfying edge
00171               value = (int)(edge_pos*(((float)percent)*0.01) + margin);
00172               done = TRUE;
00173            }
00174            break;
00175        case wxUnconstrained:
00176            if (wxLC_MEM(constraints->right, done) && wxLC_MEM(constraints->width, done)) {
00177               // compute using right edge and width
00178               value = wxLC_MEM(constraints->right, value) - wxLC_MEM(constraints->width, value) + margin;
00179               done = TRUE;
00180            } else if (wxLC_MEM(constraints->centreX, done) && wxLC_MEM(constraints->width, done)) {
00181               // compute using centreX and width
00182               value = (int)(wxLC_MEM(constraints->centreX, value) - (wxLC_MEM(constraints->width, value)/2)
00183                            + margin);
00184               done = TRUE;
00185            }
00186            break;
00187        default:
00188          break;
00189        }
00190        break; // goto bottom and return FALSE
00191     case wxRight:
00192        switch (relationship) {
00193         case wxLeftOf:
00194            if (edge_pos != -1) { // otherWin has satisfying edge
00195               value = edge_pos - margin;
00196               done = TRUE;
00197            }
00198            break;
00199         case wxRightOf:
00200            if (edge_pos != -1) { // otherWin has satisfying edge
00201               value = edge_pos + margin;
00202               done = TRUE;
00203            }
00204            break;
00205         case wxPercentOf:
00206            if (edge_pos != -1) { // otherWin has satisfying edge
00207               value = (int)(edge_pos*(((float)percent)*0.01) - margin);
00208               done = TRUE;
00209            }
00210            break;
00211        case wxUnconstrained:
00212            if (wxLC_MEM(constraints->left, done) && wxLC_MEM(constraints->width, done)) {
00213               // compute using left edge and width
00214               value = wxLC_MEM(constraints->left, value) + wxLC_MEM(constraints->width, value) - margin;
00215               done = TRUE;
00216            } else if (wxLC_MEM(constraints->centreX, done) && wxLC_MEM(constraints->width, done)) {
00217               // compute using centreX and width
00218               value = (int)(wxLC_MEM(constraints->centreX, value) + (wxLC_MEM(constraints->width, value)/2)
00219                            - margin);
00220               done = TRUE;
00221            }
00222            break;
00223        default:
00224          break;
00225        }
00226        break; // goto bottom and return FALSE
00227     case wxTop:
00228        switch (relationship) {
00229         case wxAbove:
00230            if (edge_pos != -1) { // otherWin has satisfying edge
00231               value = edge_pos - margin;
00232               done = TRUE;
00233            }
00234            break;
00235         case wxBelow:
00236            if (edge_pos != -1) { // otherWin has satisfying edge
00237               value = edge_pos + margin;
00238               done = TRUE;
00239            }
00240            break;
00241         case wxPercentOf:
00242            if (edge_pos != -1) { // otherWin has satisfying edge
00243               value = (int)(edge_pos*(((float)percent)*0.01) + margin);
00244               done = TRUE;
00245            }
00246            break;
00247        case wxUnconstrained:
00248            if (wxLC_MEM(constraints->bottom, done) && wxLC_MEM(constraints->height, done)) {
00249               // compute using bottom edge and height
00250               value = wxLC_MEM(constraints->bottom, value) - wxLC_MEM(constraints->height, value) + margin;
00251               done = TRUE;
00252            } else if (wxLC_MEM(constraints->centreY, done) && wxLC_MEM(constraints->height, done)) {
00253               // compute using centreY and height
00254               value = (int)(wxLC_MEM(constraints->centreY, value) - (wxLC_MEM(constraints->height, value)/2)
00255                            + margin);
00256               done = TRUE;
00257            }
00258            break;
00259        default:
00260          break;
00261        }
00262        break; // goto bottom and return FALSE
00263     case wxBottom:
00264        switch (relationship) {
00265         case wxAbove:
00266            if (edge_pos != -1) { // otherWin has satisfying edge
00267               value = edge_pos - margin;
00268               done = TRUE;
00269            }
00270            break;
00271         case wxBelow:
00272            if (edge_pos != -1) { // otherWin has satisfying edge
00273               value = edge_pos + margin;
00274               done = TRUE;
00275            }
00276            break;
00277         case wxPercentOf:
00278            if (edge_pos != -1) { // otherWin has satisfying edge
00279               value = (int)(edge_pos*(((float)percent)*0.01) - margin);
00280               done = TRUE;
00281            }
00282            break;
00283        case wxUnconstrained:
00284            if (wxLC_MEM(constraints->top, done) && wxLC_MEM(constraints->height, done)) {
00285               // compute using top edge and height
00286               value = wxLC_MEM(constraints->top, value) + wxLC_MEM(constraints->height, value) - margin;
00287               done = TRUE;
00288            } else if (wxLC_MEM(constraints->centreY, done) && wxLC_MEM(constraints->height, done)) {
00289               // compute using centreY and height
00290               value = (int)(wxLC_MEM(constraints->centreY, value) + (wxLC_MEM(constraints->height, value)/2)
00291                            - margin);
00292               done = TRUE;
00293            }
00294            break;
00295        default:
00296          break;
00297        }
00298        break; // goto bottom and return FALSE
00299     case wxCentreX:
00300        switch (relationship) {
00301         case wxLeftOf:
00302            if (edge_pos != -1) { // otherWin has satisfying edge
00303               value = edge_pos - margin;
00304               done = TRUE;
00305            }
00306            break;
00307         case wxRightOf:
00308            if (edge_pos != -1) { // otherWin has satisfying edge
00309               value = edge_pos + margin;
00310               done = TRUE;
00311            }
00312            break;
00313         case wxPercentOf:
00314            if (edge_pos != -1) { // otherWin has satisfying edge
00315               value = (int)(edge_pos*(((float)percent)*0.01) + margin);
00316               done = TRUE;
00317            }
00318            break;
00319        case wxUnconstrained:
00320            if (wxLC_MEM(constraints->left, done) && wxLC_MEM(constraints->width, done)) {
00321               // compute using left edge and width
00322               value = (int)(wxLC_MEM(constraints->left, value) + (wxLC_MEM(constraints->width, value)/2)
00323                            + margin);
00324               done = TRUE;
00325            } else if (wxLC_MEM(constraints->right, done) && wxLC_MEM(constraints->width, done)) {
00326               // compute using right edge and width
00327               value = (int)(wxLC_MEM(constraints->right, value) - (wxLC_MEM(constraints->width, value)/2)
00328                            + margin);
00329               done = TRUE;
00330            } else if (wxLC_MEM(constraints->left, done) && wxLC_MEM(constraints->right, done)) {
00331               // compute using left and right edge
00332               value = (int)(wxLC_MEM(constraints->left, value) 
00333                            + (wxLC_MEM(constraints->right, value)-wxLC_MEM(constraints->left, value))/2
00334                          + margin);
00335               done = TRUE;
00336            }
00337            break;
00338        default:
00339          break;
00340        }
00341        break; // goto bottom and return FALSE
00342     case wxCentreY:
00343        switch (relationship) {
00344         case wxAbove:
00345            if (edge_pos != -1) { // otherWin has satisfying edge
00346               value = edge_pos - margin;
00347               done = TRUE;
00348            }
00349            break;
00350         case wxBelow:
00351            if (edge_pos != -1) { // otherWin has satisfying edge
00352               value = edge_pos + margin;
00353               done = TRUE;
00354            }
00355            break;
00356         case wxPercentOf:
00357            if (edge_pos != -1) { // otherWin has satisfying edge
00358               value = (int)(edge_pos*(((float)percent)*0.01) + margin);
00359               done = TRUE;
00360            }
00361            break;
00362        case wxUnconstrained:
00363            if (wxLC_MEM(constraints->top, done) && wxLC_MEM(constraints->height, done)) {
00364               // compute using top edge and height
00365               value = (int)(wxLC_MEM(constraints->top, value) + (wxLC_MEM(constraints->height, value)/2)
00366                            + margin);
00367               done = TRUE;
00368            } else if (wxLC_MEM(constraints->bottom, done) && wxLC_MEM(constraints->height, done)) {
00369               // compute using bottom edge and height
00370               value = (int)(wxLC_MEM(constraints->bottom, value) - (wxLC_MEM(constraints->height, value)/2)
00371                            + margin);
00372               done = TRUE;
00373            } else if (wxLC_MEM(constraints->top, done) && wxLC_MEM(constraints->bottom, done)) {
00374               // compute using top and bottom edge
00375               value = (int)(wxLC_MEM(constraints->top, value) 
00376                            + (wxLC_MEM(constraints->bottom, value)-wxLC_MEM(constraints->top, value))/2
00377                            + margin);
00378               done = TRUE;
00379            }
00380            break;
00381        default:
00382          break;
00383        }
00384        break; // goto bottom and return FALSE
00385     case wxWidth:
00386        switch (relationship) {
00387         case wxPercentOf:
00388            if (edge_pos != -1) { // otherWin has satisfying edge
00389               value = (int)(edge_pos*(((float)percent)*0.01));
00390               done = TRUE;
00391            }
00392            break;
00393         case wxAsIs:
00394            if (win) {
00395               int h;
00396               win->GetSize(&value, &h);
00397               done = TRUE;
00398            }
00399            break;
00400        case wxUnconstrained:
00401            if (wxLC_MEM(constraints->left, done) && wxLC_MEM(constraints->right, done)) {
00402               // compute using left and right edge
00403               value = wxLC_MEM(constraints->right, value) - wxLC_MEM(constraints->left, value);
00404               done = TRUE;
00405            } else if (wxLC_MEM(constraints->left, done) && wxLC_MEM(constraints->centreX, done)) {
00406               // compute using left edge and centreX
00407               value = (wxLC_MEM(constraints->centreX, value) - wxLC_MEM(constraints->left, value)) * 2;
00408               done = TRUE;
00409            } else if (wxLC_MEM(constraints->right, done) && wxLC_MEM(constraints->centreX, done)) {
00410               // compute using right edge and centreX
00411               value = (wxLC_MEM(constraints->right, value) - wxLC_MEM(constraints->centreX, value)) * 2;
00412               done = TRUE;
00413            }
00414            break;
00415        default:
00416          break;
00417        }
00418        break; // goto bottom and return FALSE
00419     case wxHeight:
00420        switch (relationship) {
00421         case wxPercentOf:
00422            if (edge_pos != -1) { // otherWin has satisfying edge
00423               value = (int)(edge_pos*(((float)percent)*0.01));
00424               done = TRUE;
00425            }
00426            break;
00427         case wxAsIs:
00428            if (win) {
00429               int w;
00430               win->GetSize(&w, &value);
00431               done = TRUE;
00432            }
00433        case wxUnconstrained:
00434            if (wxLC_MEM(constraints->top, done) && wxLC_MEM(constraints->bottom, done)) {
00435               // compute using top and bottom edge
00436               value = wxLC_MEM(constraints->bottom, value) - wxLC_MEM(constraints->top, value);
00437               done = TRUE;
00438            } else if (wxLC_MEM(constraints->top, done) && wxLC_MEM(constraints->centreY, done)) {
00439               // compute using top edge and centreY
00440               value = (wxLC_MEM(constraints->centreY, value) - wxLC_MEM(constraints->top, value)) * 2;
00441               done = TRUE;
00442            } else if (wxLC_MEM(constraints->bottom, done) && wxLC_MEM(constraints->centreY, done)) {
00443               // compute using right edge and centreX
00444               value = (wxLC_MEM(constraints->bottom, value) - wxLC_MEM(constraints->centreY, value)) * 2;
00445               done = TRUE;
00446            }
00447            break;
00448        default:
00449          break;
00450        }
00451        break; // goto bottom and return FALSE
00452     }
00453     return done;
00454 }
00455 
00456 //-----------------------------------------------------------------------------
00457 // wxIndividualLayoutConstraint: get edge of other if obtainable
00458 //-----------------------------------------------------------------------------
00459 
00460 int wxIndividualLayoutConstraint::GetEdge(wxEdge which, wxWindow *thisWin,
00461                                      wxWindow *other)
00462 {
00463     if (!other)
00464        return -1;
00465     if ((wxWindow*)thisWin->GetParent() == other) { // dimension is obtainable immediately
00466        // Compute size of client area of parent
00467        int w, h; other->GetClientSize(&w, &h);
00468        switch (which) {
00469        case wxLeft: case wxTop:        return 0;
00470        case wxRight: case wxWidth:     return w;
00471        case wxBottom: case wxHeight:          return h;
00472        case wxCentreX:                        return (w/2);
00473        case wxCentreY:                        return (h/2);
00474        }
00475     } else {
00476        wxLayoutConstraints *constr;
00477        wxIndividualLayoutConstraint *iconstr = NULL;
00478        constr = other->GetConstraints();
00479        switch (which) {
00480        case wxLeft:      iconstr = wxLC_ADDR(constr->left); break;
00481        case wxTop:       iconstr = wxLC_ADDR(constr->top); break;
00482        case wxRight:     iconstr = wxLC_ADDR(constr->right); break;
00483        case wxBottom:           iconstr = wxLC_ADDR(constr->bottom); break;
00484        case wxWidth:     iconstr = wxLC_ADDR(constr->width); break;
00485        case wxHeight:           iconstr = wxLC_ADDR(constr->height); break;
00486        case wxCentreX:          iconstr = wxLC_ADDR(constr->centreX); break;
00487        case wxCentreY:          iconstr = wxLC_ADDR(constr->centreY); break;
00488        }
00489        if (iconstr->done)
00490            return (iconstr->value);
00491     }
00492     return -1;
00493 }
00494 
00495 //-----------------------------------------------------------------------------
00496 // do layout
00497 //-----------------------------------------------------------------------------
00498 
00499 void wxWindow::Layout(void)
00500 {
00501     /*
00502      * Main constrained layout algorithm. Look at all the child
00503      * windows, and their constraints (if any).
00504      * The idea is to keep iterating through the constraints
00505      * until all left, right, bottom and top edges, and widths and heights,
00506      * are known (or no change occurs and we've failed to resolve all
00507      * constraints).
00508      *
00509      * If the user has not specified a dimension or edge, it will be
00510      * be calculated from the other known values. E.g. If we know
00511      * the right hand edge and the left hand edge, we now know the width.
00512      * The snag here is that this means we must specify absolute dimensions
00513      * twice (in constructor and in constraint), if we wish to use the
00514      * constraint notation to just set the position, for example.
00515      * Otherwise, if we only set ONE edge and no dimension, it would never
00516      * find the other edge.
00517      *
00518      * Algorithm:
00519      *
00520      *    Mark all constraints as not done.
00521      *
00522      *    iterations = 0;
00523      *    until (no change) or (iterations >= max iterations)
00524      *    {
00525      *        For each child:
00526      *        {
00527      *            Calculate all constraints
00528      *        }
00529      *        ++iterations;
00530      *    }
00531      *
00532      *    For each child:
00533      *        Set each calculated position and size
00534      *
00535      */
00536 
00537     wxChildNode *node;
00538     wxWindow *child;
00539     wxLayoutConstraints *constr;
00540 
00541     // Layout only if children
00542     if (children->Number() == 0)
00543        return;
00544 #ifdef MZ_PRECISE_GC
00545     if (__type == wxTYPE_MENU_BAR)
00546       return;
00547 #endif
00548 
00549     // reset all constraints to NOT done
00550     for (node = children->First(); node; node = node->Next()) {
00551        child  = (wxWindow *)node->Data();
00552        if (wxSubType(child->__type, wxTYPE_FRAME))
00553            continue;
00554        constr = child->GetConstraints();
00555        constr->UnDone();
00556     }
00557     // iterate through child until (no changes) || (no left iterations)
00558     {
00559       int  left_iterations = wxLAYOUT_MAX_ITERATIONS;
00560       Bool changes;
00561       do {
00562        changes = FALSE;
00563        for (node = children->First(); node; node = node->Next()) {
00564          child  = (wxWindow *)node->Data();
00565          if (wxSubType(child->__type, wxTYPE_FRAME))
00566            continue;
00567          constr = child->GetConstraints();
00568          changes |= constr->SatisfyConstraints(child);
00569        }
00570       } while (changes && --left_iterations);
00571     }
00572     // set sizes and positions as computed above
00573     for (node = children->First(); node; node = node->Next()) {
00574        child  = (wxWindow *)node->Data();
00575        if (wxSubType(child->__type, wxTYPE_FRAME))
00576            continue;
00577        constr = child->GetConstraints();
00578        if (wxLC_MEM(constr->left, done) && wxLC_MEM(constr->right, done)
00579            && wxLC_MEM(constr->width, done) && wxLC_MEM(constr->height, done)) {
00580            // Configure calls OnSize()
00581            child->Configure(wxLC_MEM(constr->left, value),  wxLC_MEM(constr->top, value),
00582                           wxLC_MEM(constr->width, value), wxLC_MEM(constr->height, value),
00583                           wxPOS_USE_MINUS_ONE);
00584            // layout child
00585            child->Layout();
00586        }
00587     }
00588 }
00589 
00590 void wxPanel::Layout(void)
00591 {
00592   /* We can stop layout at this level, because constraints are only
00593      used for a frame's menu-bar and status-line children. */
00594   // wxWindow::Layout();
00595 }
00596 
00597 void wxFrame::Layout(void)
00598 {
00599     wxWindow *one_child   = NULL;
00600     int      num_children = 0;
00601     wxWindow *child;
00602     wxChildNode *node;
00603 
00604     // check if frame has only ONE child
00605     if (children) {
00606       for (node = children->First(); node; node = node->Next()) {
00607        child = (wxWindow*)(node->Data());
00608        if ( child && !wxSubType(child->__type, wxTYPE_FRAME) ) {
00609          // skip menubar and status line for computation
00610          int i;
00611          for (i = 0; i < num_status; i++) {
00612            if (child == (wxWindow*)status[i])
00613              break;
00614          }
00615          if (child == (wxWindow*)menubar || i < num_status) {
00616            continue;
00617          }
00618          one_child = child; ++num_children;
00619        }
00620       }
00621     }
00622 
00623     // ONE child shall fit into frame
00624     if (num_children == 1) {
00625       int ww, hh;
00626       GetClientSize(&ww, &hh);
00627       one_child->SetSize(/* PANEL_HMARGIN */ 0, /* PANEL_VMARGIN */ 0,
00628                       ww /* -2*PANEL_HMARGIN */, hh /*-2*PANEL_VMARGIN */);
00629     }
00630 
00631     // layout window (necessary for ONE child too because of menubar and status)
00632     wxWindow::Layout();
00633 }