tdf#134270 rearrange so we know the final treeview width

so we can unconditionally use the treeview width as the optimized
pre-calculated row width hint and then fix up the gen fixed column
settings to take account of the auto CHK_BTN mode

Change-Id: I2e1eaf4b1121d5e705eb7db3464f123c038db246
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97532
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 242750c..123cc18 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -167,7 +167,7 @@
    MenuItemData aItem;
    aItem.mbEnabled = bEnabled;
    vcl::Window *pContainer = mxFrame->GetWindow(GetWindowType::FirstChild);
    aItem.mxSubMenuWin.reset(VclPtr<ScCheckListMenuWindow>::Create(pContainer, mpDoc, false, -1, mxFrame->GetMenuStackLevel()+1, mxFrame.get()));
    aItem.mxSubMenuWin.reset(VclPtr<ScCheckListMenuWindow>::Create(pContainer, mpDoc, false, -1, mxFrame.get()));
    maMenuItems.emplace_back(std::move(aItem));

    mxMenu->append_text(rText);
@@ -443,25 +443,60 @@
    , maOpenTimer(this)
    , maCloseTimer(this)
{
    if (nWidth != -1)
    bool bIsSubMenu = pParent->GetParentMenu();

    int nChecksHeight = mxChecks->get_height_rows(9);
    if (!bIsSubMenu && nWidth != -1)
    {
        mnCheckWidthReq = nWidth - mxFrame->get_border_width() * 2 - 4;
        mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight);
    }

    // sort ok/cancel into native order, if this was a dialog they would be auto-sorted, but this
    // popup isn't a true dialog
    mxButtonBox->sort_native_button_order();

    mxChecks->enable_toggle_buttons(weld::ColumnToggleType::Check);
    if (!bIsSubMenu)
    {
        mxChecks->enable_toggle_buttons(weld::ColumnToggleType::Check);

        mxBox->show();
        mxEdSearch->show();
        mxButtonBox->show();
    }

    mxContainer->connect_focus_in(LINK(this, ScCheckListMenuControl, FocusHdl));
    mxMenu->connect_row_activated(LINK(this, ScCheckListMenuControl, RowActivatedHdl));
    mxMenu->connect_changed(LINK(this, ScCheckListMenuControl, SelectHdl));
    mxMenu->connect_key_press(LINK(this, ScCheckListMenuControl, MenuKeyInputHdl));

    if (!bIsSubMenu)
    {
        mxBtnOk->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
        mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
        mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl));
        mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl));
        mxChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl));
        mxChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl));
        mxChkToggleAll->connect_toggled(LINK(this, ScCheckListMenuControl, TriStateHdl));
        mxBtnSelectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
        mxBtnUnselectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
    }

    if (mbCanHaveSubMenu)
    {
        CreateDropDown();
        mxMenu->connect_size_allocate(LINK(this, ScCheckListMenuControl, TreeSizeAllocHdl));
    }

    if (!bIsSubMenu)
    {
        // determine what width the checklist will end up with
        mnCheckWidthReq = mxContainer->get_preferred_size().Width();
        // make that size fixed now, we can now use mnCheckWidthReq to speed up
        // bulk_insert_for_each
        mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight);
    }
}

IMPL_LINK_NOARG(ScCheckListMenuControl, FocusHdl, weld::Widget&, void)
@@ -493,11 +528,10 @@
}

ScCheckListMenuWindow::ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, bool bCanHaveSubMenu,
                                             int nWidth, sal_uInt16 nMenuStackLevel, ScCheckListMenuWindow* pParentMenu)
                                             int nWidth, ScCheckListMenuWindow* pParentMenu)
    : DockingWindow(pParent, "InterimDockParent", "svx/ui/interimdockparent.ui")
    , mxParentMenu(pParentMenu)
    , mxBox(get("box"))
    , mnMenuStackLevel(nMenuStackLevel)
{
    setDeferredProperties();
    mxControl.reset(new ScCheckListMenuControl(this, mxBox.get(), pDoc, bCanHaveSubMenu, nWidth));
@@ -537,24 +571,8 @@
    mxControl->GrabFocus();
}

void ScCheckListMenuControl::packWindow()
void ScCheckListMenuControl::prepWindow()
{
    mxBox->show();
    mxEdSearch->show();
    mxButtonBox->show();

    mxBtnOk->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
    mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
    mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl));
    mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl));
    mxChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl));
    mxChecks->connect_key_press(LINK(this, ScCheckListMenuControl, KeyInputHdl));
    mxChkToggleAll->connect_toggled(LINK(this, ScCheckListMenuControl, TriStateHdl));
    mxBtnSelectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));
    mxBtnUnselectSingle->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl));

    mxChecks->set_size_request(mnCheckWidthReq, mxChecks->get_height_rows(9));

    mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2);
    mnSelectedMenu = 0;
    mxMenu->set_cursor(mnSelectedMenu);
