summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Szűcs <szucs.attila3@nisz.hu>2020-08-19 10:50:22 +0200
committerLászló Németh <nemeth@numbertext.org>2020-08-28 08:56:31 +0200
commit2d43c425a0de003a37bc278c3786d89165ecaf76 (patch)
treefb5b19261e957cc60985a2a6f49a1c6e925585d9
parent33ecd0d5c4fff9511a8436513936a3f7044a775a (diff)
tdf#133160 sc: fix width of Autofilter popup window
Autofilter popup window will be automatically resized horizontally to make sure its list items are fit into the window, if possible. The window width is capped at 1024 pixel. If it is not enough, horizontal scrollbar will appear for the TreeList. Co-authored-by: Tibor Nagy (NISZ) Change-Id: I49ce9ec2c715010d604357e4955eee86d276d713 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100978 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--sc/qa/uitest/autofilter/autofilter.py45
-rw-r--r--sc/qa/uitest/autofilter/data/tdf133160.odsbin0 -> 10604 bytes
-rw-r--r--sc/source/ui/cctrl/checklistmenu.cxx25
-rw-r--r--sc/source/ui/inc/checklistmenu.hxx4
-rw-r--r--sc/source/ui/view/gridwin.cxx40
-rw-r--r--sc/uiconfig/scalc/ui/filterdropdown.ui3
6 files changed, 110 insertions, 7 deletions
diff --git a/sc/qa/uitest/autofilter/autofilter.py b/sc/qa/uitest/autofilter/autofilter.py
index 57504e66e8e9..a0264f07878c 100644
--- a/sc/qa/uitest/autofilter/autofilter.py
+++ b/sc/qa/uitest/autofilter/autofilter.py
@@ -6,6 +6,7 @@
#
from uitest.framework import UITestCase
+from uitest.uihelper.common import get_state_as_dict
from uitest.path import get_srcdir_url
from libreoffice.uno.propertyvalue import mkPropertyValues
@@ -70,4 +71,48 @@ class AutofilterTest(UITestCase):
self.assertTrue(is_row_hidden(doc, 3))
self.assertFalse(is_row_hidden(doc, 4))
+ def test_tdf133160(self):
+ doc = self.ui_test.load_file(get_url_for_data_file("tdf133160.ods"))
+
+ xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window")
+ xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "3"}))
+ xFloatWindow = self.xUITest.getFloatWindow()
+ xCheckListMenu = xFloatWindow.getChild("check_list_menu")
+ xTreeList = xCheckListMenu.getChild("check_list_box")
+ size1 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0])
+ xOkBtn = xFloatWindow.getChild("cancel")
+ xOkBtn.executeAction("CLICK", tuple())
+
+ xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "2", "ROW": "3"}))
+ xFloatWindow = self.xUITest.getFloatWindow()
+ xCheckListMenu = xFloatWindow.getChild("check_list_menu")
+ xTreeList = xCheckListMenu.getChild("check_list_box")
+ size2 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0])
+ xOkBtn = xFloatWindow.getChild("cancel")
+ xOkBtn.executeAction("CLICK", tuple())
+
+ xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "3", "ROW": "3"}))
+ xFloatWindow = self.xUITest.getFloatWindow()
+ xCheckListMenu = xFloatWindow.getChild("check_list_menu")
+ xTreeList = xCheckListMenu.getChild("check_list_box")
+ size3 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0])
+ xOkBtn = xFloatWindow.getChild("cancel")
+ xOkBtn.executeAction("CLICK", tuple())
+
+ xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "4", "ROW": "3"}))
+ xFloatWindow = self.xUITest.getFloatWindow()
+ xCheckListMenu = xFloatWindow.getChild("check_list_menu")
+ xTreeList = xCheckListMenu.getChild("check_list_box")
+ size4 = int(get_state_as_dict(xTreeList)["Size"].split('x')[0])
+
+ xOkBtn = xFloatWindow.getChild("cancel")
+ xOkBtn.executeAction("CLICK", tuple())
+
+ self.assertTrue(size1 < size2) # for me they were size1=176 size2=212 size3=459 size4=1012
+ self.assertTrue(size2 < size3) # size1 is the minimum window width, size2 based on its column width
+ self.assertTrue(size3 < size4) # size3 is a long text width
+ self.assertTrue(size4 < 1500) # size4 is the maximum window width with a really long text
+
+ self.ui_test.close_doc()
+
# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sc/qa/uitest/autofilter/data/tdf133160.ods b/sc/qa/uitest/autofilter/data/tdf133160.ods
new file mode 100644
index 000000000000..40f83e60af97
--- /dev/null
+++ b/sc/qa/uitest/autofilter/data/tdf133160.ods
Binary files differ
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 7422a1a93b52..9a9259f9f796 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -1159,14 +1159,17 @@ namespace
}
}
-size_t ScCheckListMenuControl::initMembers()
+size_t ScCheckListMenuControl::initMembers(int nMaxMemberWidth)
{
size_t n = maMembers.size();
size_t nVisMemCount = 0;
+ if (nMaxMemberWidth == -1)
+ nMaxMemberWidth = mnCheckWidthReq;
+
if (!mxChecks->n_children() && !mbHasDates)
{
- std::vector<int> aFixedWidths { mnCheckWidthReq };
+ std::vector<int> aFixedWidths { nMaxMemberWidth };
// tdf#134038 insert in the fastest order, this might be backwards so only do it for
// the !mbHasDates case where no entry depends on another to exist before getting
// inserted. We cannot retain pre-existing treeview content, only clear and fill it.
@@ -1348,4 +1351,22 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, PopupModeEndHdl, FloatingWindow*, void)
mxPopupEndAction->execute();
}
+int ScCheckListMenuControl::GetTextWidth(const OUString& rsName) const
+{
+ return mxDropDown->GetTextWidth(rsName);
+}
+
+int ScCheckListMenuControl::IncreaseWindowWidthToFitText(int nMaxTextWidth)
+{
+ int nBorder = mxFrame->get_border_width() * 2 + 4;
+ int nNewWidth = nMaxTextWidth - nBorder;
+ if (nNewWidth > mnCheckWidthReq)
+ {
+ mnCheckWidthReq = nNewWidth;
+ int nChecksHeight = mxChecks->get_height_rows(9);
+ mxChecks->set_size_request(mnCheckWidthReq, nChecksHeight);
+ }
+ return mnCheckWidthReq + nBorder;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx
index 6a6cbf43514f..f407bc96c3e3 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -130,7 +130,7 @@ public:
void setMemberSize(size_t n);
void addDateMember(const OUString& rName, double nVal, bool bVisible);
void addMember(const OUString& rName, bool bVisible);
- size_t initMembers();
+ size_t initMembers(int nMaxMemberWidth = -1);
void setConfig(const Config& rConfig);
bool isAllSelected() const;
@@ -164,6 +164,8 @@ public:
void setPopupEndAction(Action* p);
void setHasDates(bool bHasDates);
+ int GetTextWidth(const OUString& rsName) const;
+ int IncreaseWindowWidthToFitText(int nMaxTextWidth);
private:
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 296873a2ef76..9b30f3513a80 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -656,6 +656,42 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
mpAutoFilterPopup.reset(VclPtr<ScCheckListMenuWindow>::Create(this, pDoc, false, nColWidth));
ScCheckListMenuControl& rControl = mpAutoFilterPopup->get_widget();
+ // Estimate the width (in pixels) of the longest text in the list
+ ScFilterEntries aFilterEntries;
+ pDoc->GetFilterEntries(nCol, nRow, nTab, aFilterEntries);
+ int nMaxTextWidth = 0;
+ if (aFilterEntries.size() <= 10)
+ {
+ // do pixel calculation for all elements of short lists
+ for (const auto& rEntry : aFilterEntries)
+ {
+ const OUString& aText = rEntry.GetString();
+ nMaxTextWidth = std::max<int>(nMaxTextWidth, rControl.GetTextWidth(aText) + aText.getLength() * 2);
+ }
+ }
+ else
+ {
+ // find the longest string, probably it will be the longest rendered text, too
+ // (performance optimization for long lists)
+ auto itMax = aFilterEntries.begin();
+ for (auto it = itMax; it != aFilterEntries.end(); ++it)
+ {
+ int nTextWidth = it->GetString().getLength();
+ if (nMaxTextWidth < nTextWidth)
+ {
+ nMaxTextWidth = nTextWidth;
+ itMax = it;
+ }
+ }
+ nMaxTextWidth = rControl.GetTextWidth(itMax->GetString()) + nMaxTextWidth * 2;
+ }
+
+ // window should be at least as wide as the column, or the longest text + checkbox, scrollbar ... (it is estimated with 70 pixel now)
+ // window should be maximum 1024 pixel wide.
+ int nWindowWidth = std::min<int>(1024, nMaxTextWidth + 70);
+ nWindowWidth = rControl.IncreaseWindowWidthToFitText(nWindowWidth);
+ nMaxTextWidth = std::max<int>(nMaxTextWidth, nWindowWidth - 70);
+
if (bLOKActive)
mpAutoFilterPopup->SetLOKNotifier(SfxViewShell::Current());
rControl.setOKAction(new AutoFilterAction(this, AutoFilterMode::Normal));
@@ -703,8 +739,6 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
}
// Populate the check box list.
- ScFilterEntries aFilterEntries;
- pDoc->GetFilterEntries(nCol, nRow, nTab, aFilterEntries);
rControl.setHasDates(aFilterEntries.mbHasDates);
rControl.setMemberSize(aFilterEntries.size());
@@ -738,7 +772,7 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
rControl.addMenuItem(
ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom));
- rControl.initMembers();
+ rControl.initMembers(nMaxTextWidth + 20); // 20 pixel estimated for the checkbox
ScCheckListMenuControl::Config aConfig;
aConfig.mbAllowEmptySet = false;
diff --git a/sc/uiconfig/scalc/ui/filterdropdown.ui b/sc/uiconfig/scalc/ui/filterdropdown.ui
index b6a3e4f77d0e..c84131fd9721 100644
--- a/sc/uiconfig/scalc/ui/filterdropdown.ui
+++ b/sc/uiconfig/scalc/ui/filterdropdown.ui
@@ -198,7 +198,8 @@
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
- <property name="hscrollbar_policy">external</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="check_list_box">