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>