officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu | 52 +++ sw/Library_sw.mk | 1 sw/UIConfig_swriter.mk | 1 sw/source/uibase/sidebar/QuickFindPanel.cxx | 190 +++++++++++ sw/source/uibase/sidebar/QuickFindPanel.hxx | 42 ++ sw/source/uibase/sidebar/SwPanelFactory.cxx | 7 sw/uiconfig/swriter/ui/sidebarquickfind.ui | 97 +++++ 7 files changed, 390 insertions(+)
New commits: commit 9338f87a6644e9b2309c3a009af096e38fbb107e Author: khushishikhu <dpskhu13...@gmail.com> AuthorDate: Thu Dec 7 14:48:10 2023 +0530 Commit: Jim Raykowski <rayk...@gmail.com> CommitDate: Thu Apr 4 20:46:29 2024 +0200 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 <rayk...@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 e038472d704e..291f4dd84153 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 c8cc2e96814a..872ae8812286 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 309eb8666293..27b7248d74e5 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 000000000000..90f428b1ed0c --- /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 000000000000..af95bd18fb44 --- /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 5ae3a781bc2d..75b7e2f17257 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 000000000000..92e3e5bdc4fc --- /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>