diff --git a/src/guiengine/widgets/dynamic_ribbon_widget.cpp b/src/guiengine/widgets/dynamic_ribbon_widget.cpp index 524b04225..d5ccd2b5d 100644 --- a/src/guiengine/widgets/dynamic_ribbon_widget.cpp +++ b/src/guiengine/widgets/dynamic_ribbon_widget.cpp @@ -66,19 +66,26 @@ DynamicRibbonWidget::~DynamicRibbonWidget() /** Function that estimates the area (in squared pixels) that ribbon icons * would take given a number of rows (used to estimate the best number of * rows) + * \param[out] visibleItems number of items that can be displayed in this + * configuration + * \param[out] takenArea how many square pixels are taken by the icons + * \param[out] itemHeight how high each item would be in this configuration */ -int estimateIconAreaFor(const int rowCount, const int wantedIconWidth, - const int width, const int height, - const float iconAspectRatio) +void estimateIconAreaFor(const int rowCount, const int wantedIconWidth, + const int width, const int height, + const float iconAspectRatio, + int* visibleItems, int* takenArea, int* itemHeight) { const int row_height = height / rowCount; float icon_height = (float)row_height; float icon_width = row_height * iconAspectRatio; + *itemHeight = int(icon_height); const int icons_per_row = std::min(int(width / icon_width), int(width / wantedIconWidth)); - return int(icons_per_row * rowCount * icon_width * icon_height); + *visibleItems = icons_per_row * rowCount ; + *takenArea = int(*visibleItems * icon_width * icon_height); } void DynamicRibbonWidget::add() @@ -177,17 +184,36 @@ void DynamicRibbonWidget::add() const float aspect_ratio = (float)m_child_width / (float)m_child_height; // const int count = m_items.size(); - int max_area_so_far = -1; + int max_score_so_far = -1; m_row_amount = -1; for (int row_count = 1; row_count < 10; row_count++) { - const int area = estimateIconAreaFor(row_count, m_child_width, - m_w, m_h - m_label_height, aspect_ratio); - if (area > max_area_so_far) + int visible_items; + int taken_area; + int item_height; + estimateIconAreaFor(row_count, m_child_width, m_w, m_h - m_label_height, + aspect_ratio, &visible_items, &taken_area, &item_height); + + + // FIXME: this system to determine the best number of columns is really complicated! + // the score is computed from taken screen area AND visible item count. + // A number of rows that allows for the screen space to be used a lot will + // get a better score. A number of rows that allows showing very few items + // will be penalized. A configuration that makes items much smaller than + // requested in the XML file will also be penalized. + const int score = int(log(2*visible_items) * + std::min((float)item_height / (float)m_child_height, 1.0f) * + taken_area); + + //std::cout << " " << row_count << " rows : " << visible_items << " visible items; area = " + // << taken_area << "; size penalty = " << std::min((float)item_height / (float)m_child_height, 1.0f) + // << "; score = " << score << "\n"; + + if (score > max_score_so_far) { m_row_amount = row_count; - max_area_so_far = area; + max_score_so_far = score; } } assert(m_row_amount != -1);