Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsvboxwidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
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     // create widget
00046     MMSVBoxWidget *newWidget = new MMSVBoxWidget(this->rootwindow);
00047 
00048     // copy base widget
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     // through all my children
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             // size of content not set, use sizehint
00082             string sizehint = children.at(i)->getSizeHint();
00083 
00084             if (sizehint == "") {
00085                 // have no sizehint
00086                 (*num_spacers)++;
00087                 *last_spacer = i;
00088             }
00089             else {
00090                 // calculate length based on sizehint
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             // use fixed min size
00099             (*fixed_pix)+= children.at(i)->getMinHeightPix();
00100         }
00101         else {
00102             // use content height
00103             content_height = (int)((float)content_height * dyn_reduce_factor + 0.5);
00104             if (content_height <= children.at(i)->getMinHeightPix()) {
00105                 // use fixed min size
00106                 (*fixed_pix)+= children.at(i)->getMinHeightPix();
00107             }
00108             else {
00109                 // use dynamic height
00110                 (*dyn_pix)+= content_height;
00111                 (*min_dyn_pix)+= children.at(i)->getMinHeightPix();
00112             }
00113         }
00114     }
00115 
00116     // minimal size needed
00117     *required_pix = *fixed_pix + *dyn_pix;
00118 
00119     // remaining pixels
00120     *remain_pix = this->geom.h - *required_pix;
00121 
00122     // available pixels
00123     *avail_pix = this->geom.h - *fixed_pix;
00124 }
00125 
00126 
00127 void MMSVBoxWidget::recalculateChildren() {
00128 
00129     // check something
00130     if(this->children.empty())
00131         return;
00132 
00133     if(this->geomset == false)
00134         return;
00135 
00136     // first pass: check if content fits into box, start with factor 1.0
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         // calculate content size of box
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             // fine, all widgets can be put into this box
00148             break;
00149         }
00150 
00151         // negative remaining pixels, so try to reduce something
00152         if (avail_pix > min_dyn_pix) {
00153             // available pixels for dynamic widget, so calculate reduce factor and recalc content size
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             // there are no free pixels for dynamic widgets, so set reduce factor to zero and recalc content size
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             // fixed content of box does not fit into it
00170             //do not throw exception as this will left surface locks behind
00171             //throw MMSWidgetError(0,"VBOX: cannot calculate geometry (not enough free pixels)");
00172         }
00173     }
00174 
00175 
00176     // second pass: calculate geometry of all children
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             // size of content not set, use sizehint
00184             string sizehint = children.at(i)->getSizeHint();
00185 
00186             if (sizehint == "") {
00187                 // calculate height based on remaining space
00188                 rect.h = safe_len;
00189                 if ((int)i == last_spacer)
00190                     rect.h+= remain_pix % num_spacers;
00191             }
00192             else {
00193                 // calculate height based on sizehint
00194                 getPixelFromSizeHint(&rect.h, sizehint, this->geom.h, this->geom.w);
00195             }
00196         }
00197         else {
00198             // use content height
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         // set geometry of child widget
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         // next position
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     // determine width and height of my content
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             // size of content not set, use sizehint
00231             string sizehint = children.at(i)->getSizeHint();
00232 
00233             if (sizehint == "") {
00234                 // have no sizehint, we assume lowest height of 0
00235                 content_height = 0;
00236             }
00237             else {
00238                 // calculate height based on sizehint
00239                 getPixelFromSizeHint(&content_height, sizehint, this->geom.h, this->geom.w);
00240             }
00241         }
00242         else {
00243             // content size of child set, so we can set lowest width of my content
00244             if (mycw < content_width)
00245                 mycw = content_width;
00246         }
00247 
00248         mych+= content_height;
00249     }
00250 
00251     if (mycw > 0 && mych > 0) {
00252         // width and height of my content set, check min/max ranges
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         // set my size
00261         this->content_width_child = mycw;
00262         this->content_height_child = mych;
00263         this->parent->setContentSizeFromChildren();
00264     }
00265 }
00266 

Generated by doxygen