summaryrefslogtreecommitdiffstats
path: root/sw/source/ui/misc
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/ui/misc')
-rw-r--r--sw/source/ui/misc/bookmark.cxx516
-rw-r--r--sw/source/ui/misc/contentcontroldlg.cxx414
-rw-r--r--sw/source/ui/misc/contentcontrollistitemdlg.cxx48
-rw-r--r--sw/source/ui/misc/docfnote.cxx394
-rw-r--r--sw/source/ui/misc/glosbib.cxx405
-rw-r--r--sw/source/ui/misc/glossary.cxx1086
-rw-r--r--sw/source/ui/misc/impfnote.hxx83
-rw-r--r--sw/source/ui/misc/insfnote.cxx249
-rw-r--r--sw/source/ui/misc/linenum.cxx260
-rw-r--r--sw/source/ui/misc/num.cxx957
-rw-r--r--sw/source/ui/misc/outline.cxx1078
-rw-r--r--sw/source/ui/misc/pgfnote.cxx313
-rw-r--r--sw/source/ui/misc/pggrid.cxx551
-rw-r--r--sw/source/ui/misc/srtdlg.cxx428
-rw-r--r--sw/source/ui/misc/swmodalredlineacceptdlg.cxx79
-rw-r--r--sw/source/ui/misc/titlepage.cxx334
16 files changed, 7195 insertions, 0 deletions
diff --git a/sw/source/ui/misc/bookmark.cxx b/sw/source/ui/misc/bookmark.cxx
new file mode 100644
index 000000000..a25e85164
--- /dev/null
+++ b/sw/source/ui/misc/bookmark.cxx
@@ -0,0 +1,516 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <rtl/ustrbuf.hxx>
+#include <sfx2/request.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/viewoptions.hxx>
+#include <vcl/weld.hxx>
+#include <o3tl/string_view.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/XBookmarksSupplier.hpp>
+#include <officecfg/Office/Common.hxx>
+
+#include <swabstdlg.hxx>
+#include <swuiexp.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <cmdid.h>
+#include <bookmark.hxx>
+#include <docsh.hxx>
+#include <ndtxt.hxx>
+#include <strings.hrc>
+#include <IDocumentSettingAccess.hxx>
+
+using namespace ::com::sun::star;
+
+const char BookmarkTable::cSeparator(';');
+
+// callback to modify EditBox
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, ModifyHdl, weld::Entry&, void)
+{
+ ValidateBookmarks();
+ m_xBookmarksBox->unselect_all();
+ // if a string has been pasted from the clipboard then
+ // there may be illegal characters in the box
+ // sanitization
+ OUString sTmp = m_xEditBox->get_text();
+ OUString sMsg;
+ const sal_Int32 nLen = sTmp.getLength();
+ for (sal_Int32 i = 0; i < BookmarkTable::aForbiddenChars.getLength(); i++)
+ {
+ const sal_Int32 nTmpLen = sTmp.getLength();
+ sTmp = sTmp.replaceAll(OUStringChar(BookmarkTable::aForbiddenChars.getStr()[i]), "");
+ if (sTmp.getLength() != nTmpLen)
+ sMsg += OUStringChar(BookmarkTable::aForbiddenChars.getStr()[i]);
+ }
+ const bool bHasForbiddenChars = sTmp.getLength() != nLen;
+ m_xForbiddenChars->set_visible(bHasForbiddenChars);
+ if (bHasForbiddenChars)
+ m_xEditBox->set_message_type(weld::EntryMessageType::Error);
+ else
+ m_xEditBox->set_message_type(weld::EntryMessageType::Normal);
+
+ sal_Int32 nSelectedEntries = 0;
+ sal_Int32 nEntries = 0;
+ sal_Int32 nTokenIndex = 0;
+ while (!sTmp.isEmpty() && nTokenIndex >= 0)
+ {
+ OUString aToken = sTmp.getToken(0, BookmarkTable::cSeparator, nTokenIndex);
+ if (m_xBookmarksBox->GetBookmarkByName(aToken))
+ {
+ m_xBookmarksBox->SelectByName(aToken);
+ nSelectedEntries++;
+ }
+ nEntries++;
+ }
+
+ // allow to add new bookmark only if one name provided and it's not taken
+ m_xInsertBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 0 && !bHasForbiddenChars
+ && !m_bAreProtected);
+
+ // allow to delete only if all bookmarks are recognized
+ m_xDeleteBtn->set_sensitive(nEntries > 0 && nSelectedEntries == nEntries && !m_bAreProtected);
+ m_xGotoBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 1);
+ m_xRenameBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 1 && !m_bAreProtected);
+}
+
+// callback to delete a text mark
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, DeleteHdl, weld::Button&, void)
+{
+ if (!ValidateBookmarks())
+ return;
+
+ int nSelectedRows(0);
+
+ m_xBookmarksBox->selected_foreach([this, &nSelectedRows](weld::TreeIter& rEntry) {
+ // remove from model
+ sw::mark::IMark* pBookmark
+ = weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(rEntry));
+ OUString sRemoved = pBookmark->GetName();
+ IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess();
+ pMarkAccess->deleteMark(pMarkAccess->findMark(sRemoved), false);
+ SfxRequest aReq(rSh.GetView().GetViewFrame(), FN_DELETE_BOOKMARK);
+ aReq.AppendItem(SfxStringItem(FN_DELETE_BOOKMARK, sRemoved));
+ aReq.Done();
+ aTableBookmarks.erase(std::remove(aTableBookmarks.begin(), aTableBookmarks.end(),
+ std::make_pair(pBookmark, sRemoved)),
+ aTableBookmarks.end());
+
+ ++nSelectedRows;
+
+ return false;
+ });
+
+ if (!nSelectedRows)
+ return;
+
+ // remove from BookmarkTable
+ m_xBookmarksBox->remove_selection();
+
+ ValidateBookmarks();
+
+ m_xDeleteBtn->set_sensitive(false);
+ m_xGotoBtn->set_sensitive(false);
+ m_xRenameBtn->set_sensitive(false);
+ m_xInsertBtn->set_sensitive(false);
+}
+
+// callback to a goto button
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, GotoHdl, weld::Button&, void) { GotoSelectedBookmark(); }
+
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, DoubleClickHdl, weld::TreeView&, bool)
+{
+ GotoSelectedBookmark();
+ return true;
+}
+
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, SelectionChangedHdl, weld::TreeView&, void)
+{
+ if (!ValidateBookmarks())
+ return;
+ // this event should fired only if we change selection by clicking on BookmarkTable entry
+ if (!m_xBookmarksBox->has_focus())
+ return;
+
+ OUStringBuffer sEditBoxText;
+ int nSelectedRows = 0;
+ m_xBookmarksBox->selected_foreach(
+ [this, &sEditBoxText, &nSelectedRows](weld::TreeIter& rEntry) {
+ sw::mark::IMark* pBookmark
+ = weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(rEntry));
+ const OUString& sEntryName = pBookmark->GetName();
+ if (!sEditBoxText.isEmpty())
+ sEditBoxText.append(";");
+ sEditBoxText.append(sEntryName);
+ ++nSelectedRows;
+ return false;
+ });
+ if (nSelectedRows)
+ {
+ m_xInsertBtn->set_sensitive(false);
+ m_xGotoBtn->set_sensitive(nSelectedRows == 1);
+ m_xRenameBtn->set_sensitive(nSelectedRows == 1 && !m_bAreProtected);
+ m_xDeleteBtn->set_sensitive(!m_bAreProtected);
+ m_xEditBox->set_text(sEditBoxText.makeStringAndClear());
+ }
+ else
+ {
+ m_xInsertBtn->set_sensitive(!m_bAreProtected);
+ m_xGotoBtn->set_sensitive(false);
+ m_xRenameBtn->set_sensitive(false);
+ m_xDeleteBtn->set_sensitive(false);
+ }
+}
+
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, RenameHdl, weld::Button&, void)
+{
+ if (!ValidateBookmarks())
+ return;
+ auto xSelected = m_xBookmarksBox->get_selected();
+ if (!xSelected)
+ return;
+
+ sw::mark::IMark* pBookmark
+ = weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(*xSelected));
+ uno::Reference<frame::XModel> xModel = rSh.GetView().GetDocShell()->GetBaseModel();
+ uno::Reference<text::XBookmarksSupplier> xBkms(xModel, uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xNameAccess = xBkms->getBookmarks();
+ uno::Any aObj = xNameAccess->getByName(pBookmark->GetName());
+ uno::Reference<uno::XInterface> xTmp;
+ aObj >>= xTmp;
+ uno::Reference<container::XNamed> xNamed(xTmp, uno::UNO_QUERY);
+ SwAbstractDialogFactory& rFact = swui::GetFactory();
+ ScopedVclPtr<AbstractSwRenameXNamedDlg> pDlg(
+ rFact.CreateSwRenameXNamedDlg(m_xDialog.get(), xNamed, xNameAccess));
+ pDlg->SetForbiddenChars(BookmarkTable::aForbiddenChars
+ + OUStringChar(BookmarkTable::cSeparator));
+
+ if (pDlg->Execute())
+ {
+ ValidateBookmarks();
+ m_xDeleteBtn->set_sensitive(false);
+ m_xGotoBtn->set_sensitive(false);
+ m_xRenameBtn->set_sensitive(false);
+ m_xInsertBtn->set_sensitive(false);
+ }
+}
+
+// callback to an insert button. Inserts a new text mark to the current position.
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, InsertHdl, weld::Button&, void)
+{
+ OUString sBookmark = m_xEditBox->get_text();
+ rSh.SetBookmark2(vcl::KeyCode(), sBookmark, m_xHideCB->get_active(),
+ m_xConditionED->get_text());
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK(SwInsertBookmarkDlg, ChangeHideHdl, weld::Toggleable&, rBox, void)
+{
+ bool bHide = rBox.get_active();
+ m_xConditionED->set_sensitive(bHide);
+ m_xConditionFT->set_sensitive(bHide);
+}
+
+void SwInsertBookmarkDlg::GotoSelectedBookmark()
+{
+ if (!ValidateBookmarks())
+ return;
+ // if no entries selected we can't jump anywhere
+ // shouldn't be needed as we disable GoTo button when jump is not possible
+ auto xSelected = m_xBookmarksBox->get_selected();
+ if (!xSelected)
+ return;
+
+ sw::mark::IMark* pBookmark
+ = weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(*xSelected));
+
+ rSh.EnterStdMode();
+ rSh.GotoMark(pBookmark);
+}
+
+bool SwInsertBookmarkDlg::ValidateBookmarks()
+{
+ if (HaveBookmarksChanged())
+ {
+ PopulateTable();
+ m_xEditBox->set_text("");
+ return false;
+ }
+ return true;
+}
+
+bool SwInsertBookmarkDlg::HaveBookmarksChanged()
+{
+ IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess();
+ if (pMarkAccess->getBookmarksCount() != m_nLastBookmarksCount)
+ return true;
+
+ std::vector<std::pair<sw::mark::IMark*, OUString>>::const_iterator aListIter
+ = aTableBookmarks.begin();
+ for (IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
+ ppBookmark != pMarkAccess->getBookmarksEnd(); ++ppBookmark)
+ {
+ if (IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(**ppBookmark))
+ {
+ // more bookmarks then expected
+ if (aListIter == aTableBookmarks.end())
+ return true;
+ if (aListIter->first != *ppBookmark || aListIter->second != (*ppBookmark)->GetName())
+ return true;
+ ++aListIter;
+ }
+ }
+ // less bookmarks then expected
+ return aListIter != aTableBookmarks.end();
+}
+
+void SwInsertBookmarkDlg::PopulateTable()
+{
+ aTableBookmarks.clear();
+ m_xBookmarksBox->clear();
+
+ IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess();
+ for (IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
+ ppBookmark != pMarkAccess->getBookmarksEnd(); ++ppBookmark)
+ {
+ if (IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(**ppBookmark))
+ {
+ m_xBookmarksBox->InsertBookmark(*ppBookmark);
+ aTableBookmarks.emplace_back(*ppBookmark, (*ppBookmark)->GetName());
+ }
+ }
+ m_nLastBookmarksCount = pMarkAccess->getBookmarksCount();
+}
+
+SwInsertBookmarkDlg::SwInsertBookmarkDlg(weld::Window* pParent, SwWrtShell& rS)
+ : SfxDialogController(pParent, "modules/swriter/ui/insertbookmark.ui", "InsertBookmarkDialog")
+ , rSh(rS)
+ , m_nLastBookmarksCount(0)
+ , m_bSorted(false)
+ , m_xEditBox(m_xBuilder->weld_entry("name"))
+ , m_xInsertBtn(m_xBuilder->weld_button("insert"))
+ , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
+ , m_xGotoBtn(m_xBuilder->weld_button("goto"))
+ , m_xRenameBtn(m_xBuilder->weld_button("rename"))
+ , m_xHideCB(m_xBuilder->weld_check_button("hide"))
+ , m_xConditionFT(m_xBuilder->weld_label("condlabel"))
+ , m_xConditionED(new ConditionEdit(m_xBuilder->weld_entry("withcond")))
+ , m_xBookmarksBox(new BookmarkTable(m_xBuilder->weld_tree_view("bookmarks")))
+ , m_xForbiddenChars(m_xBuilder->weld_label("lbForbiddenChars"))
+{
+ m_xBookmarksBox->connect_changed(LINK(this, SwInsertBookmarkDlg, SelectionChangedHdl));
+ m_xBookmarksBox->connect_row_activated(LINK(this, SwInsertBookmarkDlg, DoubleClickHdl));
+ m_xBookmarksBox->connect_column_clicked(LINK(this, SwInsertBookmarkDlg, HeaderBarClick));
+ m_xEditBox->connect_changed(LINK(this, SwInsertBookmarkDlg, ModifyHdl));
+ m_xInsertBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, InsertHdl));
+ m_xDeleteBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, DeleteHdl));
+ m_xGotoBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, GotoHdl));
+ m_xRenameBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, RenameHdl));
+ m_xHideCB->connect_toggled(LINK(this, SwInsertBookmarkDlg, ChangeHideHdl));
+
+ m_xDeleteBtn->set_sensitive(false);
+ m_xGotoBtn->set_sensitive(false);
+ m_xRenameBtn->set_sensitive(false);
+
+ PopulateTable();
+
+ m_xEditBox->set_text(m_xBookmarksBox->GetNameProposal());
+ m_xEditBox->set_position(-1);
+
+ m_xForbiddenChars->set_label(SwResId(STR_BOOKMARK_FORBIDDENCHARS) + " "
+ + BookmarkTable::aForbiddenChars);
+ m_xForbiddenChars->set_visible(false);
+
+ if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
+ {
+ m_xHideCB->set_visible(false);
+ m_xConditionFT->set_visible(false);
+ m_xConditionED->set_visible(false);
+ }
+
+ m_bAreProtected = rSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS);
+
+ // disabled until "Hide" flag is not checked
+ m_xConditionED->set_sensitive(false);
+ m_xConditionFT->set_sensitive(false);
+
+ // restore dialog size
+ SvtViewOptions aDlgOpt(EViewType::Dialog, "BookmarkDialog");
+ if (aDlgOpt.Exists())
+ m_xDialog->set_window_state(aDlgOpt.GetWindowState().toUtf8());
+}
+
+SwInsertBookmarkDlg::~SwInsertBookmarkDlg()
+{
+ // tdf#146261 - Remember size of bookmark dialog
+ SvtViewOptions aDlgOpt(EViewType::Dialog, "BookmarkDialog");
+ OString sWindowState
+ = m_xDialog->get_window_state(WindowStateMask::Pos | WindowStateMask::Size);
+ aDlgOpt.SetWindowState(OUString::fromUtf8(sWindowState));
+}
+
+IMPL_LINK(SwInsertBookmarkDlg, HeaderBarClick, int, nColumn, void)
+{
+ if (!m_bSorted)
+ {
+ m_xBookmarksBox->make_sorted();
+ m_bSorted = true;
+ }
+
+ bool bSortAtoZ = m_xBookmarksBox->get_sort_order();
+
+ //set new arrow positions in headerbar
+ if (nColumn == m_xBookmarksBox->get_sort_column())
+ {
+ bSortAtoZ = !bSortAtoZ;
+ m_xBookmarksBox->set_sort_order(bSortAtoZ);
+ }
+ else
+ {
+ int nOldSortColumn = m_xBookmarksBox->get_sort_column();
+ if (nOldSortColumn != -1)
+ m_xBookmarksBox->set_sort_indicator(TRISTATE_INDET, nOldSortColumn);
+ m_xBookmarksBox->set_sort_column(nColumn);
+ }
+
+ if (nColumn != -1)
+ {
+ //sort lists
+ m_xBookmarksBox->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
+ }
+}
+
+BookmarkTable::BookmarkTable(std::unique_ptr<weld::TreeView> xControl)
+ : m_xControl(std::move(xControl))
+{
+ m_xControl->set_size_request(-1, m_xControl->get_height_rows(8));
+ m_xControl->set_column_fixed_widths({ 40, 110, 150, 160 });
+ m_xControl->set_selection_mode(SelectionMode::Multiple);
+}
+
+std::unique_ptr<weld::TreeIter> BookmarkTable::get_selected() const
+{
+ std::unique_ptr<weld::TreeIter> xIter(m_xControl->make_iterator());
+ if (!m_xControl->get_selected(xIter.get()))
+ xIter.reset();
+ return xIter;
+}
+
+void BookmarkTable::InsertBookmark(sw::mark::IMark* pMark)
+{
+ sw::mark::IBookmark* pBookmark = dynamic_cast<sw::mark::IBookmark*>(pMark);
+ assert(pBookmark);
+
+ OUString sBookmarkNodeText = pBookmark->GetMarkStart().nNode.GetNode().GetTextNode()->GetText();
+ sal_Int32 nBookmarkNodeTextPos = pBookmark->GetMarkStart().nContent.GetIndex();
+ sal_Int32 nBookmarkTextLen = 0;
+ bool bPulledAll = false;
+ bool bPulling = false;
+ static const sal_Int32 nMaxTextLen = 50;
+
+ if (pBookmark->IsExpanded())
+ {
+ nBookmarkTextLen = pBookmark->GetMarkEnd().nContent.GetIndex() - nBookmarkNodeTextPos;
+ }
+ else
+ {
+ if (nBookmarkNodeTextPos == sBookmarkNodeText.getLength()) // no text after bookmark
+ {
+ nBookmarkNodeTextPos = std::max<sal_Int32>(0, nBookmarkNodeTextPos - nMaxTextLen);
+ bPulling = true;
+ if (nBookmarkNodeTextPos == 0)
+ bPulledAll = true;
+ }
+ nBookmarkTextLen = sBookmarkNodeText.getLength() - nBookmarkNodeTextPos;
+ }
+ bool bExceedsLength = nBookmarkTextLen > nMaxTextLen;
+ nBookmarkTextLen = std::min<sal_Int32>(nMaxTextLen, nBookmarkTextLen);
+ sBookmarkNodeText
+ = o3tl::trim(sBookmarkNodeText.subView(nBookmarkNodeTextPos, nBookmarkTextLen));
+ if (bExceedsLength)
+ sBookmarkNodeText += "...";
+ else if (bPulling && !bPulledAll)
+ sBookmarkNodeText = "..." + sBookmarkNodeText;
+
+ const OUString& sHideCondition = pBookmark->GetHideCondition();
+ OUString sHidden = SwResId(STR_BOOKMARK_NO);
+ if (pBookmark->IsHidden() || !sHideCondition.isEmpty())
+ sHidden = SwResId(STR_BOOKMARK_YES);
+ OUString sPageNum = OUString::number(SwPaM(pMark->GetMarkStart()).GetPageNum());
+ int nRow = m_xControl->n_children();
+ m_xControl->append(weld::toId(pMark), sPageNum);
+ m_xControl->set_text(nRow, pBookmark->GetName(), 1);
+ m_xControl->set_text(nRow, sBookmarkNodeText, 2);
+ m_xControl->set_text(nRow, sHidden, 3);
+ m_xControl->set_text(nRow, sHideCondition, 4);
+}
+
+std::unique_ptr<weld::TreeIter> BookmarkTable::GetRowByBookmarkName(const OUString& sName)
+{
+ std::unique_ptr<weld::TreeIter> xRet;
+ m_xControl->all_foreach([this, &sName, &xRet](weld::TreeIter& rEntry) {
+ sw::mark::IMark* pBookmark = weld::fromId<sw::mark::IMark*>(m_xControl->get_id(rEntry));
+ if (pBookmark->GetName() == sName)
+ {
+ xRet = m_xControl->make_iterator(&rEntry);
+ return true;
+ }
+ return false;
+ });
+ return xRet;
+}
+
+sw::mark::IMark* BookmarkTable::GetBookmarkByName(const OUString& sName)
+{
+ auto xEntry = GetRowByBookmarkName(sName);
+ if (!xEntry)
+ return nullptr;
+
+ return weld::fromId<sw::mark::IMark*>(m_xControl->get_id(*xEntry));
+}
+
+void BookmarkTable::SelectByName(const OUString& sName)
+{
+ auto xEntry = GetRowByBookmarkName(sName);
+ if (!xEntry)
+ return;
+ select(*xEntry);
+}
+
+OUString BookmarkTable::GetNameProposal() const
+{
+ OUString sDefaultBookmarkName = SwResId(STR_BOOKMARK_DEF_NAME);
+ sal_Int32 nHighestBookmarkId = 0;
+ for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i)
+ {
+ sw::mark::IMark* pBookmark = weld::fromId<sw::mark::IMark*>(m_xControl->get_id(i));
+ const OUString& sName = pBookmark->GetName();
+ sal_Int32 nIndex = 0;
+ if (o3tl::getToken(sName, 0, ' ', nIndex) == sDefaultBookmarkName)
+ {
+ sal_Int32 nCurrBookmarkId = o3tl::toInt32(o3tl::getToken(sName, 0, ' ', nIndex));
+ nHighestBookmarkId = std::max<sal_Int32>(nHighestBookmarkId, nCurrBookmarkId);
+ }
+ }
+ return sDefaultBookmarkName + " " + OUString::number(nHighestBookmarkId + 1);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/contentcontroldlg.cxx b/sw/source/ui/misc/contentcontroldlg.cxx
new file mode 100644
index 000000000..95c86120e
--- /dev/null
+++ b/sw/source/ui/misc/contentcontroldlg.cxx
@@ -0,0 +1,414 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <contentcontroldlg.hxx>
+
+#include <vcl/weld.hxx>
+#include <cui/cuicharmap.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zformat.hxx>
+
+#include <wrtsh.hxx>
+#include <ndtxt.hxx>
+#include <textcontentcontrol.hxx>
+#include <IDocumentState.hxx>
+#include <swuiexp.hxx>
+#include <numfmtlb.hxx>
+
+using namespace com::sun::star;
+
+SwContentControlDlg::SwContentControlDlg(weld::Window* pParent, SwWrtShell& rWrtShell)
+ : SfxDialogController(pParent, "modules/swriter/ui/contentcontroldlg.ui",
+ "ContentControlDialog")
+ , m_rWrtShell(rWrtShell)
+ , m_xShowingPlaceHolderCB(m_xBuilder->weld_check_button("showing_place_holder"))
+ , m_xCheckboxFrame(m_xBuilder->weld_frame("checkboxframe"))
+ , m_xCheckedState(m_xBuilder->weld_entry("checkboxcheckedentry"))
+ , m_xCheckedStateBtn(m_xBuilder->weld_button("btncheckboxchecked"))
+ , m_xUncheckedState(m_xBuilder->weld_entry("checkboxuncheckedentry"))
+ , m_xUncheckedStateBtn(m_xBuilder->weld_button("btncheckboxunchecked"))
+ , m_xListItemsFrame(m_xBuilder->weld_frame("listitemsframe"))
+ , m_xListItems(m_xBuilder->weld_tree_view("listitems"))
+ , m_xListItemButtons(m_xBuilder->weld_box("listitembuttons"))
+ , m_xInsertBtn(m_xBuilder->weld_button("add"))
+ , m_xRenameBtn(m_xBuilder->weld_button("modify"))
+ , m_xDeleteBtn(m_xBuilder->weld_button("remove"))
+ , m_xMoveUpBtn(m_xBuilder->weld_button("moveup"))
+ , m_xMoveDownBtn(m_xBuilder->weld_button("movedown"))
+ , m_xDateFrame(m_xBuilder->weld_frame("dateframe"))
+ , m_xDateFormat(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("date_formats_treeview")))
+ , m_xOk(m_xBuilder->weld_button("ok"))
+{
+ m_xCheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
+ m_xUncheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
+ m_xListItems->connect_changed(LINK(this, SwContentControlDlg, SelectionChangedHdl));
+ m_xOk->connect_clicked(LINK(this, SwContentControlDlg, OkHdl));
+
+ // Only 2 items would be visible by default.
+ m_xListItems->set_size_request(-1, m_xListItems->get_height_rows(8));
+ // Only the first column would have a non-zero size by default in the SvHeaderTabListBox case.
+ m_xListItems->set_column_fixed_widths({ 100, 100 });
+
+ m_xInsertBtn->connect_clicked(LINK(this, SwContentControlDlg, InsertHdl));
+ m_xRenameBtn->connect_clicked(LINK(this, SwContentControlDlg, RenameHdl));
+ m_xDeleteBtn->connect_clicked(LINK(this, SwContentControlDlg, DeleteHdl));
+ m_xMoveUpBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveUpHdl));
+ m_xMoveDownBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveDownHdl));
+
+ const SwPosition* pStart = rWrtShell.GetCursor()->Start();
+ SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode();
+ if (!pTextNode)
+ {
+ return;
+ }
+
+ SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->nContent.GetIndex(),
+ RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT);
+ if (!pAttr)
+ {
+ return;
+ }
+
+ SwTextContentControl* pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
+ const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
+ m_pContentControl = rFormatContentControl.GetContentControl();
+
+ bool bShowingPlaceHolder = m_pContentControl->GetShowingPlaceHolder();
+ TriState eShowingPlaceHolder = bShowingPlaceHolder ? TRISTATE_TRUE : TRISTATE_FALSE;
+ m_xShowingPlaceHolderCB->set_state(eShowingPlaceHolder);
+ m_xShowingPlaceHolderCB->save_state();
+
+ if (m_pContentControl->GetCheckbox())
+ {
+ m_xCheckedState->set_text(m_pContentControl->GetCheckedState());
+ m_xCheckedState->save_value();
+ m_xUncheckedState->set_text(m_pContentControl->GetUncheckedState());
+ m_xUncheckedState->save_value();
+ }
+ else
+ {
+ m_xCheckboxFrame->set_visible(false);
+ }
+
+ if (m_pContentControl->HasListItems())
+ {
+ for (const auto& rListItem : m_pContentControl->GetListItems())
+ {
+ int nRow = m_xListItems->n_children();
+ m_xListItems->append_text(rListItem.m_aDisplayText);
+ m_xListItems->set_text(nRow, rListItem.m_aValue, 1);
+ }
+ m_aSavedListItems = m_pContentControl->GetListItems();
+ }
+ else
+ {
+ m_xListItemsFrame->set_visible(false);
+ m_xListItemButtons->set_visible(false);
+ }
+
+ if (m_pContentControl->GetDate())
+ {
+ m_xDateFormat->SetFormatType(SvNumFormatType::DATE);
+ m_xDateFormat->SetShowLanguageControl(true);
+
+ // Set height to double of the default.
+ weld::TreeView& rTreeView = dynamic_cast<weld::TreeView&>(m_xDateFormat->get_widget());
+ rTreeView.set_size_request(rTreeView.get_preferred_size().Width(),
+ rTreeView.get_height_rows(10));
+
+ OUString sFormatString = m_pContentControl->GetDateFormat();
+ OUString sLang = m_pContentControl->GetDateLanguage();
+ if (!sFormatString.isEmpty() && !sLang.isEmpty())
+ {
+ SvNumberFormatter* pNumberFormatter = m_rWrtShell.GetNumberFormatter();
+ LanguageType aLangType = LanguageTag(sLang).getLanguageType();
+ sal_uInt32 nFormat = pNumberFormatter->GetEntryKey(sFormatString, aLangType);
+ if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ sal_Int32 nCheckPos = 0;
+ SvNumFormatType nType;
+ pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat,
+ LanguageTag(sLang).getLanguageType());
+ }
+
+ if (aLangType != LANGUAGE_DONTKNOW && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ m_xDateFormat->SetDefFormat(nFormat);
+ }
+ }
+ }
+ else
+ {
+ m_xDateFrame->set_visible(false);
+ }
+}
+
+SwContentControlDlg::~SwContentControlDlg() {}
+
+IMPL_LINK_NOARG(SwContentControlDlg, OkHdl, weld::Button&, void)
+{
+ if (!m_pContentControl)
+ {
+ return;
+ }
+
+ bool bChanged = false;
+ if (m_xShowingPlaceHolderCB->get_state_changed_from_saved())
+ {
+ bool bShowingPlaceHolder = m_xShowingPlaceHolderCB->get_state() == TRISTATE_TRUE;
+ m_pContentControl->SetShowingPlaceHolder(bShowingPlaceHolder);
+ bChanged = true;
+ }
+
+ if (m_xCheckedState->get_value_changed_from_saved())
+ {
+ m_pContentControl->SetCheckedState(m_xCheckedState->get_text());
+ }
+
+ if (m_xUncheckedState->get_value_changed_from_saved())
+ {
+ m_pContentControl->SetUncheckedState(m_xUncheckedState->get_text());
+ }
+
+ std::vector<SwContentControlListItem> aItems;
+ for (int i = 0; i < m_xListItems->n_children(); ++i)
+ {
+ SwContentControlListItem aItem;
+ aItem.m_aDisplayText = m_xListItems->get_text(i, 0);
+ aItem.m_aValue = m_xListItems->get_text(i, 1);
+ aItems.push_back(aItem);
+ }
+ if (aItems != m_aSavedListItems)
+ {
+ m_pContentControl->SetListItems(aItems);
+ bChanged = true;
+ }
+
+ if (m_pContentControl->GetDate())
+ {
+ SvNumberFormatter* pNumberFormatter = m_rWrtShell.GetNumberFormatter();
+ const SvNumberformat* pFormat = pNumberFormatter->GetEntry(m_xDateFormat->GetFormat());
+ if (pFormat)
+ {
+ if (pFormat->GetFormatstring() != m_pContentControl->GetDateFormat())
+ {
+ m_pContentControl->SetDateFormat(pFormat->GetFormatstring());
+ bChanged = true;
+ }
+
+ OUString aLanguage = LanguageTag(pFormat->GetLanguage()).getBcp47();
+ if (aLanguage != m_pContentControl->GetDateLanguage())
+ {
+ m_pContentControl->SetDateLanguage(aLanguage);
+ bChanged = true;
+ }
+ }
+ }
+
+ if (bChanged)
+ {
+ m_rWrtShell.GetDoc()->getIDocumentState().SetModified();
+
+ // Make sure that the cursor gets updated with the new list items.
+ m_rWrtShell.HideCursor();
+ m_rWrtShell.ShowCursor();
+ }
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK(SwContentControlDlg, SelectCharHdl, weld::Button&, rButton, void)
+{
+ SvxCharacterMap aMap(m_xDialog.get(), nullptr, nullptr);
+ sal_UCS4 cBullet = 0;
+ sal_Int32 nIndex = 0;
+ if (&rButton == m_xCheckedStateBtn.get())
+ {
+ cBullet = m_pContentControl->GetCheckedState().iterateCodePoints(&nIndex);
+ }
+ else if (&rButton == m_xUncheckedStateBtn.get())
+ {
+ cBullet = m_pContentControl->GetUncheckedState().iterateCodePoints(&nIndex);
+ }
+ aMap.SetChar(cBullet);
+ if (aMap.run() != RET_OK)
+ {
+ return;
+ }
+
+ cBullet = aMap.GetChar();
+ if (&rButton == m_xCheckedStateBtn.get())
+ {
+ m_xCheckedState->set_text(OUString(&cBullet, 1));
+ }
+ else if (&rButton == m_xUncheckedStateBtn.get())
+ {
+ m_xUncheckedState->set_text(OUString(&cBullet, 1));
+ }
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, InsertHdl, weld::Button&, void)
+{
+ SwContentControlListItem aItem;
+ SwAbstractDialogFactory& rFact = swui::GetFactory();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), aItem));
+ if (!pDlg->Execute())
+ {
+ return;
+ }
+
+ if (aItem.m_aDisplayText.isEmpty() && aItem.m_aValue.isEmpty())
+ {
+ // Maintain the invariant that value can't be empty.
+ return;
+ }
+
+ if (aItem.m_aValue.isEmpty())
+ {
+ aItem.m_aValue = aItem.m_aDisplayText;
+ }
+
+ int nRow = m_xListItems->n_children();
+ m_xListItems->append_text(aItem.m_aDisplayText);
+ m_xListItems->set_text(nRow, aItem.m_aValue, 1);
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, RenameHdl, weld::Button&, void)
+{
+ int nRow = m_xListItems->get_selected_index();
+ if (nRow < 0)
+ {
+ return;
+ }
+
+ SwContentControlListItem aItem;
+ aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
+ aItem.m_aValue = m_xListItems->get_text(nRow, 1);
+ SwAbstractDialogFactory& rFact = swui::GetFactory();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), aItem));
+ if (!pDlg->Execute())
+ {
+ return;
+ }
+
+ if (aItem.m_aDisplayText.isEmpty() && aItem.m_aValue.isEmpty())
+ {
+ // Maintain the invariant that value can't be empty.
+ return;
+ }
+
+ if (aItem.m_aValue.isEmpty())
+ {
+ aItem.m_aValue = aItem.m_aDisplayText;
+ }
+
+ m_xListItems->set_text(nRow, aItem.m_aDisplayText, 0);
+ m_xListItems->set_text(nRow, aItem.m_aValue, 1);
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, DeleteHdl, weld::Button&, void)
+{
+ int nRow = m_xListItems->get_selected_index();
+ if (nRow < 0)
+ {
+ return;
+ }
+
+ m_xListItems->remove(nRow);
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, MoveUpHdl, weld::Button&, void)
+{
+ int nRow = m_xListItems->get_selected_index();
+ if (nRow <= 0)
+ {
+ return;
+ }
+
+ SwContentControlListItem aItem;
+ aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
+ aItem.m_aValue = m_xListItems->get_text(nRow, 1);
+ m_xListItems->remove(nRow);
+ --nRow;
+ m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
+ m_xListItems->set_text(nRow, aItem.m_aValue, 1);
+ m_xListItems->select(nRow);
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, MoveDownHdl, weld::Button&, void)
+{
+ int nRow = m_xListItems->get_selected_index();
+ int nEndPos = m_xListItems->n_children() - 1;
+ if (nRow < 0 || nRow >= nEndPos)
+ {
+ return;
+ }
+
+ SwContentControlListItem aItem;
+ aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
+ aItem.m_aValue = m_xListItems->get_text(nRow, 1);
+ m_xListItems->remove(nRow);
+ ++nRow;
+ m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
+ m_xListItems->set_text(nRow, aItem.m_aValue, 1);
+ m_xListItems->select(nRow);
+}
+
+IMPL_LINK_NOARG(SwContentControlDlg, SelectionChangedHdl, weld::TreeView&, void)
+{
+ if (!m_xListItems->has_focus())
+ {
+ return;
+ }
+
+ int nRow = m_xListItems->get_selected_index();
+ if (nRow < 0)
+ {
+ m_xRenameBtn->set_sensitive(false);
+ m_xDeleteBtn->set_sensitive(false);
+ }
+ else
+ {
+ m_xRenameBtn->set_sensitive(true);
+ m_xDeleteBtn->set_sensitive(true);
+ }
+
+ if (nRow <= 0)
+ {
+ m_xMoveUpBtn->set_sensitive(false);
+ }
+ else
+ {
+ m_xMoveUpBtn->set_sensitive(true);
+ }
+
+ int nEndPos = m_xListItems->n_children() - 1;
+ if (nRow < 0 || nRow >= nEndPos)
+ {
+ m_xMoveDownBtn->set_sensitive(false);
+ }
+ else
+ {
+ m_xMoveDownBtn->set_sensitive(true);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/contentcontrollistitemdlg.cxx b/sw/source/ui/misc/contentcontrollistitemdlg.cxx
new file mode 100644
index 000000000..6ac160aeb
--- /dev/null
+++ b/sw/source/ui/misc/contentcontrollistitemdlg.cxx
@@ -0,0 +1,48 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <contentcontrollistitemdlg.hxx>
+
+#include <formatcontentcontrol.hxx>
+
+using namespace com::sun::star;
+
+SwContentControlListItemDlg::SwContentControlListItemDlg(weld::Widget* pParent,
+ SwContentControlListItem& rItem)
+ : GenericDialogController(pParent, "modules/swriter/ui/contentcontrollistitemdlg.ui",
+ "ContentControlListItemDialog")
+ , m_rItem(rItem)
+ , m_xDisplayNameED(m_xBuilder->weld_entry("displayname"))
+ , m_xValueED(m_xBuilder->weld_entry("value"))
+ , m_xOk(m_xBuilder->weld_button("ok"))
+{
+ m_xOk->connect_clicked(LINK(this, SwContentControlListItemDlg, OkHdl));
+ m_xDisplayNameED->set_text(rItem.m_aDisplayText);
+ m_xValueED->set_text(rItem.m_aValue);
+}
+
+IMPL_LINK_NOARG(SwContentControlListItemDlg, OkHdl, weld::Button&, void)
+{
+ m_rItem.m_aDisplayText = m_xDisplayNameED->get_text();
+ m_rItem.m_aValue = m_xValueED->get_text();
+
+ m_xDialog->response(RET_OK);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/docfnote.cxx b/sw/source/ui/misc/docfnote.cxx
new file mode 100644
index 000000000..e065a272e
--- /dev/null
+++ b/sw/source/ui/misc/docfnote.cxx
@@ -0,0 +1,394 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/style.hxx>
+#include <osl/diagnose.h>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <docfnote.hxx>
+#include "impfnote.hxx"
+#include <ftninfo.hxx>
+#include <fmtcol.hxx>
+#include <pagedesc.hxx>
+#include <charfmt.hxx>
+#include <docstyle.hxx>
+#include <wdocsh.hxx>
+#include <uitool.hxx>
+#include <poolfmt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <memory>
+
+SwFootNoteOptionDlg::SwFootNoteOptionDlg(weld::Window *pParent, SwWrtShell &rS)
+ : SfxTabDialogController(pParent, "modules/swriter/ui/footendnotedialog.ui", "FootEndnoteDialog")
+ , rSh( rS )
+{
+ RemoveResetButton();
+
+ GetOKButton().connect_clicked(LINK(this, SwFootNoteOptionDlg, OkHdl));
+
+ AddTabPage("footnotes", SwFootNoteOptionPage::Create, nullptr);
+ AddTabPage("endnotes", SwEndNoteOptionPage::Create, nullptr);
+}
+
+void SwFootNoteOptionDlg::PageCreated(const OString& /*rId*/, SfxTabPage &rPage)
+{
+ static_cast<SwEndNoteOptionPage&>(rPage).SetShell(rSh);
+}
+
+IMPL_LINK(SwFootNoteOptionDlg, OkHdl, weld::Button&, rBtn, void)
+{
+ SfxItemSetFixed<1, 1> aDummySet(rSh.GetAttrPool());
+ SfxTabPage *pPage = GetTabPage("footnotes");
+ if ( pPage )
+ pPage->FillItemSet( &aDummySet );
+ pPage = GetTabPage("endnotes");
+ if ( pPage )
+ pPage->FillItemSet( &aDummySet );
+ SfxTabDialogController::OkHdl(rBtn);
+}
+
+SwEndNoteOptionPage::SwEndNoteOptionPage(weld::Container* pPage, weld::DialogController* pController, bool bEN,
+ const SfxItemSet &rSet)
+ : SfxTabPage(pPage, pController,
+ bEN ? OUString("modules/swriter/ui/endnotepage.ui") : OUString("modules/swriter/ui/footnotepage.ui"),
+ bEN ? OString("EndnotePage") : OString("FootnotePage"),
+ &rSet)
+ , pSh(nullptr)
+ , bPosDoc(false)
+ , bEndNote(bEN)
+ , m_xNumViewBox(new SwNumberingTypeListBox(m_xBuilder->weld_combo_box("numberinglb")))
+ , m_xOffsetLbl(m_xBuilder->weld_label("offset"))
+ , m_xOffsetField(m_xBuilder->weld_spin_button("offsetnf"))
+ , m_xNumCountBox(m_xBuilder->weld_combo_box("countinglb"))
+ , m_xPrefixED(m_xBuilder->weld_entry("prefix"))
+ , m_xSuffixED(m_xBuilder->weld_entry("suffix"))
+ , m_xPosFT(m_xBuilder->weld_label("pos"))
+ , m_xPosPageBox(m_xBuilder->weld_radio_button("pospagecb"))
+ , m_xPosChapterBox(m_xBuilder->weld_radio_button("posdoccb"))
+ , m_xStylesContainer(m_xBuilder->weld_widget("allstyles"))
+ , m_xParaTemplBox(m_xBuilder->weld_combo_box("parastylelb"))
+ , m_xPageTemplLbl(m_xBuilder->weld_label("pagestyleft"))
+ , m_xPageTemplBox(m_xBuilder->weld_combo_box("pagestylelb"))
+ , m_xFootnoteCharAnchorTemplBox(m_xBuilder->weld_combo_box("charanchorstylelb"))
+ , m_xFootnoteCharTextTemplBox(m_xBuilder->weld_combo_box("charstylelb"))
+ , m_xContEdit(m_xBuilder->weld_entry("conted"))
+ , m_xContFromEdit(m_xBuilder->weld_entry("contfromed"))
+{
+ m_xNumViewBox->Reload(SwInsertNumTypes::Extended);
+ if (!bEndNote)
+ {
+ m_xNumCountBox->connect_changed(LINK(this, SwEndNoteOptionPage, NumCountHdl));
+ aNumDoc = m_xNumCountBox->get_text(FTNNUM_DOC);
+ aNumPage = m_xNumCountBox->get_text(FTNNUM_PAGE);
+ aNumChapter = m_xNumCountBox->get_text(FTNNUM_CHAPTER);
+ m_xPosPageBox->connect_toggled(LINK(this, SwEndNoteOptionPage, ToggleHdl));
+ m_xPosChapterBox->connect_toggled(LINK(this, SwEndNoteOptionPage, ToggleHdl));
+ }
+ m_xParaTemplBox->make_sorted();
+}
+
+SwEndNoteOptionPage::~SwEndNoteOptionPage()
+{
+}
+
+void SwEndNoteOptionPage::Reset( const SfxItemSet* )
+{
+ std::unique_ptr<SwEndNoteInfo> pInf(bEndNote ? new SwEndNoteInfo( pSh->GetEndNoteInfo() )
+ : new SwFootnoteInfo( pSh->GetFootnoteInfo() ));
+ SfxObjectShell * pDocSh = SfxObjectShell::Current();
+
+ if (dynamic_cast<SwWebDocShell*>( pDocSh) )
+ m_xStylesContainer->hide();
+
+ if ( bEndNote )
+ {
+ bPosDoc = true;
+ }
+ else
+ {
+ const SwFootnoteInfo &rInf = pSh->GetFootnoteInfo();
+ // set position (page, chapter)
+ if ( rInf.m_ePos == FTNPOS_PAGE )
+ {
+ m_xPosPageBox->set_active(true);
+ m_xPageTemplLbl->set_sensitive(false);
+ m_xPageTemplBox->set_sensitive(false);
+ }
+ else
+ {
+ m_xPosChapterBox->set_active(true);
+ m_xNumCountBox->remove_text(aNumPage);
+ m_xNumCountBox->remove_text(aNumChapter);
+ bPosDoc = true;
+ }
+ // reference tests
+ m_xContEdit->set_text(rInf.m_aQuoVadis);
+ m_xContFromEdit->set_text(rInf.m_aErgoSum);
+
+ // collected
+ SelectNumbering(rInf.m_eNum);
+ }
+
+ // numbering
+ // art
+ m_xNumViewBox->SelectNumberingType( pInf->m_aFormat.GetNumberingType());
+ m_xOffsetField->set_value(pInf->m_nFootnoteOffset + 1);
+ m_xPrefixED->set_text(pInf->GetPrefix().replaceAll("\t", "\\t")); // fdo#65666
+ m_xSuffixED->set_text(pInf->GetSuffix().replaceAll("\t", "\\t"));
+
+ const SwCharFormat* pCharFormat = pInf->GetCharFormat(
+ *pSh->GetView().GetDocShell()->GetDoc());
+ m_xFootnoteCharTextTemplBox->set_active_text(pCharFormat->GetName());
+ m_xFootnoteCharTextTemplBox->save_value();
+
+ pCharFormat = pInf->GetAnchorCharFormat( *pSh->GetDoc() );
+ m_xFootnoteCharAnchorTemplBox->set_active_text( pCharFormat->GetName() );
+ m_xFootnoteCharAnchorTemplBox->save_value();
+
+ // styles special regions
+ // paragraph
+ SfxStyleSheetBasePool* pStyleSheetPool = pSh->GetView().GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase *pStyle = pStyleSheetPool->First(SfxStyleFamily::Para, SfxStyleSearchBits::SwExtra);
+ while(pStyle)
+ {
+ m_xParaTemplBox->append_text(pStyle->GetName());
+ pStyle = pStyleSheetPool->Next();
+ }
+
+ OUString sStr;
+ SwStyleNameMapper::FillUIName( static_cast< sal_uInt16 >(bEndNote ? RES_POOLCOLL_ENDNOTE
+ : RES_POOLCOLL_FOOTNOTE), sStr );
+ if (m_xParaTemplBox->find_text(sStr) == -1)
+ m_xParaTemplBox->append_text(sStr);
+
+ SwTextFormatColl* pColl = pInf->GetFootnoteTextColl();
+ if( !pColl )
+ m_xParaTemplBox->set_active_text(sStr); // Default
+ else
+ {
+ OSL_ENSURE(!pColl->IsDefault(), "default style for footnotes is wrong");
+ const int nPos = m_xParaTemplBox->find_text(pColl->GetName());
+ if (nPos != -1)
+ m_xParaTemplBox->set_active( nPos );
+ else
+ {
+ m_xParaTemplBox->append_text(pColl->GetName());
+ m_xParaTemplBox->set_active_text(pColl->GetName());
+ }
+ }
+
+ // page
+ for (sal_uInt16 i = RES_POOLPAGE_BEGIN; i < RES_POOLPAGE_END; ++i)
+ m_xPageTemplBox->append_text(SwStyleNameMapper::GetUIName(i, OUString()));
+
+ const size_t nCount = pSh->GetPageDescCnt();
+ for(size_t i = 0; i < nCount; ++i)
+ {
+ const SwPageDesc &rPageDesc = pSh->GetPageDesc(i);
+ if (m_xPageTemplBox->find_text(rPageDesc.GetName()) == -1)
+ m_xPageTemplBox->append_text(rPageDesc.GetName());
+ }
+ m_xPageTemplBox->make_sorted();
+
+ m_xPageTemplBox->set_active_text(pInf->GetPageDesc(*pSh->GetDoc())->GetName());
+}
+
+std::unique_ptr<SfxTabPage> SwEndNoteOptionPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet )
+{
+ return std::make_unique<SwEndNoteOptionPage>(pPage, pController, true, *rSet);
+}
+
+// Different kinds of numbering; because the Listbox has varying numbers of
+// entries, here are functions to set and query the intended kind of numbering.
+void SwEndNoteOptionPage::SelectNumbering(SwFootnoteNum const eNum)
+{
+ OUString sSelect;
+ switch(eNum)
+ {
+ case FTNNUM_DOC:
+ sSelect = aNumDoc;
+ break;
+ case FTNNUM_PAGE:
+ sSelect = aNumPage;
+ break;
+ case FTNNUM_CHAPTER:
+ sSelect = aNumChapter;
+ break;
+ default:
+ assert(false);
+ }
+ m_xNumCountBox->set_active_text(sSelect);
+ NumCountHdl(*m_xNumCountBox);
+}
+
+SwFootnoteNum SwEndNoteOptionPage::GetNumbering() const
+{
+ const int nPos = m_xNumCountBox->get_active();
+ return static_cast<SwFootnoteNum>(bPosDoc ? nPos + 2 : nPos);
+}
+
+void SwEndNoteOptionPage::SetShell( SwWrtShell &rShell )
+{
+ pSh = &rShell;
+ // collect character templates
+ m_xFootnoteCharTextTemplBox->clear();
+ m_xFootnoteCharAnchorTemplBox->clear();
+ ::FillCharStyleListBox(*m_xFootnoteCharTextTemplBox,
+ pSh->GetView().GetDocShell(), true);
+
+ ::FillCharStyleListBox(*m_xFootnoteCharAnchorTemplBox,
+ pSh->GetView().GetDocShell(), true);
+}
+
+IMPL_LINK(SwEndNoteOptionPage, ToggleHdl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+
+ if (m_xPosPageBox->get_active())
+ {
+ // Handler behind the button to collect the footnote at the page. In this case
+ // all kinds of numbering can be used.
+
+ const SwFootnoteNum eNum = GetNumbering();
+ bPosDoc = false;
+ if (m_xNumCountBox->find_text(aNumPage) == -1)
+ {
+ m_xNumCountBox->insert_text(FTNNUM_PAGE, aNumPage);
+ m_xNumCountBox->insert_text(FTNNUM_CHAPTER, aNumChapter);
+ SelectNumbering(eNum);
+ }
+ m_xPageTemplLbl->set_sensitive(false);
+ m_xPageTemplBox->set_sensitive(false);
+ }
+ else if (m_xPosChapterBox->get_active())
+ {
+ // Handler behind the button to collect the footnote at the chapter or end of
+ // the document. In this case no pagewise numbering can be used.
+
+ if ( !bPosDoc )
+ SelectNumbering(FTNNUM_DOC);
+
+ bPosDoc = true;
+ m_xNumCountBox->remove_text(aNumPage);
+ m_xNumCountBox->remove_text(aNumChapter);
+ m_xPageTemplLbl->set_sensitive(true);
+ m_xPageTemplBox->set_sensitive(true);
+ }
+}
+
+IMPL_LINK_NOARG(SwEndNoteOptionPage, NumCountHdl, weld::ComboBox&, void)
+{
+ bool bEnable = true;
+ if (m_xNumCountBox->get_count() - 1 != m_xNumCountBox->get_active())
+ {
+ bEnable = false;
+ m_xOffsetField->set_value(1);
+ }
+ m_xOffsetLbl->set_sensitive(bEnable);
+ m_xOffsetField->set_sensitive(bEnable);
+}
+
+static SwCharFormat* lcl_GetCharFormat( SwWrtShell* pSh, const OUString& rCharFormatName )
+{
+ SwCharFormat* pFormat = nullptr;
+ const sal_uInt16 nChCount = pSh->GetCharFormatCount();
+ for(sal_uInt16 i = 0; i< nChCount; i++)
+ {
+ SwCharFormat& rChFormat = pSh->GetCharFormat(i);
+ if(rChFormat.GetName() == rCharFormatName )
+ {
+ pFormat = &rChFormat;
+ break;
+ }
+ }
+ if(!pFormat)
+ {
+ SfxStyleSheetBasePool* pPool = pSh->GetView().GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase* pBase;
+ pBase = pPool->Find(rCharFormatName, SfxStyleFamily::Char);
+ if(!pBase)
+ pBase = &pPool->Make(rCharFormatName, SfxStyleFamily::Char);
+ pFormat = static_cast<SwDocStyleSheet*>(pBase)->GetCharFormat();
+ }
+ return pFormat;
+}
+
+bool SwEndNoteOptionPage::FillItemSet( SfxItemSet * )
+{
+ std::unique_ptr<SwEndNoteInfo> pInf(bEndNote ? new SwEndNoteInfo() : new SwFootnoteInfo());
+
+ pInf->m_nFootnoteOffset = m_xOffsetField->get_value() - 1;
+ pInf->m_aFormat.SetNumberingType(m_xNumViewBox->GetSelectedNumberingType() );
+ pInf->SetPrefix(m_xPrefixED->get_text().replaceAll("\\t", "\t"));
+ pInf->SetSuffix(m_xSuffixED->get_text().replaceAll("\\t", "\t"));
+
+ pInf->SetCharFormat( lcl_GetCharFormat( pSh,
+ m_xFootnoteCharTextTemplBox->get_active_text() ) );
+ pInf->SetAnchorCharFormat( lcl_GetCharFormat( pSh,
+ m_xFootnoteCharAnchorTemplBox->get_active_text() ) );
+
+ // paragraph template
+ int nPos = m_xParaTemplBox->get_active();
+ if (nPos != -1)
+ {
+ const OUString aFormatName( m_xParaTemplBox->get_active_text() );
+ SwTextFormatColl *pColl = pSh->GetParaStyle(aFormatName, SwWrtShell::GETSTYLE_CREATEANY);
+ OSL_ENSURE(pColl, "paragraph style not found");
+ pInf->SetFootnoteTextColl(*pColl);
+ }
+
+ // page template
+ pInf->ChgPageDesc( pSh->FindPageDescByName(
+ m_xPageTemplBox->get_active_text(), true ) );
+
+ if ( bEndNote )
+ {
+ if ( !(*pInf == pSh->GetEndNoteInfo()) )
+ pSh->SetEndNoteInfo( *pInf );
+ }
+ else
+ {
+ SwFootnoteInfo *pI = static_cast<SwFootnoteInfo*>(pInf.get());
+ pI->m_ePos = m_xPosPageBox->get_active() ? FTNPOS_PAGE : FTNPOS_CHAPTER;
+ pI->m_eNum = GetNumbering();
+ pI->m_aQuoVadis = m_xContEdit->get_text();
+ pI->m_aErgoSum = m_xContFromEdit->get_text();
+ if ( !(*pI == pSh->GetFootnoteInfo()) )
+ pSh->SetFootnoteInfo( *pI );
+ }
+ return true;
+}
+
+SwFootNoteOptionPage::SwFootNoteOptionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
+ : SwEndNoteOptionPage(pPage, pController, false, rSet)
+{
+}
+
+SwFootNoteOptionPage::~SwFootNoteOptionPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> SwFootNoteOptionPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet )
+{
+ return std::make_unique<SwFootNoteOptionPage>(pPage, pController, *rSet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/glosbib.cxx b/sw/source/ui/misc/glosbib.cxx
new file mode 100644
index 000000000..934cd47fb
--- /dev/null
+++ b/sw/source/ui/misc/glosbib.cxx
@@ -0,0 +1,405 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/urlobj.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/pathoptions.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <swtypes.hxx>
+#include <glosbib.hxx>
+#include <gloshdl.hxx>
+#include <glossary.hxx>
+#include <glosdoc.hxx>
+#include <swunohelper.hxx>
+
+#include <strings.hrc>
+
+#define PATH_CASE_SENSITIVE 0x01
+#define PATH_READONLY 0x02
+
+#define RENAME_TOKEN_DELIM u'\x0001'
+
+SwGlossaryGroupDlg::SwGlossaryGroupDlg(weld::Window * pParent,
+ std::vector<OUString> const& rPathArr, SwGlossaryHdl *pHdl)
+ : SfxDialogController(pParent, "modules/swriter/ui/editcategories.ui",
+ "EditCategoriesDialog")
+ , m_pParent(pParent)
+ , pGlosHdl(pHdl)
+ , m_xNameED(m_xBuilder->weld_entry("name"))
+ , m_xPathLB(m_xBuilder->weld_combo_box("pathlb"))
+ , m_xGroupTLB(m_xBuilder->weld_tree_view("group"))
+ , m_xNewPB(m_xBuilder->weld_button("new"))
+ , m_xDelPB(m_xBuilder->weld_button("delete"))
+ , m_xRenamePB(m_xBuilder->weld_button("rename"))
+{
+ int nWidth = m_xGroupTLB->get_approximate_digit_width() * 34;
+ m_xPathLB->set_size_request(nWidth, -1);
+ //just has to be something small, real size will be available space
+ m_xGroupTLB->set_size_request(nWidth, m_xGroupTLB->get_height_rows(10));
+
+ m_xGroupTLB->set_column_fixed_widths( { nWidth } );
+ m_xGroupTLB->connect_changed(LINK(this, SwGlossaryGroupDlg, SelectHdl));
+
+ m_xNewPB->connect_clicked(LINK(this, SwGlossaryGroupDlg, NewHdl));
+ m_xDelPB->connect_clicked(LINK(this, SwGlossaryGroupDlg, DeleteHdl));
+ m_xNameED->connect_changed(LINK(this, SwGlossaryGroupDlg, ModifyHdl));
+ m_xNameED->connect_insert_text(LINK(this, SwGlossaryGroupDlg, EditInsertTextHdl));
+ m_xPathLB->connect_changed(LINK(this, SwGlossaryGroupDlg, ModifyListBoxHdl));
+ m_xRenamePB->connect_clicked(LINK(this, SwGlossaryGroupDlg, RenameHdl));
+
+ m_xNameED->connect_size_allocate(LINK(this, SwGlossaryGroupDlg, EntrySizeAllocHdl));
+ m_xPathLB->connect_size_allocate(LINK(this, SwGlossaryGroupDlg, EntrySizeAllocHdl));
+
+ for (size_t i = 0; i < rPathArr.size(); ++i)
+ {
+ INetURLObject aTempURL(rPathArr[i]);
+ const OUString sPath = aTempURL.GetMainURL(INetURLObject::DecodeMechanism::WithCharset );
+ sal_uInt32 nCaseReadonly = 0;
+ utl::TempFile aTempFile(&sPath);
+ aTempFile.EnableKillingFile();
+ if(!aTempFile.IsValid())
+ nCaseReadonly |= PATH_READONLY;
+ else if( SWUnoHelper::UCB_IsCaseSensitiveFileName( aTempFile.GetURL()))
+ nCaseReadonly |= PATH_CASE_SENSITIVE;
+ m_xPathLB->append(OUString::number(nCaseReadonly), sPath);
+ }
+ m_xPathLB->set_active(0);
+ m_xPathLB->set_sensitive(true);
+
+ const size_t nCount = pHdl->GetGroupCnt();
+ /* tdf#111870 "My AutoText" comes from mytexts.bau but should be translated
+ here as well, see also SwGlossaryDlg::Init */
+ static const OUStringLiteral sMyAutoTextEnglish(u"My AutoText");
+ for( size_t i = 0; i < nCount; ++i)
+ {
+ OUString sTitle;
+ OUString sGroup = pHdl->GetGroupName(i, &sTitle);
+ if(sGroup.isEmpty())
+ continue;
+ GlosBibUserData* pData = new GlosBibUserData;
+ pData->sGroupName = sGroup;
+ if ( sTitle == sMyAutoTextEnglish )
+ pData->sGroupTitle = SwResId(STR_MY_AUTOTEXT);
+ else
+ pData->sGroupTitle = sTitle;
+ pData->sPath = m_xPathLB->get_text(o3tl::toInt32(o3tl::getToken(sGroup, 1, GLOS_DELIM)));
+ const OUString sId(weld::toId(pData));
+ m_xGroupTLB->append(sId, pData->sGroupTitle);
+ int nEntry = m_xGroupTLB->find_id(sId);
+ m_xGroupTLB->set_text(nEntry, pData->sPath, 1);
+
+ }
+ m_xGroupTLB->make_sorted();
+}
+
+SwGlossaryGroupDlg::~SwGlossaryGroupDlg()
+{
+ int nCount = m_xGroupTLB->n_children();
+ for (int i = 0; i < nCount; ++i)
+ {
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(i));
+ delete pUserData;
+ }
+}
+
+short SwGlossaryGroupDlg::run()
+{
+ short nRet = SfxDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+}
+
+void SwGlossaryGroupDlg::Apply()
+{
+ if (m_xNewPB->get_sensitive())
+ NewHdl(*m_xNewPB);
+
+ const OUString aActGroup = SwGlossaryDlg::GetCurrGroup();
+
+ for (const auto& removedStr : m_RemovedArr)
+ {
+ sal_Int32 nIdx{ 0 };
+ const OUString sDelGroup = removedStr.getToken(0, '\t', nIdx);
+ if( sDelGroup == aActGroup )
+ {
+ //when the current group is deleted, the current group has to be relocated
+ if (m_xGroupTLB->n_children())
+ {
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(0));
+ pGlosHdl->SetCurGroup(pUserData->sGroupName);
+ }
+ }
+ const OUString sMsg(SwResId(STR_QUERY_DELETE_GROUP1)
+ + o3tl::getToken(removedStr, 0, '\t', nIdx)
+ + SwResId(STR_QUERY_DELETE_GROUP2));
+
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_pParent,
+ VclMessageType::Question, VclButtonsType::YesNo, sMsg));
+ xQueryBox->set_default_response(RET_NO);
+ if (RET_YES == xQueryBox->run())
+ pGlosHdl->DelGroup( sDelGroup );
+ }
+
+ //don't rename before there was one
+ for (auto it(m_RenamedArr.cbegin()); it != m_RenamedArr.cend(); ++it)
+ {
+ sal_Int32 nIdx{ 0 };
+ OUString const sOld(it->getToken(0, RENAME_TOKEN_DELIM, nIdx));
+ OUString sNew(it->getToken(0, RENAME_TOKEN_DELIM, nIdx));
+ OUString const sTitle(it->getToken(0, RENAME_TOKEN_DELIM, nIdx));
+ pGlosHdl->RenameGroup(sOld, sNew, sTitle);
+ if (it == m_RenamedArr.begin())
+ {
+ sCreatedGroup = sNew;
+ }
+ }
+ for (auto& sNewGroup : m_InsertedArr)
+ {
+ OUString sNewTitle = sNewGroup.getToken(0, GLOS_DELIM);
+ if( sNewGroup != aActGroup )
+ {
+ pGlosHdl->NewGroup(sNewGroup, sNewTitle);
+ if(sCreatedGroup.isEmpty())
+ sCreatedGroup = sNewGroup;
+ }
+ }
+}
+
+IMPL_LINK_NOARG( SwGlossaryGroupDlg, SelectHdl, weld::TreeView&, void )
+{
+ m_xNewPB->set_sensitive(false);
+ int nFirstEntry = m_xGroupTLB->get_selected_index();
+ if (nFirstEntry == -1)
+ return;
+
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(nFirstEntry));
+ const OUString sEntry(pUserData->sGroupName);
+ const OUString sName(m_xNameED->get_text());
+ bool bExists = false;
+ int nPos = m_xGroupTLB->find_text(sName);
+ if (nPos != -1)
+ {
+ GlosBibUserData* pFoundData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(nPos));
+ bExists = pFoundData->sGroupName == sEntry;
+ }
+
+ m_xRenamePB->set_sensitive(!bExists && !sName.isEmpty());
+ m_xDelPB->set_sensitive(IsDeleteAllowed(sEntry));
+}
+
+IMPL_LINK_NOARG(SwGlossaryGroupDlg, NewHdl, weld::Button&, void)
+{
+ OUString sGroup = m_xNameED->get_text()
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(m_xPathLB->get_active());
+ OSL_ENSURE(!pGlosHdl->FindGroupName(sGroup), "group already available!");
+ m_InsertedArr.push_back(sGroup);
+ GlosBibUserData* pData = new GlosBibUserData;
+ pData->sPath = m_xPathLB->get_active_text();
+ pData->sGroupName = sGroup;
+ pData->sGroupTitle = m_xNameED->get_text();
+ OUString sId(weld::toId(pData));
+ m_xGroupTLB->append(sId, m_xNameED->get_text());
+ int nEntry = m_xGroupTLB->find_id(sId);
+ m_xGroupTLB->set_text(nEntry, pData->sPath, 1);
+ m_xGroupTLB->select(nEntry);
+ SelectHdl(*m_xGroupTLB);
+ m_xGroupTLB->scroll_to_row(nEntry);
+}
+
+IMPL_LINK_NOARG(SwGlossaryGroupDlg, EntrySizeAllocHdl, const Size&, void)
+{
+ std::vector<int> aWidths;
+ int x, y, width, height;
+ if (m_xPathLB->get_extents_relative_to(*m_xGroupTLB, x, y, width, height))
+ {
+ aWidths.push_back(x);
+ m_xGroupTLB->set_column_fixed_widths(aWidths);
+ }
+}
+
+IMPL_LINK( SwGlossaryGroupDlg, DeleteHdl, weld::Button&, rButton, void )
+{
+ int nEntry = m_xGroupTLB->get_selected_index();
+ if (nEntry == -1)
+ {
+ rButton.set_sensitive(false);
+ return;
+ }
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(nEntry));
+ OUString const sEntry(pUserData->sGroupName);
+ // if the name to be deleted is among the new ones - get rid of it
+ bool bDelete = true;
+ auto it = std::find(m_InsertedArr.begin(), m_InsertedArr.end(), sEntry);
+ if (it != m_InsertedArr.end())
+ {
+ m_InsertedArr.erase(it);
+ bDelete = false;
+ }
+ // it should probably be renamed?
+ if(bDelete)
+ {
+ it = std::find_if(m_RenamedArr.begin(), m_RenamedArr.end(),
+ [&sEntry](OUString& s) { return o3tl::getToken(s, 0, RENAME_TOKEN_DELIM) == sEntry; });
+ if (it != m_RenamedArr.end())
+ {
+ m_RenamedArr.erase(it);
+ bDelete = false;
+ }
+ }
+ if(bDelete)
+ {
+ m_RemovedArr.emplace_back(pUserData->sGroupName + "\t" + pUserData->sGroupTitle);
+ }
+ delete pUserData;
+ m_xGroupTLB->remove(nEntry);
+ if (!m_xGroupTLB->n_children())
+ rButton.set_sensitive(false);
+ //the content must be deleted - otherwise the new handler would be called in Apply()
+ m_xNameED->set_text(OUString());
+ ModifyHdl(*m_xNameED);
+}
+
+IMPL_LINK_NOARG(SwGlossaryGroupDlg, RenameHdl, weld::Button&, void)
+{
+ int nEntry = m_xGroupTLB->get_selected_index();
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(nEntry));
+ OUString sEntry(pUserData->sGroupName);
+
+ const OUString sNewTitle(m_xNameED->get_text());
+ OUString sNewName = sNewTitle
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(m_xPathLB->get_active());
+ OSL_ENSURE(!pGlosHdl->FindGroupName(sNewName), "group already available!");
+
+ // if the name to be renamed is among the new ones - replace
+ bool bDone = false;
+ auto it = std::find(m_InsertedArr.begin(), m_InsertedArr.end(), sEntry);
+ if (it != m_InsertedArr.end())
+ {
+ m_InsertedArr.erase(it);
+ m_InsertedArr.push_back(sNewName);
+ bDone = true;
+ }
+ if(!bDone)
+ {
+ sEntry += OUStringChar(RENAME_TOKEN_DELIM) + sNewName
+ + OUStringChar(RENAME_TOKEN_DELIM) + sNewTitle;
+ m_RenamedArr.push_back(sEntry);
+ }
+ delete pUserData;
+ m_xGroupTLB->remove(nEntry);
+
+ GlosBibUserData* pData = new GlosBibUserData;
+ pData->sPath = m_xPathLB->get_active_text();
+ pData->sGroupName = sNewName;
+ pData->sGroupTitle = sNewTitle;
+
+ OUString sId(weld::toId(pData));
+ m_xGroupTLB->append(sId, m_xNameED->get_text());
+ nEntry = m_xGroupTLB->find_id(sId);
+ m_xGroupTLB->set_text(nEntry, m_xPathLB->get_active_text(), 1);
+ m_xGroupTLB->select(nEntry);
+ SelectHdl(*m_xGroupTLB);
+ m_xGroupTLB->scroll_to_row(nEntry);
+}
+
+IMPL_LINK_NOARG(SwGlossaryGroupDlg, ModifyListBoxHdl, weld::ComboBox&, void)
+{
+ ModifyHdl(*m_xNameED);
+}
+
+IMPL_LINK_NOARG(SwGlossaryGroupDlg, ModifyHdl, weld::Entry&, void)
+{
+ const OUString sEntry(m_xNameED->get_text());
+ bool bEnableNew = true;
+ bool bEnableDel = false;
+ sal_uInt32 nCaseReadonly = m_xPathLB->get_active_id().toUInt32();
+ bool bDirReadonly = 0 != (nCaseReadonly&PATH_READONLY);
+
+ if (sEntry.isEmpty() || bDirReadonly)
+ bEnableNew = false;
+ else if(!sEntry.isEmpty())
+ {
+ int nPos = m_xGroupTLB->find_text(sEntry);
+ //if it's not case sensitive you have to search for yourself
+ if (nPos == -1)
+ {
+ const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
+ for (int i = 0, nEntryCount = m_xGroupTLB->n_children(); i < nEntryCount; ++i)
+ {
+ const OUString sTemp = m_xGroupTLB->get_text(i, 0);
+ nCaseReadonly = m_xPathLB->get_id(m_xPathLB->find_text(m_xGroupTLB->get_text(i,1))).toUInt32();
+ bool bCase = 0 != (nCaseReadonly & PATH_CASE_SENSITIVE);
+
+ if( !bCase && rSCmp.isEqual( sTemp, sEntry ))
+ {
+ nPos = i;
+ break;
+ }
+ }
+ }
+ if (nPos != -1)
+ {
+ bEnableNew = false;
+ m_xGroupTLB->select(nPos);
+ m_xGroupTLB->scroll_to_row(nPos);
+ SelectHdl(*m_xGroupTLB);
+ }
+ }
+ int nEntry = m_xGroupTLB->get_selected_index();
+ if (nEntry != -1)
+ {
+ GlosBibUserData* pUserData = weld::fromId<GlosBibUserData*>(m_xGroupTLB->get_id(nEntry));
+ bEnableDel = IsDeleteAllowed(pUserData->sGroupName);
+ }
+
+ m_xDelPB->set_sensitive(bEnableDel);
+ m_xNewPB->set_sensitive(bEnableNew);
+ m_xRenamePB->set_sensitive(bEnableNew && nEntry != -1);
+}
+
+bool SwGlossaryGroupDlg::IsDeleteAllowed(const OUString &rGroup)
+{
+ bool bDel = !pGlosHdl->IsReadOnly(&rGroup);
+
+ // OM: if the name is among the new region name, it is deletable
+ // as well! Because for non existing region names ReadOnly issues
+ // true.
+
+ auto it = std::find(m_InsertedArr.cbegin(), m_InsertedArr.cend(), rGroup);
+ if (it != m_InsertedArr.cend())
+ bDel = true;
+
+ return bDel;
+}
+
+IMPL_STATIC_LINK(SwGlossaryGroupDlg, EditInsertTextHdl, OUString&, rText, bool)
+{
+ rText = rText.replaceAll(OUStringChar(SVT_SEARCHPATH_DELIMITER), "");
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/glossary.cxx b/sw/source/ui/misc/glossary.cxx
new file mode 100644
index 000000000..8fe493f93
--- /dev/null
+++ b/sw/source/ui/misc/glossary.cxx
@@ -0,0 +1,1086 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <o3tl/any.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
+#include <svl/stritem.hxx>
+#include <svl/macitem.hxx>
+#include <unotools/pathoptions.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/docfilt.hxx>
+#include <osl/diagnose.h>
+
+#include <svx/svxdlg.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <unotools.hxx>
+#include <comphelper/processfactory.hxx>
+#include <ucbhelper/content.hxx>
+#include <com/sun/star/text/AutoTextContainer.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <svl/urihelper.hxx>
+#include <unotools/charclass.hxx>
+#include <swtypes.hxx>
+#include <wrtsh.hxx>
+#include <view.hxx>
+#include <glossary.hxx>
+#include <gloshdl.hxx>
+#include <glosbib.hxx>
+#include <initui.hxx>
+#include <glosdoc.hxx>
+#include <macassgn.hxx>
+#include <docsh.hxx>
+#include <shellio.hxx>
+
+#include <cmdid.h>
+#include <sfx2/filedlghelper.hxx>
+
+#include <memory>
+
+#include <strings.hrc>
+#include <iodetect.hxx>
+
+#include <officecfg/Office/Writer.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::ui::dialogs;
+using namespace ::ucbhelper;
+using namespace ::sfx2;
+
+static OUString lcl_GetValidShortCut( const OUString& rName )
+{
+ const sal_Int32 nSz = rName.getLength();
+
+ if ( 0 == nSz )
+ return rName;
+
+ sal_Int32 nStart = 1;
+ while( rName[nStart-1]==' ' && nStart < nSz )
+ nStart++;
+
+ OUStringBuffer aBuf;
+ aBuf.append(rName[nStart-1]);
+
+ for( ; nStart < nSz; ++nStart )
+ {
+ if( rName[nStart-1]==' ' && rName[nStart]!=' ')
+ aBuf.append(rName[nStart]);
+ }
+ return aBuf.makeStringAndClear();
+}
+
+struct GroupUserData
+{
+ OUString sGroupName;
+ sal_uInt16 nPathIdx;
+ bool bReadonly;
+
+ GroupUserData()
+ : nPathIdx(0),
+ bReadonly(false) {}
+};
+
+// dialog for new block name
+class SwNewGlosNameDlg : public weld::GenericDialogController
+{
+ TextFilter m_aNoSpaceFilter;
+ SwGlossaryDlg* m_pParent;
+
+ std::unique_ptr<weld::Entry> m_xNewName;
+ std::unique_ptr<weld::Entry> m_xNewShort;
+ std::unique_ptr<weld::Button> m_xOk;
+ std::unique_ptr<weld::Entry> m_xOldName;
+ std::unique_ptr<weld::Entry> m_xOldShort;
+
+protected:
+ DECL_LINK(Modify, weld::Entry&, void);
+ DECL_LINK(Rename, weld::Button&, void);
+ DECL_LINK(TextFilterHdl, OUString&, bool);
+
+public:
+ SwNewGlosNameDlg(SwGlossaryDlg* pParent,
+ const OUString& rOldName,
+ const OUString& rOldShort);
+
+ OUString GetNewName() const { return m_xNewName->get_text(); }
+ OUString GetNewShort() const { return m_xNewShort->get_text(); }
+};
+
+IMPL_LINK(SwNewGlosNameDlg, TextFilterHdl, OUString&, rTest, bool)
+{
+ rTest = m_aNoSpaceFilter.filter(rTest);
+ return true;
+}
+
+SwNewGlosNameDlg::SwNewGlosNameDlg(SwGlossaryDlg* pParent, const OUString& rOldName, const OUString& rOldShort)
+ : GenericDialogController(pParent->getDialog(), "modules/swriter/ui/renameautotextdialog.ui", "RenameAutoTextDialog")
+ , m_pParent(pParent)
+ , m_xNewName(m_xBuilder->weld_entry("newname"))
+ , m_xNewShort(m_xBuilder->weld_entry("newsc"))
+ , m_xOk(m_xBuilder->weld_button("ok"))
+ , m_xOldName(m_xBuilder->weld_entry("oldname"))
+ , m_xOldShort(m_xBuilder->weld_entry("oldsc"))
+{
+ m_xNewShort->connect_insert_text(LINK(this, SwNewGlosNameDlg, TextFilterHdl));
+
+ m_xOldName->set_text(rOldName);
+ m_xOldShort->set_text(rOldShort);
+ m_xNewName->connect_changed(LINK(this, SwNewGlosNameDlg, Modify ));
+ m_xNewShort->connect_changed(LINK(this, SwNewGlosNameDlg, Modify ));
+ m_xOk->connect_clicked(LINK(this, SwNewGlosNameDlg, Rename ));
+ m_xNewName->grab_focus();
+}
+
+// query / set currently set group
+OUString SwGlossaryDlg::GetCurrGroup()
+{
+ if( !::GetCurrGlosGroup().isEmpty() )
+ return ::GetCurrGlosGroup();
+ return SwGlossaries::GetDefName();
+}
+
+void SwGlossaryDlg::SetActGroup(const OUString &rGrp)
+{
+ ::SetCurrGlosGroup(rGrp);
+}
+
+IMPL_LINK(SwGlossaryDlg, TextFilterHdl, OUString&, rTest, bool)
+{
+ rTest = m_aNoSpaceFilter.filter(rTest);
+ return true;
+}
+
+class SwGlossaryDropTarget : public DropTargetHelper
+{
+private:
+ weld::TreeView& m_rTreeView;
+ SwGlossaryHdl* m_pGlosHdl;
+
+ virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
+ {
+ weld::TreeView* pSource = m_rTreeView.get_drag_source();
+ if (!pSource || pSource != &m_rTreeView)
+ return DND_ACTION_NONE;
+
+ std::unique_ptr<weld::TreeIter> xSelected(pSource->make_iterator());
+ bool bSelected = pSource->get_selected(xSelected.get());
+ if (!bSelected)
+ return DND_ACTION_NONE;
+
+ while (pSource->get_iter_depth(*xSelected))
+ (void)pSource->iter_parent(*xSelected);
+
+ GroupUserData* pSrcRootData = weld::fromId<GroupUserData*>(pSource->get_id(*xSelected));
+ GroupUserData* pDestRootData = nullptr;
+
+ std::unique_ptr<weld::TreeIter> xDestEntry(m_rTreeView.make_iterator());
+ bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true);
+ if (bEntry)
+ {
+ while (m_rTreeView.get_iter_depth(*xDestEntry))
+ (void)m_rTreeView.iter_parent(*xDestEntry);
+ pDestRootData = weld::fromId<GroupUserData*>(m_rTreeView.get_id(*xDestEntry));
+ }
+ if (pDestRootData == pSrcRootData)
+ return DND_ACTION_NONE;
+ sal_uInt8 nRet = DND_ACTION_COPY;
+ const bool bCheckForMove = rEvt.mnAction & DND_ACTION_MOVE;
+ if (bCheckForMove && !pSrcRootData->bReadonly)
+ nRet |= DND_ACTION_MOVE;
+ return nRet;
+ }
+
+ virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
+ {
+ weld::TreeView* pSource = m_rTreeView.get_drag_source();
+ if (!pSource)
+ return DND_ACTION_NONE;
+
+ std::unique_ptr<weld::TreeIter> xDestEntry(m_rTreeView.make_iterator());
+ bool bEntry = m_rTreeView.get_dest_row_at_pos(rEvt.maPosPixel, xDestEntry.get(), true);
+ if (!bEntry)
+ return DND_ACTION_NONE;
+
+ std::unique_ptr<weld::TreeIter> xSelected(pSource->make_iterator());
+ bool bSelected = pSource->get_selected(xSelected.get());
+ if (!bSelected)
+ return DND_ACTION_NONE;
+
+ std::unique_ptr<weld::TreeIter> xSrcParent(pSource->make_iterator(xSelected.get()));
+ while (pSource->get_iter_depth(*xSrcParent))
+ (void)pSource->iter_parent(*xSrcParent);
+
+ std::unique_ptr<weld::TreeIter> xDestParent(pSource->make_iterator(xDestEntry.get()));
+ while (pSource->get_iter_depth(*xDestParent))
+ (void)pSource->iter_parent(*xDestParent);
+
+ GroupUserData* pSrcParent = weld::fromId<GroupUserData*>(pSource->get_id(*xSrcParent));
+ GroupUserData* pDestParent = weld::fromId<GroupUserData*>(m_rTreeView.get_id(*xDestParent));
+
+ if (pDestParent != pSrcParent)
+ {
+ weld::WaitObject aBusy(&m_rTreeView);
+
+ OUString sSourceGroup = pSrcParent->sGroupName
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(pSrcParent->nPathIdx);
+
+ m_pGlosHdl->SetCurGroup(sSourceGroup);
+ OUString sTitle(pSource->get_text(*xSelected));
+ OUString sShortName(pSource->get_id(*xSelected));
+
+ OUString sDestName = pDestParent->sGroupName
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(pDestParent->nPathIdx);
+
+ bool bIsMove = rEvt.mnAction & DND_ACTION_MOVE;
+
+ const bool bRet = m_pGlosHdl->CopyOrMove(sSourceGroup, sShortName,
+ sDestName, sTitle, bIsMove);
+
+ if(bRet)
+ {
+ m_rTreeView.insert(xDestParent.get(), -1, &sTitle, &sShortName,
+ nullptr, nullptr, false, nullptr);
+ if (bIsMove)
+ {
+ pSource->remove(*xSelected);
+ }
+ }
+ }
+
+ return DND_ACTION_NONE;
+ }
+
+public:
+ SwGlossaryDropTarget(weld::TreeView& rTreeView, SwGlossaryHdl* pGlosHdl)
+ : DropTargetHelper(rTreeView.get_drop_target())
+ , m_rTreeView(rTreeView)
+ , m_pGlosHdl(pGlosHdl)
+ {
+ }
+};
+
+SwGlossaryDlg::SwGlossaryDlg(SfxViewFrame const * pViewFrame,
+ SwGlossaryHdl * pGlosHdl, SwWrtShell *pWrtShell)
+ : SfxDialogController(pViewFrame->GetFrameWeld(), "modules/swriter/ui/autotext.ui", "AutoTextDialog")
+ , m_sReadonlyPath(SwResId(STR_READONLY_PATH))
+ , m_pGlossaryHdl(pGlosHdl)
+ , m_bResume(false)
+ , m_bSelection(pWrtShell->IsSelection())
+ , m_bReadOnly(false)
+ , m_bIsOld(false)
+ , m_bIsDocReadOnly(false)
+ , m_pShell(pWrtShell)
+ , m_xInsertTipCB(m_xBuilder->weld_check_button("inserttip"))
+ , m_xNameED(m_xBuilder->weld_entry("name"))
+ , m_xShortNameLbl(m_xBuilder->weld_label("shortnameft"))
+ , m_xShortNameEdit(m_xBuilder->weld_entry("shortname"))
+ , m_xCategoryBox(m_xBuilder->weld_tree_view("category"))
+ , m_xFileRelCB(m_xBuilder->weld_check_button("relfile"))
+ , m_xNetRelCB(m_xBuilder->weld_check_button("relnet"))
+ , m_xInsertBtn(m_xBuilder->weld_button("ok"))
+ , m_xEditBtn(m_xBuilder->weld_menu_button("autotext"))
+ , m_xBibBtn(m_xBuilder->weld_button("categories"))
+ , m_xPathBtn(m_xBuilder->weld_button("path"))
+{
+ m_xCategoryBox->set_size_request(m_xCategoryBox->get_approximate_digit_width() * 52,
+ m_xCategoryBox->get_height_rows(12));
+
+ Link<SwOneExampleFrame&,void> aLink(LINK(this, SwGlossaryDlg, PreviewLoadedHdl));
+ m_xExampleFrame.reset(new SwOneExampleFrame(EX_SHOW_ONLINE_LAYOUT, &aLink));
+ m_xExampleFrameWin.reset(new weld::CustomWeld(*m_xBuilder, "example", *m_xExampleFrame));
+ Size aSize = m_xExampleFrame->GetDrawingArea()->get_ref_device().LogicToPixel(
+ Size(82, 124), MapMode(MapUnit::MapAppFont));
+ m_xExampleFrame->set_size_request(aSize.Width(), aSize.Height());
+
+ m_xShortNameEdit->connect_insert_text(LINK(this, SwGlossaryDlg, TextFilterHdl));
+
+ m_xEditBtn->connect_toggled(LINK(this, SwGlossaryDlg, EnableHdl));
+ m_xEditBtn->connect_selected(LINK(this, SwGlossaryDlg, MenuHdl));
+ m_xPathBtn->connect_clicked(LINK(this, SwGlossaryDlg, PathHdl));
+
+ m_xNameED->connect_changed(LINK(this,SwGlossaryDlg,NameModify));
+ m_xShortNameEdit->connect_changed(LINK(this,SwGlossaryDlg,NameModify));
+
+ m_xCategoryBox->connect_row_activated(LINK(this, SwGlossaryDlg, NameDoubleClick));
+ m_xCategoryBox->connect_changed(LINK(this, SwGlossaryDlg, GrpSelect));
+ m_xCategoryBox->connect_key_press(LINK(this, SwGlossaryDlg, KeyInputHdl));
+
+ m_xDropTarget.reset(new SwGlossaryDropTarget(*m_xCategoryBox, pGlosHdl));
+ rtl::Reference<TransferDataContainer> xHelper(new TransferDataContainer);
+ m_xCategoryBox->enable_drag_source(xHelper, DND_ACTION_COPYMOVE);
+
+ m_xBibBtn->connect_clicked(LINK(this,SwGlossaryDlg,BibHdl));
+
+ m_xInsertBtn->connect_clicked(LINK(this,SwGlossaryDlg,InsertHdl));
+
+ ShowPreview();
+
+ m_bIsDocReadOnly = m_pShell->GetView().GetDocShell()->IsReadOnly() ||
+ m_pShell->HasReadonlySel();
+ if( m_bIsDocReadOnly )
+ m_xInsertBtn->set_sensitive(false);
+ m_xNameED->grab_focus();
+ m_xCategoryBox->make_sorted();
+ m_xCategoryBox->set_sort_order(true);
+
+ Init();
+}
+
+SwGlossaryDlg::~SwGlossaryDlg()
+{
+}
+
+namespace
+{
+
+OUString getCurrentGlossary()
+{
+ const OUString sTemp{ ::GetCurrGlosGroup() };
+
+ // the zeroth path is not being recorded!
+ if (o3tl::starts_with(o3tl::getToken(sTemp, 1, GLOS_DELIM), u"0"))
+ return sTemp.getToken(0, GLOS_DELIM);
+
+ return sTemp;
+}
+
+}
+
+// select new group
+IMPL_LINK(SwGlossaryDlg, GrpSelect, weld::TreeView&, rBox, void)
+{
+ std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator();
+ if (!rBox.get_selected(xEntry.get()))
+ return;
+
+ std::unique_ptr<weld::TreeIter> xParent = rBox.make_iterator(xEntry.get());
+ weld::TreeIter* pParent;
+ if (rBox.get_iter_depth(*xParent))
+ {
+ rBox.iter_parent(*xParent);
+ pParent = xParent.get();
+ }
+ else
+ pParent = xEntry.get();
+ GroupUserData* pGroupData = weld::fromId<GroupUserData*>(rBox.get_id(*pParent));
+ ::SetCurrGlosGroup(pGroupData->sGroupName
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(pGroupData->nPathIdx));
+ m_pGlossaryHdl->SetCurGroup(::GetCurrGlosGroup());
+ // set current text block
+ m_bReadOnly = m_pGlossaryHdl->IsReadOnly();
+ EnableShortName( !m_bReadOnly );
+ m_xEditBtn->set_sensitive(!m_bReadOnly);
+ m_bIsOld = m_pGlossaryHdl->IsOld();
+ if( pParent != xEntry.get())
+ {
+ OUString aName(rBox.get_text(*xEntry));
+ m_xNameED->set_text(aName);
+ m_xShortNameEdit->set_text(rBox.get_id(*xEntry));
+ m_xInsertBtn->set_sensitive( !m_bIsDocReadOnly);
+ ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit->get_text());
+ }
+ else
+ {
+ m_xNameED->set_text("");
+ m_xShortNameEdit->set_text("");
+ m_xShortNameEdit->set_sensitive(false);
+ ShowAutoText("", "");
+ }
+ // update controls
+ NameModify(*m_xShortNameEdit);
+ if( SfxRequest::HasMacroRecorder( m_pShell->GetView().GetViewFrame() ) )
+ {
+ SfxRequest aReq( m_pShell->GetView().GetViewFrame(), FN_SET_ACT_GLOSSARY );
+ aReq.AppendItem(SfxStringItem(FN_SET_ACT_GLOSSARY, getCurrentGlossary()));
+ aReq.Done();
+ }
+}
+
+short SwGlossaryDlg::run()
+{
+ short nRet = SfxDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+}
+
+void SwGlossaryDlg::Apply()
+{
+ const OUString aGlosName(m_xShortNameEdit->get_text());
+ if (!aGlosName.isEmpty())
+ {
+ m_pGlossaryHdl->InsertGlossary(aGlosName);
+ }
+ if( SfxRequest::HasMacroRecorder( m_pShell->GetView().GetViewFrame() ) )
+ {
+ SfxRequest aReq( m_pShell->GetView().GetViewFrame(), FN_INSERT_GLOSSARY );
+ aReq.AppendItem(SfxStringItem(FN_INSERT_GLOSSARY, getCurrentGlossary()));
+ aReq.AppendItem(SfxStringItem(FN_PARAM_1, aGlosName));
+ aReq.Done();
+ }
+}
+
+void SwGlossaryDlg::EnableShortName(bool bOn)
+{
+ m_xShortNameLbl->set_sensitive(bOn);
+ m_xShortNameEdit->set_sensitive(bOn);
+}
+
+// does the title exist in the selected group?
+std::unique_ptr<weld::TreeIter> SwGlossaryDlg::DoesBlockExist(std::u16string_view rBlock,
+ std::u16string_view rShort)
+{
+ // look for possible entry in TreeListBox
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ if (m_xCategoryBox->get_selected(xEntry.get()))
+ {
+ if (m_xCategoryBox->get_iter_depth(*xEntry))
+ m_xCategoryBox->iter_parent(*xEntry);
+ if (!m_xCategoryBox->iter_children(*xEntry))
+ return nullptr;
+ do
+ {
+ if (rBlock == m_xCategoryBox->get_text(*xEntry) &&
+ (rShort.empty() ||
+ rShort == m_xCategoryBox->get_id(*xEntry))
+ )
+ {
+ return xEntry;
+ }
+ }
+ while (m_xCategoryBox->iter_next_sibling(*xEntry));
+ }
+ return nullptr;
+}
+
+IMPL_LINK(SwGlossaryDlg, NameModify, weld::Entry&, rEdit, void)
+{
+ const OUString aName(m_xNameED->get_text());
+ bool bNameED = &rEdit == m_xNameED.get();
+ if( aName.isEmpty() )
+ {
+ if(bNameED)
+ m_xShortNameEdit->set_text(aName);
+ m_xInsertBtn->set_sensitive(false);
+ return;
+ }
+ const bool bNotFound = !DoesBlockExist(aName, bNameED ? OUString() : rEdit.get_text());
+ if(bNameED)
+ {
+ // did the text get in to the Listbox in the Edit with a click?
+ if(bNotFound)
+ {
+ m_xShortNameEdit->set_text( lcl_GetValidShortCut( aName ) );
+ EnableShortName();
+ }
+ else
+ {
+ m_xShortNameEdit->set_text(m_pGlossaryHdl->GetGlossaryShortName(aName));
+ EnableShortName(!m_bReadOnly);
+ }
+ m_xInsertBtn->set_sensitive(!bNotFound && !m_bIsDocReadOnly);
+ }
+ else
+ {
+ //ShortNameEdit
+ if(!bNotFound)
+ {
+ m_xInsertBtn->set_sensitive(!m_bIsDocReadOnly);
+ }
+ }
+}
+
+IMPL_LINK( SwGlossaryDlg, NameDoubleClick, weld::TreeView&, rBox, bool )
+{
+ std::unique_ptr<weld::TreeIter> xEntry = rBox.make_iterator();
+ if (rBox.get_selected(xEntry.get()) && rBox.get_iter_depth(*xEntry) && !m_bIsDocReadOnly)
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+IMPL_LINK_NOARG( SwGlossaryDlg, EnableHdl, weld::Toggleable&, void )
+{
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ bool bEntry = m_xCategoryBox->get_selected(xEntry.get());
+
+ const OUString aEditText(m_xNameED->get_text());
+ const bool bHasEntry = !aEditText.isEmpty() && !m_xShortNameEdit->get_text().isEmpty();
+ const bool bExists = nullptr != DoesBlockExist(aEditText, m_xShortNameEdit->get_text());
+ const bool bIsGroup = bEntry && !m_xCategoryBox->get_iter_depth(*xEntry);
+ m_xEditBtn->set_item_visible("new", m_bSelection && bHasEntry && !bExists);
+ m_xEditBtn->set_item_visible("newtext", m_bSelection && bHasEntry && !bExists);
+ m_xEditBtn->set_item_visible("copy", bExists && !bIsGroup);
+ m_xEditBtn->set_item_visible("replace", m_bSelection && bExists && !bIsGroup && !m_bIsOld );
+ m_xEditBtn->set_item_visible("replacetext", m_bSelection && bExists && !bIsGroup && !m_bIsOld );
+ m_xEditBtn->set_item_visible("edit", bExists && !bIsGroup );
+ m_xEditBtn->set_item_visible("rename", bExists && !bIsGroup );
+ m_xEditBtn->set_item_visible("delete", bExists && !bIsGroup );
+ m_xEditBtn->set_item_visible("macro", bExists && !bIsGroup && !m_bIsOld &&
+ !m_pGlossaryHdl->IsReadOnly() );
+ m_xEditBtn->set_item_visible("import", bIsGroup && !m_bIsOld && !m_pGlossaryHdl->IsReadOnly() );
+}
+
+IMPL_LINK(SwGlossaryDlg, MenuHdl, const OString&, rItemIdent, void)
+{
+ if (rItemIdent == "edit")
+ {
+ std::unique_ptr<SwTextBlocks> pGroup = ::GetGlossaries()->GetGroupDoc ( GetCurrGrpName () );
+ pGroup.reset();
+ m_xDialog->response(RET_EDIT);
+ }
+ else if (rItemIdent == "replace")
+ {
+ m_pGlossaryHdl->NewGlossary(m_xNameED->get_text(),
+ m_xShortNameEdit->get_text());
+ }
+ else if (rItemIdent == "replacetext")
+ {
+ m_pGlossaryHdl->NewGlossary(m_xNameED->get_text(),
+ m_xShortNameEdit->get_text(),
+ false, true);
+ }
+ else if (rItemIdent == "new" || rItemIdent == "newtext")
+ {
+ bool bNoAttr = rItemIdent == "newtext";
+
+ const OUString aStr(m_xNameED->get_text());
+ const OUString aShortName(m_xShortNameEdit->get_text());
+ if(m_pGlossaryHdl->HasShortName(aShortName))
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_DOUBLE_SHORTNAME)));
+ xInfoBox->run();
+ m_xShortNameEdit->select_region(0, -1);
+ m_xShortNameEdit->grab_focus();
+ }
+ if(m_pGlossaryHdl->NewGlossary(aStr, aShortName, false, bNoAttr ))
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ if (!m_xCategoryBox->get_selected(xEntry.get()))
+ xEntry.reset();
+ else if (m_xCategoryBox->get_iter_depth(*xEntry))
+ m_xCategoryBox->iter_parent(*xEntry);
+ m_xCategoryBox->insert(xEntry.get(), -1, &aStr, &aShortName,
+ nullptr, nullptr, false, nullptr);
+
+ m_xNameED->set_text(aStr);
+ m_xShortNameEdit->set_text(aShortName);
+ NameModify(*m_xNameED); // for toggling the buttons
+
+ if( SfxRequest::HasMacroRecorder( m_pShell->GetView().GetViewFrame() ) )
+ {
+ SfxRequest aReq(m_pShell->GetView().GetViewFrame(), FN_NEW_GLOSSARY);
+ aReq.AppendItem(SfxStringItem(FN_NEW_GLOSSARY, getCurrentGlossary()));
+ aReq.AppendItem(SfxStringItem(FN_PARAM_1, aShortName));
+ aReq.AppendItem(SfxStringItem(FN_PARAM_2, aStr));
+ aReq.Done();
+ }
+ }
+ }
+ else if (rItemIdent == "copy")
+ {
+ m_pGlossaryHdl->CopyToClipboard(*m_pShell, m_xShortNameEdit->get_text());
+ }
+ else if (rItemIdent == "rename")
+ {
+ m_xShortNameEdit->set_text(m_pGlossaryHdl->GetGlossaryShortName(m_xNameED->get_text()));
+ SwNewGlosNameDlg aNewNameDlg(this, m_xNameED->get_text(), m_xShortNameEdit->get_text());
+ if (aNewNameDlg.run() == RET_OK && m_pGlossaryHdl->Rename(m_xShortNameEdit->get_text(),
+ aNewNameDlg.GetNewShort(),
+ aNewNameDlg.GetNewName()))
+ {
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ if (m_xCategoryBox->get_selected(xEntry.get()))
+ {
+ std::unique_ptr<weld::TreeIter> xOldEntry = m_xCategoryBox->make_iterator(xEntry.get());
+ if (m_xCategoryBox->get_iter_depth(*xEntry))
+ m_xCategoryBox->iter_parent(*xEntry);
+
+ std::unique_ptr<weld::TreeIter> xNewEntry = m_xCategoryBox->make_iterator();
+ OUString sId(aNewNameDlg.GetNewShort());
+ OUString sName(aNewNameDlg.GetNewName());
+
+ m_xCategoryBox->insert(xEntry.get(), -1, &sName, &sId,
+ nullptr, nullptr, false, xNewEntry.get());
+
+ m_xCategoryBox->remove(*xOldEntry);
+ m_xCategoryBox->select(*xNewEntry);
+ m_xCategoryBox->scroll_to_row(*xNewEntry);
+ }
+ }
+ GrpSelect(*m_xCategoryBox);
+ }
+ else if (rItemIdent == "delete")
+ {
+ DeleteEntry();
+ }
+ else if (rItemIdent == "macro")
+ {
+ SfxItemSetFixed<RES_FRMMACRO, RES_FRMMACRO, SID_EVENTCONFIG, SID_EVENTCONFIG> aSet( m_pShell->GetAttrPool() );
+
+ SvxMacro aStart(OUString(), OUString(), STARBASIC);
+ SvxMacro aEnd(OUString(), OUString(), STARBASIC);
+ m_pGlossaryHdl->GetMacros(m_xShortNameEdit->get_text(), aStart, aEnd );
+
+ SvxMacroItem aItem(RES_FRMMACRO);
+ if( aStart.HasMacro() )
+ aItem.SetMacro( SvMacroItemId::SwStartInsGlossary, aStart );
+ if( aEnd.HasMacro() )
+ aItem.SetMacro( SvMacroItemId::SwEndInsGlossary, aEnd );
+
+ aSet.Put( aItem );
+ aSet.Put( SwMacroAssignDlg::AddEvents( MACASSGN_AUTOTEXT ) );
+
+ const SvxMacroItem* pMacroItem;
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pMacroDlg(pFact->CreateEventConfigDialog(m_xDialog.get(), aSet,
+ m_pShell->GetView().GetViewFrame()->GetFrame().GetFrameInterface() ));
+ if ( pMacroDlg && pMacroDlg->Execute() == RET_OK &&
+ (pMacroItem = pMacroDlg->GetOutputItemSet()->GetItemIfSet( RES_FRMMACRO, false )) )
+ {
+ const SvxMacroTableDtor& rTable = pMacroItem->GetMacroTable();
+ m_pGlossaryHdl->SetMacros( m_xShortNameEdit->get_text(),
+ rTable.Get( SvMacroItemId::SwStartInsGlossary ),
+ rTable.Get( SvMacroItemId::SwEndInsGlossary ) );
+ }
+ }
+ else if (rItemIdent == "import")
+ {
+ // call the FileOpenDialog do find WinWord - Files with templates
+ FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+ aDlgHelper.SetContext(FileDialogHelper::WriterImportAutotext);
+ uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker();
+
+ SfxFilterMatcher aMatcher( SwDocShell::Factory().GetFactoryName() );
+ SfxFilterMatcherIter aIter( aMatcher );
+ std::shared_ptr<const SfxFilter> pFilter = aIter.First();
+ while ( pFilter )
+ {
+ if( pFilter->GetUserData() == FILTER_WW8 )
+ {
+ xFP->appendFilter( pFilter->GetUIName(),
+ pFilter->GetWildcard().getGlob() );
+ xFP->setCurrentFilter( pFilter->GetUIName() ) ;
+ }
+ else if( pFilter->GetUserData() == FILTER_DOCX )
+ {
+ xFP->appendFilter( pFilter->GetUIName(),
+ pFilter->GetWildcard().getGlob() );
+ xFP->setCurrentFilter( pFilter->GetUIName() ) ;
+ }
+
+ pFilter = aIter.Next();
+ }
+
+ if( aDlgHelper.Execute() == ERRCODE_NONE )
+ {
+ if( m_pGlossaryHdl->ImportGlossaries( xFP->getSelectedFiles().getConstArray()[0] ))
+ Init();
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_NO_GLOSSARIES)));
+ xInfoBox->run();
+ }
+ }
+ }
+}
+
+// dialog manage regions
+IMPL_LINK_NOARG(SwGlossaryDlg, BibHdl, weld::Button&, void)
+{
+ SwGlossaries* pGloss = ::GetGlossaries();
+ if( pGloss->IsGlosPathErr() )
+ pGloss->ShowError();
+ else
+ {
+ //check if at least one glossary path is write enabled
+ SvtPathOptions aPathOpt;
+ const OUString& sGlosPath( aPathOpt.GetAutoTextPath() );
+ bool bIsWritable = false;
+ sal_Int32 nIdx {sGlosPath.isEmpty() ? -1 : 0};
+ while (nIdx>=0)
+ {
+ const OUString sPath = URIHelper::SmartRel2Abs(
+ INetURLObject(), sGlosPath.getToken(0, ';', nIdx),
+ URIHelper::GetMaybeFileHdl());
+ try
+ {
+ Content aTestContent( sPath,
+ uno::Reference< XCommandEnvironment >(),
+ comphelper::getProcessComponentContext() );
+ Any aAny = aTestContent.getPropertyValue( "IsReadOnly" );
+ if(aAny.hasValue())
+ {
+ bIsWritable = !*o3tl::doAccess<bool>(aAny);
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+ if(bIsWritable)
+ break;
+ }
+ if(bIsWritable)
+ {
+
+ SwGlossaryGroupDlg aDlg(m_xDialog.get(), pGloss->GetPathArray(), m_pGlossaryHdl);
+ if (aDlg.run() == RET_OK)
+ {
+ Init();
+ //if new groups were created - select one of them
+ const OUString sNewGroup = aDlg.GetCreatedGroupName();
+
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ bool bEntry = m_xCategoryBox->get_iter_first(*xEntry);
+
+ while (!sNewGroup.isEmpty() && bEntry)
+ {
+ if (!m_xCategoryBox->get_iter_depth(*xEntry))
+ {
+ GroupUserData* pGroupData = weld::fromId<GroupUserData*>(m_xCategoryBox->get_id(*xEntry));
+ const OUString sGroup = pGroupData->sGroupName
+ + OUStringChar(GLOS_DELIM)
+ + OUString::number(pGroupData->nPathIdx);
+ if(sGroup == sNewGroup)
+ {
+ m_xCategoryBox->select(*xEntry);
+ m_xCategoryBox->scroll_to_row(*xEntry);
+ GrpSelect(*m_xCategoryBox);
+ break;
+ }
+ }
+ bEntry = m_xCategoryBox->iter_next(*xEntry);
+ }
+
+ }
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ m_sReadonlyPath));
+ if (RET_YES == xBox->run())
+ PathHdl(*m_xPathBtn);
+ }
+ }
+}
+
+// initialisation; from Ctor and after editing regions
+void SwGlossaryDlg::Init()
+{
+ m_xCategoryBox->freeze();
+ m_xCategoryBox->clear();
+ m_xGroupData.clear();
+ m_xCategoryBox->make_unsorted();
+
+ // display text block regions
+ const size_t nCnt = m_pGlossaryHdl->GetGroupCnt();
+ std::unique_ptr<weld::TreeIter> xSelEntry;
+ const OUString sSelStr(::GetCurrGlosGroup().getToken(0, GLOS_DELIM));
+ const sal_Int32 nSelPath = o3tl::toInt32(o3tl::getToken(::GetCurrGlosGroup(), 1, GLOS_DELIM));
+ // #i66304# - "My AutoText" comes from mytexts.bau, but should be translated
+ static const OUStringLiteral sMyAutoTextEnglish(u"My AutoText");
+ const OUString sMyAutoTextTranslated(SwResId(STR_MY_AUTOTEXT));
+ for(size_t nId = 0; nId < nCnt; ++nId )
+ {
+ OUString sTitle;
+ OUString sGroupName(m_pGlossaryHdl->GetGroupName(nId, &sTitle));
+ if(sGroupName.isEmpty())
+ continue;
+ sal_Int32 nIdx{ 0 };
+ const OUString sName{ sGroupName.getToken( 0, GLOS_DELIM, nIdx ) };
+ if(sTitle.isEmpty())
+ sTitle = sName;
+ if(sTitle == sMyAutoTextEnglish)
+ sTitle = sMyAutoTextTranslated;
+
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ m_xCategoryBox->append(xEntry.get());
+ m_xCategoryBox->set_text(*xEntry, sTitle, 0);
+ const sal_Int32 nPath = o3tl::toInt32(o3tl::getToken(sGroupName, 0, GLOS_DELIM, nIdx ));
+
+ GroupUserData* pData = new GroupUserData;
+ pData->sGroupName = sName;
+ pData->nPathIdx = static_cast< sal_uInt16 >(nPath);
+ pData->bReadonly = m_pGlossaryHdl->IsReadOnly(&sGroupName);
+ m_xGroupData.emplace_back(pData);
+
+ m_xCategoryBox->set_id(*xEntry, weld::toId(pData));
+ if (sSelStr == pData->sGroupName && nSelPath == nPath)
+ xSelEntry = m_xCategoryBox->make_iterator(xEntry.get());
+
+ // fill entries for the groups
+ {
+ m_pGlossaryHdl->SetCurGroup(sGroupName, false, true);
+ const sal_uInt16 nCount = m_pGlossaryHdl->GetGlossaryCnt();
+ for(sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ OUString sEntryName = m_pGlossaryHdl->GetGlossaryName(i);
+ OUString sId = m_pGlossaryHdl->GetGlossaryShortName(i);
+ m_xCategoryBox->insert(xEntry.get(), -1, &sEntryName, &sId,
+ nullptr, nullptr, false, nullptr);
+ }
+ }
+ }
+ // set current group and display text blocks
+ if (!xSelEntry)
+ {
+ //find a non-readonly group
+ std::unique_ptr<weld::TreeIter> xSearch = m_xCategoryBox->make_iterator();
+ if (m_xCategoryBox->get_iter_first(*xSearch))
+ {
+ do
+ {
+ if (!m_xCategoryBox->get_iter_depth(*xSearch))
+ {
+ GroupUserData* pData = weld::fromId<GroupUserData*>(m_xCategoryBox->get_id(*xSearch));
+ if (!pData->bReadonly)
+ {
+ xSelEntry = std::move(xSearch);
+ break;
+ }
+ }
+ }
+ while (m_xCategoryBox->iter_next(*xSearch));
+ }
+ if (!xSelEntry)
+ {
+ xSelEntry = std::move(xSearch);
+ if (!m_xCategoryBox->get_iter_first(*xSelEntry))
+ xSelEntry.reset();
+ }
+ }
+
+ m_xCategoryBox->thaw();
+ m_xCategoryBox->make_sorted();
+
+ if (xSelEntry)
+ {
+ m_xCategoryBox->expand_row(*xSelEntry);
+ m_xCategoryBox->select(*xSelEntry);
+ m_xCategoryBox->scroll_to_row(*xSelEntry);
+ GrpSelect(*m_xCategoryBox);
+ }
+
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+ m_xFileRelCB->set_active( rCfg.IsSaveRelFile() );
+ m_xFileRelCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl));
+ m_xNetRelCB->set_active( rCfg.IsSaveRelNet() );
+ m_xNetRelCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl));
+ m_xInsertTipCB->set_active( rCfg.IsAutoTextTip() );
+ m_xInsertTipCB->set_sensitive(!officecfg::Office::Writer::AutoFunction::Text::ShowToolTip::isReadOnly());
+ m_xInsertTipCB->connect_toggled(LINK(this, SwGlossaryDlg, CheckBoxHdl));
+}
+
+// KeyInput for ShortName - Edits without Spaces
+IMPL_LINK( SwNewGlosNameDlg, Modify, weld::Entry&, rBox, void )
+{
+ OUString aName(m_xNewName->get_text());
+ SwGlossaryDlg* pDlg = m_pParent;
+ if (&rBox == m_xNewName.get())
+ m_xNewShort->set_text(lcl_GetValidShortCut(aName));
+
+ bool bEnable = !aName.isEmpty() && !m_xNewShort->get_text().isEmpty() &&
+ (!pDlg->DoesBlockExist(aName, m_xNewShort->get_text())
+ || aName == m_xOldName->get_text());
+ m_xOk->set_sensitive(bEnable);
+}
+
+IMPL_LINK_NOARG(SwNewGlosNameDlg, Rename, weld::Button&, void)
+{
+ SwGlossaryDlg* pDlg = m_pParent;
+ OUString sNew = GetAppCharClass().uppercase(m_xNewShort->get_text());
+ if (pDlg->m_pGlossaryHdl->HasShortName(m_xNewShort->get_text())
+ && sNew != m_xOldShort->get_text())
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_DOUBLE_SHORTNAME)));
+ xBox->run();
+ m_xNewShort->grab_focus();
+ }
+ else
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK(SwGlossaryDlg, CheckBoxHdl, weld::Toggleable&, rBox, void)
+{
+ SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+ bool bCheck = rBox.get_active();
+ if (&rBox == m_xInsertTipCB.get())
+ rCfg.SetAutoTextTip(bCheck);
+ else if (&rBox == m_xFileRelCB.get())
+ rCfg.SetSaveRelFile(bCheck);
+ else
+ rCfg.SetSaveRelNet(bCheck);
+ rCfg.Commit();
+}
+
+IMPL_LINK(SwGlossaryDlg, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+ if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE)
+ {
+ DeleteEntry();
+ return true;
+ }
+ return false;
+}
+
+OUString SwGlossaryDlg::GetCurrGrpName() const
+{
+ std::unique_ptr<weld::TreeIter> xEntry = m_xCategoryBox->make_iterator();
+ if (m_xCategoryBox->get_selected(xEntry.get()))
+ {
+ if (m_xCategoryBox->get_iter_depth(*xEntry))
+ m_xCategoryBox->iter_parent(*xEntry);
+ GroupUserData* pGroupData = weld::fromId<GroupUserData*>(m_xCategoryBox->get_id(*xEntry));
+ return pGroupData->sGroupName + OUStringChar(GLOS_DELIM) + OUString::number(pGroupData->nPathIdx);
+ }
+ return OUString();
+}
+
+IMPL_LINK_NOARG( SwGlossaryDlg, PathHdl, weld::Button&, void )
+{
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<AbstractSvxMultiPathDialog> pDlg(pFact->CreateSvxPathSelectDialog(m_xDialog.get()));
+ SvtPathOptions aPathOpt;
+ const OUString sGlosPath( aPathOpt.GetAutoTextPath() );
+ pDlg->SetPath(sGlosPath);
+ if(RET_OK == pDlg->Execute())
+ {
+ const OUString sTmp(pDlg->GetPath());
+ if(sTmp != sGlosPath)
+ {
+ aPathOpt.SetAutoTextPath( sTmp );
+ ::GetGlossaries()->UpdateGlosPath( true );
+ Init();
+ }
+ }
+}
+
+IMPL_LINK_NOARG(SwGlossaryDlg, InsertHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_OK);
+}
+
+void SwGlossaryDlg::ShowPreview()
+{
+ ShowAutoText(::GetCurrGlosGroup(), m_xShortNameEdit->get_text());
+};
+
+IMPL_LINK_NOARG(SwGlossaryDlg, PreviewLoadedHdl, SwOneExampleFrame&, void)
+{
+ ResumeShowAutoText();
+}
+
+void SwGlossaryDlg::ShowAutoText(const OUString& rGroup, const OUString& rShortName)
+{
+ if (m_xExampleFrameWin->get_visible())
+ {
+ SetResumeData(rGroup, rShortName);
+ //try to make an Undo()
+ m_xExampleFrame->ClearDocument();
+ }
+}
+
+void SwGlossaryDlg::ResumeShowAutoText()
+{
+ OUString sGroup;
+ OUString sShortName;
+ if(GetResumeData(sGroup, sShortName) && m_xExampleFrameWin->get_visible())
+ {
+ if(!m_xAutoText.is())
+ {
+ //now the AutoText ListBoxes have to be filled
+ m_xAutoText = text::AutoTextContainer::create( comphelper::getProcessComponentContext() );
+ }
+
+ uno::Reference< XTextCursor > & xCursor = m_xExampleFrame->GetTextCursor();
+ if(xCursor.is())
+ {
+ if (!sShortName.isEmpty())
+ {
+ uno::Any aGroup = m_xAutoText->getByName(sGroup);
+ uno::Reference< XAutoTextGroup > xGroup;
+ if((aGroup >>= xGroup) && xGroup->hasByName(sShortName))
+ {
+ uno::Any aEntry(xGroup->getByName(sShortName));
+ uno::Reference< XAutoTextEntry > xEntry;
+ aEntry >>= xEntry;
+ xEntry->applyTo(xCursor);
+ }
+ }
+ }
+ }
+ m_bResume = false;
+}
+
+void SwGlossaryDlg::DeleteEntry()
+{
+ bool bEntry = m_xCategoryBox->get_selected(nullptr);
+
+ const OUString aTitle(m_xNameED->get_text());
+ const OUString aShortName(m_xShortNameEdit->get_text());
+
+ std::unique_ptr<weld::TreeIter> xParent;
+ std::unique_ptr<weld::TreeIter> xChild = DoesBlockExist(aTitle, aShortName);
+ if (xChild && m_xCategoryBox->get_iter_depth(*xChild))
+ {
+ xParent = m_xCategoryBox->make_iterator(xChild.get());
+ m_xCategoryBox->iter_parent(*xParent);
+ }
+
+ const bool bExists = nullptr != xChild;
+ const bool bIsGroup = bEntry && !xParent;
+
+ std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ SwResId(STR_QUERY_DELETE)));
+ if (bExists && !bIsGroup && RET_YES == xQuery->run())
+ {
+ if (!aTitle.isEmpty() && m_pGlossaryHdl->DelGlossary(aShortName))
+ {
+ OSL_ENSURE(xChild, "entry not found!");
+ m_xCategoryBox->select(*xParent);
+ m_xCategoryBox->remove(*xChild);
+ m_xNameED->set_text(OUString());
+ NameModify(*m_xNameED);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/impfnote.hxx b/sw/source/ui/misc/impfnote.hxx
new file mode 100644
index 000000000..9119ff148
--- /dev/null
+++ b/sw/source/ui/misc/impfnote.hxx
@@ -0,0 +1,83 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_SW_SOURCE_UI_MISC_IMPFNOTE_HXX
+#define INCLUDED_SW_SOURCE_UI_MISC_IMPFNOTE_HXX
+
+#include <sfx2/tabdlg.hxx>
+#include <vcl/weld.hxx>
+#include <numberingtypelistbox.hxx>
+
+enum SwFootnoteNum : unsigned;
+class SwWrtShell;
+
+class SwEndNoteOptionPage : public SfxTabPage
+{
+ OUString aNumDoc;
+ OUString aNumPage;
+ OUString aNumChapter;
+ SwWrtShell *pSh;
+ bool bPosDoc;
+ bool bEndNote;
+
+ std::unique_ptr<SwNumberingTypeListBox> m_xNumViewBox;
+ std::unique_ptr<weld::Label> m_xOffsetLbl;
+ std::unique_ptr<weld::SpinButton> m_xOffsetField;
+ std::unique_ptr<weld::ComboBox> m_xNumCountBox;
+ std::unique_ptr<weld::Entry> m_xPrefixED;
+ std::unique_ptr<weld::Entry> m_xSuffixED;
+ std::unique_ptr<weld::Label> m_xPosFT;
+ std::unique_ptr<weld::RadioButton> m_xPosPageBox;
+ std::unique_ptr<weld::RadioButton> m_xPosChapterBox;
+ std::unique_ptr<weld::Widget> m_xStylesContainer;
+ std::unique_ptr<weld::ComboBox> m_xParaTemplBox;
+ std::unique_ptr<weld::Label> m_xPageTemplLbl;
+ std::unique_ptr<weld::ComboBox> m_xPageTemplBox;
+ std::unique_ptr<weld::ComboBox> m_xFootnoteCharAnchorTemplBox;
+ std::unique_ptr<weld::ComboBox> m_xFootnoteCharTextTemplBox;
+ std::unique_ptr<weld::Entry> m_xContEdit;
+ std::unique_ptr<weld::Entry> m_xContFromEdit;
+
+ inline void SelectNumbering(SwFootnoteNum eNum);
+ SwFootnoteNum GetNumbering() const;
+
+ DECL_LINK(ToggleHdl, weld::Toggleable&, void);
+ DECL_LINK(NumCountHdl, weld::ComboBox&, void);
+
+public:
+ SwEndNoteOptionPage(weld::Container* pPage, weld::DialogController* pController, bool bEndNote, const SfxItemSet &rSet);
+ virtual ~SwEndNoteOptionPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ virtual bool FillItemSet(SfxItemSet *rSet) override;
+ virtual void Reset( const SfxItemSet* ) override;
+
+ void SetShell( SwWrtShell &rShell );
+};
+
+class SwFootNoteOptionPage : public SwEndNoteOptionPage
+{
+public:
+ SwFootNoteOptionPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet );
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet);
+ virtual ~SwFootNoteOptionPage() override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/insfnote.cxx b/sw/source/ui/misc/insfnote.cxx
new file mode 100644
index 000000000..5cdad12d3
--- /dev/null
+++ b/sw/source/ui/misc/insfnote.cxx
@@ -0,0 +1,249 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <fmtftn.hxx>
+#include <swundo.hxx>
+#include <cmdid.h>
+#include <wrtsh.hxx>
+#include <insfnote.hxx>
+#include <svx/svxdlg.hxx>
+
+#include <memory>
+
+static bool bFootnote = true;
+
+// inserting a footnote with OK
+void SwInsFootNoteDlg::Apply()
+{
+ OUString aStr;
+ if ( m_xNumberCharBtn->get_active() )
+ aStr = m_xNumberCharEdit->get_text();
+
+ if (m_bEdit)
+ {
+ m_rSh.StartAction();
+ m_rSh.Left(CRSR_SKIP_CHARS, false, 1, false );
+ m_rSh.StartUndo( SwUndoId::START );
+ SwFormatFootnote aNote( m_xEndNoteBtn->get_active() );
+ aNote.SetNumStr( aStr );
+
+ if (m_rSh.SetCurFootnote( aNote ) && m_bExtCharAvailable)
+ {
+ m_rSh.Right(CRSR_SKIP_CHARS, true, 1, false );
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet(m_rSh.GetAttrPool());
+ m_rSh.GetCurAttr(aSet);
+ const SvxFontItem &rFont = aSet.Get( RES_CHRATR_FONT );
+ SvxFontItem aFont( rFont.GetFamily(), m_aFontName,
+ rFont.GetStyleName(), rFont.GetPitch(),
+ m_eCharSet, RES_CHRATR_FONT );
+ aSet.Put( aFont );
+ m_rSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
+ m_rSh.ResetSelect(nullptr, false);
+ m_rSh.Left(CRSR_SKIP_CHARS, false, 1, false );
+ }
+ m_rSh.EndUndo( SwUndoId::END );
+ m_rSh.EndAction();
+ }
+
+ bFootnote = m_xFootnoteBtn->get_active();
+}
+
+IMPL_LINK_NOARG(SwInsFootNoteDlg, NumberEditHdl, weld::Entry&, void)
+{
+ m_xNumberCharBtn->set_active(true);
+ m_xOkBtn->set_sensitive( !m_xNumberCharEdit->get_text().isEmpty() );
+}
+
+IMPL_LINK(SwInsFootNoteDlg, NumberToggleHdl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+
+ if (m_xNumberAutoBtn->get_active())
+ m_xOkBtn->set_sensitive(true);
+ else if (m_xNumberCharBtn->get_active())
+ {
+ m_xNumberCharEdit->grab_focus();
+ m_xOkBtn->set_sensitive( !m_xNumberCharEdit->get_text().isEmpty() || m_bExtCharAvailable );
+ }
+}
+
+IMPL_LINK_NOARG(SwInsFootNoteDlg, NumberExtCharHdl, weld::Button&, void)
+{
+ m_xNumberCharBtn->set_active(true);
+
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet(m_rSh.GetAttrPool());
+ m_rSh.GetCurAttr( aSet );
+ const SvxFontItem &rFont = aSet.Get( RES_CHRATR_FONT );
+
+ SfxAllItemSet aAllSet(m_rSh.GetAttrPool());
+ aAllSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
+ aAllSet.Put( rFont );
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(m_xDialog.get(), aAllSet, nullptr));
+ if (RET_OK != pDlg->Execute())
+ return;
+
+ const SfxStringItem* pItem = SfxItemSet::GetItem<SfxStringItem>(pDlg->GetOutputItemSet(), SID_CHARMAP, false);
+ const SvxFontItem* pFontItem = SfxItemSet::GetItem<SvxFontItem>(pDlg->GetOutputItemSet(), SID_ATTR_CHAR_FONT, false);
+ if ( !pItem )
+ return;
+
+ m_xNumberCharEdit->set_text(pItem->GetValue());
+
+ if ( pFontItem )
+ {
+ m_aFontName = pFontItem->GetFamilyName();
+ m_eCharSet = pFontItem->GetCharSet();
+ vcl::Font aFont(m_aFontName, pFontItem->GetStyleName(), m_xNumberCharEdit->get_font().GetFontSize());
+ aFont.SetCharSet( pFontItem->GetCharSet() );
+ aFont.SetPitch( pFontItem->GetPitch() );
+ m_xNumberCharEdit->set_font(aFont);
+ }
+
+ m_bExtCharAvailable = true;
+ m_xOkBtn->set_sensitive(!m_xNumberCharEdit->get_text().isEmpty());
+}
+
+IMPL_LINK( SwInsFootNoteDlg, NextPrevHdl, weld::Button&, rBtn, void )
+{
+ Apply();
+
+ // go to the next foot/endnote here
+ m_rSh.ResetSelect(nullptr, false);
+ if (&rBtn == m_xNextBT.get())
+ m_rSh.GotoNextFootnoteAnchor();
+ else
+ m_rSh.GotoPrevFootnoteAnchor();
+
+ Init();
+}
+
+SwInsFootNoteDlg::SwInsFootNoteDlg(weld::Window *pParent, SwWrtShell &rShell, bool bEd)
+ : GenericDialogController(pParent, "modules/swriter/ui/insertfootnote.ui", "InsertFootnoteDialog")
+ , m_rSh(rShell)
+ , m_eCharSet(RTL_TEXTENCODING_DONTKNOW)
+ , m_bExtCharAvailable(false)
+ , m_bEdit(bEd)
+ , m_xNumberFrame(m_xBuilder->weld_widget("numberingframe"))
+ , m_xNumberAutoBtn(m_xBuilder->weld_radio_button("automatic"))
+ , m_xNumberCharBtn(m_xBuilder->weld_radio_button("character"))
+ , m_xNumberCharEdit(m_xBuilder->weld_entry("characterentry"))
+ , m_xNumberExtChar(m_xBuilder->weld_button("choosecharacter"))
+ , m_xFootnoteBtn(m_xBuilder->weld_radio_button("footnote"))
+ , m_xEndNoteBtn(m_xBuilder->weld_radio_button("endnote"))
+ , m_xOkBtn(m_xBuilder->weld_button("ok"))
+ , m_xPrevBT(m_xBuilder->weld_button("prev"))
+ , m_xNextBT(m_xBuilder->weld_button("next"))
+{
+ m_xNumberAutoBtn->connect_toggled(LINK(this,SwInsFootNoteDlg,NumberToggleHdl));
+ m_xNumberCharBtn->connect_toggled(LINK(this,SwInsFootNoteDlg,NumberToggleHdl));
+ m_xNumberExtChar->connect_clicked(LINK(this,SwInsFootNoteDlg,NumberExtCharHdl));
+ m_xNumberCharEdit->connect_changed(LINK(this,SwInsFootNoteDlg,NumberEditHdl));
+
+ m_xPrevBT->connect_clicked(LINK(this, SwInsFootNoteDlg, NextPrevHdl));
+ m_xNextBT->connect_clicked(LINK(this, SwInsFootNoteDlg, NextPrevHdl));
+
+ SwViewShell::SetCareDialog(m_xDialog);
+
+ if (m_bEdit)
+ {
+ Init();
+
+ m_xPrevBT->show();
+ m_xNextBT->show();
+ }
+}
+
+SwInsFootNoteDlg::~SwInsFootNoteDlg() COVERITY_NOEXCEPT_FALSE
+{
+ SwViewShell::SetCareDialog(nullptr);
+
+ if (m_bEdit)
+ m_rSh.ResetSelect(nullptr, false);
+}
+
+void SwInsFootNoteDlg::Init()
+{
+ SwFormatFootnote aFootnoteNote;
+ OUString sNumStr;
+ vcl::Font aFont;
+ m_bExtCharAvailable = false;
+
+ m_rSh.StartAction();
+
+ if (m_rSh.GetCurFootnote(&aFootnoteNote))
+ {
+ if (!aFootnoteNote.GetNumStr().isEmpty())
+ {
+ sNumStr = aFootnoteNote.GetNumStr();
+
+ m_rSh.Right(CRSR_SKIP_CHARS, true, 1, false );
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet(m_rSh.GetAttrPool());
+ m_rSh.GetCurAttr(aSet);
+ const SvxFontItem &rFont = aSet.Get( RES_CHRATR_FONT );
+ aFont = m_xNumberCharEdit->get_font();
+ m_aFontName = rFont.GetFamilyName();
+ m_eCharSet = rFont.GetCharSet();
+ aFont.SetFamilyName(m_aFontName);
+ aFont.SetCharSet(m_eCharSet);
+ m_bExtCharAvailable = true;
+ m_rSh.Left( CRSR_SKIP_CHARS, false, 1, false );
+ }
+ bFootnote = !aFootnoteNote.IsEndNote();
+ }
+ m_xNumberCharEdit->set_font(aFont);
+
+ const bool bNumChar = !sNumStr.isEmpty();
+
+ m_xNumberCharEdit->set_text(sNumStr);
+ m_xNumberCharBtn->set_active(bNumChar);
+ m_xNumberAutoBtn->set_active(!bNumChar);
+ if (bNumChar)
+ m_xNumberCharEdit->grab_focus();
+
+ if (bFootnote)
+ m_xFootnoteBtn->set_active(true);
+ else
+ m_xEndNoteBtn->set_active(true);
+
+ bool bNext = m_rSh.GotoNextFootnoteAnchor();
+
+ if (bNext)
+ m_rSh.GotoPrevFootnoteAnchor();
+
+ bool bPrev = m_rSh.GotoPrevFootnoteAnchor();
+
+ if (bPrev)
+ m_rSh.GotoNextFootnoteAnchor();
+
+ m_xPrevBT->set_sensitive(bPrev);
+ m_xNextBT->set_sensitive(bNext);
+
+ m_rSh.Right(CRSR_SKIP_CHARS, true, 1, false );
+
+ m_rSh.EndAction();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/linenum.cxx b/sw/source/ui/misc/linenum.cxx
new file mode 100644
index 000000000..72adb140b
--- /dev/null
+++ b/sw/source/ui/misc/linenum.cxx
@@ -0,0 +1,260 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/viewfrm.hxx>
+#include <svl/style.hxx>
+#include <svtools/unitconv.hxx>
+#include <sal/log.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <charfmt.hxx>
+
+#include <docstyle.hxx>
+
+#include <lineinfo.hxx>
+#include <linenum.hxx>
+#include <swmodule.hxx>
+#include <uitool.hxx>
+#include <usrpref.hxx>
+#include <wdocsh.hxx>
+#include <fmtline.hxx>
+#include <strings.hrc>
+
+#include <IDocumentStylePoolAccess.hxx>
+
+static rtl::Reference<SwDocStyleSheet> lcl_getDocStyleSheet(const OUString& rName, SwWrtShell *pSh)
+{
+ SfxStyleSheetBasePool* pBase = pSh->GetView().GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyle = pBase->Find(rName, SfxStyleFamily::Para);
+ SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" );
+ if(!pStyle)
+ return nullptr;
+ return new SwDocStyleSheet(*static_cast<SwDocStyleSheet*>(pStyle));
+}
+
+static void lcl_setLineNumbering(const OUString& rName, SwWrtShell* pSh, bool bLineNumber)
+{
+ rtl::Reference<SwDocStyleSheet> xStyleSheet = lcl_getDocStyleSheet(rName, pSh);
+ if(!xStyleSheet.is())
+ return;
+ SfxItemSet& rSet = xStyleSheet->GetItemSet();
+ SwFormatLineNumber aFormat;
+ aFormat.SetCountLines(bLineNumber);
+ rSet.Put(aFormat);
+ xStyleSheet->MergeIndentAttrsOfListStyle( rSet );
+ xStyleSheet->SetItemSet(rSet);
+}
+
+SwLineNumberingDlg::SwLineNumberingDlg(const SwView& rVw)
+ : SfxDialogController(rVw.GetViewFrame()->GetFrameWeld(),
+ "modules/swriter/ui/linenumbering.ui", "LineNumberingDialog")
+ , m_pSh(rVw.GetWrtShellPtr())
+ , m_xBodyContent(m_xBuilder->weld_widget("content"))
+ , m_xDivIntervalFT(m_xBuilder->weld_widget("every"))
+ , m_xDivIntervalNF(m_xBuilder->weld_spin_button("linesspin"))
+ , m_xDivRowsFT(m_xBuilder->weld_widget("lines"))
+ , m_xNumIntervalNF(m_xBuilder->weld_spin_button("intervalspin"))
+ , m_xCharStyleLB(m_xBuilder->weld_combo_box("styledropdown"))
+ , m_xFormatLB(new SwNumberingTypeListBox(m_xBuilder->weld_combo_box("formatdropdown")))
+ , m_xPosLB(m_xBuilder->weld_combo_box("positiondropdown"))
+ , m_xOffsetMF(m_xBuilder->weld_metric_spin_button("spacingspin", FieldUnit::CM))
+ , m_xDivisorED(m_xBuilder->weld_entry("textentry"))
+ , m_xCountEmptyLinesCB(m_xBuilder->weld_check_button("blanklines"))
+ , m_xCountFrameLinesCB(m_xBuilder->weld_check_button("linesintextframes"))
+ , m_xRestartEachPageCB(m_xBuilder->weld_check_button("restarteverynewpage"))
+ , m_xNumberingOnCB(m_xBuilder->weld_check_button("shownumbering"))
+ , m_xNumberingOnFooterHeader(m_xBuilder->weld_check_button("showfooterheadernumbering"))
+ , m_xOKButton(m_xBuilder->weld_button("ok"))
+ , m_xNumIntervalFT(m_xBuilder->weld_widget("interval"))
+ , m_xNumRowsFT(m_xBuilder->weld_widget("intervallines"))
+{
+ m_xFormatLB->Reload(SwInsertNumTypes::Extended);
+
+ OUString sIntervalName = m_xDivIntervalFT->get_accessible_name()
+ + "("
+ + m_xDivRowsFT->get_accessible_name()
+ + ")";
+ m_xDivIntervalNF->set_accessible_name(sIntervalName);
+
+ sIntervalName = m_xNumIntervalFT->get_accessible_name()
+ + "("
+ + m_xNumRowsFT->get_accessible_name()
+ + ")";
+ m_xNumIntervalNF->set_accessible_name(sIntervalName);
+
+ // char styles
+ ::FillCharStyleListBox(*m_xCharStyleLB, m_pSh->GetView().GetDocShell());
+
+ const SwLineNumberInfo &rInf = m_pSh->GetLineNumberInfo();
+ IDocumentStylePoolAccess& rIDSPA = m_pSh->getIDocumentStylePoolAccess();
+
+ OUString sStyleName(rInf.GetCharFormat( rIDSPA )->GetName());
+ const int nPos = m_xCharStyleLB->find_text(sStyleName);
+
+ if (nPos != -1)
+ m_xCharStyleLB->set_active(nPos);
+ else
+ {
+ if (!sStyleName.isEmpty())
+ {
+ m_xCharStyleLB->append_text(sStyleName);
+ m_xCharStyleLB->set_active_text(sStyleName);
+ }
+ }
+
+ // format
+ SvxNumType nSelFormat = rInf.GetNumType().GetNumberingType();
+
+ m_xFormatLB->SelectNumberingType(nSelFormat);
+
+ // position
+ m_xPosLB->set_active(rInf.GetPos());
+
+ // offset
+ sal_uInt16 nOffset = rInf.GetPosFromLeft();
+ if (nOffset == USHRT_MAX)
+ nOffset = 0;
+
+ FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(dynamic_cast< const SwWebDocShell*>(
+ rVw.GetDocShell()) != nullptr)->GetMetric();
+ ::SetFieldUnit(*m_xOffsetMF, eFieldUnit);
+ m_xOffsetMF->set_value(m_xOffsetMF->normalize(nOffset), FieldUnit::TWIP);
+
+ // numbering offset
+ m_xNumIntervalNF->set_value(rInf.GetCountBy());
+
+ // divider
+ m_xDivisorED->set_text(rInf.GetDivider());
+
+ // divider offset
+ m_xDivIntervalNF->set_value(rInf.GetDividerCountBy());
+
+ // count
+ m_xCountEmptyLinesCB->set_active(rInf.IsCountBlankLines());
+ m_xCountFrameLinesCB->set_active(rInf.IsCountInFlys());
+ m_xRestartEachPageCB->set_active(rInf.IsRestartEachPage());
+
+ m_xNumberingOnCB->set_active(rInf.IsPaintLineNumbers());
+
+ // Header/Footer Line Numbering
+ rtl::Reference< SwDocStyleSheet > xStyleSheet = lcl_getDocStyleSheet(SwResId(STR_POOLCOLL_FOOTER), m_pSh);
+ if(xStyleSheet.is())
+ {
+ SfxItemSet& rSet = xStyleSheet->GetItemSet();
+ const SwFormatLineNumber &aFormat = rSet.Get(RES_LINENUMBER);
+ if (aFormat.IsCount())
+ m_xNumberingOnFooterHeader->set_state(TRISTATE_TRUE);
+ else
+ m_xNumberingOnFooterHeader->set_state(TRISTATE_FALSE);
+ }
+
+ // Line Numbering
+ m_xNumberingOnCB->connect_toggled(LINK(this, SwLineNumberingDlg, LineOnOffHdl));
+ m_xDivisorED->connect_changed(LINK(this, SwLineNumberingDlg, ModifyHdl));
+ ModifyHdl(*m_xDivisorED);
+ LineOnOffHdl(*m_xNumberingOnCB);
+
+ m_xOKButton->connect_clicked(LINK(this, SwLineNumberingDlg, OKHdl));
+}
+
+SwLineNumberingDlg::~SwLineNumberingDlg()
+{
+}
+
+IMPL_LINK_NOARG(SwLineNumberingDlg, OKHdl, weld::Button&, void)
+{
+ SwLineNumberInfo aInf(m_pSh->GetLineNumberInfo());
+
+ // char styles
+ OUString sCharFormatName(m_xCharStyleLB->get_active_text());
+ SwCharFormat *pCharFormat = m_pSh->FindCharFormatByName(sCharFormatName);
+
+ if (!pCharFormat)
+ {
+ SfxStyleSheetBasePool* pPool = m_pSh->GetView().GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase* pBase;
+ pBase = pPool->Find(sCharFormatName, SfxStyleFamily::Char);
+ if(!pBase)
+ pBase = &pPool->Make(sCharFormatName, SfxStyleFamily::Char);
+ pCharFormat = static_cast<SwDocStyleSheet*>(pBase)->GetCharFormat();
+ }
+
+ if (pCharFormat)
+ aInf.SetCharFormat(pCharFormat);
+
+ // format
+ SvxNumberType aType;
+ aType.SetNumberingType(m_xFormatLB->GetSelectedNumberingType());
+ aInf.SetNumType(aType);
+
+ // position
+ aInf.SetPos(static_cast<LineNumberPosition>(m_xPosLB->get_active()));
+
+ // offset
+ aInf.SetPosFromLeft(o3tl::narrowing<sal_uInt16>(m_xOffsetMF->denormalize(m_xOffsetMF->get_value(FieldUnit::TWIP))));
+
+ // numbering offset
+ aInf.SetCountBy(o3tl::narrowing<sal_uInt16>(m_xNumIntervalNF->get_value()));
+
+ // divider
+ aInf.SetDivider(m_xDivisorED->get_text());
+
+ // divider offset
+ aInf.SetDividerCountBy(o3tl::narrowing<sal_uInt16>(m_xDivIntervalNF->get_value()));
+
+ // count
+ aInf.SetCountBlankLines(m_xCountEmptyLinesCB->get_active());
+ aInf.SetCountInFlys(m_xCountFrameLinesCB->get_active());
+ aInf.SetRestartEachPage(m_xRestartEachPageCB->get_active());
+
+ aInf.SetPaintLineNumbers(m_xNumberingOnCB->get_active());
+
+ m_pSh->SetLineNumberInfo(aInf);
+
+ // Set LineNumber explicitly for Header and Footer
+ lcl_setLineNumbering(SwResId(STR_POOLCOLL_FOOTER), m_pSh, m_xNumberingOnFooterHeader->get_active());
+ lcl_setLineNumbering(SwResId(STR_POOLCOLL_HEADER), m_pSh, m_xNumberingOnFooterHeader->get_active());
+ if( m_xNumberingOnFooterHeader->get_active())
+ m_xNumberingOnFooterHeader->set_state(TRISTATE_TRUE);
+ else
+ m_xNumberingOnFooterHeader->set_state(TRISTATE_FALSE);
+
+ m_xDialog->response(RET_OK);
+}
+
+// modify
+IMPL_LINK_NOARG(SwLineNumberingDlg, ModifyHdl, weld::Entry&, void)
+{
+ bool bEnable = m_xNumberingOnCB->get_active() && !m_xDivisorED->get_text().isEmpty();
+
+ m_xDivIntervalFT->set_sensitive(bEnable);
+ m_xDivIntervalNF->set_sensitive(bEnable);
+ m_xDivRowsFT->set_sensitive(bEnable);
+}
+
+// On/Off
+IMPL_LINK_NOARG(SwLineNumberingDlg, LineOnOffHdl, weld::Toggleable&, void)
+{
+ bool bEnable = m_xNumberingOnCB->get_active();
+ m_xBodyContent->set_sensitive(bEnable);
+ ModifyHdl(*m_xDivisorED);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/num.cxx b/sw/source/ui/misc/num.cxx
new file mode 100644
index 000000000..b41e15b15
--- /dev/null
+++ b/sw/source/ui/misc/num.cxx
@@ -0,0 +1,957 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/numitem.hxx>
+#include <cmdid.h>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <wview.hxx>
+#include <uitool.hxx>
+#include <wdocsh.hxx>
+#include <uiitems.hxx>
+#include <poolfmt.hxx>
+#include <shellres.hxx>
+#include <outline.hxx>
+#include <num.hxx>
+
+#include <SwStyleNameMapper.hxx>
+#include <svx/dialogs.hrc>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/slstitm.hxx>
+#include <svl/intitem.hxx>
+#include <comphelper/lok.hxx>
+#include <osl/diagnose.h>
+
+static bool bLastRelative = false;
+
+//See cui/uiconfig/ui/numberingpositionpage.ui for effectively a duplicate
+//dialog to this one, except with a different preview window impl.
+//TODO, determine if SwNumPositionTabPage and SvxNumPositionTabPage can be
+//merged
+SwNumPositionTabPage::SwNumPositionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
+ : SfxTabPage(pPage, pController, "modules/swriter/ui/outlinepositionpage.ui", "OutlinePositionPage", &rSet)
+ , pSaveNum(nullptr)
+ , pWrtSh(nullptr)
+ , pOutlineDlg(nullptr)
+ , nActNumLvl(0)
+ , bModified(false)
+ , bPreset(false)
+ , bInInintControl(false)
+ , bLabelAlignmentPosAndSpaceModeActive(false)
+ , m_xLevelLB(m_xBuilder->weld_tree_view("levellb"))
+ , m_xPositionFrame(m_xBuilder->weld_widget("numberingframe"))
+ , m_xDistBorderFT(m_xBuilder->weld_label("indent"))
+ , m_xDistBorderMF(m_xBuilder->weld_metric_spin_button("indentmf", FieldUnit::CM))
+ , m_xRelativeCB(m_xBuilder->weld_check_button("relative"))
+ , m_xIndentFT(m_xBuilder->weld_label("numberingwidth"))
+ , m_xIndentMF(m_xBuilder->weld_metric_spin_button("numberingwidthmf", FieldUnit::CM))
+ , m_xDistNumFT(m_xBuilder->weld_label("numdist"))
+ , m_xDistNumMF(m_xBuilder->weld_metric_spin_button("numdistmf", FieldUnit::CM))
+ , m_xAlignFT(m_xBuilder->weld_label("numalign"))
+ , m_xAlignLB(m_xBuilder->weld_combo_box("numalignlb"))
+ , m_xLabelFollowedByFT(m_xBuilder->weld_label("numfollowedby"))
+ , m_xLabelFollowedByLB(m_xBuilder->weld_combo_box("numfollowedbylb"))
+ , m_xListtabFT(m_xBuilder->weld_label("at"))
+ , m_xListtabMF(m_xBuilder->weld_metric_spin_button("atmf", FieldUnit::CM))
+ , m_xAlign2FT(m_xBuilder->weld_label("num2align"))
+ , m_xAlign2LB(m_xBuilder->weld_combo_box("num2alignlb"))
+ , m_xAlignedAtFT(m_xBuilder->weld_label("alignedat"))
+ , m_xAlignedAtMF(m_xBuilder->weld_metric_spin_button("alignedatmf", FieldUnit::CM))
+ , m_xIndentAtFT(m_xBuilder->weld_label("indentat"))
+ , m_xIndentAtMF(m_xBuilder->weld_metric_spin_button("indentatmf", FieldUnit::CM))
+ , m_xStandardPB(m_xBuilder->weld_button("standard"))
+ , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN))
+{
+ SetExchangeSupport();
+
+ m_xLevelLB->set_selection_mode(SelectionMode::Multiple);
+
+ m_xRelativeCB->set_active(true);
+ m_xAlignLB->connect_changed(LINK(this, SwNumPositionTabPage, EditModifyHdl));
+ m_xAlign2LB->connect_changed(LINK(this, SwNumPositionTabPage, EditModifyHdl));
+ for (int i = 0; i < m_xAlignLB->get_count(); ++i)
+ {
+ m_xAlign2LB->append_text(m_xAlignLB->get_text(i));
+ }
+ m_xAlign2FT->set_label(m_xAlignFT->get_label());
+
+ Link<weld::MetricSpinButton&, void> aLk = LINK(this, SwNumPositionTabPage, DistanceHdl);
+ m_xDistBorderMF->connect_value_changed(aLk);
+ m_xDistNumMF->connect_value_changed(aLk);
+ m_xIndentMF->connect_value_changed(aLk);
+
+ m_xLabelFollowedByLB->connect_changed( LINK(this, SwNumPositionTabPage, LabelFollowedByHdl_Impl) );
+
+ aLk = LINK(this, SwNumPositionTabPage, ListtabPosHdl_Impl);
+ m_xListtabMF->connect_value_changed(aLk);
+
+ aLk = LINK(this, SwNumPositionTabPage, AlignAtHdl_Impl);
+ m_xAlignedAtMF->connect_value_changed(aLk);
+
+ aLk = LINK(this, SwNumPositionTabPage, IndentAtHdl_Impl);
+ m_xIndentAtMF->connect_value_changed(aLk);
+
+ m_xLevelLB->connect_changed(LINK(this, SwNumPositionTabPage, LevelHdl));
+ m_xRelativeCB->connect_toggled(LINK(this, SwNumPositionTabPage, RelativeHdl));
+ m_xStandardPB->connect_clicked(LINK(this, SwNumPositionTabPage, StandardHdl));
+
+ // insert levels
+ for(sal_uInt16 i = 1; i <= MAXLEVEL; i++)
+ m_xLevelLB->append_text(OUString::number(i));
+ OUString sEntry = "1 - " + OUString::number(MAXLEVEL);
+ m_xLevelLB->append_text(sEntry);
+ m_xLevelLB->select_text(sEntry);
+
+ m_xRelativeCB->set_active(bLastRelative);
+ m_aPreviewWIN.SetPositionMode();
+}
+
+SwNumPositionTabPage::~SwNumPositionTabPage()
+{
+ pActNum.reset();
+ pOutlineDlg = nullptr;
+}
+
+void SwNumPositionTabPage::InitControls()
+{
+ bInInintControl = true;
+ const bool bRelative = !bLabelAlignmentPosAndSpaceModeActive &&
+ m_xRelativeCB->get_sensitive() && m_xRelativeCB->get_active();
+ const bool bSingleSelection = m_xLevelLB->count_selected_rows() == 1 &&
+ USHRT_MAX != nActNumLvl;
+
+ m_xDistBorderMF->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive &&
+ ( bSingleSelection || bRelative || pOutlineDlg != nullptr ) );
+ m_xDistBorderFT->set_sensitive( !bLabelAlignmentPosAndSpaceModeActive &&
+ ( bSingleSelection || bRelative || pOutlineDlg != nullptr ) );
+
+ bool bSetDistEmpty = false;
+ bool bSameDistBorderNum = !bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameDist = !bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameIndent = !bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameAdjust = true;
+
+ bool bSameLabelFollowedBy = bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameListtab = bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameAlignAt = bLabelAlignmentPosAndSpaceModeActive;
+ bool bSameIndentAt = bLabelAlignmentPosAndSpaceModeActive;
+
+ const SwNumFormat* aNumFormatArr[MAXLEVEL];
+ sal_uInt16 nMask = 1;
+ sal_uInt16 nLvl = USHRT_MAX;
+ tools::Long nFirstBorderTextRelative = -1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ aNumFormatArr[i] = &pActNum->Get(i);
+ if(nActNumLvl & nMask)
+ {
+ if(USHRT_MAX == nLvl)
+ {
+ nLvl = i;
+ }
+
+ if( i > nLvl)
+ {
+ bSameAdjust &= aNumFormatArr[i]->GetNumAdjust() == aNumFormatArr[nLvl]->GetNumAdjust();
+ if ( !bLabelAlignmentPosAndSpaceModeActive )
+ {
+ if(bRelative)
+ {
+ const tools::Long nBorderTextRelative =
+ aNumFormatArr[i]->GetAbsLSpace() + aNumFormatArr[i]->GetFirstLineOffset() -
+ aNumFormatArr[i - 1]->GetAbsLSpace() + aNumFormatArr[i - 1]->GetFirstLineOffset();
+ if (nFirstBorderTextRelative == -1)
+ nFirstBorderTextRelative = nBorderTextRelative;
+ else
+ bSameDistBorderNum &= nFirstBorderTextRelative == nBorderTextRelative;
+ }
+ else
+ {
+ bSameDistBorderNum &=
+ aNumFormatArr[i]->GetAbsLSpace() - aNumFormatArr[i]->GetFirstLineOffset() ==
+ aNumFormatArr[i - 1]->GetAbsLSpace() - aNumFormatArr[i - 1]->GetFirstLineOffset();
+ }
+
+ bSameDist &= aNumFormatArr[i]->GetCharTextDistance() == aNumFormatArr[nLvl]->GetCharTextDistance();
+ bSameIndent &= aNumFormatArr[i]->GetFirstLineOffset() == aNumFormatArr[nLvl]->GetFirstLineOffset();
+ }
+ else
+ {
+ bSameLabelFollowedBy &=
+ aNumFormatArr[i]->GetLabelFollowedBy() == aNumFormatArr[nLvl]->GetLabelFollowedBy();
+ bSameListtab &=
+ aNumFormatArr[i]->GetListtabPos() == aNumFormatArr[nLvl]->GetListtabPos();
+ bSameAlignAt &=
+ ( ( aNumFormatArr[i]->GetIndentAt() + aNumFormatArr[i]->GetFirstLineIndent() )
+ == ( aNumFormatArr[nLvl]->GetIndentAt() + aNumFormatArr[nLvl]->GetFirstLineIndent() ) );
+ bSameIndentAt &=
+ aNumFormatArr[i]->GetIndentAt() == aNumFormatArr[nLvl]->GetIndentAt();
+ }
+ }
+ }
+ nMask <<= 1;
+
+ }
+ if (MAXLEVEL <= nLvl)
+ {
+ OSL_ENSURE(false, "cannot happen.");
+ return;
+ }
+ if(bSameDistBorderNum)
+ {
+ tools::Long nDistBorderNum;
+ if(bRelative)
+ {
+ nDistBorderNum = static_cast<tools::Long>(aNumFormatArr[nLvl]->GetAbsLSpace())+ aNumFormatArr[nLvl]->GetFirstLineOffset();
+ if(nLvl)
+ nDistBorderNum -= static_cast<tools::Long>(aNumFormatArr[nLvl - 1]->GetAbsLSpace())+ aNumFormatArr[nLvl - 1]->GetFirstLineOffset();
+ }
+ else
+ {
+ nDistBorderNum = static_cast<tools::Long>(aNumFormatArr[nLvl]->GetAbsLSpace())+ aNumFormatArr[nLvl]->GetFirstLineOffset();
+ }
+ m_xDistBorderMF->set_value(m_xDistBorderMF->normalize(nDistBorderNum),FieldUnit::TWIP);
+ }
+ else
+ bSetDistEmpty = true;
+
+ if(bSameDist)
+ m_xDistNumMF->set_value(m_xDistNumMF->normalize(aNumFormatArr[nLvl]->GetCharTextDistance()), FieldUnit::TWIP);
+ else
+ m_xDistNumMF->set_text(OUString());
+ if(bSameIndent)
+ m_xIndentMF->set_value(m_xIndentMF->normalize(-aNumFormatArr[nLvl]->GetFirstLineOffset()), FieldUnit::TWIP);
+ else
+ m_xIndentMF->set_text(OUString());
+
+ if(bSameAdjust)
+ {
+ sal_Int32 nPos = 1; // centered
+ if(aNumFormatArr[nLvl]->GetNumAdjust() == SvxAdjust::Left)
+ nPos = 0;
+ else if(aNumFormatArr[nLvl]->GetNumAdjust() == SvxAdjust::Right)
+ nPos = 2;
+ m_xAlignLB->set_active(nPos);
+ m_xAlign2LB->set_active( nPos );
+ }
+ else
+ {
+ m_xAlignLB->set_active(-1);
+ m_xAlign2LB->set_active(-1);
+ }
+
+ if ( bSameLabelFollowedBy )
+ {
+ sal_Int32 nPos = 0; // LISTTAB
+ if ( aNumFormatArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::SPACE )
+ {
+ nPos = 1;
+ }
+ else if ( aNumFormatArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NOTHING )
+ {
+ nPos = 2;
+ }
+ else if ( aNumFormatArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::NEWLINE )
+ {
+ nPos = 3;
+ }
+ m_xLabelFollowedByLB->set_active(nPos);
+ }
+ else
+ {
+ m_xLabelFollowedByLB->set_active(-1);
+ }
+
+ if ( aNumFormatArr[nLvl]->GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
+ {
+ m_xListtabFT->set_sensitive(true);
+ m_xListtabMF->set_sensitive(true);
+ if ( bSameListtab )
+ {
+ m_xListtabMF->set_value(m_xListtabMF->normalize(aNumFormatArr[nLvl]->GetListtabPos()),FieldUnit::TWIP);
+ }
+ else
+ {
+ m_xListtabMF->set_text(OUString());
+ }
+ }
+ else
+ {
+ m_xListtabFT->set_sensitive( false );
+ m_xListtabMF->set_sensitive( false );
+ m_xListtabMF->set_text(OUString());
+ }
+
+ if ( bSameAlignAt )
+ {
+ m_xAlignedAtMF->set_value(
+ m_xAlignedAtMF->normalize( aNumFormatArr[nLvl]->GetIndentAt() +
+ aNumFormatArr[nLvl]->GetFirstLineIndent()),
+ FieldUnit::TWIP );
+ }
+ else
+ {
+ m_xAlignedAtMF->set_text(OUString());
+ }
+
+ if ( bSameIndentAt )
+ {
+ m_xIndentAtMF->set_value(
+ m_xIndentAtMF->normalize( aNumFormatArr[nLvl]->GetIndentAt()), FieldUnit::TWIP );
+ }
+ else
+ {
+ m_xIndentAtMF->set_text(OUString());
+ }
+
+ if (bSetDistEmpty)
+ m_xDistBorderMF->set_text(OUString());
+
+ bInInintControl = false;
+}
+
+void SwNumPositionTabPage::ActivatePage(const SfxItemSet& )
+{
+ const SfxPoolItem* pItem;
+ sal_uInt16 nTmpNumLvl =
+ pOutlineDlg ? SwOutlineTabDialog::GetActNumLevel() : 0;
+ const SfxItemSet* pExampleSet = GetDialogExampleSet();
+ if(pExampleSet && pExampleSet->GetItemState(FN_PARAM_NUM_PRESET, false, &pItem) != SfxItemState::UNKNOWN)
+ {
+ bPreset = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+ }
+ bModified = (!pActNum->GetNumFormat( 0 ) || bPreset);
+ if(*pActNum != *pSaveNum ||
+ nActNumLvl != nTmpNumLvl )
+ {
+ *pActNum = *pSaveNum;
+ nActNumLvl = nTmpNumLvl;
+ sal_uInt16 nMask = 1;
+ m_xLevelLB->unselect_all();
+ if (nActNumLvl == USHRT_MAX)
+ m_xLevelLB->select(MAXLEVEL);
+ else
+ {
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ if (nActNumLvl & nMask)
+ m_xLevelLB->select(i);
+ nMask <<= 1 ;
+ }
+ }
+
+ InitPosAndSpaceMode();
+ ShowControlsDependingOnPosAndSpaceMode();
+
+ InitControls();
+ }
+ m_xRelativeCB->set_sensitive(1 != nActNumLvl);
+ m_aPreviewWIN.Invalidate();
+}
+
+DeactivateRC SwNumPositionTabPage::DeactivatePage(SfxItemSet *_pSet)
+{
+ SwOutlineTabDialog::SetActNumLevel(nActNumLvl);
+ if(_pSet)
+ FillItemSet(_pSet);
+ return DeactivateRC::LeavePage;
+
+}
+
+bool SwNumPositionTabPage::FillItemSet( SfxItemSet* rSet )
+{
+ if(pOutlineDlg)
+ *pOutlineDlg->GetNumRule() = *pActNum;
+ else if(bModified && pActNum)
+ {
+ *pSaveNum = *pActNum;
+ rSet->Put(SwUINumRuleItem( *pSaveNum ));
+ rSet->Put(SfxBoolItem(FN_PARAM_NUM_PRESET, false));
+ }
+ return bModified;
+}
+
+void SwNumPositionTabPage::Reset( const SfxItemSet* rSet )
+{
+ if (pOutlineDlg)
+ {
+ pSaveNum = pOutlineDlg->GetNumRule();
+ m_xLevelLB->set_selection_mode(SelectionMode::Single);
+ }
+ else if(const SwUINumRuleItem* pNumberItem = rSet->GetItemIfSet(FN_PARAM_ACT_NUMBER, false))
+ pSaveNum = const_cast<SwUINumRuleItem*>(pNumberItem)->GetNumRule();
+
+ nActNumLvl = SwOutlineTabDialog::GetActNumLevel();
+ sal_uInt16 nMask = 1;
+ m_xLevelLB->unselect_all();
+ if(nActNumLvl == USHRT_MAX)
+ {
+ m_xLevelLB->select(MAXLEVEL);
+ }
+ else
+ {
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ if (nActNumLvl & nMask)
+ m_xLevelLB->select(i);
+ nMask <<= 1;
+ }
+ }
+
+ if(!pActNum)
+ pActNum.reset(new SwNumRule(*pSaveNum));
+ else if(*pSaveNum != *pActNum)
+ *pActNum = *pSaveNum;
+ m_aPreviewWIN.SetNumRule(pActNum.get());
+ InitPosAndSpaceMode();
+ ShowControlsDependingOnPosAndSpaceMode();
+ InitControls();
+ bModified = false;
+}
+
+void SwNumPositionTabPage::InitPosAndSpaceMode()
+{
+ if ( pActNum == nullptr )
+ {
+ OSL_FAIL( "<SwNumPositionTabPage::InitPosAndSpaceMode()> - misusage of method -> <pAktNum> has to be already set!" );
+ return;
+ }
+
+ SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode =
+ SvxNumberFormat::LABEL_ALIGNMENT;
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if(nActNumLvl & nMask)
+ {
+ SvxNumberFormat aNumFormat( pActNum->Get(i) );
+ ePosAndSpaceMode = aNumFormat.GetPositionAndSpaceMode();
+ if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ break;
+ }
+ }
+ nMask <<= 1;
+ }
+
+ bLabelAlignmentPosAndSpaceModeActive =
+ ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT;
+}
+
+void SwNumPositionTabPage::ShowControlsDependingOnPosAndSpaceMode()
+{
+ m_xDistBorderFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xDistBorderMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xRelativeCB->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xIndentFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xIndentMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xDistNumFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xDistNumMF->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlignFT->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlignLB->set_visible( !bLabelAlignmentPosAndSpaceModeActive );
+
+ m_xLabelFollowedByFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xLabelFollowedByLB->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xListtabFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xListtabMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlign2FT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlign2LB->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlignedAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xAlignedAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xIndentAtFT->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+ m_xIndentAtMF->set_visible( bLabelAlignmentPosAndSpaceModeActive );
+}
+
+std::unique_ptr<SfxTabPage> SwNumPositionTabPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<SwNumPositionTabPage>(pPage, pController, *rAttrSet);
+}
+
+void SwNumPositionTabPage::SetWrtShell(SwWrtShell* pSh)
+{
+ pWrtSh = pSh;
+
+ const SwTwips nWidth = pWrtSh->GetAnyCurRect(CurRectType::Frame).Width();
+
+ m_xDistBorderMF->set_max(m_xDistBorderMF->normalize( nWidth ), FieldUnit::TWIP );
+ m_xDistNumMF->set_max(m_xDistNumMF->normalize( nWidth ), FieldUnit::TWIP);
+ m_xIndentMF->set_max(m_xIndentMF->normalize( nWidth ), FieldUnit::TWIP );
+ m_xListtabMF->set_max(m_xListtabMF->normalize( nWidth ), FieldUnit::TWIP );
+ m_xAlignedAtMF->set_max(m_xAlignedAtMF->normalize( nWidth ), FieldUnit::TWIP );
+ m_xIndentAtMF->set_max(m_xIndentAtMF->normalize( nWidth ), FieldUnit::TWIP );
+
+ const SwRect& rPrtRect = pWrtSh->GetAnyCurRect(CurRectType::Page);
+ m_aPreviewWIN.SetPageWidth(rPrtRect.Width());
+ FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>( &pWrtSh->GetView()) != nullptr );
+ if(eMetric == FieldUnit::MM)
+ {
+ m_xDistBorderMF->set_digits(1);
+ m_xDistNumMF->set_digits(1);
+ m_xIndentMF->set_digits(1);
+ m_xListtabMF->set_digits(1);
+ m_xAlignedAtMF->set_digits(1);
+ m_xIndentAtMF->set_digits(1);
+ }
+ m_xDistBorderMF->set_unit( eMetric );
+ m_xDistNumMF->set_unit( eMetric );
+ m_xIndentMF->set_unit( eMetric );
+ m_xListtabMF->set_unit( eMetric );
+ m_xAlignedAtMF->set_unit( eMetric );
+ m_xIndentAtMF->set_unit( eMetric );
+}
+
+IMPL_LINK_NOARG(SwNumPositionTabPage, EditModifyHdl, weld::ComboBox&, void)
+{
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActNumLvl & nMask)
+ {
+ SwNumFormat aNumFormat(pActNum->Get(i));
+
+ const int nPos = m_xAlignLB->get_visible()
+ ? m_xAlignLB->get_active()
+ : m_xAlign2LB->get_active();
+ SvxAdjust eAdjust = SvxAdjust::Center;
+ if(nPos == 0)
+ eAdjust = SvxAdjust::Left;
+ else if(nPos == 2)
+ eAdjust = SvxAdjust::Right;
+ aNumFormat.SetNumAdjust( eAdjust );
+ pActNum->Set(i, aNumFormat);
+ }
+ nMask <<= 1;
+ }
+ SetModified();
+}
+
+IMPL_LINK( SwNumPositionTabPage, LevelHdl, weld::TreeView&, rBox, void )
+{
+ sal_uInt16 nSaveNumLvl = nActNumLvl;
+ nActNumLvl = 0;
+ auto aRows = rBox.get_selected_rows();
+ if ((std::find(aRows.begin(), aRows.end(), MAXLEVEL) != aRows.end()) &&
+ (aRows.size() == 1 || nSaveNumLvl != 0xffff))
+ {
+ nActNumLvl = 0xFFFF;
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ rBox.unselect(i);
+ }
+ else if (!aRows.empty())
+ {
+ sal_uInt16 nMask = 1;
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ if (std::find(aRows.begin(), aRows.end(), i) != aRows.end())
+ nActNumLvl |= nMask;
+ nMask <<= 1;
+ }
+ rBox.unselect(MAXLEVEL);
+ }
+ else
+ {
+ nActNumLvl = nSaveNumLvl;
+ sal_uInt16 nMask = 1;
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ if(nActNumLvl & nMask)
+ {
+ rBox.select(i);
+ break;
+ }
+ nMask <<=1;
+ }
+ }
+ m_xRelativeCB->set_sensitive(1 != nActNumLvl);
+ SetModified();
+ InitPosAndSpaceMode();
+ ShowControlsDependingOnPosAndSpaceMode();
+ InitControls();
+}
+
+IMPL_LINK(SwNumPositionTabPage, DistanceHdl, weld::MetricSpinButton&, rField, void)
+{
+ if(bInInintControl)
+ return;
+ tools::Long nValue = static_cast< tools::Long >(rField.denormalize(rField.get_value(FieldUnit::TWIP)));
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActNumLvl & nMask)
+ {
+ SwNumFormat aNumFormat( pActNum->Get( i ) );
+ if (&rField == m_xDistBorderMF.get())
+ {
+
+ if (m_xRelativeCB->get_active() && m_xRelativeCB->get_sensitive())
+ {
+ if(0 == i)
+ {
+ auto const nTmp = aNumFormat.GetFirstLineOffset();
+ aNumFormat.SetAbsLSpace( nValue - nTmp );
+ }
+ else
+ {
+ tools::Long nTmp = pActNum->Get( i - 1 ).GetAbsLSpace() +
+ pActNum->Get( i - 1 ).GetFirstLineOffset() -
+ pActNum->Get( i ).GetFirstLineOffset();
+
+ aNumFormat.SetAbsLSpace( nValue + nTmp );
+ }
+ }
+ else
+ {
+ aNumFormat.SetAbsLSpace( nValue - aNumFormat.GetFirstLineOffset());
+ }
+ }
+ else if (&rField == m_xDistNumMF.get())
+ {
+ aNumFormat.SetCharTextDistance( nValue );
+ }
+ else if (&rField == m_xIndentMF.get())
+ {
+ // now AbsLSpace also has to be modified by FirstLineOffset
+ tools::Long nDiff = nValue + aNumFormat.GetFirstLineOffset();
+ auto const nAbsLSpace = aNumFormat.GetAbsLSpace();
+ aNumFormat.SetAbsLSpace( nAbsLSpace + nDiff );
+ aNumFormat.SetFirstLineOffset( -nValue );
+ }
+
+ pActNum->Set( i, aNumFormat );
+ }
+ nMask <<= 1;
+ }
+
+ SetModified();
+ if(!m_xDistBorderMF->get_sensitive())
+ m_xDistBorderMF->set_text(OUString());
+}
+
+IMPL_LINK( SwNumPositionTabPage, RelativeHdl, weld::Toggleable&, rBox, void )
+{
+ bool bOn = rBox.get_active();
+ bool bSingleSelection = m_xLevelLB->n_children() == 1 && USHRT_MAX != nActNumLvl;
+ bool bSetValue = false;
+ tools::Long nValue = 0;
+ if(bOn || bSingleSelection)
+ {
+ sal_uInt16 nMask = 1;
+ bool bFirst = true;
+ bSetValue = true;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActNumLvl & nMask)
+ {
+ const SwNumFormat &rNumFormat = pActNum->Get(i);
+ if(bFirst)
+ {
+ nValue = rNumFormat.GetAbsLSpace();
+ if(bOn && i)
+ nValue -= pActNum->Get(i - 1).GetAbsLSpace();
+ }
+ else
+ bSetValue = nValue == rNumFormat.GetAbsLSpace() - pActNum->Get(i - 1).GetAbsLSpace();
+ bFirst = false;
+ }
+ nMask <<= 1;
+ }
+
+ }
+ if(bSetValue)
+ m_xDistBorderMF->set_value(m_xDistBorderMF->normalize(nValue), FieldUnit::TWIP);
+ else
+ m_xDistBorderMF->set_text(OUString());
+ m_xDistBorderMF->set_sensitive(bOn || bSingleSelection || pOutlineDlg);
+ bLastRelative = bOn;
+}
+
+IMPL_LINK_NOARG(SwNumPositionTabPage, LabelFollowedByHdl_Impl, weld::ComboBox&, void)
+{
+ // determine value to be set at the chosen list levels
+ SvxNumberFormat::LabelFollowedBy eLabelFollowedBy = SvxNumberFormat::LISTTAB;
+ {
+ const int nPos = m_xLabelFollowedByLB->get_active();
+ if ( nPos == 1 )
+ {
+ eLabelFollowedBy = SvxNumberFormat::SPACE;
+ }
+ else if ( nPos == 2 )
+ {
+ eLabelFollowedBy = SvxNumberFormat::NOTHING;
+ }
+ else if ( nPos == 3 )
+ {
+ eLabelFollowedBy = SvxNumberFormat::NEWLINE;
+ }
+ }
+
+ // set value at the chosen list levels
+ bool bSameListtabPos = true;
+ sal_uInt16 nFirstLvl = USHRT_MAX;
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if ( nActNumLvl & nMask )
+ {
+ SwNumFormat aNumFormat( pActNum->Get(i) );
+ aNumFormat.SetLabelFollowedBy( eLabelFollowedBy );
+ pActNum->Set( i, aNumFormat );
+
+ if ( nFirstLvl == USHRT_MAX )
+ {
+ nFirstLvl = i;
+ }
+ else
+ {
+ bSameListtabPos &= aNumFormat.GetListtabPos() ==
+ pActNum->Get( nFirstLvl ).GetListtabPos();
+ }
+ }
+ nMask <<= 1;
+ }
+
+ // enable/disable metric field for list tab stop position depending on
+ // selected item following the list label.
+ m_xListtabFT->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB );
+ m_xListtabMF->set_sensitive( eLabelFollowedBy == SvxNumberFormat::LISTTAB );
+ if ( bSameListtabPos && eLabelFollowedBy == SvxNumberFormat::LISTTAB )
+ {
+ m_xListtabMF->set_value(
+ m_xListtabMF->normalize( pActNum->Get( nFirstLvl ).GetListtabPos() ),
+ FieldUnit::TWIP );
+ }
+ else
+ {
+ m_xListtabMF->set_text(OUString());
+ }
+
+ SetModified();
+}
+
+IMPL_LINK( SwNumPositionTabPage, ListtabPosHdl_Impl, weld::MetricSpinButton&, rField, void )
+{
+ // determine value to be set at the chosen list levels
+ const tools::Long nValue = static_cast< tools::Long >(rField.denormalize(rField.get_value(FieldUnit::TWIP)));
+
+ // set value at the chosen list levels
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if ( nActNumLvl & nMask )
+ {
+ SwNumFormat aNumFormat( pActNum->Get(i) );
+ aNumFormat.SetListtabPos( nValue );
+ pActNum->Set( i, aNumFormat );
+ }
+ nMask <<= 1;
+ }
+
+ SetModified();
+}
+
+IMPL_LINK( SwNumPositionTabPage, AlignAtHdl_Impl, weld::MetricSpinButton&, rField, void )
+{
+ // determine value to be set at the chosen list levels
+ const tools::Long nValue = static_cast< tools::Long >(rField.denormalize(rField.get_value(FieldUnit::TWIP)));
+
+ // set value at the chosen list levels
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if ( nActNumLvl & nMask )
+ {
+ SwNumFormat aNumFormat( pActNum->Get(i) );
+ const tools::Long nFirstLineIndent = nValue - aNumFormat.GetIndentAt();
+ aNumFormat.SetFirstLineIndent( nFirstLineIndent );
+ pActNum->Set( i, aNumFormat );
+ }
+ nMask <<= 1;
+ }
+
+ SetModified();
+}
+
+IMPL_LINK( SwNumPositionTabPage, IndentAtHdl_Impl, weld::MetricSpinButton&, rField, void )
+{
+ // determine value to be set at the chosen list levels
+ const tools::Long nValue = static_cast< tools::Long >(rField.denormalize(rField.get_value(FieldUnit::TWIP)));
+
+ // set value at the chosen list levels
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ {
+ if ( nActNumLvl & nMask )
+ {
+ SwNumFormat aNumFormat( pActNum->Get(i) );
+ const tools::Long nAlignedAt = aNumFormat.GetIndentAt() +
+ aNumFormat.GetFirstLineIndent();
+ aNumFormat.SetIndentAt( nValue );
+ const tools::Long nNewFirstLineIndent = nAlignedAt - nValue;
+ aNumFormat.SetFirstLineIndent( nNewFirstLineIndent );
+ pActNum->Set( i, aNumFormat );
+ }
+ nMask <<= 1;
+ }
+
+ SetModified();
+}
+
+IMPL_LINK_NOARG(SwNumPositionTabPage, StandardHdl, weld::Button&, void)
+{
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActNumLvl & nMask)
+ {
+ SwNumFormat aNumFormat( pActNum->Get( i ) );
+ SwNumRule aTmpNumRule( pWrtSh->GetUniqueNumRuleName(),
+ aNumFormat.GetPositionAndSpaceMode(),
+ pOutlineDlg ? OUTLINE_RULE : NUM_RULE );
+ const SwNumFormat& aTempFormat(aTmpNumRule.Get( i ));
+ aNumFormat.SetPositionAndSpaceMode( aTempFormat.GetPositionAndSpaceMode() );
+ if ( aTempFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aNumFormat.SetAbsLSpace( aTempFormat.GetAbsLSpace());
+ aNumFormat.SetCharTextDistance( aTempFormat.GetCharTextDistance() );
+ aNumFormat.SetFirstLineOffset( aTempFormat.GetFirstLineOffset() );
+ }
+ else if ( aTempFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aNumFormat.SetNumAdjust( aTempFormat.GetNumAdjust() );
+ aNumFormat.SetLabelFollowedBy( aTempFormat.GetLabelFollowedBy() );
+ aNumFormat.SetListtabPos( aTempFormat.GetListtabPos() );
+ aNumFormat.SetFirstLineIndent( aTempFormat.GetFirstLineIndent() );
+ aNumFormat.SetIndentAt( aTempFormat.GetIndentAt() );
+ }
+ pActNum->Set( i, aNumFormat );
+ }
+ nMask <<= 1;
+ }
+
+ InitControls();
+ SetModified();
+}
+
+#ifdef DBG_UTIL
+void SwNumPositionTabPage::SetModified()
+{
+ bModified = true;
+ m_aPreviewWIN.SetLevel(nActNumLvl);
+ m_aPreviewWIN.Invalidate();
+}
+#endif
+
+SwSvxNumBulletTabDialog::SwSvxNumBulletTabDialog(weld::Window* pParent,
+ const SfxItemSet* pSwItemSet, SwWrtShell & rSh)
+ : SfxTabDialogController(pParent, "modules/swriter/ui/bulletsandnumbering.ui", "BulletsAndNumberingDialog",
+ pSwItemSet)
+ , rWrtSh(rSh)
+ , m_xDummyCombo(m_xBuilder->weld_combo_box("dummycombo"))
+{
+ weld::Button* pButton = GetUserButton();
+ pButton->connect_clicked(LINK(this, SwSvxNumBulletTabDialog, RemoveNumberingHdl));
+ pButton->set_sensitive(rWrtSh.GetNumRuleAtCurrCursorPos() != nullptr);
+ AddTabPage("singlenum", RID_SVXPAGE_PICK_SINGLE_NUM );
+ AddTabPage("bullets", RID_SVXPAGE_PICK_BULLET );
+ AddTabPage("outlinenum", RID_SVXPAGE_PICK_NUM );
+ AddTabPage("graphics", RID_SVXPAGE_PICK_BMP );
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ RemoveTabPage("customize");
+ }
+ else
+ {
+ AddTabPage("customize", RID_SVXPAGE_NUM_OPTIONS );
+ }
+
+ AddTabPage("position", RID_SVXPAGE_NUM_POSITION );
+}
+
+SwSvxNumBulletTabDialog::~SwSvxNumBulletTabDialog()
+{
+}
+
+void SwSvxNumBulletTabDialog::PageCreated(const OString& rPageId, SfxTabPage& rPage)
+{
+ // set styles' names and metric
+ OUString sNumCharFormat, sBulletCharFormat;
+ SwStyleNameMapper::FillUIName( RES_POOLCHR_NUM_LEVEL, sNumCharFormat );
+ SwStyleNameMapper::FillUIName( RES_POOLCHR_BULLET_LEVEL, sBulletCharFormat );
+
+ if (rPageId == "singlenum")
+ {
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ aSet.Put (SfxStringItem(SID_NUM_CHAR_FMT,sNumCharFormat));
+ aSet.Put (SfxStringItem(SID_BULLET_CHAR_FMT,sBulletCharFormat));
+ rPage.PageCreated(aSet);
+ }
+ else if (rPageId == "bullets")
+ {
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ aSet.Put (SfxStringItem(SID_BULLET_CHAR_FMT,sBulletCharFormat));
+ rPage.PageCreated(aSet);
+ }
+ else if (rPageId == "customize")
+ {
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ aSet.Put (SfxStringItem(SID_NUM_CHAR_FMT,sNumCharFormat));
+ aSet.Put (SfxStringItem(SID_BULLET_CHAR_FMT,sBulletCharFormat));
+ // collect char styles
+ m_xDummyCombo->clear();
+ m_xDummyCombo->append_text(SwViewShell::GetShellRes()->aStrNone);
+ SwDocShell* pDocShell = rWrtSh.GetView().GetDocShell();
+ ::FillCharStyleListBox(*m_xDummyCombo, pDocShell);
+
+ std::vector<OUString> aList;
+ aList.reserve(m_xDummyCombo->get_count());
+ for (sal_Int32 j = 0; j < m_xDummyCombo->get_count(); j++)
+ aList.push_back(m_xDummyCombo->get_text(j));
+
+ aSet.Put( SfxStringListItem( SID_CHAR_FMT_LIST_BOX,&aList ) ) ;
+
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast< const SwWebDocShell *>( pDocShell ) != nullptr);
+ aSet.Put ( SfxUInt16Item(SID_METRIC_ITEM, static_cast< sal_uInt16 >(eMetric) ) );
+ rPage.PageCreated(aSet);
+ }
+ else if (rPageId == "position")
+ {
+ SwDocShell* pDocShell = rWrtSh.GetView().GetDocShell();
+ FieldUnit eMetric = ::GetDfltMetric(dynamic_cast< const SwWebDocShell *>( pDocShell ) != nullptr);
+ SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool()));
+ aSet.Put ( SfxUInt16Item(SID_METRIC_ITEM, static_cast< sal_uInt16 >(eMetric)) );
+ rPage.PageCreated(aSet);
+ }
+}
+
+short SwSvxNumBulletTabDialog::Ok()
+{
+ short nRet = SfxTabDialogController::Ok();
+ m_xExampleSet->ClearItem(SID_PARAM_NUM_PRESET);
+ return nRet;
+}
+
+IMPL_LINK_NOARG(SwSvxNumBulletTabDialog, RemoveNumberingHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_USER);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/outline.cxx b/sw/source/ui/misc/outline.cxx
new file mode 100644
index 000000000..533028ebe
--- /dev/null
+++ b/sw/source/ui/misc/outline.cxx
@@ -0,0 +1,1078 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/virdev.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <editeng/brushitem.hxx>
+#include <unotools/configmgr.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <num.hxx>
+#include <view.hxx>
+#include <docsh.hxx>
+#include <uitool.hxx>
+#include <wrtsh.hxx>
+#include <swmodule.hxx>
+#include <fmtcol.hxx>
+#include <outline.hxx>
+#include <uinums.hxx>
+#include <poolfmt.hxx>
+#include <shellres.hxx>
+#include <svl/style.hxx>
+#include <charfmt.hxx>
+#include <docstyle.hxx>
+#include <viewopt.hxx>
+#include <outline.hrc>
+#include <strings.hrc>
+#include <paratr.hxx>
+#include <svtools/colorcfg.hxx>
+
+#include <IDocumentOutlineNodes.hxx>
+
+using namespace ::com::sun::star;
+
+namespace {
+
+class SwNumNamesDlg : public weld::GenericDialogController
+{
+ std::unique_ptr<weld::Entry> m_xFormEdit;
+ std::unique_ptr<weld::TreeView> m_xFormBox;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+
+ DECL_LINK( ModifyHdl, weld::Entry&, void );
+ DECL_LINK( SelectHdl, weld::TreeView&, void );
+ DECL_LINK( DoubleClickHdl, weld::TreeView&, bool );
+
+public:
+ explicit SwNumNamesDlg(weld::Window *pParent);
+ void SetUserNames(const OUString *pList[]);
+ OUString GetName() const { return m_xFormEdit->get_text(); }
+ int GetCurEntryPos() const { return m_xFormBox->get_selected_index(); }
+};
+
+}
+
+// remember selected entry
+IMPL_LINK( SwNumNamesDlg, SelectHdl, weld::TreeView&, rBox, void )
+{
+ m_xFormEdit->set_text(rBox.get_selected_text());
+ m_xFormEdit->select_region(0, -1);
+}
+
+/** set user defined names
+ *
+ * @param pList list of user defined names; unknown positions for the user are 0.
+ */
+void SwNumNamesDlg::SetUserNames(const OUString *pList[])
+{
+ sal_uInt16 nSelect = 0;
+ for (sal_uInt16 i = 0; i < SwChapterNumRules::nMaxRules; ++i)
+ {
+ if(pList[i])
+ {
+ m_xFormBox->remove(i);
+ m_xFormBox->insert_text(i, *pList[i]);
+ if (i == nSelect)
+ nSelect++;
+ }
+ }
+ m_xFormBox->select(std::min(nSelect, o3tl::narrowing<sal_uInt16>(m_xFormBox->n_children() - 1)));
+ SelectHdl(*m_xFormBox);
+}
+
+// unlock OK-Button when text is in Edit
+IMPL_LINK( SwNumNamesDlg, ModifyHdl, weld::Entry&, rBox, void )
+{
+ m_xOKBtn->set_sensitive(!rBox.get_text().isEmpty());
+}
+
+// DoubleClickHdl
+IMPL_LINK_NOARG(SwNumNamesDlg, DoubleClickHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+SwNumNamesDlg::SwNumNamesDlg(weld::Window *pParent)
+ : GenericDialogController(pParent,
+ "modules/swriter/ui/numberingnamedialog.ui",
+ "NumberingNameDialog")
+ , m_xFormEdit(m_xBuilder->weld_entry("entry"))
+ , m_xFormBox(m_xBuilder->weld_tree_view("form"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+{
+ for (size_t i = 0; i < SAL_N_ELEMENTS(OUTLINE_STYLE); ++i)
+ m_xFormBox->append_text(SwResId(OUTLINE_STYLE[i]));
+
+ m_xFormEdit->connect_changed(LINK(this, SwNumNamesDlg, ModifyHdl));
+ m_xFormBox->connect_changed(LINK(this, SwNumNamesDlg, SelectHdl));
+ m_xFormBox->connect_row_activated(LINK(this, SwNumNamesDlg, DoubleClickHdl));
+ m_xFormBox->set_size_request(-1, m_xFormBox->get_height_rows(9));
+}
+
+static sal_uInt16 lcl_BitToLevel(sal_uInt16 nActLevel)
+{
+ sal_uInt16 nTmp = nActLevel;
+ sal_uInt16 nTmpLevel = 0;
+ while( 0 != (nTmp >>= 1) )
+ nTmpLevel++;
+ return nTmpLevel;
+}
+
+sal_uInt16 SwOutlineTabDialog::nNumLevel = 1;
+
+SwOutlineTabDialog::SwOutlineTabDialog(weld::Window* pParent, const SfxItemSet* pSwItemSet,
+ SwWrtShell &rSh)
+ : SfxTabDialogController(pParent, "modules/swriter/ui/outlinenumbering.ui", "OutlineNumberingDialog", pSwItemSet)
+ , rWrtSh(rSh)
+ , pChapterNumRules(SW_MOD()->GetChapterNumRules())
+ , bModified(rWrtSh.IsModified())
+ , m_xMenuButton(m_xBuilder->weld_menu_button("format"))
+{
+ m_xMenuButton->connect_toggled(LINK(this, SwOutlineTabDialog, FormHdl));
+ m_xMenuButton->connect_selected(LINK(this, SwOutlineTabDialog, MenuSelectHdl));
+
+ xNumRule.reset(new SwNumRule(*rSh.GetOutlineNumRule()));
+ GetCancelButton().connect_clicked(LINK(this, SwOutlineTabDialog, CancelHdl));
+
+ AddTabPage("position", &SwNumPositionTabPage::Create, nullptr);
+ AddTabPage("numbering", &SwOutlineSettingsTabPage::Create, nullptr);
+
+ OUString sHeadline;
+ sal_uInt16 i;
+
+ for( i = 0; i < MAXLEVEL; ++i )
+ {
+ // if the style wasn't created yet, it's still at this position
+ if( !rWrtSh.GetParaStyle( sHeadline =
+ SwStyleNameMapper::GetUIName( static_cast< sal_uInt16 >(RES_POOLCOLL_HEADLINE1 + i),
+ sHeadline )) )
+ aCollNames[i] = sHeadline;
+ }
+
+ // query the text templates' outlining levels
+ const sal_uInt16 nCount = rWrtSh.GetTextFormatCollCount();
+ for(i = 0; i < nCount; ++i )
+ {
+ SwTextFormatColl &rTextColl = rWrtSh.GetTextFormatColl(i);
+ if(!rTextColl.IsDefault())
+ {
+ if(rTextColl.IsAssignedToListLevelOfOutlineStyle())
+ {
+ int nOutLevel = rTextColl.GetAssignedOutlineStyleLevel();
+ aCollNames[ nOutLevel ] = rTextColl.GetName();
+ }
+ }
+ }
+}
+
+SwOutlineTabDialog::~SwOutlineTabDialog()
+{
+}
+
+void SwOutlineTabDialog::PageCreated(const OString& rPageId, SfxTabPage& rPage)
+{
+ if (rPageId == "position")
+ {
+ static_cast<SwNumPositionTabPage&>(rPage).SetWrtShell(&rWrtSh);
+ static_cast<SwNumPositionTabPage&>(rPage).SetOutlineTabDialog(this);
+ }
+ else if (rPageId == "numbering")
+ {
+ static_cast<SwOutlineSettingsTabPage&>(rPage).SetWrtShell(&rWrtSh);
+ }
+}
+
+IMPL_LINK_NOARG(SwOutlineTabDialog, CancelHdl, weld::Button&, void)
+{
+ if (!bModified)
+ rWrtSh.ResetModified();
+ m_xDialog->response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(SwOutlineTabDialog, FormHdl, weld::Toggleable&, void)
+{
+ if (!m_xMenuButton->get_active())
+ return;
+
+ // fill PopupMenu
+ for(sal_uInt16 i = 0; i < SwChapterNumRules::nMaxRules; ++i)
+ {
+ const SwNumRulesWithName *pRules = pChapterNumRules->GetRules(i);
+ if (!pRules)
+ continue;
+ m_xMenuButton->set_item_label("form" + OString::number(i + 1), pRules->GetName());
+ }
+}
+
+IMPL_LINK(SwOutlineTabDialog, MenuSelectHdl, const OString&, rIdent, void)
+{
+ sal_uInt8 nLevelNo = 0;
+
+ if (rIdent == "form1")
+ nLevelNo = 1;
+ else if (rIdent == "form2")
+ nLevelNo = 2;
+ else if (rIdent == "form3")
+ nLevelNo = 3;
+ else if (rIdent == "form4")
+ nLevelNo = 4;
+ else if (rIdent == "form5")
+ nLevelNo = 5;
+ else if (rIdent == "form6")
+ nLevelNo = 6;
+ else if (rIdent == "form7")
+ nLevelNo = 7;
+ else if (rIdent == "form8")
+ nLevelNo = 8;
+ else if (rIdent == "form9")
+ nLevelNo = 9;
+ else if (rIdent == "saveas")
+ {
+ SwNumNamesDlg aDlg(m_xDialog.get());
+ const OUString *aStrArr[SwChapterNumRules::nMaxRules];
+ for(sal_uInt16 i = 0; i < SwChapterNumRules::nMaxRules; ++i)
+ {
+ const SwNumRulesWithName *pRules = pChapterNumRules->GetRules(i);
+ if(pRules)
+ aStrArr[i] = &pRules->GetName();
+ else
+ aStrArr[i] = nullptr;
+ }
+ aDlg.SetUserNames(aStrArr);
+ if (aDlg.run() == RET_OK)
+ {
+ const OUString aName(aDlg.GetName());
+ pChapterNumRules->ApplyNumRules( SwNumRulesWithName(
+ *xNumRule, aName ), aDlg.GetCurEntryPos() );
+ m_xMenuButton->set_item_label("form" + OString::number(aDlg.GetCurEntryPos() + 1), aName);
+ }
+ return;
+ }
+
+ if( nLevelNo-- )
+ {
+ const SwNumRulesWithName *pRules = pChapterNumRules->GetRules( nLevelNo );
+ if( pRules )
+ {
+ pRules->ResetNumRule(rWrtSh, *xNumRule);
+ xNumRule->SetRuleType( OUTLINE_RULE );
+ SfxTabPage* pOutlinePage = GetTabPage("numbering");
+ assert(pOutlinePage);
+ static_cast<SwOutlineSettingsTabPage*>(pOutlinePage)->SetNumRule(xNumRule.get());
+ }
+ else
+ *xNumRule = *rWrtSh.GetOutlineNumRule();
+ }
+
+ SfxTabPage* pPage = GetCurTabPage();
+ pPage->Reset(GetOutputItemSet());
+}
+
+sal_uInt16 SwOutlineTabDialog::GetLevel(std::u16string_view rFormatName) const
+{
+ for(sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ if(aCollNames[i] == rFormatName)
+ return i;
+ }
+ return MAXLEVEL;
+}
+
+short SwOutlineTabDialog::Ok()
+{
+ SfxTabDialogController::Ok();
+ // set levels for all created templates; has to be done in order to
+ // delete possibly cancelled assignments again.
+
+ // encapsulate changes into an action to avoid effects on the current cursor
+ // position during the changes.
+ rWrtSh.StartAction();
+
+ const SwNumRule * pOutlineRule = rWrtSh.GetOutlineNumRule();
+
+ sal_uInt16 i, nCount = rWrtSh.GetTextFormatCollCount();
+ for( i = 0; i < nCount; ++i )
+ {
+ SwTextFormatColl &rTextColl = rWrtSh.GetTextFormatColl(i);
+ if( !rTextColl.IsDefault() )
+ {
+ const SfxPoolItem & rItem =
+ rTextColl.GetFormatAttr(RES_PARATR_NUMRULE, false);
+
+ if (static_cast<sal_uInt8>(GetLevel(rTextColl.GetName())) == MAXLEVEL)
+ {
+ if(rTextColl.IsAssignedToListLevelOfOutlineStyle())
+ {
+ rTextColl.DeleteAssignmentToListLevelOfOutlineStyle();
+ }
+ if (static_cast<const SwNumRuleItem &>(rItem).GetValue() ==
+ pOutlineRule->GetName())
+ {
+ rTextColl.ResetFormatAttr(RES_PARATR_NUMRULE);
+ }
+ }
+ else
+ {
+ rTextColl.AssignToListLevelOfOutlineStyle(GetLevel(rTextColl.GetName()));
+
+ if (static_cast<const SwNumRuleItem &>(rItem).GetValue() !=
+ pOutlineRule->GetName())
+ {
+ SwNumRuleItem aItem(pOutlineRule->GetName());
+ rTextColl.SetFormatAttr(aItem);
+ }
+ }
+ }
+ }
+
+ for(i = 0; i < MAXLEVEL; ++i )
+ {
+ OUString sHeadline;
+ ::SwStyleNameMapper::FillUIName( static_cast< sal_uInt16 >(RES_POOLCOLL_HEADLINE1 + i),
+ sHeadline );
+ SwTextFormatColl* pColl = rWrtSh.FindTextFormatCollByName( sHeadline );
+ if( !pColl && aCollNames[i] != sHeadline)
+ {
+ SwTextFormatColl* pTextColl = rWrtSh.GetTextCollFromPool(
+ static_cast< sal_uInt16 >(RES_POOLCOLL_HEADLINE1 + i) );
+ pTextColl->DeleteAssignmentToListLevelOfOutlineStyle();
+ pTextColl->ResetFormatAttr(RES_PARATR_NUMRULE);
+
+ if( !aCollNames[i].isEmpty() )
+ {
+ pTextColl = rWrtSh.GetParaStyle(
+ aCollNames[i], SwWrtShell::GETSTYLE_CREATESOME);
+ if(pTextColl)
+ {
+ pTextColl->AssignToListLevelOfOutlineStyle(i);
+ SwNumRuleItem aItem(pOutlineRule->GetName());
+ pTextColl->SetFormatAttr(aItem);
+ }
+ }
+ }
+ }
+
+ rWrtSh.SetOutlineNumRule(*xNumRule);
+
+ // #i30443#
+ rWrtSh.EndAction();
+
+ return RET_OK;
+}
+
+SwOutlineSettingsTabPage::SwOutlineSettingsTabPage(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet& rSet)
+ : SfxTabPage(pPage, pController, "modules/swriter/ui/outlinenumberingpage.ui", "OutlineNumberingPage", &rSet)
+ , aNoFormatName(SwResId(SW_STR_NONE))
+ , pSh(nullptr)
+ , pNumRule(nullptr)
+ , pCollNames(nullptr)
+ , nActLevel(1)
+ , m_xLevelLB(m_xBuilder->weld_tree_view("level"))
+ , m_xCollBox(m_xBuilder->weld_combo_box("style"))
+ , m_xNumberBox(new SwNumberingTypeListBox(m_xBuilder->weld_combo_box("numbering")))
+ , m_xCharFormatLB(m_xBuilder->weld_combo_box("charstyle"))
+ , m_xAllLevelFT(m_xBuilder->weld_label("sublevelsft"))
+ , m_xAllLevelNF(m_xBuilder->weld_spin_button("sublevelsnf"))
+ , m_xPrefixED(m_xBuilder->weld_entry("prefix"))
+ , m_xSuffixED(m_xBuilder->weld_entry("suffix"))
+ , m_xStartEdit(m_xBuilder->weld_spin_button("startat"))
+ , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWIN))
+{
+ SetExchangeSupport();
+
+ m_xNumberBox->Reload(SwInsertNumTypes::NoNumbering | SwInsertNumTypes::Extended);
+ m_xCollBox->make_sorted();
+ m_xCollBox->append_text(aNoFormatName);
+ m_xLevelLB->connect_changed(LINK(this, SwOutlineSettingsTabPage, LevelHdl));
+ m_xAllLevelNF->connect_value_changed(LINK(this, SwOutlineSettingsTabPage, ToggleComplete));
+ m_xCollBox->connect_changed(LINK(this, SwOutlineSettingsTabPage, CollSelect));
+ m_xNumberBox->connect_changed(LINK(this, SwOutlineSettingsTabPage, NumberSelect));
+ m_xPrefixED->connect_changed(LINK(this, SwOutlineSettingsTabPage, DelimModify));
+ m_xSuffixED->connect_changed(LINK(this, SwOutlineSettingsTabPage, DelimModify));
+ m_xStartEdit->connect_value_changed(LINK(this, SwOutlineSettingsTabPage, StartModified));
+ m_xCharFormatLB->make_sorted();
+ m_xCharFormatLB->connect_changed(LINK(this, SwOutlineSettingsTabPage, CharFormatHdl));
+}
+
+void SwOutlineSettingsTabPage::Update()
+{
+ // if a template was already selected for this level, select it in the ListBox
+ m_xCollBox->set_sensitive(USHRT_MAX != nActLevel);
+ if(USHRT_MAX == nActLevel)
+ {
+ bool bSamePrefix = true;
+ bool bSameSuffix = true;
+ bool bSameType = true;
+ bool bSameComplete = true;
+ bool bSameStart = true;
+ bool bSameCharFormat = true;
+
+ const SwNumFormat* aNumFormatArr[MAXLEVEL];
+ const SwCharFormat* pFirstFormat = nullptr;
+
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+
+ aNumFormatArr[ i ] = &pNumRule->Get(i);
+ if(i == 0)
+ pFirstFormat = aNumFormatArr[i]->GetCharFormat();
+ else
+ {
+ bSameType &= aNumFormatArr[i]->GetNumberingType() == aNumFormatArr[0]->GetNumberingType();
+ bSameStart &= aNumFormatArr[i]->GetStart() == aNumFormatArr[0]->GetStart();
+ bSamePrefix &= aNumFormatArr[i]->GetPrefix() == aNumFormatArr[0]->GetPrefix();
+ bSameSuffix &= aNumFormatArr[i]->GetSuffix() == aNumFormatArr[0]->GetSuffix();
+ bSameComplete &= aNumFormatArr[i]->GetIncludeUpperLevels() == aNumFormatArr[0]->GetIncludeUpperLevels();
+ const SwCharFormat* pFormat = aNumFormatArr[i]->GetCharFormat();
+ bSameCharFormat &= (!pFirstFormat && !pFormat)
+ || (pFirstFormat && pFormat && pFormat->GetName() == pFirstFormat->GetName());
+ }
+ }
+ CheckForStartValue_Impl(aNumFormatArr[0]->GetNumberingType());
+ if (bSameType)
+ m_xNumberBox->SelectNumberingType( aNumFormatArr[0]->GetNumberingType() );
+ else
+ m_xNumberBox->SetNoSelection();
+ if(bSameStart)
+ m_xStartEdit->set_value(aNumFormatArr[0]->GetStart());
+ else
+ m_xStartEdit->set_text(OUString());
+ if(bSamePrefix)
+ m_xPrefixED->set_text(aNumFormatArr[0]->GetPrefix());
+ else
+ m_xPrefixED->set_text(OUString());
+ if(bSameSuffix)
+ m_xSuffixED->set_text(aNumFormatArr[0]->GetSuffix());
+ else
+ m_xSuffixED->set_text(OUString());
+
+ if (bSameCharFormat)
+ {
+ if (pFirstFormat)
+ m_xCharFormatLB->set_active_text(pFirstFormat->GetName());
+ else
+ m_xCharFormatLB->set_active_text(SwViewShell::GetShellRes()->aStrNone);
+ }
+ else
+ m_xCharFormatLB->set_active(-1);
+
+ m_xAllLevelFT->set_sensitive(true);
+ m_xAllLevelNF->set_sensitive(true);
+ m_xAllLevelNF->set_max(MAXLEVEL);
+ if (bSameComplete)
+ {
+ m_xAllLevelNF->set_value(aNumFormatArr[0]->GetIncludeUpperLevels());
+ }
+ else
+ {
+ m_xAllLevelNF->set_text(OUString());
+ }
+ }
+ else
+ {
+ sal_uInt16 nTmpLevel = lcl_BitToLevel(nActLevel);
+ OUString aColl(pCollNames[nTmpLevel]);
+ if(!aColl.isEmpty())
+ m_xCollBox->set_active_text(aColl);
+ else
+ m_xCollBox->set_active_text(aNoFormatName);
+ const SwNumFormat &rFormat = pNumRule->Get(nTmpLevel);
+
+ m_xNumberBox->SelectNumberingType( rFormat.GetNumberingType() );
+ m_xPrefixED->set_text(rFormat.GetPrefix());
+ m_xSuffixED->set_text(rFormat.GetSuffix());
+ const SwCharFormat* pFormat = rFormat.GetCharFormat();
+ if(pFormat)
+ m_xCharFormatLB->set_active_text(pFormat->GetName());
+ else
+ m_xCharFormatLB->set_active_text(SwViewShell::GetShellRes()->aStrNone);
+
+ if (nTmpLevel || rFormat.HasListFormat())
+ {
+ m_xAllLevelFT->set_sensitive(true);
+ m_xAllLevelNF->set_sensitive(true);
+ m_xAllLevelNF->set_max(nTmpLevel + 1);
+ m_xAllLevelNF->set_min(rFormat.HasListFormat() ? 0 : 1);
+ m_xAllLevelNF->set_value(rFormat.GetIncludeUpperLevels());
+ }
+ else
+ {
+ m_xAllLevelNF->set_text(OUString());
+ m_xAllLevelNF->set_sensitive(false);
+ m_xAllLevelFT->set_sensitive(false);
+ }
+ CheckForStartValue_Impl(rFormat.GetNumberingType());
+ m_xStartEdit->set_value( rFormat.GetStart() );
+ }
+ SetModified();
+}
+
+IMPL_LINK( SwOutlineSettingsTabPage, LevelHdl, weld::TreeView&, rBox, void )
+{
+ nActLevel = 0;
+ auto aRows = rBox.get_selected_rows();
+ if (std::find(aRows.begin(), aRows.end(), MAXLEVEL) != aRows.end())
+ {
+ nActLevel = 0xFFFF;
+ }
+ else
+ {
+ sal_uInt16 nMask = 1;
+ for( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
+ {
+ if (std::find(aRows.begin(), aRows.end(), i) != aRows.end())
+ nActLevel |= nMask;
+ nMask <<= 1;
+ }
+ }
+ Update();
+}
+
+IMPL_LINK(SwOutlineSettingsTabPage, ToggleComplete, weld::SpinButton&, rEdit, void)
+{
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActLevel & nMask)
+ {
+ SwNumFormat aNumFormat(pNumRule->Get(i));
+ aNumFormat.SetIncludeUpperLevels( std::min( static_cast<sal_uInt8>(rEdit.get_value()),
+ static_cast<sal_uInt8>(i + 1)) );
+ // Set the same prefix/suffix to generate list format with changed IncludedUpperLevels
+ aNumFormat.SetListFormat(aNumFormat.GetPrefix(), aNumFormat.GetSuffix(), i);
+ pNumRule->Set(i, aNumFormat);
+ }
+ nMask <<= 1;
+ }
+ SetModified();
+}
+
+IMPL_LINK( SwOutlineSettingsTabPage, CollSelect, weld::ComboBox&, rBox, void )
+{
+ sal_uInt8 i;
+
+ const OUString aCollName(rBox.get_active_text());
+ //0xFFFF not allowed here (disable)
+ sal_uInt16 nTmpLevel = lcl_BitToLevel(nActLevel);
+ OUString sOldName( pCollNames[nTmpLevel] );
+
+ for( i = 0; i < MAXLEVEL; ++i)
+ pCollNames[i] = aSaveCollNames[i];
+
+ if(aCollName == aNoFormatName)
+ pCollNames[nTmpLevel].clear();
+ else
+ {
+ pCollNames[nTmpLevel] = aCollName;
+ // template already in use?
+ for( i = 0; i < MAXLEVEL; ++i)
+ if(i != nTmpLevel && pCollNames[i] == aCollName )
+ pCollNames[i].clear();
+ }
+
+ // search the oldname and put it into the current entries
+ if( !sOldName.isEmpty() )
+ for( i = 0; i < MAXLEVEL; ++i)
+ if( aSaveCollNames[ i ] == sOldName && i != nTmpLevel &&
+ pCollNames[ i ].isEmpty() )
+ {
+ sal_uInt8 n;
+ for( n = 0; n < MAXLEVEL; ++n )
+ if( pCollNames[ n ] == sOldName )
+ break;
+
+ if( MAXLEVEL == n )
+ // it was an outline level name and the current entries is zero.
+ pCollNames[ i ] = sOldName;
+ }
+
+ SetModified();
+ CollSave();
+}
+
+void SwOutlineSettingsTabPage::CollSave()
+{
+ for (sal_uInt8 i = 0; i < MAXLEVEL; ++i)
+ aSaveCollNames[i] = pCollNames[i];
+}
+
+IMPL_LINK_NOARG(SwOutlineSettingsTabPage, NumberSelect, weld::ComboBox&, void)
+{
+ sal_uInt16 nMask = 1;
+ SvxNumType nNumberType = m_xNumberBox->GetSelectedNumberingType();
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActLevel & nMask)
+ {
+ SwNumFormat aNumFormat(pNumRule->Get(i));
+ aNumFormat.SetNumberingType(nNumberType);
+ pNumRule->Set(i, aNumFormat);
+ CheckForStartValue_Impl(nNumberType);
+ }
+ nMask <<= 1;
+ }
+ SetModified();
+}
+
+IMPL_LINK_NOARG(SwOutlineSettingsTabPage, DelimModify, weld::Entry&, void)
+{
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActLevel & nMask)
+ {
+ SwNumFormat aNumFormat(pNumRule->Get(i));
+ aNumFormat.SetListFormat( m_xPrefixED->get_text(), m_xSuffixED->get_text(), i );
+ pNumRule->Set(i, aNumFormat);
+ }
+ nMask <<= 1;
+ }
+ SetModified();
+}
+
+IMPL_LINK( SwOutlineSettingsTabPage, StartModified, weld::SpinButton&, rEdit, void )
+{
+ sal_uInt16 nMask = 1;
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActLevel & nMask)
+ {
+ SwNumFormat aNumFormat(pNumRule->Get(i));
+ aNumFormat.SetStart(o3tl::narrowing<sal_uInt16>(rEdit.get_value()));
+ pNumRule->Set(i, aNumFormat);
+ }
+ nMask <<= 1;
+ }
+ SetModified();
+}
+
+IMPL_LINK_NOARG(SwOutlineSettingsTabPage, CharFormatHdl, weld::ComboBox&, void)
+{
+ OUString sEntry = m_xCharFormatLB->get_active_text();
+ sal_uInt16 nMask = 1;
+ bool bFormatNone = sEntry == SwViewShell::GetShellRes()->aStrNone;
+ SwCharFormat* pFormat = nullptr;
+ if(!bFormatNone)
+ {
+ sal_uInt16 nChCount = pSh->GetCharFormatCount();
+ for(sal_uInt16 i = 0; i < nChCount; i++)
+ {
+ SwCharFormat& rChFormat = pSh->GetCharFormat(i);
+ if(rChFormat.GetName() == sEntry)
+ {
+ pFormat = &rChFormat;
+ break;
+ }
+ }
+ if(!pFormat)
+ {
+ SfxStyleSheetBasePool* pPool = pSh->GetView().GetDocShell()->GetStyleSheetPool();
+ SfxStyleSheetBase* pBase;
+ pBase = pPool->Find(sEntry, SfxStyleFamily::Char);
+ if(!pBase)
+ pBase = &pPool->Make(sEntry, SfxStyleFamily::Page);
+ pFormat = static_cast<SwDocStyleSheet*>(pBase)->GetCharFormat();
+
+ }
+ }
+
+ for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
+ {
+ if(nActLevel & nMask)
+ {
+ SwNumFormat aNumFormat(pNumRule->Get(i));
+ if(bFormatNone)
+ aNumFormat.SetCharFormat(nullptr);
+ else
+ aNumFormat.SetCharFormat(pFormat);
+ pNumRule->Set(i, aNumFormat);
+ }
+ nMask <<= 1;
+ }
+}
+
+SwOutlineSettingsTabPage::~SwOutlineSettingsTabPage()
+{
+}
+
+void SwOutlineSettingsTabPage::SetWrtShell(SwWrtShell* pShell)
+{
+ pSh = pShell;
+ // query this document's NumRules
+ pNumRule = static_cast<SwOutlineTabDialog*>(GetDialogController())->GetNumRule();
+ pCollNames = static_cast<SwOutlineTabDialog*>(GetDialogController())->GetCollNames();
+
+ CollSave();
+
+ m_aPreviewWIN.SetNumRule(pNumRule);
+ m_aPreviewWIN.SetOutlineNames(pCollNames);
+ // set start value - nActLevel must be 1 here
+ sal_uInt16 nTmpLevel = lcl_BitToLevel(nActLevel);
+ const SwNumFormat& rNumFormat = pNumRule->Get( nTmpLevel );
+ m_xStartEdit->set_value( rNumFormat.GetStart() );
+
+ // create pool formats for headlines
+ for (sal_uInt16 i = 0; i < MAXLEVEL; ++i)
+ {
+ m_xCollBox->append_text( SwStyleNameMapper::GetUIName(
+ static_cast< sal_uInt16 >(RES_POOLCOLL_HEADLINE1 + i), OUString()));
+ m_xLevelLB->append_text( OUString::number(i + 1) );
+ }
+ OUString sStr = "1 - " + OUString::number(MAXLEVEL);
+ m_xLevelLB->append_text(sStr);
+
+ // query the texttemplates' outlining levels
+ const sal_uInt16 nCount = pSh->GetTextFormatCollCount();
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ SwTextFormatColl &rTextColl = pSh->GetTextFormatColl(i);
+ if(!rTextColl.IsDefault())
+ {
+ sStr = rTextColl.GetName();
+ if (m_xCollBox->find_text(sStr) == -1)
+ m_xCollBox->append_text(sStr);
+ }
+ }
+
+ m_xNumberBox->SelectNumberingType(rNumFormat.GetNumberingType());
+ SwOutlineNodes::size_type nOutlinePos = pSh->GetOutlinePos(MAXLEVEL);
+ int nTmp = 0;
+ if(nOutlinePos != SwOutlineNodes::npos)
+ {
+ nTmp = o3tl::narrowing<sal_uInt16>(pSh->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos));
+ }
+ m_xLevelLB->select(nTmp-1);
+
+ // collect char styles
+ m_xCharFormatLB->clear();
+ m_xCharFormatLB->append_text(SwViewShell::GetShellRes()->aStrNone);
+
+ // char styles
+ ::FillCharStyleListBox(*m_xCharFormatLB,
+ pSh->GetView().GetDocShell());
+ Update();
+}
+
+void SwOutlineSettingsTabPage::ActivatePage(const SfxItemSet& )
+{
+ nActLevel = SwOutlineTabDialog::GetActNumLevel();
+ if(nActLevel != USHRT_MAX)
+ m_xLevelLB->select(lcl_BitToLevel(nActLevel));
+ else
+ m_xLevelLB->select(MAXLEVEL);
+ LevelHdl(*m_xLevelLB);
+}
+
+DeactivateRC SwOutlineSettingsTabPage::DeactivatePage(SfxItemSet*)
+{
+ SwOutlineTabDialog::SetActNumLevel(nActLevel);
+ return DeactivateRC::LeavePage;
+}
+
+bool SwOutlineSettingsTabPage::FillItemSet( SfxItemSet* )
+{
+ return true;
+}
+
+void SwOutlineSettingsTabPage::Reset( const SfxItemSet* rSet )
+{
+ ActivatePage(*rSet);
+}
+
+std::unique_ptr<SfxTabPage> SwOutlineSettingsTabPage::Create(weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<SwOutlineSettingsTabPage>(pPage, pController, *rAttrSet);
+}
+
+void SwOutlineSettingsTabPage::CheckForStartValue_Impl(sal_uInt16 nNumberingType)
+{
+ bool bIsNull = m_xStartEdit->get_value() == 0;
+ bool bNoZeroAllowed = nNumberingType < SVX_NUM_ARABIC ||
+ SVX_NUM_CHARS_UPPER_LETTER_N == nNumberingType ||
+ SVX_NUM_CHARS_LOWER_LETTER_N == nNumberingType;
+ m_xStartEdit->set_min(bNoZeroAllowed ? 1 : 0);
+ if (bIsNull && bNoZeroAllowed)
+ StartModified(*m_xStartEdit);
+}
+
+static tools::Long lcl_DrawBullet(vcl::RenderContext* pVDev, const SwNumFormat& rFormat, tools::Long nXStart, tools::Long nYStart, const Size& rSize)
+{
+ vcl::Font aTmpFont(pVDev->GetFont());
+
+ // via Uno it's possible that no font has been set!
+ vcl::Font aFont(rFormat.GetBulletFont() ? *rFormat.GetBulletFont() : aTmpFont);
+ Size aTmpSize(rSize);
+ aTmpSize.setWidth( aTmpSize.Width() * ( rFormat.GetBulletRelSize()) );
+ aTmpSize.setWidth( aTmpSize.Width() / 100 ) ;
+ aTmpSize.setHeight( aTmpSize.Height() * ( rFormat.GetBulletRelSize()) );
+ aTmpSize.setHeight( aTmpSize.Height() / 100 ) ;
+ // in case of a height of zero it is drawn in original height
+ if(!aTmpSize.Height())
+ aTmpSize.setHeight( 1 );
+ aFont.SetFontSize(aTmpSize);
+ aFont.SetTransparent(true);
+ Color aBulletColor = rFormat.GetBulletColor();
+ if(aBulletColor == COL_AUTO)
+ aBulletColor = pVDev->GetFillColor().IsDark() ? COL_WHITE : COL_BLACK;
+ else if(aBulletColor == pVDev->GetFillColor())
+ aBulletColor.Invert();
+ aFont.SetColor(aBulletColor);
+ pVDev->SetFont( aFont );
+ sal_UCS4 cBullet = rFormat.GetBulletChar();
+ OUString aText(&cBullet, 1);
+ tools::Long nY = nYStart;
+ nY -= ((aTmpSize.Height() - rSize.Height())/ 2);
+ pVDev->DrawText( Point(nXStart, nY), aText );
+ tools::Long nRet = pVDev->GetTextWidth(aText);
+
+ pVDev->SetFont(aTmpFont);
+ return nRet;
+}
+
+static tools::Long lcl_DrawGraphic(vcl::RenderContext& rVDev, const SwNumFormat &rFormat, tools::Long nXStart, tools::Long nYStart, tools::Long nDivision)
+{
+ const SvxBrushItem* pBrushItem = rFormat.GetBrush();
+ tools::Long nRet = 0;
+ if (pBrushItem)
+ {
+ const Graphic* pGraphic = pBrushItem->GetGraphic();
+ if (pGraphic)
+ {
+ Size aGSize( rFormat.GetGraphicSize());
+ aGSize.setWidth( aGSize.Width() / nDivision );
+ nRet = aGSize.Width();
+ aGSize.setHeight( aGSize.Height() / nDivision );
+ pGraphic->Draw(rVDev, Point(nXStart, nYStart), rVDev.PixelToLogic(aGSize));
+ }
+ }
+ return nRet;
+}
+
+void NumberingPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ const Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
+
+ ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext);
+ pVDev->SetMapMode(rRenderContext.GetMapMode());
+ pVDev->SetOutputSize(aSize);
+
+ // #101524# OJ
+ pVDev->SetFillColor(SwViewOption::GetDocColor());
+ pVDev->SetLineColor(SwViewOption::GetDocBoundariesColor());
+ pVDev->DrawRect(tools::Rectangle(Point(0,0), aSize));
+
+ if (pActNum)
+ {
+ tools::Long nWidthRelation = 30; // chapter dialog
+ if(nPageWidth)
+ {
+ nWidthRelation = nPageWidth / aSize.Width();
+ if(bPosition)
+ nWidthRelation = nWidthRelation * 2 / 3;
+ else
+ nWidthRelation = nWidthRelation / 4;
+ }
+
+ // height per level
+ const tools::Long nXStep = aSize.Width() / (3 * MAXLEVEL * ((MAXLEVEL < 10) ? 2 : 1));
+ const tools::Long nYStep = (aSize.Height() - 6)/ MAXLEVEL;
+ tools::Long nYStart = 4;
+ aStdFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, GetAppLanguage(),
+ GetDefaultFontFlags::OnlyOne, &rRenderContext);
+
+ if (svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR, false).nColor == COL_AUTO)
+ aStdFont.SetColor( SwViewOption::GetDocColor().IsDark() ? COL_WHITE : COL_BLACK );
+ else
+ aStdFont.SetColor( SwViewOption::GetFontColor() );
+
+ const tools::Long nFontHeight = nYStep * ( bPosition ? 15 : 6 ) / 10;
+ aStdFont.SetFontSize(Size( 0, nFontHeight ));
+
+ tools::Long nPreNum = pActNum->Get(0).GetStart();
+
+ if (bPosition)
+ {
+ const tools::Long nLineHeight = nFontHeight * 8 / 7;
+ sal_uInt8 nStart = 0;
+ while (!(nActLevel & (1 << nStart)))
+ {
+ nStart++;
+ }
+ if(nStart) // so that possible predecessors and successors are showed
+ nStart--;
+
+ SwNumberTree::tNumberVector aNumVector;
+ sal_uInt8 nEnd = std::min(sal_uInt8(nStart + 3), MAXLEVEL);
+ for (sal_uInt8 nLevel = nStart; nLevel < nEnd; ++nLevel)
+ {
+ const SwNumFormat &rFormat = pActNum->Get(nLevel);
+ aNumVector.push_back(rFormat.GetStart());
+
+ tools::Long nXStart( 0 );
+ tools::Long nTextOffset( 0 );
+ tools::Long nNumberXPos( 0 );
+ if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
+ {
+ nXStart = rFormat.GetAbsLSpace() / nWidthRelation;
+ nTextOffset = rFormat.GetCharTextDistance() / nWidthRelation;
+ nNumberXPos = nXStart;
+ const tools::Long nFirstLineOffset = (-rFormat.GetFirstLineOffset()) / nWidthRelation;
+
+ if(nFirstLineOffset <= nNumberXPos)
+ nNumberXPos -= nFirstLineOffset;
+ else
+ nNumberXPos = 0;
+ }
+ else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
+ {
+ const tools::Long nTmpNumberXPos((rFormat.GetIndentAt() + rFormat.GetFirstLineIndent()) / nWidthRelation);
+ nNumberXPos = (nTmpNumberXPos < 0) ? 0 : nTmpNumberXPos;
+ }
+
+ tools::Long nBulletWidth = 0;
+ if (SVX_NUM_BITMAP == rFormat.GetNumberingType())
+ {
+ nBulletWidth = lcl_DrawGraphic(*pVDev, rFormat, nNumberXPos,
+ nYStart, nWidthRelation);
+ }
+ else if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType())
+ {
+ nBulletWidth = lcl_DrawBullet(pVDev.get(), rFormat, nNumberXPos,
+ nYStart, aStdFont.GetFontSize());
+ }
+ else
+ {
+ pVDev->SetFont(aStdFont);
+ if(pActNum->IsContinusNum())
+ aNumVector[nLevel] = nPreNum;
+ OUString aText(pActNum->MakeNumString( aNumVector ));
+ pVDev->DrawText( Point(nNumberXPos, nYStart), aText );
+ nBulletWidth = pVDev->GetTextWidth(aText);
+ nPreNum++;
+ }
+ if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
+ rFormat.GetLabelFollowedBy() == SvxNumberFormat::SPACE )
+ {
+ pVDev->SetFont(aStdFont);
+ OUString aText(' ');
+ pVDev->DrawText( Point(nNumberXPos, nYStart), aText );
+ nBulletWidth += pVDev->GetTextWidth(aText);
+ }
+
+ tools::Long nTextXPos(0);
+ if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
+ {
+ nTextXPos = nXStart;
+ if (nTextOffset < 0)
+ nTextXPos = nTextXPos + nTextOffset;
+ if (nNumberXPos + nBulletWidth + nTextOffset > nTextXPos)
+ nTextXPos = nNumberXPos + nBulletWidth + nTextOffset;
+ }
+ else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
+ {
+ switch (rFormat.GetLabelFollowedBy())
+ {
+ case SvxNumberFormat::LISTTAB:
+ {
+ nTextXPos = rFormat.GetListtabPos() / nWidthRelation;
+ if (nTextXPos < nNumberXPos + nBulletWidth)
+ {
+ nTextXPos = nNumberXPos + nBulletWidth;
+ }
+ }
+ break;
+ case SvxNumberFormat::SPACE:
+ case SvxNumberFormat::NOTHING:
+ case SvxNumberFormat::NEWLINE:
+ {
+ nTextXPos = nNumberXPos + nBulletWidth;
+ }
+ break;
+ }
+
+ nXStart = rFormat.GetIndentAt() / nWidthRelation;
+ }
+
+ tools::Rectangle aRect1(Point(nTextXPos, nYStart + nFontHeight / 2), Size(aSize.Width() / 2, 2));
+ pVDev->SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor()); // COL_BLACK );
+ pVDev->DrawRect(aRect1);
+
+ tools::Rectangle aRect2(Point(nXStart, nYStart + nLineHeight + nFontHeight / 2), Size(aSize.Width() / 2, 2));
+ pVDev->DrawRect(aRect2);
+ nYStart += 2 * nLineHeight;
+ }
+ }
+ else
+ {
+ SwNumberTree::tNumberVector aNumVector;
+ const tools::Long nLineHeight = nFontHeight * 3 / 2;
+ for (sal_uInt8 nLevel = 0; nLevel < MAXLEVEL; ++nLevel, nYStart = nYStart + nYStep)
+ {
+ const SwNumFormat &rFormat = pActNum->Get(nLevel);
+ aNumVector.push_back(rFormat.GetStart());
+ tools::Long nXStart(0);
+ if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
+ {
+ nXStart = rFormat.GetAbsLSpace() / nWidthRelation;
+ }
+ else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
+ {
+ const tools::Long nTmpXStart((rFormat.GetIndentAt() + rFormat.GetFirstLineIndent() ) / nWidthRelation);
+ nXStart = (nTmpXStart < 0) ? 0 : nTmpXStart;
+ }
+ nXStart /= 2;
+ nXStart += 2;
+ tools::Long nTextOffset;
+ if (SVX_NUM_BITMAP == rFormat.GetNumberingType())
+ {
+ lcl_DrawGraphic(*pVDev, rFormat, nXStart, nYStart, nWidthRelation);
+ nTextOffset = nLineHeight + nXStep;
+ }
+ else if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType())
+ {
+ nTextOffset = lcl_DrawBullet(pVDev.get(), rFormat, nXStart, nYStart, aStdFont.GetFontSize());
+ nTextOffset += nXStep;
+ }
+ else
+ {
+ pVDev->SetFont(aStdFont);
+ if (pActNum->IsContinusNum())
+ aNumVector[nLevel] = nPreNum;
+ OUString aText(pActNum->MakeNumString( aNumVector ));
+ pVDev->DrawText( Point(nXStart, nYStart), aText );
+ nTextOffset = pVDev->GetTextWidth(aText) + nXStep;
+ nPreNum++;
+ }
+ pVDev->SetFont(aStdFont);
+ pVDev->DrawText(
+ Point(nXStart + nTextOffset, nYStart),
+ (pOutlineNames == nullptr
+ ? utl::ConfigManager::getProductName()
+ : pOutlineNames[nLevel]));
+ }
+ }
+ }
+ rRenderContext.DrawOutDev(Point(0,0), aSize, Point(0,0), aSize, *pVDev);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/pgfnote.cxx b/sw/source/ui/misc/pgfnote.cxx
new file mode 100644
index 000000000..fa94ea19e
--- /dev/null
+++ b/sw/source/ui/misc/pgfnote.cxx
@@ -0,0 +1,313 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <fmtfsize.hxx>
+#include <hintids.hxx>
+#include <svtools/unitconv.hxx>
+#include <vcl/fieldvalues.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <editeng/borderline.hxx>
+#include <editeng/sizeitem.hxx>
+#include <svx/pageitem.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <uitool.hxx>
+#include <pagedesc.hxx>
+#include <pgfnote.hxx>
+#include <uiitems.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+const WhichRangesContainer SwFootNotePage::aPageRg(svl::Items<FN_PARAM_FTN_INFO, FN_PARAM_FTN_INFO>);
+
+// handler to switch between the different possibilities how the footnote
+// region's height can be set.
+IMPL_LINK_NOARG(SwFootNotePage, HeightPage, weld::Toggleable&, void)
+{
+ if (m_xMaxHeightPageBtn->get_active())
+ m_xMaxHeightEdit->set_sensitive(false);
+}
+
+IMPL_LINK_NOARG(SwFootNotePage, HeightMetric, weld::Toggleable&, void)
+{
+ if (m_xMaxHeightBtn->get_active())
+ {
+ m_xMaxHeightEdit->set_sensitive(true);
+ m_xMaxHeightEdit->grab_focus();
+ }
+}
+
+// handler limit values
+IMPL_LINK_NOARG(SwFootNotePage, HeightModify, weld::MetricSpinButton&, void)
+{
+ m_xMaxHeightEdit->set_max(m_xMaxHeightEdit->normalize(lMaxHeight -
+ (m_xDistEdit->denormalize(m_xDistEdit->get_value(FieldUnit::TWIP)) +
+ m_xLineDistEdit->denormalize(m_xLineDistEdit->get_value(FieldUnit::TWIP)))),
+ FieldUnit::TWIP);
+ if (m_xMaxHeightEdit->get_value(FieldUnit::NONE) < 0)
+ m_xMaxHeightEdit->set_value(0, FieldUnit::NONE);
+ m_xDistEdit->set_max(m_xDistEdit->normalize(lMaxHeight -
+ (m_xMaxHeightEdit->denormalize(m_xMaxHeightEdit->get_value(FieldUnit::TWIP)) +
+ m_xLineDistEdit->denormalize(m_xLineDistEdit->get_value(FieldUnit::TWIP)))),
+ FieldUnit::TWIP);
+ if (m_xDistEdit->get_value(FieldUnit::NONE) < 0)
+ m_xDistEdit->set_value(0, FieldUnit::NONE);
+ m_xLineDistEdit->set_max(m_xLineDistEdit->normalize(lMaxHeight -
+ (m_xMaxHeightEdit->denormalize(m_xMaxHeightEdit->get_value(FieldUnit::TWIP)) +
+ m_xDistEdit->denormalize(m_xDistEdit->get_value(FieldUnit::TWIP)))),
+ FieldUnit::TWIP);
+}
+
+IMPL_LINK_NOARG(SwFootNotePage, LineWidthChanged_Impl, weld::MetricSpinButton&, void)
+{
+ sal_Int64 nVal = m_xLineWidthEdit->get_value(FieldUnit::NONE);
+ nVal = static_cast<sal_Int64>(vcl::ConvertDoubleValue(
+ nVal,
+ m_xLineWidthEdit->get_digits(),
+ m_xLineWidthEdit->get_unit(), MapUnit::MapTwip ));
+ m_xLineTypeBox->SetWidth(nVal);
+}
+
+IMPL_LINK(SwFootNotePage, LineColorSelected_Impl, ColorListBox&, rColorBox, void)
+{
+ m_xLineTypeBox->SetColor(rColorBox.GetSelectEntryColor());
+}
+
+SwFootNotePage::SwFootNotePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
+ : SfxTabPage(pPage, pController, "modules/swriter/ui/footnoteareapage.ui", "FootnoteAreaPage", &rSet)
+ , lMaxHeight(0)
+ , m_xMaxHeightPageBtn(m_xBuilder->weld_radio_button("maxheightpage"))
+ , m_xMaxHeightBtn(m_xBuilder->weld_radio_button("maxheight"))
+ , m_xMaxHeightEdit(m_xBuilder->weld_metric_spin_button("maxheightsb", FieldUnit::CM))
+ , m_xDistEdit(m_xBuilder->weld_metric_spin_button("spacetotext", FieldUnit::CM))
+ , m_xLinePosBox(m_xBuilder->weld_combo_box("position"))
+ , m_xLineTypeBox(new SvtLineListBox(m_xBuilder->weld_menu_button("style")))
+ , m_xLineWidthEdit(m_xBuilder->weld_metric_spin_button("thickness", FieldUnit::POINT))
+ , m_xLineColorBox(new ColorListBox(m_xBuilder->weld_menu_button("color"),
+ [this]{ return GetDialogController()->getDialog(); }))
+ , m_xLineLengthEdit(m_xBuilder->weld_metric_spin_button("length", FieldUnit::PERCENT))
+ , m_xLineDistEdit(m_xBuilder->weld_metric_spin_button("spacingtocontents", FieldUnit::CM))
+{
+ SetExchangeSupport();
+ FieldUnit aMetric = ::GetDfltMetric(false);
+ ::SetFieldUnit(*m_xMaxHeightEdit, aMetric);
+ ::SetFieldUnit(*m_xDistEdit, aMetric);
+ ::SetFieldUnit(*m_xLineDistEdit, aMetric);
+ MeasurementSystem eSys = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum();
+ tools::Long nHeightValue = MeasurementSystem::Metric != eSys ? 1440 : 1134;
+ m_xMaxHeightEdit->set_value(m_xMaxHeightEdit->normalize(nHeightValue),FieldUnit::TWIP);
+}
+
+SwFootNotePage::~SwFootNotePage()
+{
+ m_xLineColorBox.reset();
+ m_xLineTypeBox.reset();
+}
+
+std::unique_ptr<SfxTabPage> SwFootNotePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet)
+{
+ return std::make_unique<SwFootNotePage>(pPage, pController, *rSet);
+}
+
+void SwFootNotePage::Reset(const SfxItemSet *rSet)
+{
+ // if no example exists, otherwise Init here in Activate
+ std::optional<SwPageFootnoteInfo> pDefFootnoteInfo;
+ const SwPageFootnoteInfo* pFootnoteInfo;
+ const SfxPoolItem* pItem = SfxTabPage::GetItem(*rSet, FN_PARAM_FTN_INFO);
+ if( pItem )
+ {
+ pFootnoteInfo = &static_cast<const SwPageFootnoteInfoItem*>(pItem)->GetPageFootnoteInfo();
+ }
+ else
+ {
+ // when "standard" is being activated the footnote item is deleted,
+ // that's why a footnote structure has to be created here
+ pDefFootnoteInfo.emplace();
+ pFootnoteInfo = &*pDefFootnoteInfo;
+ }
+ // footnote area's height
+ SwTwips lHeight = pFootnoteInfo->GetHeight();
+ if(lHeight)
+ {
+ m_xMaxHeightEdit->set_value(m_xMaxHeightEdit->normalize(lHeight),FieldUnit::TWIP);
+ m_xMaxHeightBtn->set_active(true);
+ }
+ else
+ {
+ m_xMaxHeightPageBtn->set_active(true);
+ m_xMaxHeightEdit->set_sensitive(false);
+ }
+ m_xMaxHeightPageBtn->connect_toggled(LINK(this,SwFootNotePage,HeightPage));
+ m_xMaxHeightBtn->connect_toggled(LINK(this,SwFootNotePage,HeightMetric));
+ Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwFootNotePage, HeightModify);
+ m_xMaxHeightEdit->connect_value_changed(aLk);
+ m_xDistEdit->connect_value_changed(aLk);
+ m_xLineDistEdit->connect_value_changed(aLk);
+
+ // Separator width
+ m_xLineWidthEdit->connect_value_changed(LINK(this, SwFootNotePage, LineWidthChanged_Impl));
+
+ sal_Int64 nWidthPt = static_cast<sal_Int64>(vcl::ConvertDoubleValue(
+ sal_Int64( pFootnoteInfo->GetLineWidth() ), m_xLineWidthEdit->get_digits(),
+ MapUnit::MapTwip, m_xLineWidthEdit->get_unit( ) ));
+ m_xLineWidthEdit->set_value(nWidthPt, FieldUnit::NONE);
+
+ // Separator style
+ m_xLineTypeBox->SetSourceUnit( FieldUnit::TWIP );
+
+ m_xLineTypeBox->InsertEntry(
+ ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::SOLID),
+ SvxBorderLineStyle::SOLID );
+ m_xLineTypeBox->InsertEntry(
+ ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::DOTTED),
+ SvxBorderLineStyle::DOTTED );
+ m_xLineTypeBox->InsertEntry(
+ ::editeng::SvxBorderLine::getWidthImpl(SvxBorderLineStyle::DASHED),
+ SvxBorderLineStyle::DASHED );
+ m_xLineTypeBox->SetWidth( pFootnoteInfo->GetLineWidth( ) );
+ m_xLineTypeBox->SelectEntry( pFootnoteInfo->GetLineStyle() );
+
+ // Separator Color
+ m_xLineColorBox->SelectEntry(pFootnoteInfo->GetLineColor());
+ m_xLineColorBox->SetSelectHdl(LINK(this, SwFootNotePage, LineColorSelected_Impl));
+ m_xLineTypeBox->SetColor(pFootnoteInfo->GetLineColor());
+
+ // position
+ m_xLinePosBox->set_active(static_cast<sal_Int32>(pFootnoteInfo->GetAdj()));
+
+ // width
+ Fraction aTmp( 100, 1 );
+ aTmp *= pFootnoteInfo->GetWidth();
+ m_xLineLengthEdit->set_value(static_cast<tools::Long>(aTmp), FieldUnit::PERCENT);
+
+ // gap footnote area
+ m_xDistEdit->set_value(m_xDistEdit->normalize(pFootnoteInfo->GetTopDist()), FieldUnit::TWIP);
+ m_xLineDistEdit->set_value(
+ m_xLineDistEdit->normalize(pFootnoteInfo->GetBottomDist()), FieldUnit::TWIP);
+ ActivatePage( *rSet );
+}
+
+// stuff attributes into the set, when OK
+bool SwFootNotePage::FillItemSet(SfxItemSet *rSet)
+{
+ SwPageFootnoteInfoItem aItem(GetItemSet().Get(FN_PARAM_FTN_INFO));
+
+ // that's the original
+ SwPageFootnoteInfo &rFootnoteInfo = aItem.GetPageFootnoteInfo();
+
+ // footnote area's height
+ if (m_xMaxHeightBtn->get_active())
+ rFootnoteInfo.SetHeight( static_cast< SwTwips >(
+ m_xMaxHeightEdit->denormalize(m_xMaxHeightEdit->get_value(FieldUnit::TWIP))));
+ else
+ rFootnoteInfo.SetHeight(0);
+
+ // gap footnote area
+ rFootnoteInfo.SetTopDist( static_cast< SwTwips >(
+ m_xDistEdit->denormalize(m_xDistEdit->get_value(FieldUnit::TWIP))));
+ rFootnoteInfo.SetBottomDist( static_cast< SwTwips >(
+ m_xLineDistEdit->denormalize(m_xLineDistEdit->get_value(FieldUnit::TWIP))));
+
+ // Separator style
+ rFootnoteInfo.SetLineStyle(m_xLineTypeBox->GetSelectEntryStyle());
+
+ // Separator width
+ sal_Int64 nWidth = m_xLineWidthEdit->get_value(FieldUnit::NONE);
+ nWidth = static_cast<tools::Long>(vcl::ConvertDoubleValue(
+ nWidth,
+ m_xLineWidthEdit->get_digits(),
+ m_xLineWidthEdit->get_unit(), MapUnit::MapTwip ));
+ rFootnoteInfo.SetLineWidth( nWidth );
+
+ // Separator color
+ rFootnoteInfo.SetLineColor(m_xLineColorBox->GetSelectEntryColor());
+
+ // Position
+ rFootnoteInfo.SetAdj(static_cast<css::text::HorizontalAdjust>(m_xLinePosBox->get_active()));
+
+ // Width
+ rFootnoteInfo.SetWidth(Fraction(m_xLineLengthEdit->get_value(FieldUnit::PERCENT), 100));
+
+ const SfxPoolItem* pOldItem;
+ if(nullptr == (pOldItem = GetOldItem( *rSet, FN_PARAM_FTN_INFO )) ||
+ aItem != *pOldItem )
+ rSet->Put(aItem);
+
+ return true;
+}
+
+void SwFootNotePage::ActivatePage(const SfxItemSet& rSet)
+{
+ auto const & rSize = rSet.Get( RES_FRM_SIZE );
+ lMaxHeight = rSize.GetHeight();
+
+ if( const SvxSetItem* pHeaderSetItem = rSet.GetItemIfSet( rSet.GetPool()->GetWhich( SID_ATTR_PAGE_HEADERSET), false ) )
+ {
+ const SfxItemSet& rHeaderSet = pHeaderSetItem->GetItemSet();
+ const SfxBoolItem& rHeaderOn =
+ rHeaderSet.Get( rSet.GetPool()->GetWhich( SID_ATTR_PAGE_ON ) );
+
+ if ( rHeaderOn.GetValue() )
+ {
+ const SvxSizeItem& rSizeItem =
+ rHeaderSet.Get(rSet.GetPool()->GetWhich(SID_ATTR_PAGE_SIZE));
+ lMaxHeight -= rSizeItem.GetSize().Height();
+ }
+ }
+
+ if( const SvxSetItem* pFooterSetItem = rSet.GetItemIfSet( rSet.GetPool()->GetWhich( SID_ATTR_PAGE_FOOTERSET),
+ false ) )
+ {
+ const SfxItemSet& rFooterSet = pFooterSetItem->GetItemSet();
+ const SfxBoolItem& rFooterOn = rFooterSet.Get( SID_ATTR_PAGE_ON );
+
+ if ( rFooterOn.GetValue() )
+ {
+ const SvxSizeItem& rSizeItem =
+ rFooterSet.Get( rSet.GetPool()->GetWhich( SID_ATTR_PAGE_SIZE ) );
+ lMaxHeight -= rSizeItem.GetSize().Height();
+ }
+ }
+
+ if ( const SvxULSpaceItem* pSpaceItem = rSet.GetItemIfSet( RES_UL_SPACE , false ) )
+ {
+ lMaxHeight -= pSpaceItem->GetUpper() + pSpaceItem->GetLower();
+ }
+
+ lMaxHeight *= 8;
+ lMaxHeight /= 10;
+
+ // set maximum values
+ HeightModify(*m_xMaxHeightEdit);
+}
+
+DeactivateRC SwFootNotePage::DeactivatePage( SfxItemSet* _pSet)
+{
+ if(_pSet)
+ FillItemSet(_pSet);
+
+ return DeactivateRC::LeavePage;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/pggrid.cxx b/sw/source/ui/misc/pggrid.cxx
new file mode 100644
index 000000000..c483c4f47
--- /dev/null
+++ b/sw/source/ui/misc/pggrid.cxx
@@ -0,0 +1,551 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cmdid.h>
+#include <hintids.hxx>
+#include <svx/colorbox.hxx>
+#include <editeng/sizeitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/ruler.hxx>
+#include <pggrid.hxx>
+#include <tgrditem.hxx>
+#include <svx/pageitem.hxx>
+
+#include <wrtsh.hxx>
+#include <doc.hxx>
+#include <swmodule.hxx>
+#include <view.hxx>
+
+constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
+
+SwTextGridPage::SwTextGridPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet)
+ : SfxTabPage(pPage, pController, "modules/swriter/ui/textgridpage.ui", "TextGridPage", &rSet)
+ , m_nRubyUserValue(0)
+ , m_bRubyUserValue(false)
+ , m_aPageSize(constTwips_5mm, constTwips_5mm)
+ , m_bVertical(false)
+ , m_bSquaredMode(false)
+ , m_bHRulerChanged(false)
+ , m_bVRulerChanged(false)
+ , m_xNoGridRB(m_xBuilder->weld_radio_button("radioRB_NOGRID"))
+ , m_xLinesGridRB(m_xBuilder->weld_radio_button("radioRB_LINESGRID"))
+ , m_xCharsGridRB(m_xBuilder->weld_radio_button("radioRB_CHARSGRID"))
+ , m_xSnapToCharsCB(m_xBuilder->weld_check_button("checkCB_SNAPTOCHARS"))
+ , m_xExampleWN(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aExampleWN))
+ , m_xLayoutFL(m_xBuilder->weld_widget("frameFL_LAYOUT"))
+ , m_xLinesPerPageNF(m_xBuilder->weld_spin_button("spinNF_LINESPERPAGE"))
+ , m_xLinesRangeFT(m_xBuilder->weld_label("labelFT_LINERANGE"))
+ , m_xTextSizeMF(m_xBuilder->weld_metric_spin_button("spinMF_TEXTSIZE", FieldUnit::POINT))
+ , m_xCharsPerLineFT(m_xBuilder->weld_label("labelFT_CHARSPERLINE"))
+ , m_xCharsPerLineNF(m_xBuilder->weld_spin_button("spinNF_CHARSPERLINE"))
+ , m_xCharsRangeFT(m_xBuilder->weld_label("labelFT_CHARRANGE"))
+ , m_xCharWidthFT(m_xBuilder->weld_label("labelFT_CHARWIDTH"))
+ , m_xCharWidthMF(m_xBuilder->weld_metric_spin_button("spinMF_CHARWIDTH", FieldUnit::POINT))
+ , m_xRubySizeFT(m_xBuilder->weld_label("labelFT_RUBYSIZE"))
+ , m_xRubySizeMF(m_xBuilder->weld_metric_spin_button("spinMF_RUBYSIZE", FieldUnit::POINT))
+ , m_xRubyBelowCB(m_xBuilder->weld_check_button("checkCB_RUBYBELOW"))
+ , m_xDisplayFL(m_xBuilder->weld_widget("frameFL_DISPLAY"))
+ , m_xDisplayCB(m_xBuilder->weld_check_button("checkCB_DISPLAY"))
+ , m_xPrintCB(m_xBuilder->weld_check_button("checkCB_PRINT"))
+ , m_xColorLB(new ColorListBox(m_xBuilder->weld_menu_button("listLB_COLOR"),
+ [this]{ return GetDialogController()->getDialog(); }))
+{
+ Link<weld::SpinButton&,void> aLink = LINK(this, SwTextGridPage, CharorLineChangedHdl);
+ m_xCharsPerLineNF->connect_value_changed(aLink);
+ m_xLinesPerPageNF->connect_value_changed(aLink);
+
+ Link<weld::MetricSpinButton&,void> aSizeLink = LINK(this, SwTextGridPage, TextSizeChangedHdl);
+ m_xTextSizeMF->connect_value_changed(aSizeLink);
+ m_xRubySizeMF->connect_value_changed(aSizeLink);
+ m_xCharWidthMF->connect_value_changed(aSizeLink);
+
+ Link<weld::Toggleable&,void> aGridTypeHdl = LINK(this, SwTextGridPage, GridTypeHdl);
+ m_xNoGridRB->connect_toggled(aGridTypeHdl);
+ m_xLinesGridRB->connect_toggled(aGridTypeHdl);
+ m_xCharsGridRB->connect_toggled(aGridTypeHdl);
+
+ m_xColorLB->SetSelectHdl(LINK(this, SwTextGridPage, ColorModifyHdl));
+ m_xPrintCB->connect_toggled(LINK(this, SwTextGridPage, GridModifyClickHdl));
+ m_xRubyBelowCB->connect_toggled(LINK(this, SwTextGridPage, GridModifyClickHdl));
+
+ m_xDisplayCB->connect_toggled(LINK(this, SwTextGridPage, DisplayGridHdl));
+
+ //Get the default paper mode
+ if (SwView *pView = GetActiveView())
+ {
+ SwWrtShell* pSh = pView->GetWrtShellPtr();
+ if( pSh )
+ {
+ m_bSquaredMode = pSh->GetDoc()->IsSquaredPageMode();
+ }
+ }
+ if( m_bSquaredMode )
+ {
+
+ m_xRubySizeFT->show();
+ m_xRubySizeMF->show();
+ m_xRubyBelowCB->show();
+ m_xSnapToCharsCB->hide();
+ m_xCharWidthFT->hide();
+ m_xCharWidthMF->hide();
+ }
+ else
+ {
+ m_xRubySizeFT->hide();
+ m_xRubySizeMF->hide();
+ m_xRubyBelowCB->hide();
+ m_xSnapToCharsCB->show();
+ m_xCharWidthFT->show();
+ m_xCharWidthMF->show();
+ }
+}
+
+SwTextGridPage::~SwTextGridPage()
+{
+ m_xColorLB.reset();
+}
+
+std::unique_ptr<SfxTabPage> SwTextGridPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet)
+{
+ return std::make_unique<SwTextGridPage>(pPage, pController, *rSet);
+}
+
+bool SwTextGridPage::FillItemSet(SfxItemSet *rSet)
+{
+ bool bRet = false;
+ if (m_xNoGridRB->get_state_changed_from_saved() ||
+ m_xLinesGridRB->get_state_changed_from_saved() ||
+ m_xLinesPerPageNF->get_value_changed_from_saved() ||
+ m_xTextSizeMF->get_value_changed_from_saved() ||
+ m_xCharsPerLineNF->get_value_changed_from_saved() ||
+ m_xSnapToCharsCB->get_state_changed_from_saved() ||
+ m_xRubySizeMF->get_value_changed_from_saved() ||
+ m_xCharWidthMF->get_value_changed_from_saved() ||
+ m_xRubyBelowCB->get_state_changed_from_saved() ||
+ m_xDisplayCB->get_state_changed_from_saved() ||
+ m_xPrintCB->get_state_changed_from_saved() ||
+ m_xColorLB->IsValueChangedFromSaved())
+ {
+ PutGridItem(*rSet);
+ bRet = true;
+ }
+
+ // draw ticks of ruler
+ if (SwView * pView = GetActiveView())
+ {
+ if ( m_bHRulerChanged )
+ pView->GetHRuler().DrawTicks();
+ if ( m_bVRulerChanged )
+ pView->GetVRuler().DrawTicks();
+ }
+ return bRet;
+}
+
+void SwTextGridPage::Reset(const SfxItemSet *rSet)
+{
+ sal_Int32 nLinesPerPage = 0;
+
+ if(SfxItemState::DEFAULT <= rSet->GetItemState(RES_TEXTGRID))
+ {
+ const SwTextGridItem& rGridItem = rSet->Get(RES_TEXTGRID);
+ weld::RadioButton* pButton = nullptr;
+ switch(rGridItem.GetGridType())
+ {
+ case GRID_NONE : pButton = m_xNoGridRB.get(); break;
+ case GRID_LINES_ONLY : pButton = m_xLinesGridRB.get(); break;
+ default: pButton = m_xCharsGridRB.get();
+ }
+ pButton->set_active(true);
+ m_xDisplayCB->set_active(rGridItem.IsDisplayGrid());
+ GridTypeHdl(*pButton);
+ m_xSnapToCharsCB->set_active(rGridItem.IsSnapToChars());
+ nLinesPerPage = rGridItem.GetLines();
+
+ SetLinesOrCharsRanges(*m_xLinesRangeFT , m_xLinesPerPageNF->get_max());
+ m_nRubyUserValue = rGridItem.GetBaseHeight();
+ m_bRubyUserValue = true;
+ m_xTextSizeMF->set_value(m_xTextSizeMF->normalize(m_nRubyUserValue), FieldUnit::TWIP);
+ m_xRubySizeMF->set_value(m_xRubySizeMF->normalize(rGridItem.GetRubyHeight()), FieldUnit::TWIP);
+ m_xCharWidthMF->set_value(m_xCharWidthMF->normalize(rGridItem.GetBaseWidth()), FieldUnit::TWIP);
+ m_xRubyBelowCB->set_active(rGridItem.IsRubyTextBelow());
+ m_xPrintCB->set_active(rGridItem.IsPrintGrid());
+ m_xColorLB->SelectEntry(rGridItem.GetColor());
+ }
+ UpdatePageSize(*rSet);
+
+ if (nLinesPerPage > 0)
+ m_xLinesPerPageNF->set_value(nLinesPerPage);
+
+ m_xNoGridRB->save_state();
+ m_xLinesGridRB->save_state();
+ m_xSnapToCharsCB->save_state();
+ m_xLinesPerPageNF->save_value();
+ m_xTextSizeMF->save_value();
+ m_xCharsPerLineNF->save_value();
+ m_xRubySizeMF->save_value();
+ m_xCharWidthMF->save_value();
+ m_xRubyBelowCB->save_state();
+ m_xDisplayCB->save_state();
+ m_xPrintCB->save_state();
+ m_xColorLB->SaveValue();
+}
+
+void SwTextGridPage::ActivatePage( const SfxItemSet& rSet )
+{
+ m_aExampleWN.Hide();
+ m_aExampleWN.UpdateExample(rSet);
+ UpdatePageSize(rSet);
+ m_aExampleWN.Show();
+ m_aExampleWN.Invalidate();
+}
+
+DeactivateRC SwTextGridPage::DeactivatePage( SfxItemSet* )
+{
+ return DeactivateRC::LeavePage;
+}
+
+void SwTextGridPage::PutGridItem(SfxItemSet& rSet)
+{
+ SwTextGridItem aGridItem;
+ aGridItem.SetGridType(m_xNoGridRB->get_active() ? GRID_NONE :
+ m_xLinesGridRB->get_active() ? GRID_LINES_ONLY : GRID_LINES_CHARS );
+ aGridItem.SetSnapToChars(m_xSnapToCharsCB->get_active());
+ aGridItem.SetLines( static_cast< sal_uInt16 >(m_xLinesPerPageNF->get_value()) );
+ aGridItem.SetBaseHeight( static_cast< sal_uInt16 >(
+ m_bRubyUserValue ? m_nRubyUserValue :
+ m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP))) );
+ // Tdf#151544: set ruby height from the value get from UI only when in square page mode.
+ // When in normal mode, the ruby height should be zero.
+ if (m_bSquaredMode)
+ aGridItem.SetRubyHeight(static_cast<sal_uInt16>(m_xRubySizeMF->denormalize(m_xRubySizeMF->get_value(FieldUnit::TWIP))));
+ else
+ aGridItem.SetRubyHeight(0);
+ aGridItem.SetBaseWidth( static_cast< sal_uInt16 >(m_xCharWidthMF->denormalize(m_xCharWidthMF->get_value(FieldUnit::TWIP))) );
+ aGridItem.SetRubyTextBelow(m_xRubyBelowCB->get_active());
+ aGridItem.SetSquaredMode(m_bSquaredMode);
+ aGridItem.SetDisplayGrid(m_xDisplayCB->get_active());
+ aGridItem.SetPrintGrid(m_xPrintCB->get_active());
+ aGridItem.SetColor(m_xColorLB->GetSelectEntryColor());
+ rSet.Put(aGridItem);
+
+ SwView * pView = ::GetActiveView();
+ if (pView && aGridItem.GetGridType() != GRID_NONE)
+ {
+ if ( aGridItem.GetGridType() == GRID_LINES_CHARS )
+ {
+ m_bHRulerChanged = true;
+ }
+ m_bVRulerChanged = true;
+ pView->GetHRuler().SetCharWidth(static_cast<tools::Long>(m_xCharWidthMF->get_value(FieldUnit::TWIP)/56.7));
+ pView->GetVRuler().SetLineHeight(static_cast<tools::Long>(m_xTextSizeMF->get_value(FieldUnit::TWIP)/56.7));
+ }
+}
+
+void SwTextGridPage::UpdatePageSize(const SfxItemSet& rSet)
+{
+ if( SfxItemState::UNKNOWN != rSet.GetItemState( RES_FRAMEDIR ))
+ {
+ const SvxFrameDirectionItem& rDirItem =
+ rSet.Get(RES_FRAMEDIR);
+ m_bVertical = rDirItem.GetValue() == SvxFrameDirection::Vertical_RL_TB||
+ rDirItem.GetValue() == SvxFrameDirection::Vertical_LR_TB;
+ }
+
+ if( SfxItemState::SET != rSet.GetItemState( SID_ATTR_PAGE_SIZE ))
+ return;
+
+ const SvxSizeItem& rSize = rSet.Get(SID_ATTR_PAGE_SIZE);
+ const SvxLRSpaceItem& rLRSpace = rSet.Get( RES_LR_SPACE );
+ const SvxULSpaceItem& rULSpace = rSet.Get( RES_UL_SPACE );
+ const SvxBoxItem& rBox = rSet.Get(RES_BOX);
+ sal_Int32 nDistanceLR = rLRSpace.GetLeft() + rLRSpace.GetRight();
+ sal_Int32 nDistanceUL = rULSpace.GetUpper() + rULSpace.GetLower();
+
+ for( const TypedWhichId<SvxSetItem> & nId : { SID_ATTR_PAGE_HEADERSET, SID_ATTR_PAGE_FOOTERSET })
+ {
+ if( const SvxSetItem* pItem = rSet.GetItemIfSet( nId, false ) )
+ {
+ const SfxItemSet& rExtraSet = pItem->GetItemSet();
+ const SfxBoolItem& rOn =
+ rExtraSet.Get( rSet.GetPool()->GetWhich( SID_ATTR_PAGE_ON ) );
+
+ if ( rOn.GetValue() )
+ {
+ const SvxSizeItem& rSizeItem =
+ rExtraSet.Get(rSet.GetPool()->GetWhich(SID_ATTR_PAGE_SIZE));
+ nDistanceUL += rSizeItem.GetSize().Height();
+ }
+ }
+ }
+
+ sal_Int32 nValue1 = rSize.GetSize().Height() - nDistanceUL -
+ rBox.GetDistance(SvxBoxItemLine::TOP) -
+ rBox.GetDistance(SvxBoxItemLine::BOTTOM);
+ sal_Int32 nValue2 = rSize.GetSize().Width() - nDistanceLR -
+ rBox.GetDistance(SvxBoxItemLine::LEFT) -
+ rBox.GetDistance(SvxBoxItemLine::RIGHT);
+ if(m_bVertical)
+ {
+ m_aPageSize.setWidth( nValue1 );
+ m_aPageSize.setHeight( nValue2 );
+ }
+ else
+ {
+ m_aPageSize.setWidth( nValue2 );
+ m_aPageSize.setHeight( nValue1 );
+ }
+
+ sal_Int32 nTextSize = static_cast< sal_Int32 >(m_bRubyUserValue ?
+ m_nRubyUserValue :
+ m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)));
+
+ if ( m_bSquaredMode )
+ {
+ sal_Int32 nCharsPerLine = m_aPageSize.Width() / nTextSize;
+ m_xCharsPerLineNF->set_max(nCharsPerLine);
+ m_xCharsPerLineNF->set_sensitive(nCharsPerLine != 0);
+ m_xCharsPerLineNF->set_value(nCharsPerLine);
+ sal_Int32 nMaxLines = m_aPageSize.Height() /
+ ( m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)) +
+ m_xRubySizeMF->denormalize(m_xRubySizeMF->get_value(FieldUnit::TWIP)));
+ m_xLinesPerPageNF->set_max(nMaxLines);
+ m_xLinesPerPageNF->set_sensitive(nMaxLines != 0);
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+ }
+ else
+ {
+ sal_Int32 nTextWidth = static_cast< sal_Int32 >(m_xCharWidthMF->denormalize(m_xCharWidthMF->get_value(FieldUnit::TWIP)));
+ m_xLinesPerPageNF->set_value(m_aPageSize.Height() / nTextSize);
+ if (nTextWidth)
+ m_xCharsPerLineNF->set_value(m_aPageSize.Width() / nTextWidth);
+ else
+ m_xCharsPerLineNF->set_value(45);
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+ }
+}
+
+void SwTextGridPage::SetLinesOrCharsRanges(weld::Label& rField, const sal_Int32 nValue )
+{
+ OUString aFieldStr = "( 1 -" + OUString::number(nValue) + " )";
+ rField.set_label(aFieldStr);
+}
+
+WhichRangesContainer SwTextGridPage::GetRanges()
+{
+ return WhichRangesContainer(svl::Items<RES_TEXTGRID, RES_TEXTGRID>);
+}
+
+IMPL_LINK(SwTextGridPage, CharorLineChangedHdl, weld::SpinButton&, rField, void)
+{
+ //if in squared mode
+ if ( m_bSquaredMode )
+ {
+ if (m_xCharsPerLineNF.get() == &rField)
+ {
+ auto nValue = m_xCharsPerLineNF->get_value();
+ assert(nValue && "div-by-zero");
+ auto nWidth = m_aPageSize.Width() / nValue;
+ m_xTextSizeMF->set_value(m_xTextSizeMF->normalize(nWidth), FieldUnit::TWIP);
+ //prevent rounding errors in the MetricField by saving the used value
+ m_nRubyUserValue = nWidth;
+ m_bRubyUserValue = true;
+
+ }
+ //set maximum line per page
+ {
+ sal_Int32 nMaxLines = static_cast< sal_Int32 >(m_aPageSize.Height() /
+ ( m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)) +
+ m_xRubySizeMF->denormalize(m_xRubySizeMF->get_value(FieldUnit::TWIP))));
+ m_xLinesPerPageNF->set_max(nMaxLines);
+ m_xLinesPerPageNF->set_sensitive(nMaxLines != 0);
+ }
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ }
+ else//in normal mode
+ {
+ if (m_xLinesPerPageNF.get() == &rField)
+ {
+ auto nValue = m_xLinesPerPageNF->get_value();
+ assert(nValue && "div-by-zero");
+ auto nHeight = m_aPageSize.Height() / nValue;
+ m_xTextSizeMF->set_value(m_xTextSizeMF->normalize(nHeight), FieldUnit::TWIP);
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+
+ m_nRubyUserValue = nHeight;
+ m_bRubyUserValue = true;
+ }
+ else if (m_xCharsPerLineNF.get() == &rField)
+ {
+ auto nValue = m_xCharsPerLineNF->get_value();
+ assert(nValue && "div-by-zero");
+ auto nWidth = m_aPageSize.Width() / nValue;
+ m_xCharWidthMF->set_value(m_xCharWidthMF->normalize(nWidth), FieldUnit::TWIP);
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ }
+ }
+ GridModifyHdl();
+}
+
+IMPL_LINK(SwTextGridPage, TextSizeChangedHdl, weld::MetricSpinButton&, rField, void)
+{
+ //if in squared mode
+ if( m_bSquaredMode )
+ {
+ if (m_xTextSizeMF.get() == &rField)
+ {
+ m_bRubyUserValue = false;
+
+ // fdo#50941: set maximum characters per line
+ sal_Int32 nTextSize = static_cast< sal_Int32 >(m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)));
+ if (nTextSize > 0)
+ {
+ sal_Int32 nMaxChars = m_aPageSize.Width() / nTextSize;
+ m_xCharsPerLineNF->set_value(nMaxChars);
+ m_xCharsPerLineNF->set_max(nMaxChars);
+ m_xCharsPerLineNF->set_sensitive(nMaxChars != 0);
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ }
+ }
+ //set maximum line per page
+ {
+ sal_Int32 nMaxLines = static_cast< sal_Int32 >(m_aPageSize.Height() /
+ ( m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)) +
+ m_xRubySizeMF->denormalize(m_xRubySizeMF->get_value(FieldUnit::TWIP))));
+ m_xLinesPerPageNF->set_max(nMaxLines);
+ m_xLinesPerPageNF->set_sensitive(nMaxLines != 0);
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+ }
+ }
+ else
+ {
+ if (m_xTextSizeMF.get() == &rField)
+ {
+ sal_Int32 nTextSize = static_cast< sal_Int32 >(m_xTextSizeMF->denormalize(m_xTextSizeMF->get_value(FieldUnit::TWIP)));
+ m_xLinesPerPageNF->set_value(m_aPageSize.Height() / nTextSize);
+ m_bRubyUserValue = false;
+ SetLinesOrCharsRanges( *m_xLinesRangeFT , m_xLinesPerPageNF->get_max() );
+ }
+ else if (m_xCharWidthMF.get() == &rField)
+ {
+ sal_Int32 nTextWidth = static_cast< sal_Int32 >(m_xCharWidthMF->denormalize(m_xCharWidthMF->get_value(FieldUnit::TWIP)));
+ sal_Int32 nMaxChar = 45 ;
+ if (nTextWidth)
+ nMaxChar = m_aPageSize.Width() / nTextWidth;
+ m_xCharsPerLineNF->set_value( nMaxChar );
+ SetLinesOrCharsRanges( *m_xCharsRangeFT , m_xCharsPerLineNF->get_max() );
+ }
+ //rubySize is disabled
+ }
+ GridModifyHdl();
+}
+
+IMPL_LINK(SwTextGridPage, GridTypeHdl, weld::Toggleable&, rButton, void)
+{
+ if (!rButton.get_active())
+ return;
+
+ if (m_xNoGridRB.get() == &rButton)
+ {
+ // GRID_NONE mode:
+ // "Layout" and "Display" sections should all be disabled.
+ m_xLayoutFL->set_sensitive(false);
+ m_xDisplayFL->set_sensitive(false);
+ }
+ else
+ {
+ // GRID_LINES_ONLY or GRID_LINES_CHARS mode:
+ // "Layout" and "Display" sections should all be enabled;
+ // DisplayGridHdl should be executed;
+ m_xLayoutFL->set_sensitive(true);
+ m_xDisplayFL->set_sensitive(true);
+ DisplayGridHdl(*m_xDisplayCB);
+ }
+
+ if (m_xCharsGridRB.get() == &rButton)
+ {
+ // GRID_LINES_CHARS mode:
+ // "Snap to character" should be enabled;
+ // "Characters per line" should be enabled;
+ // "Characters range" should be enabled;
+ m_xSnapToCharsCB->set_sensitive(true);
+ m_xCharsPerLineFT->set_sensitive(true);
+ m_xCharsPerLineNF->set_sensitive(true);
+ m_xCharsRangeFT->set_sensitive(true);
+ m_xCharWidthFT->set_sensitive(true);
+ m_xCharWidthMF->set_sensitive(true);
+ }
+ else
+ {
+ // GRID_NONE or GRID_LINES_ONLY mode:
+ // "Snap to character" should be disabled;
+ // "Characters per line" should be disabled;
+ // "Characters range" should be disabled;
+ m_xSnapToCharsCB->set_sensitive(false);
+ m_xCharsPerLineFT->set_sensitive(false);
+ m_xCharsPerLineNF->set_sensitive(false);
+ m_xCharsRangeFT->set_sensitive(false);
+ m_xCharWidthFT->set_sensitive(false);
+ m_xCharWidthMF->set_sensitive(false);
+ }
+
+ if (m_xNoGridRB.get() != &rButton)
+ {
+ // GRID_LINES_ONLY or GRID_LINES_CHARS mode: (additionally)
+ // TextSizeChangedHdl should be executed to recalculate which dependencies are sensitive.
+ TextSizeChangedHdl(*m_xTextSizeMF);
+ }
+
+ GridModifyHdl();
+}
+
+IMPL_LINK_NOARG(SwTextGridPage, DisplayGridHdl, weld::Toggleable&, void)
+{
+ bool bChecked = m_xDisplayCB->get_active();
+ m_xPrintCB->set_sensitive(bChecked);
+ m_xPrintCB->set_active(bChecked);
+}
+
+IMPL_LINK_NOARG(SwTextGridPage, GridModifyClickHdl, weld::Toggleable&, void)
+{
+ GridModifyHdl();
+}
+
+IMPL_LINK_NOARG(SwTextGridPage, ColorModifyHdl, ColorListBox&, void)
+{
+ GridModifyHdl();
+}
+
+void SwTextGridPage::GridModifyHdl()
+{
+ const SfxItemSet& rOldSet = GetItemSet();
+ SfxItemSet aSet(rOldSet);
+ const SfxItemSet* pExSet = GetDialogExampleSet();
+ if(pExSet)
+ aSet.Put(*pExSet);
+ PutGridItem(aSet);
+ m_aExampleWN.UpdateExample(aSet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/srtdlg.cxx b/sw/source/ui/misc/srtdlg.cxx
new file mode 100644
index 000000000..52ca7ba66
--- /dev/null
+++ b/sw/source/ui/misc/srtdlg.cxx
@@ -0,0 +1,428 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <srtdlg.hxx>
+
+#include <editeng/editids.hrc>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <svl/intitem.hxx>
+#include <svx/svxdlg.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <svtools/collatorres.hxx>
+#include <swwait.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <strings.hrc>
+#include <swtable.hxx>
+#include <sortopt.hxx>
+#include <node.hxx>
+#include <tblsel.hxx>
+#include <memory>
+
+static bool bCheck1 = true;
+static bool bCheck2 = false;
+static bool bCheck3 = false;
+
+static sal_uInt16 nCol1 = 1;
+static sal_uInt16 nCol2 = 1;
+static sal_uInt16 nCol3 = 1;
+
+static sal_uInt16 nType1 = 0;
+static sal_uInt16 nType2 = 0;
+static sal_uInt16 nType3 = 0;
+
+static LanguageType nLang = LANGUAGE_NONE;
+
+static bool bAsc1 = true;
+static bool bAsc2 = true;
+static bool bAsc3 = true;
+static bool bCol = false;
+static bool bCsSens= false;
+
+static sal_Unicode cDeli = '\t';
+
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+// determine lines and columns for table selection
+static bool lcl_GetSelTable( SwWrtShell const &rSh, sal_uInt16& rX, sal_uInt16& rY )
+{
+ const SwTableNode* pTableNd = rSh.IsCursorInTable();
+ if( !pTableNd )
+ return false;
+
+ FndBox_ aFndBox( nullptr, nullptr );
+
+ // look for all boxes / lines
+ {
+ SwSelBoxes aSelBoxes;
+ ::GetTableSel( rSh, aSelBoxes );
+ FndPara aPara( aSelBoxes, &aFndBox );
+ const SwTable& rTable = pTableNd->GetTable();
+ ForEach_FndLineCopyCol( const_cast<SwTableLines&>(rTable.GetTabLines()), &aPara );
+ }
+ rX = aFndBox.GetLines().size();
+ if( !rX )
+ return false;
+
+ rY = aFndBox.GetLines().front()->GetBoxes().size();
+ return true;
+}
+
+// init list
+SwSortDlg::SwSortDlg(weld::Window* pParent, SwWrtShell &rShell)
+ : GenericDialogController(pParent, "modules/swriter/ui/sortdialog.ui", "SortDialog")
+ , m_pParent(pParent)
+ , m_xColLbl(m_xBuilder->weld_label("column"))
+ , m_xKeyCB1(m_xBuilder->weld_check_button("key1"))
+ , m_xColEdt1(m_xBuilder->weld_spin_button("colsb1"))
+ , m_xTypDLB1(m_xBuilder->weld_combo_box("typelb1"))
+ , m_xSortUp1RB(m_xBuilder->weld_radio_button("up1"))
+ , m_xSortDn1RB(m_xBuilder->weld_radio_button("down1"))
+ , m_xKeyCB2(m_xBuilder->weld_check_button("key2"))
+ , m_xColEdt2(m_xBuilder->weld_spin_button("colsb2"))
+ , m_xTypDLB2(m_xBuilder->weld_combo_box("typelb2"))
+ , m_xSortUp2RB(m_xBuilder->weld_radio_button("up2"))
+ , m_xSortDn2RB(m_xBuilder->weld_radio_button("down2"))
+ , m_xKeyCB3(m_xBuilder->weld_check_button("key3"))
+ , m_xColEdt3(m_xBuilder->weld_spin_button("colsb3"))
+ , m_xTypDLB3(m_xBuilder->weld_combo_box("typelb3"))
+ , m_xSortUp3RB(m_xBuilder->weld_radio_button("up3"))
+ , m_xSortDn3RB(m_xBuilder->weld_radio_button("down3"))
+ , m_xColumnRB(m_xBuilder->weld_radio_button("columns"))
+ , m_xRowRB(m_xBuilder->weld_radio_button("rows"))
+ , m_xDelimTabRB(m_xBuilder->weld_radio_button("tabs"))
+ , m_xDelimFreeRB(m_xBuilder->weld_radio_button("character"))
+ , m_xDelimEdt(m_xBuilder->weld_entry("separator"))
+ , m_xDelimPB(m_xBuilder->weld_button("delimpb"))
+ , m_xLangLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("langlb")))
+ , m_xCaseCB(m_xBuilder->weld_check_button("matchcase"))
+ , aColText(SwResId(STR_COL))
+ , aRowText(SwResId(STR_ROW))
+ , aNumericText(SwResId(STR_NUMERIC))
+ , rSh(rShell)
+ , nX(99)
+ , nY(99)
+{
+ if(rSh.GetSelectionType() &
+ (SelectionType::Table|SelectionType::TableCell) )
+ {
+ m_xColumnRB->set_active(bCol);
+ m_xColLbl->set_label(bCol ? aRowText : aColText);
+ m_xRowRB->set_active(!bCol);
+ m_xDelimTabRB->set_sensitive(false);
+ m_xDelimFreeRB->set_sensitive(false);
+ m_xDelimEdt->set_sensitive(false);
+ }
+ else
+ {
+ m_xColumnRB->set_sensitive(false);
+ m_xRowRB->set_active(true);
+ m_xColLbl->set_label(aColText);
+ }
+
+ // Set accessible names here because text of m_xColLbl may be changed
+ // by the if-else block above
+ m_xColEdt1->set_accessible_name(m_xColLbl->get_label());
+ m_xColEdt2->set_accessible_name(m_xColLbl->get_label());
+ m_xColEdt3->set_accessible_name(m_xColLbl->get_label());
+
+ // initialise
+ Link<weld::Toggleable&,void> aLk = LINK(this, SwSortDlg, CheckHdl);
+ m_xKeyCB1->connect_toggled( aLk );
+ m_xKeyCB2->connect_toggled( aLk );
+ m_xKeyCB3->connect_toggled( aLk );
+ m_xColumnRB->connect_toggled( aLk );
+ m_xRowRB->connect_toggled( aLk );
+
+ aLk = LINK(this, SwSortDlg, DelimHdl);
+ m_xDelimFreeRB->connect_toggled(aLk);
+ m_xDelimTabRB->connect_toggled(aLk);
+
+ m_xDelimPB->connect_clicked( LINK( this, SwSortDlg, DelimCharHdl ));
+
+ m_xKeyCB1->set_active(bCheck1);
+ m_xKeyCB2->set_active(bCheck2);
+ m_xKeyCB3->set_active(bCheck3);
+
+ m_xColEdt1->set_value(nCol1);
+ m_xColEdt2->set_value(nCol2);
+ m_xColEdt3->set_value(nCol3);
+
+ // first initialise the language, then select the
+ if( LANGUAGE_NONE == nLang || LANGUAGE_DONTKNOW == nLang )
+ nLang = GetAppLanguage();
+
+ m_xLangLB->SetLanguageList( SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, true );
+ m_xLangLB->set_active_id(nLang);
+
+ LanguageHdl( nullptr );
+ m_xLangLB->connect_changed( LINK( this, SwSortDlg, LanguageListBoxHdl ));
+
+ m_xSortUp1RB->set_active(bAsc1);
+ m_xSortDn1RB->set_active(!bAsc1);
+ m_xSortUp2RB->set_active(bAsc2);
+ m_xSortDn2RB->set_active(!bAsc2);
+ m_xSortUp3RB->set_active(bAsc3);
+ m_xSortDn3RB->set_active(!bAsc3);
+
+ m_xCaseCB->set_active( bCsSens );
+
+ m_xDelimTabRB->set_active(cDeli == '\t');
+ if(!m_xDelimTabRB->get_active())
+ {
+ m_xDelimEdt->set_text(OUString(cDeli));
+ m_xDelimFreeRB->set_active(true);
+ DelimHdl(*m_xDelimFreeRB);
+ }
+ else
+ DelimHdl(*m_xDelimTabRB);
+
+ if( ::lcl_GetSelTable( rSh, nX, nY) )
+ {
+ sal_uInt16 nMax = m_xRowRB->get_active()? nY : nX;
+ m_xColEdt1->set_max(nMax);
+ m_xColEdt2->set_max(nMax);
+ m_xColEdt3->set_max(nMax);
+ }
+}
+
+sal_Unicode SwSortDlg::GetDelimChar() const
+{
+ sal_Unicode cRet = '\t';
+ if( !m_xDelimTabRB->get_active() )
+ {
+ OUString aTmp(m_xDelimEdt->get_text());
+ if( !aTmp.isEmpty() )
+ cRet = aTmp[0];
+ }
+ return cRet;
+}
+
+short SwSortDlg::run()
+{
+ short nRet = GenericDialogController::run();
+ if (nRet == RET_OK)
+ Apply();
+ return nRet;
+}
+
+// pass on to the Core
+void SwSortDlg::Apply()
+{
+ // save all settings
+ bCheck1 = m_xKeyCB1->get_active();
+ bCheck2 = m_xKeyCB2->get_active();
+ bCheck3 = m_xKeyCB3->get_active();
+
+ nCol1 = m_xColEdt1->get_value();
+ nCol2 = m_xColEdt2->get_value();
+ nCol3 = m_xColEdt3->get_value();
+
+ nType1 = m_xTypDLB1->get_active();
+ nType2 = m_xTypDLB2->get_active();
+ nType3 = m_xTypDLB3->get_active();
+
+ bAsc1 = m_xSortUp1RB->get_active();
+ bAsc2 = m_xSortUp2RB->get_active();
+ bAsc3 = m_xSortUp3RB->get_active();
+ bCol = m_xColumnRB->get_active();
+ nLang = m_xLangLB->get_active_id();
+ cDeli = GetDelimChar();
+ bCsSens = m_xCaseCB->get_active();
+
+ SwSortOptions aOptions;
+ if( bCheck1 )
+ {
+ OUString sEntry( m_xTypDLB1->get_active_text() );
+ if( sEntry == aNumericText )
+ sEntry.clear();
+ else if (!m_xTypDLB1->get_active_id().isEmpty())
+ sEntry = m_xTypDLB1->get_active_id();
+
+ aOptions.aKeys.push_back(
+ SwSortKey( nCol1, sEntry,
+ bAsc1 ? SwSortOrder::Ascending : SwSortOrder::Descending ));
+ }
+
+ if( bCheck2 )
+ {
+ OUString sEntry( m_xTypDLB2->get_active_text() );
+ if( sEntry == aNumericText )
+ sEntry.clear();
+ else if (!m_xTypDLB2->get_active_id().isEmpty())
+ sEntry = m_xTypDLB2->get_active_id();
+
+ aOptions.aKeys.push_back(
+ SwSortKey( nCol2, sEntry,
+ bAsc2 ? SwSortOrder::Ascending : SwSortOrder::Descending ));
+ }
+
+ if( bCheck3 )
+ {
+ OUString sEntry( m_xTypDLB3->get_active_text() );
+ if( sEntry == aNumericText )
+ sEntry.clear();
+ else if (!m_xTypDLB3->get_active_id().isEmpty())
+ sEntry = m_xTypDLB3->get_active_id();
+
+ aOptions.aKeys.push_back(
+ SwSortKey( nCol3, sEntry,
+ bAsc3 ? SwSortOrder::Ascending : SwSortOrder::Descending ));
+ }
+
+ aOptions.eDirection = bCol ? SwSortDirection::Columns : SwSortDirection::Rows;
+ aOptions.cDeli = cDeli;
+ aOptions.nLanguage = nLang;
+ aOptions.bTable = rSh.IsTableMode();
+ aOptions.bIgnoreCase = !bCsSens;
+
+ bool bRet;
+ {
+ SwWait aWait( *rSh.GetView().GetDocShell(), true );
+ rSh.StartAllAction();
+ bRet = rSh.Sort( aOptions );
+ if( bRet )
+ rSh.SetModified();
+ rSh.EndAllAction();
+ }
+
+ if (!bRet)
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_pParent,
+ VclMessageType::Info, VclButtonsType::Ok,
+ SwResId(STR_SRTERR)));
+ xInfoBox->run();
+ }
+}
+
+IMPL_LINK( SwSortDlg, DelimHdl, weld::Toggleable&, rButton, void )
+{
+ bool bEnable = &rButton == m_xDelimFreeRB.get() && m_xDelimFreeRB->get_sensitive();
+ m_xDelimEdt->set_sensitive( bEnable );
+ m_xDelimPB->set_sensitive( bEnable );
+}
+
+IMPL_LINK_NOARG(SwSortDlg, DelimCharHdl, weld::Button&, void)
+{
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ SfxAllItemSet aSet( rSh.GetAttrPool() );
+ aSet.Put( SfxInt32Item( SID_ATTR_CHAR, GetDelimChar() ) );
+ ScopedVclPtr<SfxAbstractDialog> pMap(pFact->CreateCharMapDialog(m_xDialog.get(), aSet, nullptr));
+ if( RET_OK == pMap->Execute() )
+ {
+ const SfxInt32Item* pItem = SfxItemSet::GetItem<SfxInt32Item>(pMap->GetOutputItemSet(), SID_ATTR_CHAR, false);
+ if ( pItem )
+ m_xDelimEdt->set_text(OUString(sal_Unicode(pItem->GetValue())));
+ }
+}
+
+IMPL_LINK( SwSortDlg, CheckHdl, weld::Toggleable&, rControl, void )
+{
+ if (&rControl == m_xRowRB.get())
+ {
+ m_xColLbl->set_label(aColText);
+ m_xColEdt1->set_max(nY);
+ m_xColEdt2->set_max(nY);
+ m_xColEdt3->set_max(nY);
+
+ m_xColEdt1->set_accessible_name(aColText);
+ m_xColEdt2->set_accessible_name(aColText);
+ m_xColEdt3->set_accessible_name(aColText);
+ }
+ else if (&rControl == m_xColumnRB.get())
+ {
+ m_xColLbl->set_label(aRowText);
+ m_xColEdt1->set_max(nX);
+ m_xColEdt2->set_max(nX);
+ m_xColEdt3->set_max(nX);
+
+ m_xColEdt1->set_accessible_name(aRowText);
+ m_xColEdt2->set_accessible_name(aRowText);
+ m_xColEdt3->set_accessible_name(aRowText);
+ }
+ else if(!m_xKeyCB1->get_active() &&
+ !m_xKeyCB2->get_active() &&
+ !m_xKeyCB3->get_active())
+ {
+ rControl.set_active(true);
+ }
+}
+
+IMPL_LINK( SwSortDlg, LanguageListBoxHdl, weld::ComboBox&, rLBox, void )
+{
+ LanguageHdl(&rLBox);
+}
+
+void SwSortDlg::LanguageHdl(weld::ComboBox const* pLBox)
+{
+ Sequence < OUString > aSeq( GetAppCollator().listCollatorAlgorithms(
+ LanguageTag( m_xLangLB->get_active_id()).getLocale() ));
+
+ if (!m_xColRes)
+ m_xColRes.reset(new CollatorResource);
+
+ const int nLstBoxCnt = 3;
+ weld::ComboBox* aLstArr[ nLstBoxCnt ] = { m_xTypDLB1.get(), m_xTypDLB2.get(), m_xTypDLB3.get() };
+ sal_uInt16* const aTypeArr[ nLstBoxCnt ] = { &nType1, &nType2, &nType3 };
+ OUString aOldStrArr[ nLstBoxCnt ];
+
+ for( int n = 0; n < nLstBoxCnt; ++n )
+ {
+ weld::ComboBox* pL = aLstArr[ n ];
+ OUString sUserData = pL->get_active_id();
+ if (!sUserData.isEmpty())
+ aOldStrArr[ n ] = sUserData;
+ pL->clear();
+ }
+
+ OUString sAlg, sUINm;
+ const sal_Int32 nEnd = aSeq.getLength();
+ for( sal_Int32 nCnt = 0; nCnt <= nEnd; ++nCnt )
+ {
+ if( nCnt < nEnd )
+ {
+ sAlg = aSeq[ nCnt ];
+ sUINm = m_xColRes->GetTranslation( sAlg );
+ }
+ else
+ sUINm = sAlg = aNumericText;
+
+ for( int n = 0; n < nLstBoxCnt; ++n )
+ {
+ weld::ComboBox* pL = aLstArr[ n ];
+ pL->append(sAlg, sUINm);
+ if (pLBox && sAlg == aOldStrArr[n])
+ pL->set_active_id(sAlg);
+ }
+ }
+
+ for( int n = 0; n < nLstBoxCnt; ++n )
+ {
+ weld::ComboBox* pL = aLstArr[ n ];
+ if( !pLBox )
+ pL->set_active(*aTypeArr[n]);
+ else if (pL->get_active() == -1)
+ pL->set_active(0);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/swmodalredlineacceptdlg.cxx b/sw/source/ui/misc/swmodalredlineacceptdlg.cxx
new file mode 100644
index 000000000..0d2f2672b
--- /dev/null
+++ b/sw/source/ui/misc/swmodalredlineacceptdlg.cxx
@@ -0,0 +1,79 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/ctredlin.hxx>
+#include <unotools/viewoptions.hxx>
+
+#include <redlndlg.hxx>
+#include <swmodalredlineacceptdlg.hxx>
+
+SwModalRedlineAcceptDlg::SwModalRedlineAcceptDlg(weld::Window *pParent)
+ : SfxDialogController(pParent, "svx/ui/acceptrejectchangesdialog.ui",
+ "AcceptRejectChangesDialog")
+ , m_xContentArea(m_xDialog->weld_content_area())
+{
+ m_xDialog->set_modal(true);
+
+ m_xImplDlg.reset(new SwRedlineAcceptDlg(m_xDialog, m_xBuilder.get(), m_xContentArea.get(), true));
+
+ SvtViewOptions aDlgOpt(EViewType::Dialog, OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8));
+ if (aDlgOpt.Exists())
+ {
+ css::uno::Any aUserItem = aDlgOpt.GetUserItem("UserItem");
+ OUString sExtraData;
+ aUserItem >>= sExtraData;
+ m_xImplDlg->Initialize(sExtraData);
+ }
+ m_xImplDlg->Activate(); // for data's initialisation
+}
+
+SwModalRedlineAcceptDlg::~SwModalRedlineAcceptDlg()
+{
+ AcceptAll(false); // refuse everything remaining
+
+ OUString sExtraData;
+ m_xImplDlg->FillInfo(sExtraData);
+ SvtViewOptions aDlgOpt(EViewType::Dialog, OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8));
+ aDlgOpt.SetUserItem("UserItem", css::uno::Any(sExtraData));
+
+ m_xDialog->set_modal(false);
+}
+
+void SwModalRedlineAcceptDlg::Activate()
+{
+}
+
+void SwModalRedlineAcceptDlg::AcceptAll( bool bAccept )
+{
+ SvxTPFilter* pFilterTP = m_xImplDlg->GetChgCtrl().GetFilterPage();
+
+ if (pFilterTP->IsDate() || pFilterTP->IsAuthor() ||
+ pFilterTP->IsRange() || pFilterTP->IsAction())
+ {
+ pFilterTP->CheckDate(false); // turn off all filters
+ pFilterTP->CheckAuthor(false);
+ pFilterTP->CheckRange(false);
+ pFilterTP->CheckAction(false);
+ m_xImplDlg->FilterChangedHdl(nullptr);
+ }
+
+ m_xImplDlg->CallAcceptReject( false, bAccept );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/misc/titlepage.cxx b/sw/source/ui/misc/titlepage.cxx
new file mode 100644
index 000000000..4308c8db2
--- /dev/null
+++ b/sw/source/ui/misc/titlepage.cxx
@@ -0,0 +1,334 @@
+/* -*- 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 <view.hxx>
+#include <swmodule.hxx>
+#include <wrtsh.hxx>
+#include <poolfmt.hxx>
+#include <docsh.hxx>
+
+#include <titlepage.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+
+namespace
+{
+ bool lcl_GetPageDesc(SwWrtShell& rSh, sal_uInt16 &rPageNo, std::unique_ptr<const SwFormatPageDesc>* ppPageFormatDesc)
+ {
+ bool bRet = false;
+ SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC> aSet(rSh.GetAttrPool());
+ if (rSh.GetCurAttr(aSet))
+ {
+ if (const SwFormatPageDesc* pDescItem = aSet.GetItemIfSet( RES_PAGEDESC ))
+ {
+ ::std::optional<sal_uInt16> oNumOffset = pDescItem->GetNumOffset();
+ if (oNumOffset)
+ rPageNo = *oNumOffset;
+ if (ppPageFormatDesc)
+ ppPageFormatDesc->reset(static_cast<const SwFormatPageDesc *>(pDescItem->Clone()));
+ bRet = true;
+ }
+ }
+ return bRet;
+ }
+
+ void lcl_ChangePage(SwWrtShell& rSh, sal_uInt16 nNewNumber, const SwPageDesc *pNewDesc)
+ {
+ const size_t nCurIdx = rSh.GetCurPageDesc();
+ const SwPageDesc &rCurrentDesc = rSh.GetPageDesc(nCurIdx);
+
+ std::unique_ptr<const SwFormatPageDesc> pPageFormatDesc;
+ sal_uInt16 nDontCare;
+ lcl_GetPageDesc(rSh, nDontCare, &pPageFormatDesc);
+
+ // If we want a new number then set it, otherwise reuse the existing one
+ sal_uInt16 nPgNo = 0;
+ if (nNewNumber)
+ {
+ // -1: Allow special case to prevent inheriting re-numbering from the existing page.
+ nPgNo = nNewNumber == SAL_MAX_UINT16 ? 0 : nNewNumber;
+ }
+ else if (pPageFormatDesc)
+ {
+ ::std::optional<sal_uInt16> oNumOffset = pPageFormatDesc->GetNumOffset();
+ if (oNumOffset)
+ nPgNo = *oNumOffset;
+ }
+
+ // If we want a new descriptor then set it, otherwise reuse the existing one
+ if (pNewDesc || nPgNo)
+ {
+ SwFormatPageDesc aPageFormatDesc(pNewDesc ? pNewDesc : &rCurrentDesc);
+ if (nPgNo) aPageFormatDesc.SetNumOffset(nPgNo);
+ rSh.SetAttrItem(aPageFormatDesc);
+ }
+ }
+
+ void lcl_PushCursor(SwWrtShell& rSh)
+ {
+ rSh.LockView(true);
+ rSh.StartAllAction();
+ rSh.SwCursorShell::Push();
+ }
+
+ void lcl_PopCursor(SwWrtShell& rSh)
+ {
+ rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
+ rSh.EndAllAction();
+ rSh.LockView(false);
+ }
+
+ sal_uInt16 lcl_GetCurrentPage(const SwWrtShell& rSh)
+ {
+ OUString sDummy;
+ sal_uInt16 nPhyNum=1, nVirtNum=1;
+ rSh.GetPageNumber(0, true, nPhyNum, nVirtNum, sDummy);
+ return nPhyNum;
+ }
+
+bool lcl_GotoPage(SwWrtShell& rSh, const sal_uInt16 nStartingPage, sal_uInt16 nOffset = 0)
+{
+ rSh.GotoPage(nStartingPage, /*bRecord=*/false);
+
+ sal_uInt16 nCurrentPage = lcl_GetCurrentPage(rSh);
+ // return false if at document end (unless that was the requested destination)
+ if (nCurrentPage == rSh.GetPageCnt())
+ return nCurrentPage == nStartingPage + nOffset;
+
+ if (nCurrentPage != nStartingPage)
+ {
+ assert(nStartingPage != 1 && "Physical page 1 couldn't be found/moved to?");
+ // Probably there is an auto-inserted blank page to handle odd/even, which Goto doesn't understand.
+ rSh.GotoPage(nStartingPage + 1, /*bRecord=*/false);
+
+ nCurrentPage = lcl_GetCurrentPage(rSh);
+ assert(nCurrentPage == nStartingPage + 1 && "Impossible, since unknown goes to last page");
+ if (nCurrentPage != nStartingPage + 1)
+ return false;
+ }
+ // Now that we have the correct starting point, move to the correct offset.
+ while (nOffset--)
+ rSh.SttNxtPg();
+ return true;
+}
+} // namespace
+
+/*
+ * Only include the Index page in the list if the page count implies one
+ * to reduce confusing things
+ */
+void SwTitlePageDlg::FillList()
+{
+ sal_uInt16 nTitlePages = m_xPageCountNF->get_value();
+ m_xPagePropertiesLB->clear();
+ if (mpTitleDesc)
+ m_xPagePropertiesLB->append_text(mpTitleDesc->GetName());
+ if (nTitlePages > 1 && mpIndexDesc)
+ m_xPagePropertiesLB->append_text(mpIndexDesc->GetName());
+ if (mpNormalDesc)
+ m_xPagePropertiesLB->append_text(mpNormalDesc->GetName());
+ m_xPagePropertiesLB->set_active(0);
+}
+
+sal_uInt16 SwTitlePageDlg::GetInsertPosition() const
+{
+ sal_uInt16 nPage = 1;
+ if (m_xPageStartNF->get_sensitive())
+ nPage = m_xPageStartNF->get_value();
+ return nPage;
+}
+
+SwTitlePageDlg::SwTitlePageDlg(weld::Window *pParent)
+ : SfxDialogController(pParent, "modules/swriter/ui/titlepage.ui", "DLG_TITLEPAGE")
+ , mpTitleDesc(nullptr)
+ , mpIndexDesc(nullptr)
+ , mpNormalDesc(nullptr)
+ , m_xUseExistingPagesRB(m_xBuilder->weld_radio_button("RB_USE_EXISTING_PAGES"))
+ , m_xPageCountNF(m_xBuilder->weld_spin_button("NF_PAGE_COUNT"))
+ , m_xDocumentStartRB(m_xBuilder->weld_radio_button("RB_DOCUMENT_START"))
+ , m_xPageStartRB(m_xBuilder->weld_radio_button("RB_PAGE_START"))
+ , m_xPageStartNF(m_xBuilder->weld_spin_button("NF_PAGE_START"))
+ , m_xRestartNumberingCB(m_xBuilder->weld_check_button("CB_RESTART_NUMBERING"))
+ , m_xRestartNumberingNF(m_xBuilder->weld_spin_button("NF_RESTART_NUMBERING"))
+ , m_xSetPageNumberCB(m_xBuilder->weld_check_button("CB_SET_PAGE_NUMBER"))
+ , m_xSetPageNumberNF(m_xBuilder->weld_spin_button("NF_SET_PAGE_NUMBER"))
+ , m_xPagePropertiesLB(m_xBuilder->weld_combo_box("LB_PAGE_PROPERTIES"))
+ , m_xPagePropertiesPB(m_xBuilder->weld_button("PB_PAGE_PROPERTIES"))
+ , m_xOkPB(m_xBuilder->weld_button("ok"))
+{
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return;
+ SwWrtShell& rWrtShell = pView->GetWrtShell();
+
+ m_xOkPB->connect_clicked(LINK(this, SwTitlePageDlg, OKHdl));
+ m_xRestartNumberingCB->connect_toggled(LINK(this, SwTitlePageDlg, RestartNumberingHdl));
+ m_xSetPageNumberCB->connect_toggled(LINK(this, SwTitlePageDlg, SetPageNumberHdl));
+ m_xPageStartNF->set_max(rWrtShell.GetPageCnt() + 1);
+
+ sal_uInt16 nSetPage = 1;
+ sal_uInt16 nResetPage = 1;
+ sal_uInt16 nTitlePages = 1;
+ lcl_PushCursor(rWrtShell);
+
+ SwView& rView = rWrtShell.GetView();
+ rView.InvalidateRulerPos();
+
+ bool bMaybeResetNumbering = false;
+
+ mpTitleDesc = rWrtShell.GetPageDescFromPool(RES_POOLPAGE_FIRST);
+ mpIndexDesc = rWrtShell.GetPageDescFromPool(RES_POOLPAGE_REGISTER);
+ mpNormalDesc = rWrtShell.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
+
+ rWrtShell.StartOfSection();
+ if (lcl_GetPageDesc(rWrtShell, nSetPage, &mpPageFormatDesc))
+ {
+ if (mpPageFormatDesc->GetPageDesc() == mpTitleDesc)
+ {
+ while (rWrtShell.SttNxtPg())
+ {
+ const size_t nCurIdx = rWrtShell.GetCurPageDesc();
+ const SwPageDesc& rPageDesc = rWrtShell.GetPageDesc(nCurIdx);
+
+ if (mpIndexDesc != &rPageDesc)
+ {
+ mpNormalDesc = &rPageDesc;
+ bMaybeResetNumbering = lcl_GetPageDesc(rWrtShell, nResetPage, nullptr);
+ break;
+ }
+ ++nTitlePages;
+ }
+ }
+ }
+ lcl_PopCursor(rWrtShell);
+
+ m_xUseExistingPagesRB->set_active(true);
+ m_xPageCountNF->set_value(nTitlePages);
+ m_xPageCountNF->connect_value_changed(LINK(this, SwTitlePageDlg, ValueChangeHdl));
+
+ m_xDocumentStartRB->set_active(true);
+ m_xPageStartNF->set_sensitive(false);
+ m_xPageStartNF->set_value(lcl_GetCurrentPage(rWrtShell));
+ Link<weld::Toggleable&,void> aStartPageHdl = LINK(this, SwTitlePageDlg, StartPageHdl);
+ m_xDocumentStartRB->connect_toggled(aStartPageHdl);
+ m_xPageStartRB->connect_toggled(aStartPageHdl);
+
+ m_xRestartNumberingNF->set_value(nResetPage);
+ if (bMaybeResetNumbering && nResetPage > 0)
+ {
+ m_xRestartNumberingCB->set_active(true);
+ }
+ m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
+
+ m_xSetPageNumberNF->set_value(nSetPage);
+ if (nSetPage > 1)
+ m_xSetPageNumberCB->set_active(true);
+ m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
+
+ FillList();
+ m_xPagePropertiesPB->connect_clicked(LINK(this, SwTitlePageDlg, EditHdl));
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, ValueChangeHdl, weld::SpinButton&, void)
+{
+ if (m_xPageCountNF->get_value() == 1 || m_xPageCountNF->get_value() == 2)
+ FillList();
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, RestartNumberingHdl, weld::Toggleable&, void)
+{
+ m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, SetPageNumberHdl, weld::Toggleable&, void)
+{
+ m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, StartPageHdl, weld::Toggleable&, void)
+{
+ m_xPageStartNF->set_sensitive(m_xPageStartRB->get_active());
+}
+
+SwTitlePageDlg::~SwTitlePageDlg()
+{
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, EditHdl, weld::Button&, void)
+{
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return;
+ SwWrtShell& rWrtShell = pView->GetWrtShell();
+ SwView& rView = rWrtShell.GetView();
+ rView.GetDocShell()->FormatPage(getDialog(), m_xPagePropertiesLB->get_active_text(), "page", rWrtShell);
+ rView.InvalidateRulerPos();
+}
+
+IMPL_LINK_NOARG(SwTitlePageDlg, OKHdl, weld::Button&, void)
+{
+ SwView* pView = GetActiveView();
+ if (!pView)
+ return;
+ SwWrtShell& rWrtShell = pView->GetWrtShell();
+ lcl_PushCursor(rWrtShell);
+
+ rWrtShell.StartUndo();
+
+ SwFormatPageDesc aTitleDesc(mpTitleDesc);
+
+ if (m_xSetPageNumberCB->get_active())
+ aTitleDesc.SetNumOffset(m_xSetPageNumberNF->get_value());
+ else if (mpPageFormatDesc)
+ aTitleDesc.SetNumOffset(mpPageFormatDesc->GetNumOffset());
+
+ sal_uInt16 nNumTitlePages = m_xPageCountNF->get_value();
+ if (!m_xUseExistingPagesRB->get_active())
+ {
+ // Assuming that a failure to GotoPage means the end of the document,
+ // insert new pages after the last page.
+ if (!lcl_GotoPage(rWrtShell, GetInsertPosition()))
+ {
+ rWrtShell.EndPg();
+ // Add one more page as a content page to follow the new title pages.
+ rWrtShell.InsertPageBreak();
+ }
+ for (sal_uInt16 nI = 0; nI < nNumTitlePages; ++nI)
+ rWrtShell.InsertPageBreak();
+ // In order to be able to access these new pages, the layout needs to be recalculated first.
+ rWrtShell.CalcLayout();
+ }
+
+ if (lcl_GotoPage(rWrtShell, GetInsertPosition()))
+ {
+ rWrtShell.SetAttrItem(aTitleDesc);
+ for (sal_uInt16 nI = 1; nI < nNumTitlePages; ++nI)
+ {
+ if (rWrtShell.SttNxtPg())
+ lcl_ChangePage(rWrtShell, SAL_MAX_UINT16, mpIndexDesc);
+ }
+ }
+
+ if ((m_xRestartNumberingCB->get_active() || nNumTitlePages > 1)
+ && lcl_GotoPage(rWrtShell, GetInsertPosition(), nNumTitlePages))
+ {
+ sal_uInt16 nPgNo
+ = m_xRestartNumberingCB->get_active() ? m_xRestartNumberingNF->get_value() : 0;
+ const SwPageDesc* pNewDesc = nNumTitlePages > 1 ? mpNormalDesc : nullptr;
+ lcl_ChangePage(rWrtShell, nPgNo, pNewDesc);
+ }
+
+ rWrtShell.EndUndo();
+ lcl_PopCursor(rWrtShell);
+ if (!m_xUseExistingPagesRB->get_active())
+ lcl_GotoPage(rWrtShell, GetInsertPosition());
+ m_xDialog->response(RET_OK);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */