tdf#95405 Sidebar: Quick Find for writer
Implemented the quick find deck on the sidebar of Writer with a corresponding panel in it.
Change-Id: Ic4ce6823e11b27b3386e820a657bc5d973e47007
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160500
Tested-by: Jenkins
Reviewed-by: Jim Raykowski <raykowj@gmail.com>
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
index e038472..291f4dd 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu
@@ -335,7 +335,28 @@
</prop>
</node>
<node oor:name="FindDeck" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en-US">Find</value>
</prop>
<prop oor:name="Id" oor:type="xs:string">
<value>FindDeck</value>
</prop>
<prop oor:name="IconURL" oor:type="xs:string">
<value>private:graphicrepository/cmd/lc_recsearch.png</value>
</prop>
<prop oor:name="ContextList">
<value oor:separator=";">
WriterVariants, any, visible ;
</value>
</prop>
<prop oor:name="OrderIndex" oor:type="xs:int">
<value>1000</value>
</prop>
</node>
</node>
<node oor:name="PanelList">
<node oor:name="StylesPropertyPanel" oor:op="replace">
@@ -2020,6 +2041,37 @@
</prop>
</node>
<node oor:name="QuickFindPanel" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en-US">QuickFind</value>
</prop>
<prop oor:name="TitleBarIsOptional" oor:type="xs:boolean">
<value>true</value>
</prop>
<prop oor:name="Id" oor:type="xs:string">
<value>QuickFindPanel</value>
</prop>
<prop oor:name="DeckId" oor:type="xs:string">
<value>FindDeck</value>
</prop>
<prop oor:name="ContextList">
<value oor:separator=";">
Writer, any, visible;
</value>
</prop>
<prop oor:name="ImplementationURL" oor:type="xs:string">
<value>private:resource/toolpanel/SwPanelFactory/QuickFindPanel</value>
</prop>
<prop oor:name="OrderIndex" oor:type="xs:int">
<value>300</value>
</prop>
<prop oor:name="WantsAWT" oor:type="xs:boolean">
<value>false</value>
</prop>
</node>
</node>
</node>
</oor:component-data>
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index c8cc2e9..872ae88 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -736,6 +736,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
sw/source/uibase/sidebar/SwPanelFactory \
sw/source/uibase/sidebar/WriterInspectorTextPanel \
sw/source/uibase/sidebar/A11yCheckIssuesPanel \
sw/source/uibase/sidebar/QuickFindPanel \
sw/source/uibase/table/chartins \
sw/source/uibase/table/swtablerep \
sw/source/uibase/table/tablemgr \
diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index 309eb86..27b7248 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -291,6 +291,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
sw/uiconfig/swriter/ui/sidebarstylepresets \
sw/uiconfig/swriter/ui/sidebartableedit \
sw/uiconfig/swriter/ui/sidebartheme \
sw/uiconfig/swriter/ui/sidebarquickfind \
sw/uiconfig/swriter/ui/sortdialog \
sw/uiconfig/swriter/ui/spellmenu \
sw/uiconfig/swriter/ui/splittable \
diff --git a/sw/source/uibase/sidebar/QuickFindPanel.cxx b/sw/source/uibase/sidebar/QuickFindPanel.cxx
new file mode 100644
index 0000000..90f428b
--- /dev/null
+++ b/sw/source/uibase/sidebar/QuickFindPanel.cxx
@@ -0,0 +1,190 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#include "QuickFindPanel.hxx"
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <svl/srchitem.hxx>
#include <view.hxx>
#include <comphelper/dispatchcommand.hxx>
#include <comphelper/propertysequence.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <swmodule.hxx>
#include <pam.hxx>
#include <contentindex.hxx>
#include <node.hxx>
#include <ndtxt.hxx>
#include <edtwin.hxx>
#include <com/sun/star/uno/Any.h>
using namespace css;
using namespace std;
const int MinimumPanelWidth = 250;
namespace sw::sidebar
{
std::unique_ptr<PanelLayout> QuickFindPanel::Create(weld::Widget* pParent)
{
if (pParent == nullptr)
throw css::lang::IllegalArgumentException(
"no parent Window given to QuickFindPanel::Create", nullptr, 0);
return std::make_unique<QuickFindPanel>(pParent);
}
QuickFindPanel::QuickFindPanel(weld::Widget* pParent)
: PanelLayout(pParent, "QuickFindPanel", "modules/swriter/ui/sidebarquickfind.ui")
, m_xSearchFindEntry(m_xBuilder->weld_entry("Find"))
, m_xSearchFindsList(m_xBuilder->weld_tree_view("searchfinds"))
, m_nRowHeight(m_xSearchFindsList->get_height_rows(4))
, m_pWrtShell(::GetActiveWrtShell())
{
m_xContainer->set_size_request(MinimumPanelWidth, -1);
m_xSearchFindsList->set_size_request(1, m_nRowHeight);
m_xSearchFindEntry->connect_activate(
LINK(this, QuickFindPanel, SearchFindEntryActivateHandler));
m_xSearchFindEntry->connect_changed(LINK(this, QuickFindPanel, SearchFindEntryChangedHandler));
m_xSearchFindsList->connect_custom_get_size(
LINK(this, QuickFindPanel, SearchFindsListCustomGetSizeHandler));
m_xSearchFindsList->connect_custom_render(LINK(this, QuickFindPanel, SearchFindsListRender));
m_xSearchFindsList->set_column_custom_renderer(1, true);
m_xSearchFindsList->connect_changed(
LINK(this, QuickFindPanel, SearchFindsListSelectionChangedHandler));
m_xSearchFindsList->connect_row_activated(
LINK(this, QuickFindPanel, SearchFindsListRowActivatedHandler));
}
QuickFindPanel::~QuickFindPanel()
{
m_xSearchFindEntry.reset();
m_xSearchFindsList.reset();
}
IMPL_LINK_NOARG(QuickFindPanel, SearchFindEntryActivateHandler, weld::Entry&, bool)
{
FillSearchFindsList();
return true;
}
IMPL_LINK_NOARG(QuickFindPanel, SearchFindsListCustomGetSizeHandler, weld::TreeView::get_size_args,
Size)
{
return Size(1, m_nRowHeight);
}
IMPL_LINK(QuickFindPanel, SearchFindsListRender, weld::TreeView::render_args, aPayload, void)
{
vcl::RenderContext& rRenderContext = std::get<0>(aPayload);
const ::tools::Rectangle& rRect = std::get<1>(aPayload);
const OUString& rId = std::get<3>(aPayload);
int nIndex = m_xSearchFindsList->find_id(rId);
OUString aEntry(m_xSearchFindsList->get_text(nIndex));
DrawTextFlags const nTextStyle = DrawTextFlags::Left | DrawTextFlags::VCenter
| DrawTextFlags::MultiLine | DrawTextFlags::WordBreak;
tools::Rectangle aRect(
rRect.TopLeft(),
Size(rRenderContext.GetOutputSize().Width() - rRect.Left(), rRect.GetHeight()));
rRenderContext.DrawText(aRect, aEntry, nTextStyle);
}
IMPL_LINK_NOARG(QuickFindPanel, SearchFindsListSelectionChangedHandler, weld::TreeView&, void)
{
std::unique_ptr<SwPaM>& rxPaM = m_vPaMs[m_xSearchFindsList->get_cursor_index()];
m_pWrtShell->StartAction();
bool bFound = false;
for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
{
if (*rxPaM->GetPoint() == *rPaM.GetPoint() && *rxPaM->GetMark() == *rPaM.GetMark())
{
bFound = true;
break;
}
m_pWrtShell->GoNextCursor();
}
if (!bFound)
{
m_pWrtShell->AssureStdMode();
m_pWrtShell->SetSelection(*rxPaM);
}
m_pWrtShell->EndAction();
SwShellCursor* pShellCursor = m_pWrtShell->GetCursor_();
std::vector<basegfx::B2DRange> vRanges;
for (const SwRect& rRect : *pShellCursor)
{
tools::Rectangle aRect = rRect.SVRect();
vRanges.emplace_back(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
}
m_pWrtShell->GetView().BringToAttention(std::move(vRanges));
}
IMPL_LINK_NOARG(QuickFindPanel, SearchFindsListRowActivatedHandler, weld::TreeView&, bool)
{
m_pWrtShell->GetView().GetEditWin().GrabFocus();
return true;
}
IMPL_LINK_NOARG(QuickFindPanel, SearchFindEntryChangedHandler, weld::Entry&, void)
{
m_xSearchFindsList->clear();
}
void QuickFindPanel::FillSearchFindsList()
{
m_vPaMs.clear();
m_xSearchFindsList->clear();
const OUString& sText = m_xSearchFindEntry->get_text();
css::uno::Sequence<css::beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({
{ "SearchItem.SearchString", css::uno::Any(sText) },
{ "SearchItem.Backward", css::uno::Any(false) },
{ "SearchItem.Command", css::uno::Any(sal_uInt16(SvxSearchCmd::FIND_ALL)) },
}));
comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues);
if (m_pWrtShell->HasMark())
{
for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
{
SwPosition* pMarkPosition = rPaM.GetMark();
const SwContentIndex aContentIndex = pMarkPosition->nContent;
const SwContentNode* pContentNode = aContentIndex.GetContentNode();
const SwTextNode* pTextNode = pContentNode->GetTextNode();
const OUString& sNodeText = pTextNode->GetText();
auto nMarkIndex = rPaM.GetMark()->nContent.GetIndex();
auto nPointIndex = rPaM.GetPoint()->nContent.GetIndex();
auto nStartIndex = nMarkIndex - 50;
if (nStartIndex < 0)
nStartIndex = 0;
auto nEndIndex = nPointIndex + 50;
if (nEndIndex > sNodeText.getLength())
{
nEndIndex = sNodeText.getLength();
}
auto nCount = nMarkIndex - nStartIndex;
OUString sTextBeforeFind = OUString::Concat(sNodeText.subView(nStartIndex, nCount));
auto nCount1 = nPointIndex - nMarkIndex;
OUString sFind = OUString::Concat(sNodeText.subView(nMarkIndex, nCount1));
auto nCount2 = nEndIndex - nPointIndex;
OUString sTextAfterFind = OUString::Concat(sNodeText.subView(nPointIndex, nCount2));
OUString sStr = sTextBeforeFind + "[" + sFind + "]" + sTextAfterFind;
std::unique_ptr<SwPaM> xPaM(std::make_unique<SwPaM>(*rPaM.GetMark(), *rPaM.GetPoint()));
m_vPaMs.push_back(std::move(xPaM));
OUString sId = OUString::number(m_xSearchFindsList->n_children());
m_xSearchFindsList->append(sId, sStr);
}
}
}
}
// end of namespace ::sw::sidebar
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/QuickFindPanel.hxx b/sw/source/uibase/sidebar/QuickFindPanel.hxx
new file mode 100644
index 0000000..af95bd1
--- /dev/null
+++ b/sw/source/uibase/sidebar/QuickFindPanel.hxx
@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#pragma once
#include <sfx2/sidebar/PanelLayout.hxx>
#include <wrtsh.hxx>
namespace sw::sidebar
{
class QuickFindPanel : public PanelLayout
{
public:
static std::unique_ptr<PanelLayout> Create(weld::Widget* pParent);
QuickFindPanel(weld::Widget* pParent);
virtual ~QuickFindPanel() override;
private:
std::unique_ptr<weld::Entry> m_xSearchFindEntry;
std::unique_ptr<weld::TreeView> m_xSearchFindsList;
std::vector<std::unique_ptr<SwPaM>> m_vPaMs;
int m_nRowHeight;
SwWrtShell* m_pWrtShell;
DECL_LINK(SearchFindEntryActivateHandler, weld::Entry&, bool);
DECL_LINK(SearchFindsListCustomGetSizeHandler, weld::TreeView::get_size_args, Size);
DECL_LINK(SearchFindsListRender, weld::TreeView::render_args, void);
DECL_LINK(SearchFindsListSelectionChangedHandler, weld::TreeView&, void);
DECL_LINK(SearchFindEntryChangedHandler, weld::Entry&, void);
DECL_LINK(SearchFindsListRowActivatedHandler, weld::TreeView&, bool);
void FillSearchFindsList();
};
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/sidebar/SwPanelFactory.cxx b/sw/source/uibase/sidebar/SwPanelFactory.cxx
index 5ae3a78..75b7e2f 100644
--- a/sw/source/uibase/sidebar/SwPanelFactory.cxx
+++ b/sw/source/uibase/sidebar/SwPanelFactory.cxx
@@ -26,6 +26,7 @@
#include "PageFormatPanel.hxx"
#include "PageHeaderPanel.hxx"
#include "PageFooterPanel.hxx"
#include "QuickFindPanel.hxx"
#include "WrapPropertyPanel.hxx"
#include "WriterInspectorTextPanel.hxx"
#include "TableEditPanel.hxx"
@@ -203,6 +204,12 @@ Reference<ui::XUIElement> SAL_CALL SwPanelFactory::createUIElement (
xElement = sfx2::sidebar::SidebarPanelBase::Create(
rsResourceURL, xFrame, std::move(xPanel), ui::LayoutSize(-1,-1,-1));
}
else if (rsResourceURL.endsWith("/QuickFindPanel"))
{
std::unique_ptr<PanelLayout> xPanel = sw::sidebar::QuickFindPanel::Create(pParent);
xElement = sfx2::sidebar::SidebarPanelBase::Create(rsResourceURL, xFrame, std::move(xPanel),
ui::LayoutSize(-1, -1, -1));
}
return xElement;
}
diff --git a/sw/uiconfig/swriter/ui/sidebarquickfind.ui b/sw/uiconfig/swriter/ui/sidebarquickfind.ui
new file mode 100644
index 0000000..92e3e5b
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/sidebarquickfind.ui
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface domain="sw">
<requires lib="gtk+" version="3.20"/>
<object class="GtkTreeStore" id="liststore1">
<columns>
<!-- column-name text1 -->
<column type="gchararray"/>
<!-- column-name text2 -->
<column type="gchararray"/>
<!-- column-name id -->
<column type="gchararray"/>
</columns>
</object>
<!-- n-columns=1 n-rows=1 -->
<object class="GtkGrid" id="QuickFindPanel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="row-spacing">6</property>
<property name="column-spacing">6</property>
<property name="row-homogeneous">True</property>
<property name="column-homogeneous">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="border-width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkEntry" id="Find">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="placeholder-text">Find</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="searchfinds">
<property name="width-request">-1</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="border-width">0</property>
<property name="model">liststore1</property>
<property name="headers-visible">False</property>
<property name="enable-search">False</property>
<property name="search-column">1</property>
<property name="show-expanders">False</property>
<property name="activate-on-single-click">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn0"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<child>
<object class="GtkCellRendererText" id="cellrenderertext"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</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">0</property>
<property name="top-attach">0</property>
</packing>
</child>
</object>
</interface>