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