void CLayoutVertical::computeSize() { // Nombre d'objets enfants const int nbr_children = getNumChildren(); // Dimensions minimales et maximales du layout int min_height = 0; int max_height = 0; int min_width = 0; int max_width = 0; // Hauteur et largeur de chaque widget std::vector<int> widgets_h_min; std::vector<int> widgets_w_min; std::vector<int> widgets_h_max; std::vector<int> widgets_w_max; widgets_h_min.reserve(nbr_children); widgets_w_min.reserve(nbr_children); widgets_h_max.reserve(nbr_children); widgets_w_max.reserve(nbr_children); int totalStretch = 0; // On cherche la taille de chaque objet for (std::list<TLayoutItem>::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { totalStretch += it->stretch; // Dimensions minimales int tmp_w = it->widget->getMinWidth(); widgets_w_min.push_back(tmp_w); int tmp_h = it->widget->getMinHeight(); widgets_h_min.push_back(tmp_h); tmp_w = SumInt(tmp_w, m_padding.getLeft() + m_padding.getRight()); if (tmp_w > min_width) { min_width = tmp_w; } min_height = SumInt(min_height, SumInt(tmp_h, m_padding.getTop() + m_padding.getBottom())); // Dimensions maximales tmp_w = it->widget->getMaxWidth(); widgets_w_max.push_back(tmp_w); tmp_h = it->widget->getMaxHeight(); widgets_h_max.push_back(tmp_h); tmp_w = SumInt(tmp_w, m_padding.getLeft() + m_padding.getRight()); if (tmp_w > max_width) { max_width = tmp_w; } max_height = SumInt(max_height, SumInt(tmp_h, m_padding.getTop() + m_padding.getBottom())); } min_width = SumInt(min_width, m_margin.getLeft() + m_margin.getRight()); max_width = SumInt(max_width, m_margin.getLeft() + m_margin.getRight()); min_height = SumInt(min_height, m_margin.getTop() + m_margin.getBottom()); max_height = SumInt(max_height, m_margin.getTop() + m_margin.getBottom()); setMinSize(min_width, min_height); setMaxSize(max_width, max_height); // Espace à répartir int residu = 0; if (min_height < m_height) { residu = m_height - min_height; } // Dimensions de chaque objet enfant std::vector<int> widgets_w; std::vector<int> widgets_h; widgets_w.reserve(nbr_children); widgets_h.reserve(nbr_children); int growingStretch = totalStretch; int growingChildren = nbr_children; // Calcul des dimensions de chaque objet enfant for (int i = 0; i < nbr_children; ++i) { if (widgets_w_min[i] < widgets_w_max[i]) { if (widgets_w_max[i] < m_width - m_padding.getLeft() - m_padding.getRight()) widgets_w[i] = widgets_w_min[i]; else widgets_w[i] = m_width - m_padding.getLeft() - m_padding.getRight(); } else { widgets_w[i] = widgets_w_min[i]; } widgets_h[i] = widgets_h_min[i]; if (widgets_h[i] >= widgets_h_max[i]) { --growingChildren; } } while (residu > 0) { if (growingStretch == 0) { // Tous les widgets ont leur taille maximale if (growingChildren == 0) { int nbr_first = residu % nbr_children; int add_pixel = residu / nbr_children; residu = 0; int i = 0; // On modifie la taille des cases for (std::list<TLayoutItem>::iterator it = m_children.begin(); it != m_children.end(); ++it, ++i) { it->size = widgets_h[i] + m_padding.getTop() + m_padding.getBottom() + add_pixel; if (i < nbr_first) ++(it->size); } } else { float pixelPerStretch = static_cast<float>(residu) / static_cast<float>(growingChildren); int pixelAdd = pixelPerStretch; if (pixelAdd == 0) { growingChildren = 0; continue; } int i = 0; // Pour chaque objet enfant for (std::list<TLayoutItem>::iterator it = m_children.begin(); it != m_children.end(); ++it, ++i) { // On peut agrandir le widget if (widgets_h[i] < widgets_h_max[i]) { int pixelCanAdd = widgets_h_max[i] - widgets_h[i]; if (pixelCanAdd >= pixelAdd) { widgets_h[i] += pixelAdd; residu -= pixelAdd; if (pixelCanAdd == pixelAdd) { --growingChildren; } } else { widgets_h[i] += pixelCanAdd; residu -= pixelCanAdd; --growingChildren; } it->size = widgets_h[i] + m_padding.getTop() + m_padding.getBottom(); } } } } else { float pixelPerStretch = static_cast<float>(residu) / static_cast<float>(growingStretch); if (pixelPerStretch < 1.0f) { growingStretch = 0; growingChildren = 0; continue; } bool noChange = true; int i = 0; // Pour chaque objet enfant for (std::list<TLayoutItem>::iterator it = m_children.begin(); it != m_children.end(); ++it, ++i) { // On peut agrandir le widget if (widgets_h[i] < widgets_h_max[i]) { int pixelAdd = pixelPerStretch * it->stretch; int pixelCanAdd = widgets_h_max[i] - widgets_h[i]; if (pixelCanAdd >= pixelAdd) { widgets_h[i] += pixelAdd; residu -= pixelAdd; if (pixelCanAdd == pixelAdd) { --growingChildren; growingStretch -= it->stretch; } } else { widgets_h[i] += pixelCanAdd; residu -= pixelCanAdd; --growingChildren; growingStretch -= it->stretch; } it->size = widgets_h[i] + m_padding.getTop() + m_padding.getBottom(); noChange = false; } } // Tous les widgets ont leur taille maximale if (noChange) { i = 0; // Pour chaque objet enfant for (std::list<TLayoutItem>::iterator it = m_children.begin(); it != m_children.end(); ++it, ++i) { int pixelAdd = pixelPerStretch * it->stretch; residu -= pixelAdd; it->size = widgets_h[i] + m_padding.getTop() + m_padding.getBottom() + pixelAdd; } growingStretch = 0; growingChildren = 0; } } } int offset = m_margin.getTop(); int i = 0; // On modifie la liste des objets for (std::list<TLayoutItem>::iterator it = m_children.begin(); it != m_children.end(); ++it, ++i) { // Dimensions de l'objet it->widget->setSize(widgets_w[i], widgets_h[i]); // Position de l'objet switch (it->align) { case AlignTopLeft: it->widget->setPosition(m_margin.getLeft() + m_padding.getLeft(), offset + m_padding.getTop()); break; case AlignTopCenter: it->widget->setPosition((m_width - widgets_w[i]) / 2, offset + m_padding.getTop()); break; case AlignTopRight: it->widget->setPosition(m_width - m_padding.getRight() - widgets_w[i], offset + m_padding.getTop()); break; case AlignMiddleLeft: it->widget->setPosition(m_margin.getLeft() + m_padding.getLeft(), offset + (it->size - widgets_h[i]) / 2); break; default: case AlignMiddleCenter: it->widget->setPosition((m_width - widgets_w[i] ) / 2 , offset + (it->size - widgets_h[i]) / 2); break; case AlignMiddleRight: it->widget->setPosition(m_width - m_padding.getRight() - widgets_w[i], offset + (it->size - widgets_h[i]) / 2); break; case AlignBottomLeft: it->widget->setPosition(m_margin.getLeft() + m_padding.getLeft(), offset + it->size - widgets_h[i] - m_padding.getBottom()); break; case AlignBottomCenter: it->widget->setPosition((m_width - widgets_w[i]) / 2 , offset + it->size - widgets_h[i] - m_padding.getBottom()); break; case AlignBottomRight: it->widget->setPosition(m_width - m_padding.getRight() - widgets_w[i], offset + it->size - widgets_h[i] - m_padding.getBottom()); break; } offset += it->size; } }
int sumOfLevels(TreeNodePtr root){ return SumInt(0,root); }
int SumInt(int level,TreeNodePtr p){ if (p == NULL) return 0; return level + SumInt(level+1,p->leftPtr) + SumInt(level+1,p->rightPtr); }
int SumInt(int level, TreeNodePtr P){ if (P == NULL) return 0; return level + SumInt(level+1,P->left) + SumInt(level+1,P->right); }