@@ -1161,7 +1179,7 @@
            insertMember(*mxChecks, rIter, maMembers[i]);
            if (maMembers[i].mbVisible)
                ++nVisMemCount;
        }, mnCheckWidthReq != -1 ? &aFixedWidths : nullptr);
        }, &aFixedWidths);
    }
    else
    {
@@ -1276,7 +1294,7 @@

void ScCheckListMenuControl::launch(const tools::Rectangle& rRect)
{
    packWindow();
    prepWindow();
    if (!maConfig.mbAllowEmptySet)
        // We need to have at least one member selected.
        mxBtnOk->set_sensitive(GetCheckedEntryCount() != 0);
diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx
index a6fc2e5..5703c1d 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -183,10 +183,9 @@
    };

    /**
     * Calculate the appropriate window size, the position and size of each
     * control based on the menu items.
     * Calculate the appropriate window size based on the menu items.
     */
    void packWindow();
    void prepWindow();
    void setAllMemberState(bool bSet);
    void selectCurrentMemberOnly(bool bSet);
    void updateMemberParents(const weld::TreeIter* pLeaf, size_t nIdx);
@@ -312,7 +311,7 @@
{
public:
    explicit ScCheckListMenuWindow(vcl::Window* pParent, ScDocument* pDoc, bool bCanHaveSubMenu, int nWidth = -1,
                                   sal_uInt16 nMenuStackLevel = 0, ScCheckListMenuWindow* pParentMenu = nullptr);
                                   ScCheckListMenuWindow* pParentMenu = nullptr);
    virtual void dispose() override;
    virtual ~ScCheckListMenuWindow() override;

@@ -322,13 +321,10 @@
    ScCheckListMenuWindow* GetParentMenu() { return mxParentMenu; }
    ScCheckListMenuControl& get_widget() { return *mxControl; }

    sal_uInt16 GetMenuStackLevel() const { return mnMenuStackLevel; }

private:
    VclPtr<ScCheckListMenuWindow> mxParentMenu;
    VclPtr<vcl::Window> mxBox;
    std::unique_ptr<ScCheckListMenuControl> mxControl;
    sal_uInt16 mnMenuStackLevel;
};

#endif
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index d724c23..cd1109b 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3256,7 +3256,6 @@
    // which columns should be custom rendered
    o3tl::sorted_vector<int> m_aCustomRenders;
    bool m_bTogglesAsRadio;
    bool m_bDisableCheckBoxAutoWidth;
    int m_nSortColumn;

    DECL_LINK(SelectHdl, SvTreeListBox*, void);
@@ -3397,8 +3396,7 @@
    {
        SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
        m_xTreeView->InitViewData(pViewData, pEntry);
        if (!m_bDisableCheckBoxAutoWidth)
            m_xTreeView->CheckBoxInserted(pEntry);
        m_xTreeView->CheckBoxInserted(pEntry);
    }

    void do_set_toggle(SvTreeListEntry* pEntry, TriState eState, int col)
@@ -3499,7 +3497,6 @@
        , m_aCheckButtonData(pTreeView, false)
        , m_aRadioButtonData(pTreeView, true)
        , m_bTogglesAsRadio(false)
        , m_bDisableCheckBoxAutoWidth(false)
        , m_nSortColumn(-1)
    {
        m_xTreeView->SetNodeDefaultImages();
@@ -3580,7 +3577,6 @@

    virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override
    {
        m_bDisableCheckBoxAutoWidth = true;
        std::vector<long> aTabPositions;
        aTabPositions.push_back(0);
        for (size_t i = 0; i < rWidths.size(); ++i)
@@ -3693,11 +3689,14 @@
        if (pFixedWidths)
            set_column_fixed_widths(*pFixedWidths);

        bool bHasAutoCheckButton(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN);
        size_t nExtraCols = bHasAutoCheckButton ? 2 : 1;

        Image aDummy;
        for (int i = 0; i < nSourceCount; ++i)
        {
            aVclIter.iter = new SvTreeListEntry;
            if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN)
            if (bHasAutoCheckButton)
                AddStringItem(aVclIter.iter, "", -1);
            aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
            m_xTreeView->Insert(aVclIter.iter, nullptr, TREELIST_APPEND);
@@ -3709,7 +3708,7 @@
            size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount());
            for (size_t j = 0; j < nFixedWidths; ++j)
            {
                SvLBoxItem& rItem = aVclIter.iter->GetItem(j);
                SvLBoxItem& rItem = aVclIter.iter->GetItem(j + nExtraCols);
                SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem);
                pViewDataItem->mnWidth = (*pFixedWidths)[j];
            }