diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2023-01-25 13:51:17 +0530 |
---|---|---|
committer | Dennis Francis <dennis.francis@collabora.com> | 2023-04-27 08:35:59 +0200 |
commit | 2f8d10b0b9baa03b8a713e9fd1342fe6c8094fb4 (patch) | |
tree | f008321e237e02ca032178711e27a16969718312 /sc/source/ui/cctrl | |
parent | 292f422c421336c43bafe5ee048832137d617436 (diff) |
sc: pivot table compact layout
This implements compact layout for pivot tables. In ooxml each row field
can have a compact layout setting. Support for any such "mixed" layout
of tabular/outline/compact per field is also implemented. This also
implements expand/collpse toggle buttons to field labels to make pivot
tables with compact layout more usable. Such buttons are also available
if other layouts are used.
Conflicts:
sc/qa/unit/pivottable_filters_test.cxx
sc/source/ui/cctrl/checklistmenu.cxx
sc/source/ui/inc/checklistmenu.hxx
Change-Id: Ieaa1f3bd282ebdec804d0b45a0af7b3d95a2027f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151057
Tested-by: Jenkins
Reviewed-by: Dennis Francis <dennis.francis@collabora.com>
Diffstat (limited to 'sc/source/ui/cctrl')
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 58 | ||||
-rw-r--r-- | sc/source/ui/cctrl/dpcontrol.cxx | 74 |
2 files changed, 130 insertions, 2 deletions
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 456b0fe8b76a..2ff0e4a4dc00 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -373,6 +373,27 @@ void ScCheckListMenuControl::endSubMenu(ScListSubMenuControl& rSubMenu) } } +void ScCheckListMenuControl::addFields(const std::vector<OUString>& aFields) +{ + if (!mbIsMultiField) + return; + + mxFieldsCombo->clear(); + + for (auto& aField: aFields) + mxFieldsCombo->append_text(aField); + + mxFieldsCombo->set_active(0); +} + +tools::Long ScCheckListMenuControl::getField() +{ + if (!mbIsMultiField) + return -1; + + return mxFieldsCombo->get_active(); +} + void ScCheckListMenuControl::selectMenuItem(size_t nPos, bool bSubMenuTimer) { mxMenu->select(nPos == MENU_NOT_SELECTED ? -1 : nPos); @@ -476,13 +497,15 @@ constexpr int nCheckListVisibleRows = 9; constexpr int nColorListVisibleRows = 9; ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData& rViewData, - bool bHasDates, int nWidth) + bool bHasDates, int nWidth, bool bIsMultiField) : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/filterdropdown.ui")) , mxPopover(mxBuilder->weld_popover("FilterDropDown")) , mxContainer(mxBuilder->weld_container("container")) , mxMenu(mxBuilder->weld_tree_view("menu")) , mxScratchIter(mxMenu->make_iterator()) , mxNonMenu(mxBuilder->weld_widget("nonmenu")) + , mxFieldsComboLabel(mxBuilder->weld_label("select_field_label")) + , mxFieldsCombo(mxBuilder->weld_combo_box("multi_field_combo")) , mxEdSearch(mxBuilder->weld_entry("search_edit")) , mxBox(mxBuilder->weld_widget("box")) , mxListChecks(mxBuilder->weld_tree_view("check_list_box")) @@ -508,6 +531,7 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData , maOpenTimer(this) , maCloseTimer(this) , maSearchEditTimer("ScCheckListMenuControl maSearchEditTimer") + , mbIsMultiField(bIsMultiField) { mxTreeChecks->set_clicks_to_toggle(1); mxListChecks->set_clicks_to_toggle(1); @@ -556,6 +580,16 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData mxListChecks->enable_toggle_buttons(weld::ColumnToggleType::Check); mxBox->show(); + if (mbIsMultiField) + { + mxFieldsComboLabel->show(); + mxFieldsCombo->show(); + } + else + { + mxFieldsComboLabel->hide(); + mxFieldsCombo->hide(); + } mxEdSearch->show(); mxButtonBox->show(); @@ -565,6 +599,8 @@ ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData mxBtnOk->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); mxBtnCancel->connect_clicked(LINK(this, ScCheckListMenuControl, ButtonHdl)); + if (mbIsMultiField) + mxFieldsCombo->connect_changed(LINK(this, ScCheckListMenuControl, ComboChangedHdl)); mxEdSearch->connect_changed(LINK(this, ScCheckListMenuControl, EdModifyHdl)); mxEdSearch->connect_activate(LINK(this, ScCheckListMenuControl, EdActivateHdl)); mxTreeChecks->connect_toggled(LINK(this, ScCheckListMenuControl, CheckHdl)); @@ -744,6 +780,12 @@ namespace } } +IMPL_LINK_NOARG(ScCheckListMenuControl, ComboChangedHdl, weld::ComboBox&, void) +{ + if (mbIsMultiField && mxFieldChangedAction) + mxFieldChangedAction->execute(); +} + IMPL_LINK_NOARG(ScCheckListMenuControl, SearchEditTimeoutHdl, Timer*, void) { OUString aSearchText = mxEdSearch->get_text(); @@ -1078,6 +1120,15 @@ void ScCheckListMenuControl::addMember(const OUString& rName, const double nVal, maMembers.emplace_back(std::move(aMember)); } +void ScCheckListMenuControl::clearMembers() +{ + maMembers.clear(); + + mpChecks->freeze(); + mpChecks->clear(); + mpChecks->thaw(); +} + std::unique_ptr<weld::TreeIter> ScCheckListMenuControl::FindEntry(const weld::TreeIter* pParent, std::u16string_view sNode) { std::unique_ptr<weld::TreeIter> xEntry = mpChecks->make_iterator(pParent); @@ -1501,6 +1552,11 @@ void ScCheckListMenuControl::setPopupEndAction(Action* p) mxPopupEndAction.reset(p); } +void ScCheckListMenuControl::setFieldChangedAction(Action* p) +{ + mxFieldChangedAction.reset(p); +} + IMPL_LINK_NOARG(ScCheckListMenuControl, PopupModeEndHdl, weld::Popover&, void) { mbIsPoppedUp = false; diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx index b7d61ce002c7..34eea011ee05 100644 --- a/sc/source/ui/cctrl/dpcontrol.cxx +++ b/sc/source/ui/cctrl/dpcontrol.cxx @@ -32,8 +32,12 @@ ScDPFieldButton::ScDPFieldButton(OutputDevice* pOutDev, const StyleSettings* pSt mpDoc(pDoc), mpOutDev(pOutDev), mpStyle(pStyle), + mnToggleIndent(0), mbBaseButton(true), mbPopupButton(false), + mbPopupButtonMulti(false), + mbToggleButton(false), + mbToggleCollapse(false), mbHasHiddenMember(false), mbPopupPressed(false), mbPopupLeft(false) @@ -74,6 +78,18 @@ void ScDPFieldButton::setDrawPopupButton(bool b) mbPopupButton = b; } +void ScDPFieldButton::setDrawPopupButtonMulti(bool b) +{ + mbPopupButtonMulti = b; +} + +void ScDPFieldButton::setDrawToggleButton(bool b, bool bCollapse, sal_Int32 nIndent) +{ + mbToggleButton = b; + mbToggleCollapse = bCollapse; + mnToggleIndent = nIndent; +} + void ScDPFieldButton::setHasHiddenMember(bool b) { mbHasHiddenMember = b; @@ -140,9 +156,12 @@ void ScDPFieldButton::draw() mpOutDev->Pop(); } - if (mbPopupButton) + if (mbPopupButton || mbPopupButtonMulti) drawPopupButton(); + if (mbToggleButton) + drawToggleButton(); + mpOutDev->EnableMapMode(bOldMapEnabled); } @@ -174,6 +193,34 @@ void ScDPFieldButton::getPopupBoundingBox(Point& rPos, Size& rSize) const rSize.setHeight(nH); } +void ScDPFieldButton::getToggleBoundingBox(Point& rPos, Size& rSize) const +{ + const float fScaleFactor = mpOutDev->GetDPIScaleFactor(); + + tools::Long nMaxSize = 13 * fScaleFactor; // Button max size in either dimension + tools::Long nMargin = 3 * fScaleFactor; + + tools::Long nIndent = fScaleFactor * o3tl::convert(mnToggleIndent, o3tl::Length::twip, o3tl::Length::px); + tools::Long nW = std::min(maSize.getWidth() / 2, nMaxSize); + tools::Long nH = std::min(maSize.getHeight(), nMaxSize); + nIndent = std::min(nIndent, maSize.getWidth()); + + double fZoom = static_cast<double>(maZoomY) > 1.0 ? static_cast<double>(maZoomY) : 1.0; + if (fZoom > 1.0) + { + nW = fZoom * (nW - 1); + nH = fZoom * (nH - 1); + nIndent = fZoom * (nIndent -1); + nMargin = fZoom * (nMargin - 1); + } + + // FIXME: RTL case ? + rPos.setX(maPos.getX() + nIndent - nW + nMargin); + rPos.setY(maPos.getY() + maSize.getHeight() / 2 - nH / 2 + nMargin); + rSize.setWidth(nW - nMargin - 1); + rSize.setHeight(nH - nMargin - 1); +} + void ScDPFieldButton::drawPopupButton() { Point aPos; @@ -226,4 +273,29 @@ void ScDPFieldButton::drawPopupButton() } } +void ScDPFieldButton::drawToggleButton() +{ + Point aPos; + Size aSize; + getToggleBoundingBox(aPos, aSize); + + // Background & outer black border + mpOutDev->SetLineColor(COL_BLACK); + mpOutDev->SetFillColor(); + mpOutDev->DrawRect(tools::Rectangle(aPos, aSize)); + + Point aCenter(aPos.X() + aSize.getWidth() / 2, aPos.Y() + aSize.getHeight() / 2); + + mpOutDev->DrawLine( + Point(aPos.X() + 2, aCenter.Y()), + Point(aPos.X() + aSize.getWidth() - 2, aCenter.Y())); + + if (!mbToggleCollapse) + { + mpOutDev->DrawLine( + Point(aCenter.X(), aPos.Y() + 2), + Point(aCenter.X(), aPos.Y() + aSize.getHeight() - 2)); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |