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 #include "mmsgui/mmsvboxwidget.h"
00034 
00035 MMSVBoxWidget::MMSVBoxWidget(MMSWindow *root) : MMSWidget::MMSWidget() {
00036     create(root);
00037 }
00038 
00039 bool MMSVBoxWidget::create(MMSWindow *root) {
00040     this->type = MMSWIDGETTYPE_VBOX;
00041     return MMSWidget::create(root, false, true, false, false, true, true, false);
00042 }
00043 
00044 MMSWidget *MMSVBoxWidget::copyWidget() {
00045     
00046     MMSVBoxWidget *newWidget = new MMSVBoxWidget(this->rootwindow);
00047 
00048     
00049     MMSWidget::copyWidget((MMSWidget*)newWidget);
00050 
00051     return newWidget;
00052 }
00053 
00054 void MMSVBoxWidget::add(MMSWidget *widget) {
00055     widget->setParent(this);
00056     this->children.push_back(widget);
00057     if (this->getRootWindow())
00058         this->getRootWindow()->add(widget);
00059     this->recalculateChildren();
00060 }
00061 
00062 
00063 
00064 void MMSVBoxWidget::calcSize(int *num_spacers, int *last_spacer,
00065                              int *required_pix, int *remain_pix, int *avail_pix, int *fixed_pix, int *dyn_pix, int *min_dyn_pix,
00066                              float dyn_reduce_factor) {
00067     *num_spacers  = 0;
00068     *last_spacer  = -1;
00069     *required_pix = 0;
00070     *remain_pix   = 0;
00071     *avail_pix    = 0;
00072     *fixed_pix    = 0;
00073     *dyn_pix      = 0;
00074     *min_dyn_pix  = 0;
00075 
00076     
00077     for(unsigned int i = 0; i < this->children.size(); i++) {
00078         int content_width;
00079         int content_height;
00080         if (!children.at(i)->getContentSize(&content_width, &content_height)) {
00081             
00082             string sizehint = children.at(i)->getSizeHint();
00083 
00084             if (sizehint == "") {
00085                 
00086                 (*num_spacers)++;
00087                 *last_spacer = i;
00088             }
00089             else {
00090                 
00091                 int len;
00092                 getPixelFromSizeHint(&len, sizehint, this->geom.h, this->geom.w);
00093                 (*fixed_pix)+= len;
00094             }
00095         }
00096         else
00097         if (dyn_reduce_factor < 0.0001) {
00098             
00099             (*fixed_pix)+= children.at(i)->getMinHeightPix();
00100         }
00101         else {
00102             
00103             content_height = (int)((float)content_height * dyn_reduce_factor + 0.5);
00104             if (content_height <= children.at(i)->getMinHeightPix()) {
00105                 
00106                 (*fixed_pix)+= children.at(i)->getMinHeightPix();
00107             }
00108             else {
00109                 
00110                 (*dyn_pix)+= content_height;
00111                 (*min_dyn_pix)+= children.at(i)->getMinHeightPix();
00112             }
00113         }
00114     }
00115 
00116     
00117     *required_pix = *fixed_pix + *dyn_pix;
00118 
00119     
00120     *remain_pix = this->geom.h - *required_pix;
00121 
00122     
00123     *avail_pix = this->geom.h - *fixed_pix;
00124 }
00125 
00126 
00127 void MMSVBoxWidget::recalculateChildren() {
00128 
00129     
00130     if(this->children.empty())
00131         return;
00132 
00133     if(this->geomset == false)
00134         return;
00135 
00136     
00137     int num_spacers, last_spacer;
00138     int required_pix, remain_pix, avail_pix, fixed_pix, dyn_pix, min_dyn_pix;
00139     float dyn_reduce_factor = 1.0f;
00140     while (1) {
00141         
00142         calcSize(&num_spacers, &last_spacer,
00143                  &required_pix, &remain_pix, &avail_pix, &fixed_pix, &dyn_pix, &min_dyn_pix,
00144                  dyn_reduce_factor);
00145 
00146         if (remain_pix >= 0) {
00147             
00148             break;
00149         }
00150 
00151         
00152         if (avail_pix > min_dyn_pix) {
00153             
00154             dyn_reduce_factor = (float)((float)avail_pix) / ((float)dyn_pix / dyn_reduce_factor);
00155             continue;
00156         }
00157         else
00158         if (avail_pix == min_dyn_pix) {
00159             
00160             dyn_reduce_factor = 0.0f;
00161             continue;
00162         }
00163         else {
00164             if (!this->getName().empty())
00165                 printf("VBOX (%s): cannot calculate geometry (not enough free pixels)\n", this->getName().c_str());
00166             else
00167                 printf("VBOX: cannot calculate geometry (not enough free pixels)\n");
00168             return;
00169             
00170             
00171             
00172         }
00173     }
00174 
00175 
00176     
00177     int next_pos = this->geom.y;
00178     int safe_len = (num_spacers) ? remain_pix / num_spacers : 0;
00179     for (unsigned int i = 0; i < this->children.size(); i++) {
00180         MMSFBRectangle rect;
00181         int content_width, content_height;
00182         if (!children.at(i)->getContentSize(&content_width, &content_height)) {
00183             
00184             string sizehint = children.at(i)->getSizeHint();
00185 
00186             if (sizehint == "") {
00187                 
00188                 rect.h = safe_len;
00189                 if ((int)i == last_spacer)
00190                     rect.h+= remain_pix % num_spacers;
00191             }
00192             else {
00193                 
00194                 getPixelFromSizeHint(&rect.h, sizehint, this->geom.h, this->geom.w);
00195             }
00196         }
00197         else {
00198             
00199             rect.h = (int)((float)content_height * dyn_reduce_factor + 0.5);
00200             if (rect.h < children.at(i)->getMinHeightPix())
00201                 rect.h = children.at(i)->getMinHeightPix();
00202         }
00203 
00204         
00205         rect.y = next_pos;
00206         rect.x = this->geom.x;
00207         rect.w = this->geom.w;
00208         this->children.at(i)->setGeometry(rect);
00209 
00210         
00211         next_pos+= rect.h;
00212     }
00213 }
00214 
00215 void MMSVBoxWidget::setContentSizeFromChildren() {
00216     if (!this->minmax_set) {
00217         return;
00218     }
00219 
00220     if (!this->parent)
00221         return;
00222 
00223     
00224     int mycw = getMinWidthPix();
00225     int mych = 0;
00226     for (unsigned int i = 0; i < this->children.size(); i++) {
00227         int content_width, content_height;
00228 
00229         if (!children.at(i)->getContentSize(&content_width, &content_height)) {
00230             
00231             string sizehint = children.at(i)->getSizeHint();
00232 
00233             if (sizehint == "") {
00234                 
00235                 content_height = 0;
00236             }
00237             else {
00238                 
00239                 getPixelFromSizeHint(&content_height, sizehint, this->geom.h, this->geom.w);
00240             }
00241         }
00242         else {
00243             
00244             if (mycw < content_width)
00245                 mycw = content_width;
00246         }
00247 
00248         mych+= content_height;
00249     }
00250 
00251     if (mycw > 0 && mych > 0) {
00252         
00253         if (mych < getMinHeightPix())
00254             mych = getMinHeightPix();
00255         if (getMaxWidthPix() > 0 && mycw > getMaxWidthPix())
00256             mycw = getMaxWidthPix();
00257         if (getMaxHeightPix() > 0 && mych > getMaxHeightPix())
00258             mych = getMaxHeightPix();
00259 
00260         
00261         this->content_width_child = mycw;
00262         this->content_height_child = mych;
00263         this->parent->setContentSizeFromChildren();
00264     }
00265 }
00266