summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarper Akdemir <sarper.akdemir.extern@allotropia.de>2023-11-09 20:18:44 +0300
committerThorsten Behrens <thorsten.behrens@allotropia.de>2024-02-22 13:51:47 +0100
commit71a7fdfae4d350c950fec5a8b59ad45168945a28 (patch)
tree0386d39292895f5a0eab07e560e4cfe8b28d4c86
parent75275cf453975f9b391e024b0431869496db0189 (diff)
tdf#33603: sd: add notes panel for normal viewcib_contract49-7.6.5.2.M1
Change-Id: Ibc6e8a3f126c443453c5ecab52ba988a4f4f56e6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159288 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
-rw-r--r--officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu8
-rw-r--r--sd/Library_sd.mk1
-rw-r--r--sd/UIConfig_simpress.mk2
-rw-r--r--sd/inc/strings.hrc1
-rw-r--r--sd/source/ui/app/sddll.cxx2
-rw-r--r--sd/source/ui/dlg/NotesChildWindow.cxx632
-rw-r--r--sd/source/ui/inc/NotesChildWindow.hxx108
-rw-r--r--sd/source/ui/view/ViewShellBase.cxx24
-rw-r--r--sd/source/ui/view/drvwshrg.cxx3
-rw-r--r--sd/uiconfig/simpress/menubar/menubar.xml1
-rw-r--r--sd/uiconfig/simpress/ui/noteschildwindow.ui41
-rw-r--r--sd/uiconfig/simpress/ui/notespanelcontextmenu.ui9
12 files changed, 832 insertions, 0 deletions
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
index cca1b2ec38ae..618dbfa0d837 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
@@ -24,6 +24,14 @@
<value xml:lang="en-US">S~lide</value>
</prop>
</node>
+ <node oor:name=".uno:NotesChildWindow" oor:op="replace">
+ <prop oor:name="Label" oor:type="xs:string">
+ <value xml:lang="en-US">Notes Panel</value>
+ </prop>
+ <prop oor:name="Properties" oor:type="xs:int">
+ <value>1</value>
+ </prop>
+ </node>
<node oor:name=".uno:PageMenu" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">~Page</value>
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index 926dd86ee755..d7483cb77c25 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -232,6 +232,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\
sd/source/ui/dlg/AnimationChildWindow \
sd/source/ui/dlg/LayerTabBar \
sd/source/ui/dlg/NavigatorChildWindow \
+ sd/source/ui/dlg/NotesChildWindow \
sd/source/ui/dlg/PaneChildWindows \
sd/source/ui/dlg/PaneShells \
sd/source/ui/dlg/SpellDialogChildWindow \
diff --git a/sd/UIConfig_simpress.mk b/sd/UIConfig_simpress.mk
index ab6b2875e7bc..f0395c7646f2 100644
--- a/sd/UIConfig_simpress.mk
+++ b/sd/UIConfig_simpress.mk
@@ -147,6 +147,8 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/simpress,\
sd/uiconfig/simpress/ui/notebookbar_groupedbar_full \
sd/uiconfig/simpress/ui/notebookbar_groupedbar_compact \
sd/uiconfig/simpress/ui/notebookbar_online \
+ sd/uiconfig/simpress/ui/noteschildwindow \
+ sd/uiconfig/simpress/ui/notespanelcontextmenu \
sd/uiconfig/simpress/ui/optimpressgeneralpage \
sd/uiconfig/simpress/ui/pagesfieldbox \
sd/uiconfig/simpress/ui/photoalbum \
diff --git a/sd/inc/strings.hrc b/sd/inc/strings.hrc
index 3e1ddd1542e7..adf9f6538129 100644
--- a/sd/inc/strings.hrc
+++ b/sd/inc/strings.hrc
@@ -315,6 +315,7 @@
#define STR_PRESOBJ_OUTLINE NC_("STR_PRESOBJ_OUTLINE", "Click to add Text" )
#define STR_PRESOBJ_TEXT NC_("STR_PRESOBJ_TEXT", "Click to add Text" )
#define STR_PRESOBJ_NOTESTEXT NC_("STR_PRESOBJ_NOTESTEXT", "Click to add Notes" )
+#define STR_PRESOBJ_NOTESTEXT_MISSING NC_("STR_PRESOBJ_NOTESTEXT_MISSING", "Notes placeholder object is missing for the current slide." )
#define STR_PRESOBJ_TITLE_MOBILE NC_("STR_PRESOBJ_TITLE_MOBILE", "Double-tap to add Title" )
#define STR_PRESOBJ_OUTLINE_MOBILE NC_("STR_PRESOBJ_OUTLINE_MOBILE", "Double-tap to add Text" )
#define STR_PRESOBJ_TEXT_MOBILE NC_("STR_PRESOBJ_TEXT_MOBILE", "Double-tap to add Text" )
diff --git a/sd/source/ui/app/sddll.cxx b/sd/source/ui/app/sddll.cxx
index b4734310a39b..331c32afe5a7 100644
--- a/sd/source/ui/app/sddll.cxx
+++ b/sd/source/ui/app/sddll.cxx
@@ -48,6 +48,7 @@
#include <OutlineViewShell.hxx>
#include <OutlineViewShellBase.hxx>
#include <PaneChildWindows.hxx>
+#include <NotesChildWindow.hxx>
#include <SpellDialogChildWindow.hxx>
#include <SlideSorterViewShell.hxx>
#include <SlideSorterViewShellBase.hxx>
@@ -178,6 +179,7 @@ void SdDLL::RegisterControllers(SdModule* pMod)
::sd::LeftPaneImpressChildWindow::RegisterChildWindow(false, pMod);
::sd::LeftPaneDrawChildWindow::RegisterChildWindow(false, pMod);
::sfx2::sidebar::SidebarChildWindow::RegisterChildWindow(false, pMod);
+ ::sd::NotesChildWindow::RegisterChildWindow(false, pMod);
DevelopmentToolChildWindow::RegisterChildWindow(false, pMod);
::sd::SdNavigatorWrapper::RegisterChildWindow(false, pMod, SfxChildWindowFlags::NEVERHIDE);
diff --git a/sd/source/ui/dlg/NotesChildWindow.cxx b/sd/source/ui/dlg/NotesChildWindow.cxx
new file mode 100644
index 000000000000..0ab856da55ef
--- /dev/null
+++ b/sd/source/ui/dlg/NotesChildWindow.cxx
@@ -0,0 +1,632 @@
+/* -*- 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 <DrawDocShell.hxx>
+#include <DrawViewShell.hxx>
+#include <EventMultiplexer.hxx>
+#include <NotesChildWindow.hxx>
+#include <Outliner.hxx>
+#include <ViewShellBase.hxx>
+#include <app.hrc>
+#include <config_wasm_strip.h>
+#include <drawdoc.hxx>
+#include <drawview.hxx>
+#include <sdpage.hxx>
+#include <sdresid.hxx>
+
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editstat.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/commandinfoprovider.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <strings.hrc>
+
+namespace sd
+{
+SFX_IMPL_DOCKINGWINDOW_WITHID(NotesChildWindow, SID_NOTES_WINDOW);
+
+NotesChildWindow::NotesChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId,
+ SfxBindings* pBindings, SfxChildWinInfo* pInfo)
+ : SfxChildWindow(pParentWindow, nId)
+{
+ VclPtr<NotesChildDockingWindow> pWin
+ = VclPtr<NotesChildDockingWindow>::Create(pBindings, this, pParentWindow);
+ SetWindow(pWin);
+ SetAlignment(SfxChildAlignment::BOTTOM);
+ pWin->setDeferredProperties();
+ pWin->SetSizePixel({ 200, 200 });
+ pWin->set_border_width(3);
+ pWin->set_margin_top(11);
+ pWin->Initialize(pInfo);
+}
+
+NotesChildDockingWindow::NotesChildDockingWindow(SfxBindings* _pBindings,
+ SfxChildWindow* pChildWindow, Window* pParent)
+ : SfxDockingWindow(_pBindings, pChildWindow, pParent, "NotesChildEditWindow",
+ "modules/simpress/ui/noteschildwindow.ui")
+ , mpViewShellBase(ViewShellBase::GetViewShellBase(_pBindings->GetDispatcher()->GetFrame()))
+ , m_xEditWindow(
+ new NotesEditWindow(*this, m_xBuilder->weld_scrolled_window("scrolledwin", true)))
+{
+ mpOutliner = std::make_unique<Outliner>(&mpViewShellBase->GetDocShell()->GetPool(),
+ OutlinerMode::TextObject);
+
+ mpOutlinerView = std::make_unique<OutlinerView>(mpOutliner.get(), nullptr);
+ mpOutliner->InsertView(mpOutlinerView.get());
+
+ m_xEditWindowWeld
+ = std::make_unique<weld::CustomWeld>(*m_xBuilder, "noteschildeditview", *m_xEditWindow);
+}
+
+DrawViewShell* NotesChildDockingWindow::GetDrawViewShell()
+{
+ auto pDocShell = GetViewShellBase()->GetDocShell();
+ if (!pDocShell)
+ return nullptr;
+
+ return dynamic_cast<DrawViewShell*>(pDocShell->GetViewShell());
+}
+
+NotesChildDockingWindow::~NotesChildDockingWindow() { disposeOnce(); }
+
+void NotesChildDockingWindow::dispose()
+{
+ m_xEditWindow.reset();
+ m_xEditWindowWeld.reset();
+ SfxDockingWindow::dispose();
+}
+
+NotesEditWindow::NotesEditWindow(NotesChildDockingWindow& rParentWindow,
+ std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)
+ : mrParentWindow(rParentWindow)
+ , m_xScrolledWindow(std::move(pScrolledWindow))
+ , aModifyIdle("NotesEditWindow ModifyIdle")
+{
+ aModifyIdle.SetInvokeHandler(LINK(this, NotesEditWindow, ModifyTimerHdl));
+ aModifyIdle.SetPriority(TaskPriority::LOWEST);
+
+ SetAcceptsTab(true);
+ m_xScrolledWindow->connect_vadjustment_changed(LINK(this, NotesEditWindow, ScrollHdl));
+}
+
+NotesEditWindow::~NotesEditWindow()
+{
+ aModifyIdle.Stop();
+ m_xScrolledWindow.reset();
+ if (!mrParentWindow.GetViewShellBase())
+ return;
+
+ mrParentWindow.GetViewShellBase()->GetEventMultiplexer()->RemoveEventListener(
+ LINK(this, NotesEditWindow, EventMultiplexerListener));
+}
+
+IMPL_LINK(NotesEditWindow, EventMultiplexerListener, tools::EventMultiplexerEvent&, rEvent, void)
+{
+ switch (rEvent.meEventId)
+ {
+ case EventMultiplexerEventId::CurrentPageChanged:
+ case EventMultiplexerEventId::MainViewRemoved:
+ case EventMultiplexerEventId::MainViewAdded:
+ provideNoteText();
+ break;
+ default:
+ break;
+ }
+}
+
+void NotesEditWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ Size aSize(pDrawingArea->get_size_request());
+ if (aSize.Width() == -1)
+ aSize.setWidth(500);
+ if (aSize.Height() == -1)
+ aSize.setHeight(100);
+ pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
+
+ SetOutputSizePixel(aSize);
+
+ weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
+
+ EnableRTL(false);
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ Color aBgColor = rStyleSettings.GetWindowColor();
+
+ OutputDevice& rDevice = pDrawingArea->get_ref_device();
+
+ rDevice.SetMapMode(MapMode(MapUnit::MapTwip));
+ rDevice.SetBackground(aBgColor);
+
+ Size aOutputSize(rDevice.PixelToLogic(aSize));
+
+ EditView* pEditView = GetEditView();
+ pEditView->setEditViewCallbacks(this);
+
+ EditEngine* pEditEngine = GetEditEngine();
+ pEditEngine->SetPaperSize(aOutputSize);
+ pEditEngine->SetRefDevice(&rDevice);
+
+ pEditEngine->SetControlWord(pEditEngine->GetControlWord() | EEControlBits::MARKFIELDS);
+ pEditView->SetOutputArea(::tools::Rectangle(Point(0, 0), aOutputSize));
+
+ pEditView->SetBackgroundColor(aBgColor);
+
+ pDrawingArea->set_cursor(PointerStyle::Text);
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ InitAccessible();
+#endif
+
+ mrParentWindow.GetViewShellBase()->GetEventMultiplexer()->AddEventListener(
+ LINK(this, NotesEditWindow, EventMultiplexerListener));
+
+ // For setGlobalScale to work correctly EEControlBits::STRETCHING must be set.
+ mrParentWindow.GetOutliner()->SetControlWord(mrParentWindow.GetOutliner()->GetControlWord()
+ | EEControlBits::STRETCHING);
+ mrParentWindow.GetOutliner()->setGlobalScale(30.0, 30.0);
+
+ provideNoteText();
+
+ GetEditEngine()->SetStatusEventHdl(LINK(this, NotesEditWindow, EditStatusHdl));
+}
+
+void NotesEditWindow::doScroll()
+{
+ if (m_xEditView)
+ {
+ auto currentDocPos = m_xEditView->GetVisArea().Top();
+ auto nDiff = currentDocPos - m_xScrolledWindow->vadjustment_get_value();
+ // we expect SetScrollBarRange callback to be triggered by Scroll
+ // to set where we ended up
+ m_xEditView->Scroll(0, nDiff);
+ }
+}
+
+void NotesEditWindow::setScrollBarRange()
+{
+ EditEngine* pEditEngine = GetEditEngine();
+ if (!pEditEngine)
+ return;
+ if (!m_xScrolledWindow)
+ return;
+ EditView* pEditView = GetEditView();
+ if (!pEditView)
+ return;
+
+ int nVUpper = pEditEngine->GetTextHeight();
+ int nVCurrentDocPos = pEditView->GetVisArea().Top();
+ const Size aOut(pEditView->GetOutputArea().GetSize());
+ int nVStepIncrement = aOut.Height() * 2 / 10;
+ int nVPageIncrement = aOut.Height() * 8 / 10;
+ int nVPageSize = aOut.Height();
+
+ /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
+ effectively...
+
+ lower = gtk_adjustment_get_lower
+ upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
+
+ and requires that upper > lower or the deceleration animation never ends
+ */
+ nVPageSize = std::min(nVPageSize, nVUpper);
+
+ m_xScrolledWindow->vadjustment_configure(nVCurrentDocPos, 0, nVUpper, nVStepIncrement,
+ nVPageIncrement, nVPageSize);
+}
+
+void NotesEditWindow::showContextMenu(const Point& rPos)
+{
+ ::tools::Rectangle aRect(rPos, Size(1, 1));
+ weld::Widget* pPopupParent = GetDrawingArea();
+ std::unique_ptr<weld::Builder> xBuilder(
+ Application::CreateBuilder(pPopupParent, "modules/simpress/ui/notespanelcontextmenu.ui"));
+ std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu"));
+
+ auto xFrame = mrParentWindow.GetDrawViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
+ OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
+
+ SfxItemSet aSet(mrParentWindow.GetOutlinerView()->GetAttribs());
+ int nInsertPos = 0;
+ xMenu->insert(nInsertPos++, ".uno:Bold",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Bold", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Bold", xFrame),
+ TRISTATE_TRUE);
+
+ if (aSet.GetItemState(EE_CHAR_WEIGHT) == SfxItemState::SET)
+ {
+ if (aSet.Get(EE_CHAR_WEIGHT).GetWeight() == WEIGHT_BOLD)
+ xMenu->set_active(".uno:Bold", true);
+ }
+
+ xMenu->insert(nInsertPos++, ".uno:Italic",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Italic", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Italic", xFrame),
+ TRISTATE_TRUE);
+
+ if (aSet.GetItemState(EE_CHAR_ITALIC) == SfxItemState::SET)
+ {
+ if (aSet.Get(EE_CHAR_ITALIC).GetPosture() != ITALIC_NONE)
+ xMenu->set_active(".uno:Italic", true);
+ }
+
+ xMenu->insert(
+ nInsertPos++, ".uno:Underline",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Underline", aModuleName)),
+ nullptr, nullptr, vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Underline", xFrame),
+ TRISTATE_TRUE);
+
+ if (aSet.GetItemState(EE_CHAR_UNDERLINE) == SfxItemState::SET)
+ {
+ if (aSet.Get(EE_CHAR_UNDERLINE).GetLineStyle() != LINESTYLE_NONE)
+ xMenu->set_active(".uno:Underline", true);
+ }
+
+ xMenu->insert(
+ nInsertPos++, ".uno:Strikeout",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Strikeout", aModuleName)),
+ nullptr, nullptr, vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Strikeout", xFrame),
+ TRISTATE_TRUE);
+
+ if (aSet.GetItemState(EE_CHAR_STRIKEOUT) == SfxItemState::SET)
+ {
+ if (aSet.Get(EE_CHAR_STRIKEOUT).GetStrikeout() != STRIKEOUT_NONE)
+ xMenu->set_active(".uno:Strikeout", true);
+ }
+
+ xMenu->insert_separator(nInsertPos++, "separator2");
+
+ xMenu->insert(nInsertPos++, ".uno:Copy",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Copy", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Copy", xFrame),
+ TRISTATE_INDET);
+
+ xMenu->insert(nInsertPos++, ".uno:Paste",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:Paste", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:Paste", xFrame),
+ TRISTATE_INDET);
+
+ bool bCanPaste = false;
+ {
+ TransferableDataHelper aDataHelper(
+ TransferableDataHelper::CreateFromClipboard(GetClipboard()));
+ bCanPaste = aDataHelper.GetFormatCount() != 0;
+ }
+
+ xMenu->insert_separator(nInsertPos++, "separator3");
+
+ xMenu->insert(
+ nInsertPos++, ".uno:DefaultBullet",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:DefaultBullet", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:DefaultBullet", xFrame),
+ TRISTATE_TRUE);
+
+ ESelection aSel(GetEditView()->GetSelection());
+ aSel.Adjust();
+ bool bBulletsEnabled = true;
+ for (sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++)
+ {
+ if (mrParentWindow.GetOutliner()->GetDepth(nPara) == -1)
+ {
+ bBulletsEnabled = false;
+ break;
+ }
+ }
+
+ if (bBulletsEnabled)
+ xMenu->set_active(".uno:DefaultBullet", true);
+
+ xMenu->insert(
+ nInsertPos++, ".uno:OutlineLeft",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:OutlineLeft", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:OutlineLeft", xFrame),
+ TRISTATE_INDET);
+
+ xMenu->insert(
+ nInsertPos++, ".uno:OutlineRight",
+ vcl::CommandInfoProvider::GetMenuLabelForCommand(
+ vcl::CommandInfoProvider::GetCommandProperties(".uno:OutlineRight", aModuleName)),
+ nullptr, nullptr,
+ vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:OutlineRight", xFrame),
+ TRISTATE_INDET);
+
+ xMenu->set_sensitive(".uno:Copy", mrParentWindow.GetOutlinerView()->HasSelection());
+ xMenu->set_sensitive(".uno:Paste", bCanPaste);
+
+ auto sId = xMenu->popup_at_rect(pPopupParent, aRect);
+
+ if (sId == ".uno:Copy")
+ {
+ mrParentWindow.GetOutlinerView()->Copy();
+ }
+ else if (sId == ".uno:Paste")
+ {
+ mrParentWindow.GetOutlinerView()->PasteSpecial();
+ }
+ else if (sId == ".uno:DefaultBullet")
+ {
+ mrParentWindow.GetOutlinerView()->ToggleBullets();
+ }
+ else if (sId == ".uno:OutlineLeft" || sId == ".uno:OutlineRight")
+ {
+ bool isOutlineLeft = sId == ".uno:OutlineLeft";
+ for (sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++)
+ {
+ auto nCurrentDepth = mrParentWindow.GetOutliner()->GetDepth(nPara);
+ if (nCurrentDepth == -1)
+ continue;
+
+ mrParentWindow.GetOutlinerView()->SetDepth(nPara, isOutlineLeft ? --nCurrentDepth
+ : ++nCurrentDepth);
+ }
+ }
+ else if (!sId.isEmpty())
+ {
+ SfxItemSet aEditAttr(mrParentWindow.GetOutlinerView()->GetAttribs());
+ SfxItemSet aNewAttr(mrParentWindow.GetOutliner()->GetEmptyItemSet());
+
+ if (sId == ".uno:Bold")
+ {
+ FontWeight eFW = aEditAttr.Get(EE_CHAR_WEIGHT).GetWeight();
+ aNewAttr.Put(
+ SvxWeightItem(eFW == WEIGHT_NORMAL ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT));
+ }
+ else if (sId == ".uno:Italic")
+ {
+ FontItalic eFI = aEditAttr.Get(EE_CHAR_ITALIC).GetPosture();
+ aNewAttr.Put(
+ SvxPostureItem(eFI == ITALIC_NORMAL ? ITALIC_NONE : ITALIC_NORMAL, EE_CHAR_ITALIC));
+ }
+ else if (sId == ".uno:Underline")
+ {
+ FontLineStyle eFU = aEditAttr.Get(EE_CHAR_UNDERLINE).GetLineStyle();
+ aNewAttr.Put(SvxUnderlineItem(
+ eFU == LINESTYLE_SINGLE ? LINESTYLE_NONE : LINESTYLE_SINGLE, EE_CHAR_UNDERLINE));
+ }
+ else if (sId == ".uno:Strikeout")
+ {
+ FontStrikeout eFSO = aEditAttr.Get(EE_CHAR_STRIKEOUT).GetStrikeout();
+ aNewAttr.Put(SvxCrossedOutItem(
+ eFSO == STRIKEOUT_SINGLE ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, EE_CHAR_STRIKEOUT));
+ }
+
+ mrParentWindow.GetOutlinerView()->SetAttribs(aNewAttr);
+ }
+}
+
+void NotesEditWindow::EditViewScrollStateChange() { setScrollBarRange(); }
+
+EditView* NotesEditWindow::GetEditView() const
+{
+ if (!mrParentWindow.GetOutlinerView())
+ return nullptr;
+ return &mrParentWindow.GetOutlinerView()->GetEditView();
+}
+
+EditEngine* NotesEditWindow::GetEditEngine() const
+{
+ if (!mrParentWindow.GetOutlinerView())
+ return nullptr;
+ return mrParentWindow.GetOutlinerView()->GetEditView().GetEditEngine();
+}
+
+void NotesEditWindow::GetFocus()
+{
+ if (auto pDrawViewShell = mrParentWindow.GetDrawViewShell())
+ {
+ if (auto pDrawView = pDrawViewShell->GetDrawView())
+ {
+ pDrawView->EndTextEditCurrentView();
+ pDrawView->UnmarkAll();
+ }
+ }
+
+ if (mpTextObj && mpTextObj->IsEmptyPresObj())
+ {
+ // clear the "Click to add Notes" text on enter of the window.
+ mrParentWindow.GetOutliner()->SetToEmptyText();
+ }
+ WeldEditView::GetFocus();
+}
+
+bool NotesEditWindow::CanFocus() const
+{
+ auto pDocShell = mrParentWindow.GetViewShellBase()->GetDocShell();
+ if (pDocShell && pDocShell->IsReadOnly())
+ return false;
+
+ return mpTextObj;
+}
+
+void NotesEditWindow::LoseFocus()
+{
+ aModifyIdle.Stop();
+ if (mpTextObj)
+ {
+ if (GetText().getLength() == 0)
+ {
+ // if the notes are empty restore the placeholder text and state.
+ SdPage* pPage = dynamic_cast<SdPage*>(mpTextObj->getSdrPageFromSdrObject());
+ if (pPage)
+ pPage->RestoreDefaultText(mpTextObj);
+ }
+ else
+ setNotesToDoc();
+ }
+
+ WeldEditView::LoseFocus();
+}
+
+bool NotesEditWindow::Command(const CommandEvent& rCEvt)
+{
+ if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
+ {
+ showContextMenu(rCEvt.GetMousePosPixel());
+ return true;
+ }
+
+ return WeldEditView::Command(rCEvt);
+}
+
+void NotesEditWindow::provideNoteText()
+{
+ removeListener();
+ mpTextObj = nullptr;
+ SetText(SdResId(STR_PRESOBJ_NOTESTEXT_MISSING));
+
+ const auto pDrawViewShell = mrParentWindow.GetDrawViewShell();
+ if (!pDrawViewShell)
+ return;
+
+ SdPage* pCurrentPage = pDrawViewShell->getCurrentPage();
+ if (!pCurrentPage)
+ return;
+
+ SdDrawDocument* pDoc = pDrawViewShell->GetDoc();
+ if (!pDoc)
+ return;
+
+ SdPage* pNotesPage = pDoc->GetSdPage((pCurrentPage->GetPageNum() - 1) >> 1, PageKind::Notes);
+ if (!pNotesPage)
+ return;
+
+ SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
+ if (!pNotesObj)
+ return;
+
+ mpTextObj = dynamic_cast<SdrTextObj*>(pNotesObj);
+ addListener();
+ getNotesFromDoc();
+}
+
+void NotesEditWindow::removeListener()
+{
+ if (mpTextObj)
+ mpTextObj->RemoveListener(*this);
+}
+void NotesEditWindow::addListener()
+{
+ if (mpTextObj)
+ mpTextObj->AddListener(*this);
+}
+
+void NotesEditWindow::setListenerIgnored(bool bIgnore) { mbIgnoreNotifications = bIgnore; }
+bool NotesEditWindow::isListenerIgnored() { return mbIgnoreNotifications; }
+
+void NotesEditWindow::getNotesFromDoc()
+{
+ if (!mpTextObj)
+ return;
+
+ // Ignore notifications that will rebound from updating the text
+ SetModifyHdl(Link<LinkParamNone*, void>());
+ setListenerIgnored(true);
+
+ if (OutlinerParaObject* pPara = mpTextObj->GetOutlinerParaObject())
+ mrParentWindow.GetOutliner()->SetText(*pPara);
+
+ setListenerIgnored(false);
+ SetModifyHdl(LINK(this, NotesEditWindow, EditModifiedHdl));
+}
+
+void NotesEditWindow::setNotesToDoc()
+{
+ if (!mpTextObj)
+ return;
+
+ setListenerIgnored(true);
+
+ std::optional<OutlinerParaObject> pNewText = mrParentWindow.GetOutliner()->CreateParaObject();
+ mpTextObj->SetOutlinerParaObject(std::move(pNewText));
+ if (mpTextObj->IsEmptyPresObj())
+ mpTextObj->SetEmptyPresObj(false);
+
+ setListenerIgnored(false);
+}
+
+void NotesEditWindow::Notify(SfxBroadcaster&, const SfxHint& rHint)
+{
+ if (isListenerIgnored())
+ return;
+
+ if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
+ {
+ const SdrHint& rSdrHint = reinterpret_cast<const SdrHint&>(rHint);
+ switch (rSdrHint.GetKind())
+ {
+ case SdrHintKind::ObjectRemoved:
+ case SdrHintKind::ModelCleared:
+ provideNoteText();
+ break;
+ case SdrHintKind::ObjectChange:
+ case SdrHintKind::EndEdit:
+ getNotesFromDoc();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+IMPL_LINK_NOARG(NotesEditWindow, EditStatusHdl, EditStatus&, void) { Resize(); }
+
+IMPL_LINK_NOARG(NotesEditWindow, EditModifiedHdl, LinkParamNone*, void)
+{
+ // EditEngine calls ModifyHdl many times in succession for some edits.
+ // (e.g. when deleting multiple lines)
+ // Debounce the rapid ModifyHdl calls using a timer.
+ aModifyIdle.Start();
+ return;
+}
+
+IMPL_LINK_NOARG(NotesEditWindow, ModifyTimerHdl, Timer*, void)
+{
+ setNotesToDoc();
+ aModifyIdle.Stop();
+}
+
+IMPL_LINK(NotesEditWindow, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
+{
+ if (EditView* pEditView = GetEditView())
+ {
+ pEditView->SetVisArea(::tools::Rectangle(Point(0, rScrolledWindow.vadjustment_get_value()),
+ pEditView->GetVisArea().GetSize()));
+ pEditView->Invalidate();
+ }
+ doScroll();
+}
+
+} // end of namespace ::sd
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sd/source/ui/inc/NotesChildWindow.hxx b/sd/source/ui/inc/NotesChildWindow.hxx
new file mode 100644
index 000000000000..5242595bcb24
--- /dev/null
+++ b/sd/source/ui/inc/NotesChildWindow.hxx
@@ -0,0 +1,108 @@
+/* -*- 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 <svx/weldeditview.hxx>
+#include <sfx2/dockwin.hxx>
+
+class Outliner;
+class OutlinerView;
+class SdrTextObj;
+
+namespace sd::tools
+{
+class EventMultiplexerEvent;
+}
+
+namespace sd
+{
+class ViewShellBase;
+class DrawViewShell;
+class NotesChildWindow;
+class NotesEditWindow;
+class NotesChildDockingWindow;
+
+class NotesEditWindow : public WeldEditView, public SfxListener
+{
+ NotesChildDockingWindow& mrParentWindow;
+ std::unique_ptr<weld::ScrolledWindow> m_xScrolledWindow;
+ Idle aModifyIdle;
+
+ SdrTextObj* mpTextObj = nullptr;
+ bool mbIgnoreNotifications = false;
+
+ void doScroll();
+ void setScrollBarRange();
+ void showContextMenu(const Point& rPos);
+
+ DECL_LINK(ScrollHdl, weld::ScrolledWindow&, void);
+ DECL_LINK(EditStatusHdl, EditStatus&, void);
+ DECL_LINK(EditModifiedHdl, LinkParamNone*, void);
+ DECL_LINK(ModifyTimerHdl, Timer*, void);
+ DECL_LINK(EventMultiplexerListener, tools::EventMultiplexerEvent&, void);
+
+ void removeListener();
+ void addListener();
+
+ void setListenerIgnored(bool bIgnore);
+ bool isListenerIgnored();
+
+ void getNotesFromDoc();
+ void setNotesToDoc();
+
+public:
+ NotesEditWindow(NotesChildDockingWindow& rParentWindow,
+ std::unique_ptr<weld::ScrolledWindow> pScrolledWindow);
+ virtual ~NotesEditWindow() override;
+
+ void provideNoteText();
+ bool HasNotesPlaceholder() { return mpTextObj; }
+
+ virtual void EditViewScrollStateChange() override;
+ virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+ virtual EditView* GetEditView() const override;
+ virtual EditEngine* GetEditEngine() const override;
+ virtual void GetFocus() override;
+ virtual bool CanFocus() const override;
+ virtual void LoseFocus() override;
+ virtual bool Command(const CommandEvent& rCEvt) override;
+ virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+};
+
+class NotesChildDockingWindow final : public SfxDockingWindow
+{
+ ViewShellBase* mpViewShellBase;
+ std::unique_ptr<NotesEditWindow> m_xEditWindow;
+ std::unique_ptr<weld::CustomWeld> m_xEditWindowWeld;
+
+ std::unique_ptr<OutlinerView> mpOutlinerView;
+ std::unique_ptr<Outliner> mpOutliner;
+
+public:
+ NotesChildDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow, Window* pParent);
+ virtual ~NotesChildDockingWindow() override;
+ void dispose() override;
+
+ OutlinerView* GetOutlinerView() { return mpOutlinerView.get(); }
+ ::Outliner* GetOutliner() { return mpOutliner.get(); }
+ ViewShellBase* GetViewShellBase() { return mpViewShellBase; }
+ DrawViewShell* GetDrawViewShell();
+};
+
+class NotesChildWindow final : public SfxChildWindow
+{
+public:
+ SFX_DECL_CHILDWINDOW_WITHID(NotesChildWindow);
+ NotesChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings,
+ SfxChildWinInfo* pInfo);
+};
+
+} // end of namespace ::sd
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx
index 9099988969d8..671a56f99389 100644
--- a/sd/source/ui/view/ViewShellBase.cxx
+++ b/sd/source/ui/view/ViewShellBase.cxx
@@ -628,6 +628,15 @@ void ViewShellBase::Execute (SfxRequest& rRequest)
framework::FrameworkHelper::msSlideSorterURL);
break;
+ case SID_NOTES_WINDOW:
+ {
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ SfxViewFrame& rViewFrame = pViewShell->GetViewFrame();
+ auto nID = rRequest.GetSlot();
+ rViewFrame.ToggleChildWindow(nID);
+ break;
+ }
+
case SID_TOGGLE_TABBAR_VISIBILITY:
{
SdOptions* pOptions = SD_MOD()->GetSdOptions(GetDocument()->GetDocumentType());
@@ -1277,6 +1286,21 @@ void ViewShellBase::Implementation::GetSlotState (SfxItemSet& rSet)
bState = xConfiguration->hasResource(xResourceId);
break;
+ case SID_NOTES_WINDOW:
+ {
+ bState = false;
+ auto* pViewShell = SfxViewShell::Current();
+ if (pViewShell)
+ {
+ auto& rViewFrame = pViewShell->GetViewFrame();
+ if (rViewFrame.KnowsChildWindow(nItemId))
+ {
+ bState = rViewFrame.HasChildWindow(nItemId);
+ }
+ }
+ break;
+ }
+
case SID_DRAWINGMODE:
case SID_NORMAL_MULTI_PANE_GUI:
case SID_SLIDE_MASTER_MODE:
diff --git a/sd/source/ui/view/drvwshrg.cxx b/sd/source/ui/view/drvwshrg.cxx
index 792d5b833a54..9871db2e2de7 100644
--- a/sd/source/ui/view/drvwshrg.cxx
+++ b/sd/source/ui/view/drvwshrg.cxx
@@ -40,6 +40,7 @@
#include <SpellDialogChildWindow.hxx>
#include <GraphicViewShell.hxx>
#include <AnimationChildWindow.hxx>
+#include <NotesChildWindow.hxx>
using namespace sd;
#define ShellClass_DrawViewShell
@@ -77,6 +78,7 @@ void DrawViewShell::InitInterface_Impl()
GetStaticInterface()->RegisterChildWindow(
sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(::sd::NotesChildWindow::GetChildWindowId());
}
// SdGraphicViewShell
@@ -103,6 +105,7 @@ void GraphicViewShell::InitInterface_Impl()
GetStaticInterface()->RegisterChildWindow(
sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
+ GetStaticInterface()->RegisterChildWindow(::sd::NotesChildWindow::GetChildWindowId());
}
} // end of namespace sd
diff --git a/sd/uiconfig/simpress/menubar/menubar.xml b/sd/uiconfig/simpress/menubar/menubar.xml
index 78489c56383e..ba1cc4868cc0 100644
--- a/sd/uiconfig/simpress/menubar/menubar.xml
+++ b/sd/uiconfig/simpress/menubar/menubar.xml
@@ -125,6 +125,7 @@
<menu:menuitem menu:id=".uno:StatusBarVisible" menu:style="text"/>
<menu:menuitem menu:id=".uno:LeftPaneImpress" menu:style="text"/>
<menu:menuitem menu:id=".uno:ToggleTabBarVisibility" menu:style="text"/>
+ <menu:menuitem menu:id=".uno:NotesChildWindow" menu:style="text"/>
<menu:menuseparator/>
<menu:menuitem menu:id=".uno:ShowRuler"/>
<menu:menu menu:id=".uno:GridMenu">
diff --git a/sd/uiconfig/simpress/ui/noteschildwindow.ui b/sd/uiconfig/simpress/ui/noteschildwindow.ui
new file mode 100644
index 000000000000..de09708702f1
--- /dev/null
+++ b/sd/uiconfig/simpress/ui/noteschildwindow.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="sd">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="NotesChildEditWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwin">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">0</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">always</property>
+ <property name="shadow-type">etched-out</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="noteschildeditview">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/sd/uiconfig/simpress/ui/notespanelcontextmenu.ui b/sd/uiconfig/simpress/ui/notespanelcontextmenu.ui
new file mode 100644
index 000000000000..e6ca46e8a7cf
--- /dev/null
+++ b/sd/uiconfig/simpress/ui/notespanelcontextmenu.ui
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="sd">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkMenu" id="menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+</interface>