summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/Library_sw.mk1
-rw-r--r--sw/Module_sw.mk1
-rw-r--r--sw/UIConfig_swriter.mk1
-rw-r--r--sw/UITest_sw_uibase_docvw.mk16
-rw-r--r--sw/inc/swtypes.hxx1
-rw-r--r--sw/qa/uitest/uibase/docvw/docvw.py36
-rw-r--r--sw/source/core/crsr/viscrs.cxx28
-rw-r--r--sw/source/uibase/docvw/FrameControlsManager.cxx27
-rw-r--r--sw/source/uibase/docvw/contentcontrolaliasbutton.cxx150
-rw-r--r--sw/source/uibase/inc/FrameControlsManager.hxx2
-rw-r--r--sw/source/uibase/inc/contentcontrolaliasbutton.hxx42
-rw-r--r--sw/uiconfig/swriter/ui/contentcontrolaliasbutton.ui28
12 files changed, 331 insertions, 2 deletions
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index d5c59fa4cc4a..218d92cc748b 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -642,6 +642,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
sw/source/uibase/docvw/SidebarTxtControl \
sw/source/uibase/docvw/HeaderFooterWin \
sw/source/uibase/docvw/OutlineContentVisibilityWin \
+ sw/source/uibase/docvw/contentcontrolaliasbutton \
sw/source/uibase/docvw/edtdd \
sw/source/uibase/docvw/edtwin \
sw/source/uibase/docvw/edtwin2 \
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index 754411a7dc42..1f7a90605a11 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -216,6 +216,7 @@ $(eval $(call gb_Module_add_uicheck_targets,sw,\
UITest_sw_ui_fmtui \
UITest_sw_ui_index \
UITest_sw_ui_misc \
+ UITest_sw_uibase_docvw \
UITest_sw_uibase_shells \
UITest_classification \
UITest_writer_macro_tests \
diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index 02ea3ded32d0..185adbbc247a 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -132,6 +132,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
sw/uiconfig/swriter/ui/combobox \
sw/uiconfig/swriter/ui/comboboxfragment \
sw/uiconfig/swriter/ui/conditionpage \
+ sw/uiconfig/swriter/ui/contentcontrolaliasbutton \
sw/uiconfig/swriter/ui/contentcontrolcalendar \
sw/uiconfig/swriter/ui/contentcontroldlg \
sw/uiconfig/swriter/ui/contentcontroldropdown \
diff --git a/sw/UITest_sw_uibase_docvw.mk b/sw/UITest_sw_uibase_docvw.mk
new file mode 100644
index 000000000000..7b07dd8ca8e5
--- /dev/null
+++ b/sw/UITest_sw_uibase_docvw.mk
@@ -0,0 +1,16 @@
+# 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/.
+#
+
+$(eval $(call gb_UITest_UITest,sw_uibase_docvw))
+
+$(eval $(call gb_UITest_add_modules,sw_uibase_docvw,$(SRCDIR)/sw/qa/uitest,\
+ uibase/docvw/ \
+))
+
+$(eval $(call gb_UITest_set_defs,sw_uibase_docvw, \
+ TDOC="$(SRCDIR)/sw/qa/uitest/data" \
+))
diff --git a/sw/inc/swtypes.hxx b/sw/inc/swtypes.hxx
index 55ed0c22240d..96c0fb5008c3 100644
--- a/sw/inc/swtypes.hxx
+++ b/sw/inc/swtypes.hxx
@@ -246,6 +246,7 @@ enum class FrameControlType
Header,
Footer,
FloatingTable,
+ ContentControl,
Outline
};
diff --git a/sw/qa/uitest/uibase/docvw/docvw.py b/sw/qa/uitest/uibase/docvw/docvw.py
new file mode 100644
index 000000000000..e2640df96343
--- /dev/null
+++ b/sw/qa/uitest/uibase/docvw/docvw.py
@@ -0,0 +1,36 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/.
+#
+
+from uitest.framework import UITestCase
+
+
+class Test(UITestCase):
+ def testContentControlAliasButton(self):
+ with self.ui_test.create_doc_in_start_center("writer") as xComponent:
+ # Given a document with a content control that has a non-empty alias:
+ self.xUITest.executeCommand(".uno:InsertContentControl")
+ paragraphs = xComponent.Text.createEnumeration()
+ paragraph = paragraphs.nextElement()
+ portions = paragraph.createEnumeration()
+ portion = portions.nextElement()
+ contentControl = portion.ContentControl
+ contentControl.Alias = "myalias"
+
+ # When entering that content control with the cursor:
+ xCursor = xComponent.getCurrentController().getViewCursor()
+ xCursor.gotoStart(False)
+ xCursor.goRight(1, False)
+
+ # Then make sure that the alias button shows up:
+ xWindow = self.xUITest.getTopFocusWindow()
+ # Without the accompanying fix in place, this test would have failed, SwEditWin didn't
+ # have an alias button child.
+ self.assertIn("ContentControlAliasButton", xWindow.getChildren())
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 3ea1fdfc9536..35ff9c7ae2e1 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -64,6 +64,7 @@
#include <textcontentcontrol.hxx>
#include <dropdowncontentcontrolbutton.hxx>
#include <datecontentcontrolbutton.hxx>
+#include <FrameControlsManager.hxx>
// Here static members are defined. They will get changed on alteration of the
// MapMode. This is done so that on ShowCursor the same size does not have to be
@@ -634,6 +635,7 @@ void SwSelPaintRects::HighlightContentControl()
{
std::vector<basegfx::B2DRange> aContentControlRanges;
std::vector<OString> aLOKRectangles;
+ SwRect aFirstPortionPaintArea;
SwRect aLastPortionPaintArea;
std::shared_ptr<SwContentControl> pContentControl;
@@ -677,12 +679,14 @@ void SwSelPaintRects::HighlightContentControl()
if (!pRects->empty())
{
+ aFirstPortionPaintArea = (*pRects)[0];
aLastPortionPaintArea = (*pRects)[pRects->size() - 1];
}
pContentControl = pCurContentControlAtCursor->GetContentControl().GetContentControl();
}
}
+ auto pWrtShell = dynamic_cast<const SwWrtShell*>(GetShell());
if (!aContentControlRanges.empty())
{
if (comphelper::LibreOfficeKit::isActive())
@@ -734,7 +738,6 @@ void SwSelPaintRects::HighlightContentControl()
if (pContentControl && pContentControl->HasListItems())
{
- auto pWrtShell = dynamic_cast<const SwWrtShell*>(GetShell());
if (pWrtShell)
{
auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin());
@@ -754,7 +757,6 @@ void SwSelPaintRects::HighlightContentControl()
}
if (pContentControl && pContentControl->GetDate())
{
- auto pWrtShell = dynamic_cast<const SwWrtShell*>(GetShell());
if (pWrtShell)
{
auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin());
@@ -772,6 +774,21 @@ void SwSelPaintRects::HighlightContentControl()
m_pContentControlButton->Show();
}
}
+
+ if (pWrtShell)
+ {
+ auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin());
+ SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
+ if (pContentControl && !pContentControl->GetAlias().isEmpty())
+ {
+ Point aTopLeftPixel = rEditWin.LogicToPixel(aFirstPortionPaintArea.TopLeft());
+ rMngr.SetContentControlAliasButton(pContentControl.get(), aTopLeftPixel);
+ }
+ else
+ {
+ rMngr.HideControls(FrameControlType::ContentControl);
+ }
+ }
}
else
{
@@ -788,6 +805,13 @@ void SwSelPaintRects::HighlightContentControl()
{
m_pContentControlButton.disposeAndClear();
}
+
+ if (pWrtShell)
+ {
+ auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin());
+ SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
+ rMngr.HideControls(FrameControlType::ContentControl);
+ }
}
}
diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx
index bb2733aa60a3..93254830a2f1 100644
--- a/sw/source/uibase/docvw/FrameControlsManager.cxx
+++ b/sw/source/uibase/docvw/FrameControlsManager.cxx
@@ -22,6 +22,7 @@
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weldutils.hxx>
+#include <contentcontrolaliasbutton.hxx>
SwFrameControlsManager::SwFrameControlsManager( SwEditWin* pEditWin ) :
m_pEditWin( pEditWin )
@@ -174,6 +175,32 @@ void SwFrameControlsManager::SetUnfloatTableButton( const SwFlyFrame* pFlyFrame,
pControl->ShowAll( bShow );
}
+void SwFrameControlsManager::SetContentControlAliasButton(SwContentControl* pContentControl,
+ Point aTopLeftPixel)
+{
+ SwFrameControlPtr pControl;
+ SwFrameControlPtrMap& rControls = m_aControls[FrameControlType::ContentControl];
+ // We don't really have a key, the SwPaM's mark decides what is the single content control in
+ // this view that can have an alias button.
+ SwFrameControlPtrMap::iterator it = rControls.find(nullptr);
+ if (it != rControls.end())
+ pControl = it->second;
+ else
+ {
+ pControl = std::make_shared<SwFrameControl>(
+ VclPtr<SwContentControlAliasButton>::Create(m_pEditWin, pContentControl).get());
+ const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions();
+ pControl->SetReadonly(pViewOpt->IsReadonly());
+ rControls[nullptr] = pControl;
+ }
+
+ auto pButton = dynamic_cast<SwContentControlAliasButton*>(pControl->GetWindow());
+ assert(pButton);
+ pButton->SetOffset(aTopLeftPixel);
+ pButton->SetContentControl(pContentControl);
+ pControl->ShowAll(true);
+}
+
SwFrameMenuButtonBase::SwFrameMenuButtonBase(SwEditWin* pEditWin, const SwFrame* pFrame,
const OUString& rUIXMLDescription, const OString& rID)
: InterimItemWindow(pEditWin, rUIXMLDescription, rID)
diff --git a/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx b/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx
new file mode 100644
index 000000000000..f1edd71919dc
--- /dev/null
+++ b/sw/source/uibase/docvw/contentcontrolaliasbutton.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <contentcontrolaliasbutton.hxx>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <drawinglayer/attribute/fontattribute.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
+#include <vcl/metric.hxx>
+
+#include <HeaderFooterWin.hxx>
+#include <edtwin.hxx>
+#include <formatcontentcontrol.hxx>
+#include <swabstdlg.hxx>
+#include <view.hxx>
+#include <viewopt.hxx>
+#include <wrtsh.hxx>
+
+#define TEXT_PADDING 3
+#define BOX_DISTANCE 3
+#define BUTTON_WIDTH 12
+
+SwContentControlAliasButton::SwContentControlAliasButton(SwEditWin* pEditWin,
+ SwContentControl* pContentControl)
+ : SwFrameMenuButtonBase(pEditWin, nullptr, "modules/swriter/ui/contentcontrolaliasbutton.ui",
+ "ContentControlAliasButton")
+ , m_xPushButton(m_xBuilder->weld_button("button"))
+ , m_sLabel(pContentControl->GetAlias())
+{
+ m_xPushButton->set_accessible_name(m_sLabel);
+ m_xPushButton->connect_clicked(LINK(this, SwContentControlAliasButton, ClickHdl));
+ m_xVirDev = m_xPushButton->create_virtual_device();
+ SetVirDevFont();
+}
+
+SwContentControlAliasButton::~SwContentControlAliasButton() { disposeOnce(); }
+
+void SwContentControlAliasButton::dispose()
+{
+ m_xPushButton.reset();
+ m_xVirDev.disposeAndClear();
+ SwFrameMenuButtonBase::dispose();
+}
+
+void SwContentControlAliasButton::SetOffset(Point aTopLeftPixel)
+{
+ // Compute the text size and get the box position & size from it.
+ tools::Rectangle aTextRect;
+ m_xVirDev->GetTextBoundRect(aTextRect, m_sLabel);
+ tools::Rectangle aTextPxRect = m_xVirDev->LogicToPixel(aTextRect);
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ Size aBoxSize(aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2,
+ aFontMetric.GetLineHeight() + TEXT_PADDING * 2);
+ Point aBoxPos(aTopLeftPixel.X() + BOX_DISTANCE, aTopLeftPixel.Y() - aBoxSize.Height());
+
+ // Set the position & size of the window.
+ SetPosSizePixel(aBoxPos, aBoxSize);
+ m_xVirDev->SetOutputSizePixel(aBoxSize);
+
+ PaintButton();
+}
+
+IMPL_LINK_NOARG(SwContentControlAliasButton, ClickHdl, weld::Button&, void)
+{
+ if (m_bReadOnly)
+ {
+ return;
+ }
+
+ SwView& rView = GetEditWin()->GetView();
+ SwWrtShell& rWrtSh = rView.GetWrtShell();
+ SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+ ScopedVclPtr<VclAbstractDialog> pDlg(
+ pFact->CreateSwContentControlDlg(GetEditWin()->GetFrameWeld(), rWrtSh));
+ VclAbstractDialog::AsyncContext aContext;
+ aContext.maEndDialogFn = [](sal_Int32) {};
+ pDlg->StartExecuteAsync(aContext);
+}
+
+void SwContentControlAliasButton::PaintButton()
+{
+ if (!m_xVirDev)
+ {
+ return;
+ }
+
+ m_xVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
+ drawinglayer::primitive2d::Primitive2DContainer aSeq;
+ tools::Rectangle aRect(Point(0, 0), m_xVirDev->PixelToLogic(GetSizePixel()));
+
+ // Create button
+ SwFrameButtonPainter::PaintButton(aSeq, aRect, /*bOnTop=*/false);
+
+ // Create the text primitive
+ basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor();
+ basegfx::B2DVector aFontSize;
+ drawinglayer::attribute::FontAttribute aFontAttr
+ = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, m_xVirDev->GetFont(),
+ false, false);
+
+ FontMetric aFontMetric = m_xVirDev->GetFontMetric(m_xVirDev->GetFont());
+ double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING;
+ double nTextOffsetX = std::abs(aRect.GetWidth() - m_xVirDev->GetTextWidth(m_sLabel)) / 2.0;
+ Point aTextPos(nTextOffsetX, nTextOffsetY);
+
+ basegfx::B2DHomMatrix aTextMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aFontSize.getX(), aFontSize.getY(), static_cast<double>(aTextPos.X()),
+ static_cast<double>(aTextPos.Y()));
+
+ aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
+ aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), {},
+ std::move(aFontAttr), css::lang::Locale(), aLineColor)));
+
+ // Create the processor and process the primitives
+ drawinglayer::geometry::ViewInformation2D aViewInfo;
+ std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor
+ = drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*m_xVirDev, aViewInfo);
+
+ pProcessor->process(aSeq);
+
+ m_xPushButton->set_custom_button(m_xVirDev.get());
+}
+
+void SwContentControlAliasButton::ShowAll(bool bShow) { Show(bShow); }
+
+bool SwContentControlAliasButton::Contains(const Point& rDocPt) const
+{
+ tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ return aRect.Contains(rDocPt);
+}
+
+void SwContentControlAliasButton::SetReadonly(bool bReadonly) { m_bReadOnly = bReadonly; }
+
+void SwContentControlAliasButton::SetContentControl(SwContentControl* pContentControl)
+{
+ m_sLabel = pContentControl->GetAlias();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/FrameControlsManager.hxx b/sw/source/uibase/inc/FrameControlsManager.hxx
index f73f226b36d7..945534fcd31c 100644
--- a/sw/source/uibase/inc/FrameControlsManager.hxx
+++ b/sw/source/uibase/inc/FrameControlsManager.hxx
@@ -20,6 +20,7 @@ class SwPageFrame;
class SwEditWin;
class SwContentFrame;
class SwTextNode;
+class SwContentControl;
typedef std::shared_ptr< SwFrameControl > SwFrameControlPtr;
@@ -49,6 +50,7 @@ class SwFrameControlsManager
void SetPageBreakControl( const SwPageFrame* pPageFrame );
void SetUnfloatTableButton( const SwFlyFrame* pFlyFrame, bool bShow, Point aTopRightPixel = Point() );
void SetOutlineContentVisibilityButton(const SwContentFrame* pContentFrame);
+ void SetContentControlAliasButton( SwContentControl* pContentControl, Point aTopLeftPixel );
};
#endif
diff --git a/sw/source/uibase/inc/contentcontrolaliasbutton.hxx b/sw/source/uibase/inc/contentcontrolaliasbutton.hxx
new file mode 100644
index 000000000000..818a4415b937
--- /dev/null
+++ b/sw/source/uibase/inc/contentcontrolaliasbutton.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "FrameControl.hxx"
+
+class SwEditWin;
+class SwContentControl;
+
+/// In case the content control has an alias/title, this widget shows it above the top left corner
+/// of the content control till the cursor is inside the content control.
+class SwContentControlAliasButton final : public SwFrameMenuButtonBase
+{
+ std::unique_ptr<weld::Button> m_xPushButton;
+ OUString m_sLabel;
+ bool m_bReadOnly = false;
+
+public:
+ SwContentControlAliasButton(SwEditWin* pEditWin, SwContentControl* pContentControl);
+ ~SwContentControlAliasButton() override;
+
+ bool Contains(const Point& rDocPt) const override;
+ void SetReadonly(bool bReadonly) override;
+ void ShowAll(bool bShow) override;
+ void dispose() override;
+
+ void SetContentControl(SwContentControl* pContentControl);
+ void SetOffset(Point aTopLeftPixel);
+
+private:
+ DECL_LINK(ClickHdl, weld::Button&, void);
+ void PaintButton();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/uiconfig/swriter/ui/contentcontrolaliasbutton.ui b/sw/uiconfig/swriter/ui/contentcontrolaliasbutton.ui
new file mode 100644
index 000000000000..e61ec634693e
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/contentcontrolaliasbutton.ui
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.1 -->
+<interface domain="sw">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="ContentControlAliasButton">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkButton" id="button">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="relief">none</property>
+ <property name="always-show-image">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>