Resolves tdf#156227 - More appealing feedback for find/quickfind
ErrorMessageType removed in favor of an infobar-like label
Accessibility notification added for the quickfind bar
Change-Id: Iec2498d04152392b3e181146005bdb0c9db8ec50
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156943
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
diff --git a/include/svx/labelitemwindow.hxx b/include/svx/labelitemwindow.hxx
index 5271482..d9aeccb 100644
--- a/include/svx/labelitemwindow.hxx
+++ b/include/svx/labelitemwindow.hxx
@@ -12,14 +12,23 @@
#include <vcl/InterimItemWindow.hxx>
#include <svx/svxdllapi.h>
enum class LabelItemWindowType
{
Text,
Info,
};
class SVXCORE_DLLPUBLIC LabelItemWindow final : public InterimItemWindow
{
private:
std::unique_ptr<weld::Box> m_xBox;
std::unique_ptr<weld::Label> m_xLabel;
std::unique_ptr<weld::Image> m_xImage;
public:
LabelItemWindow(vcl::Window* pParent, const OUString& rLabel);
void set_label(const OUString& rLabel);
void set_label(const OUString& rLabel,
const LabelItemWindowType eType = LabelItemWindowType::Text);
OUString get_label() const;
void SetOptimalSize();
diff --git a/include/svx/srchdlg.hxx b/include/svx/srchdlg.hxx
index f069af4..7223a51 100644
--- a/include/svx/srchdlg.hxx
+++ b/include/svx/srchdlg.hxx
@@ -177,6 +177,8 @@ private:
std::unique_ptr<weld::ComboBox> m_xSearchTmplLB;
std::unique_ptr<weld::Label> m_xSearchAttrText;
std::unique_ptr<weld::Label> m_xSearchLabel;
std::unique_ptr<weld::Image> m_xSearchIcon;
std::unique_ptr<weld::Box> m_xSearchBox;
std::unique_ptr<weld::Frame> m_xReplaceFrame;
std::unique_ptr<weld::ComboBox> m_xReplaceLB;
diff --git a/svx/source/dialog/srchdlg.cxx b/svx/source/dialog/srchdlg.cxx
index a17711b..b5cf7bc 100644
--- a/svx/source/dialog/srchdlg.cxx
+++ b/svx/source/dialog/srchdlg.cxx
@@ -285,6 +285,8 @@ SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWi
, m_xSearchTmplLB(m_xBuilder->weld_combo_box("searchlist"))
, m_xSearchAttrText(m_xBuilder->weld_label("searchdesc"))
, m_xSearchLabel(m_xBuilder->weld_label("searchlabel"))
, m_xSearchIcon(m_xBuilder->weld_image("searchicon"))
, m_xSearchBox(m_xBuilder->weld_box("searchbox"))
, m_xReplaceFrame(m_xBuilder->weld_frame("replaceframe"))
, m_xReplaceLB(m_xBuilder->weld_combo_box("replaceterm"))
, m_xReplaceTmplLB(m_xBuilder->weld_combo_box("replacelist"))
@@ -340,6 +342,9 @@ SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWi
m_xSearchTmplLB->make_sorted();
m_xSearchAttrText->hide();
m_xSearchLabel->set_font_color(Color(0x00, 0x47, 0x85));
this->SetSearchLabel(""); // hide the message but keep the box height
m_xReplaceTmplLB->make_sorted();
m_xReplaceAttrText->hide();
@@ -581,14 +586,18 @@ void SvxSearchDialog::SetSearchLabel(const OUString& rStr)
m_xSearchLabel->set_label(rStr);
if (!rStr.isEmpty())
{
// hide/show to fire SHOWING state change event so search label text
// is announced by screen reader
m_xSearchLabel->hide();
m_xSearchLabel->show();
m_xSearchIcon->show();
m_xSearchBox->set_background(Color(0xBD, 0xE5, 0xF8)); // same as InfobarType::INFO
}
if (rStr == SvxResId(RID_SVXSTR_SEARCH_NOT_FOUND))
m_xSearchLB->set_entry_message_type(weld::EntryMessageType::Error);
else
{
const Size aSize = m_xSearchBox->get_preferred_size();
m_xSearchLabel->hide();
m_xSearchIcon->hide();
m_xSearchBox->set_size_request(-1, aSize.Height());
m_xSearchBox->set_background(COL_TRANSPARENT);
}
}
void SvxSearchDialog::ApplyTransliterationFlags_Impl( TransliterationFlags nSettings )
@@ -2360,8 +2369,6 @@ SfxChildWinInfo SvxSearchDialogWrapper::GetInfo() const
static void lcl_SetSearchLabelWindow(const OUString& rStr, SfxViewFrame& rViewFrame)
{
bool bNotFound = rStr == SvxResId(RID_SVXSTR_SEARCH_NOT_FOUND);
css::uno::Reference< css::beans::XPropertySet > xPropSet(
rViewFrame.GetFrame().GetFrameInterface(), css::uno::UNO_QUERY_THROW);
css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
@@ -2380,21 +2387,8 @@ static void lcl_SetSearchLabelWindow(const OUString& rStr, SfxViewFrame& rViewFr
{
LabelItemWindow* pSearchLabel = dynamic_cast<LabelItemWindow*>(pToolBox->GetItemWindow(id));
assert(pSearchLabel);
pSearchLabel->set_label(rStr);
if (rStr.isEmpty())
pSearchLabel->SetSizePixel(Size(16, pSearchLabel->GetSizePixel().Height()));
else
pSearchLabel->SetOptimalSize();
}
if (pToolBox->GetItemCommand(id) == ".uno:FindText")
{
FindTextFieldControl* pFindText = dynamic_cast<FindTextFieldControl*>(pToolBox->GetItemWindow(id));
assert(pFindText);
if (bNotFound)
pFindText->set_entry_message_type(weld::EntryMessageType::Error);
else
pFindText->set_entry_message_type(weld::EntryMessageType::Normal);
pSearchLabel->set_label(rStr, LabelItemWindowType::Info);
pSearchLabel->SetOptimalSize();
}
}
xLayoutManager->doLayout();
diff --git a/svx/source/form/labelitemwindow.cxx b/svx/source/form/labelitemwindow.cxx
index 77965cb..bdff03e 100644
--- a/svx/source/form/labelitemwindow.cxx
+++ b/svx/source/form/labelitemwindow.cxx
@@ -11,11 +11,14 @@
LabelItemWindow::LabelItemWindow(vcl::Window* pParent, const OUString& rLabel)
: InterimItemWindow(pParent, "svx/ui/labelbox.ui", "LabelBox")
, m_xBox(m_xBuilder->weld_box("LabelBox"))
, m_xLabel(m_xBuilder->weld_label("label"))
, m_xImage(m_xBuilder->weld_image("image"))
{
InitControlBase(m_xLabel.get());
m_xLabel->set_label(rLabel);
m_xImage->hide();
SetOptimalSize();
@@ -24,13 +27,30 @@ LabelItemWindow::LabelItemWindow(vcl::Window* pParent, const OUString& rLabel)
void LabelItemWindow::SetOptimalSize()
{
Size aSize(m_xLabel->get_preferred_size());
Size aSize(m_xBox->get_preferred_size());
aSize.AdjustWidth(12);
SetSizePixel(aSize);
}
void LabelItemWindow::set_label(const OUString& rLabel) { m_xLabel->set_label(rLabel); }
void LabelItemWindow::set_label(const OUString& rLabel, const LabelItemWindowType eType)
{
m_xLabel->set_visible(false); // a11y announcement
m_xLabel->set_label(rLabel);
if ((eType == LabelItemWindowType::Text) || rLabel.isEmpty())
{
m_xImage->hide();
m_xLabel->set_font_color(COL_AUTO);
m_xBox->set_background(COL_AUTO);
}
else if (eType == LabelItemWindowType::Info)
{
m_xImage->show();
m_xLabel->set_font_color(Color(0x00, 0x47, 0x85));
m_xBox->set_background(Color(0xBD, 0xE5, 0xF8)); // same as InfobarType::INFO
}
m_xLabel->set_visible(!rLabel.isEmpty());
}
OUString LabelItemWindow::get_label() const { return m_xLabel->get_label(); }
diff --git a/svx/uiconfig/ui/findreplacedialog.ui b/svx/uiconfig/ui/findreplacedialog.ui
index fbb0335..57a16e6 100644
--- a/svx/uiconfig/ui/findreplacedialog.ui
+++ b/svx/uiconfig/ui/findreplacedialog.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<interface domain="svx">
<requires lib="gtk+" version="3.20"/>
<object class="GtkDialog" id="FindReplaceDialog">
@@ -172,26 +172,6 @@
</packing>
</child>
<child>
<object class="GtkLabel" id="searchlabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="no-show-all">True</property>
<property name="hexpand">True</property>
<property name="wrap">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<child internal-child="accessible">
<object class="AtkObject" id="searchlabel-atkobject">
<property name="AtkObject::accessible-role" translatable="no">notification</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="checkboxrow">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -302,6 +282,64 @@
</packing>
</child>
<child>
<object class="GtkBox" id="searchbox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<child>
<object class="GtkImage" id="searchicon">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">6</property>
<property name="margin-end">3</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<property name="icon-name">res/info.png</property>
<child internal-child="accessible">
<object class="AtkObject" id="searchicon-atkobject">
<property name="AtkObject::accessible-name" translatable="yes" context="findreplacedialog|searchicon">Search icon</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="searchlabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="no-show-all">True</property>
<property name="halign">start</property>
<property name="margin-start">3</property>
<property name="margin-end">6</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<property name="hexpand">True</property>
<property name="wrap">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0</property>
<child internal-child="accessible">
<object class="AtkObject" id="searchlabel-atkobject">
<property name="AtkObject::accessible-role">notification</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
diff --git a/svx/uiconfig/ui/labelbox.ui b/svx/uiconfig/ui/labelbox.ui
index eca99a4..f77cd5d 100644
--- a/svx/uiconfig/ui/labelbox.ui
+++ b/svx/uiconfig/ui/labelbox.ui
@@ -1,20 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.40.0 -->
<interface domain="svx">
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="LabelBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="spacing">4</property>
<child>
<object class="GtkLabel" id="label">
<object class="GtkImage" id="image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="xalign">0</property>
<property name="can-focus">False</property>
<property name="margin-start">6</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<property name="icon-name">res/info.png</property>
</object>
<packing>
<property name="expand">False</property>
@@ -22,5 +23,25 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-end">6</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="xalign">0</property>
<child internal-child="accessible">
<object class="AtkObject" id="label-atkobject">
<property name="AtkObject::accessible-role">notification</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</interface>