// -----------------------------------------------------------------------------
void DynamicRibbonWidget::buildInternalStructure()
{
    //printf("****DynamicRibbonWidget::buildInternalStructure()****\n");

    // ---- Clean-up what was previously there
    for (unsigned int i=0; i<m_children.size(); i++)
    {
        IGUIElement* elem = m_children[i].m_element;
        if (elem != NULL && m_children[i].m_type == WTYPE_RIBBON)
        {
            elem->remove();
            m_children.erase(i);
            i--;
        }
    }
    m_rows.clearWithoutDeleting(); // rows already deleted above, don't double-delete

    m_left_widget->m_element->setVisible(true);
    assert( m_left_widget->ok() );
    assert( m_right_widget->ok() );

    // ---- determine column amount
    const float row_height = (float)(m_h - m_label_height)/(float)m_row_amount;
    float ratio_zoom = (float)row_height / (float)(m_child_height - m_label_height);
    m_col_amount = (int)roundf( m_w / ( m_child_width*ratio_zoom ) );

    // ajust column amount to not add more item slots than we actually need
    const int item_count = (int) m_items.size();
    //Log::info("DynamicRibbonWidget", "%d items; %d cells", item_count, row_amount * m_col_amount);
    if (m_row_amount*m_col_amount > item_count)
    {
        m_col_amount = (int)ceil((float)item_count/(float)m_row_amount);
        //Log::info("DynamicRibbonWidget", "Adjusting m_col_amount to be %d", m_col_amount);
    }

    assert( m_left_widget->ok() );
    assert( m_right_widget->ok() );

    // Hide arrows when everything is visible
    if (item_count <= m_row_amount*m_col_amount)
    {
        m_scrolling_enabled = false;
        m_left_widget->m_element->setVisible(false);
        m_right_widget->m_element->setVisible(false);
    }
    else
    {
        m_scrolling_enabled = true;
        m_left_widget->m_element->setVisible(true);
        m_right_widget->m_element->setVisible(true);
    }

    // ---- add rows
    int added_item_count = 0;
    for (int n=0; n<m_row_amount; n++)
    {
        RibbonWidget* ribbon;
        if (m_combo)
        {
            ribbon = new RibbonWidget(RIBBON_COMBO);
        }
        else
        {
            ribbon = new RibbonWidget(RIBBON_TOOLBAR);
        }
        ribbon->setListener(this);
        ribbon->m_reserved_id = m_ids[n];

        ribbon->m_x = m_x + (m_scrolling_enabled ? m_arrows_w : 0);
        ribbon->m_y = m_y + (int)(n*row_height);
        ribbon->m_w = m_w - (m_scrolling_enabled ? m_arrows_w*2 : 0);
        ribbon->m_h = (int)(row_height);
        ribbon->m_type = WTYPE_RIBBON;

        std::stringstream name;
        name << this->m_properties[PROP_ID] << "_row" << n;
        ribbon->m_properties[PROP_ID] = name.str();
        ribbon->m_event_handler = this;

        // calculate font size
        if (m_col_amount > 0)
        {
            m_font->setScale(GUIEngine::getFont()->getScale() *
                getFontScale((ribbon->m_w / m_col_amount) - 30));
        }

        // add columns
        for (int i=0; i<m_col_amount; i++)
        {
            // stretch the *texture* within the widget (and the widget has the right aspect ratio)
            // (Yeah, that's complicated, but screenshots are saved compressed horizontally so it's hard to be clean)
            IconButtonWidget* icon = new IconButtonWidget(IconButtonWidget::SCALE_MODE_STRETCH, false, true);
            icon->m_properties[PROP_ICON]="textures/transparence.png";

            // set size to get proper ratio (as most textures are saved scaled down to 256x256)
            icon->m_properties[PROP_WIDTH] = m_properties[PROP_CHILD_WIDTH];
            icon->m_properties[PROP_HEIGHT] = m_properties[PROP_CHILD_HEIGHT];
            icon->m_w = atoi(icon->m_properties[PROP_WIDTH].c_str());
            icon->m_h = atoi(icon->m_properties[PROP_HEIGHT].c_str());
            icon->setLabelFont(m_font);

            // If we want each icon to have its own label, we must make it non-empty, otherwise
            // it will assume there is no label and none will be created (FIXME: that's ugly)
            if (m_properties[PROP_LABELS_LOCATION] == "each") icon->m_text = " ";

            //Log::info("DynamicRibbonWidget", "Ribbon text = %s", m_properties[PROP_TEXT].c_str());

            ribbon->m_children.push_back( icon );
            added_item_count++;

            // stop adding columns when we have enough items
            if (added_item_count == item_count)
            {
                assert(!m_scrolling_enabled); // we can see all items, so scrolling must be off
                break;
            }
            else if (added_item_count > item_count)
            {
                assert(false);
                break;
            }
        }
        m_children.push_back( ribbon );
        m_rows.push_back( ribbon );
        ribbon->add();

        // stop filling rows when we have enough items
        if (added_item_count == item_count)
        {
            assert(!m_scrolling_enabled); // we can see all items, so scrolling must be off
            break;
        }
    }

#ifdef DEBUG
    if (!m_scrolling_enabled)
    {
        // debug checks
        int childrenCount = 0;
        for (unsigned int n=0; n<m_rows.size(); n++)
        {
            childrenCount += m_rows[n].m_children.size();
        }
        assert(childrenCount == (int)m_items.size());
    }
#endif
}