tdf#33603: sd: rework notes panel

To be able to support various dispatch commands, sidebar, proper
user configuration, and more - reworked the previous notes panel
implementation as a sd::View/sd::ViewShell pair that plays nice
with Impress framework.

To be able to support TextObjectBar(Shell) functionality, without
having TextObjectBar as a SubShell (In the current sd::framework
implementation AFAICS, SubShells are only possible for the
MainViewShell - this doesn't work for notes panel which is never
used as the MainViewShell.).

A workaround is implemented where NotesPanel inherits dispatching
slots from TextObjectBar, and for these inherited slots forwards
the calls to TextObjectBar's implementation.

This workaround could be removed if/when, SubShell support
outside of MainViewShell is implemented.

Known issues/TODO:
- Drag & Drop crashes / doesn't work.

- Some notes placeholder syncing problems on page change, edit mode
  change.

- A rendering issue related to resizing when ArrangeGUIElements
  isn't called on resize.

Change-Id: I588a4854fbedf6556e001fee1693b32410cbc23f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165770
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index 6c6a37f..17d167d 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -253,19 +253,19 @@ public:

    // Now at this outliner, events can be send, attributes can be set,
    // call Cut/Copy/Paste, call Undo/Redo, and so on...
    const SdrOutliner* GetTextEditOutliner() const
    virtual const SdrOutliner* GetTextEditOutliner() const
    {
        return mpTextEditOutliner.get();
    }
    SdrOutliner* GetTextEditOutliner()
    virtual SdrOutliner* GetTextEditOutliner()
    {
        return mpTextEditOutliner.get();
    }
    const OutlinerView* GetTextEditOutlinerView() const
    virtual const OutlinerView* GetTextEditOutlinerView() const
    {
        return mpTextEditOutlinerView;
    }
    OutlinerView* GetTextEditOutlinerView()
    virtual OutlinerView* GetTextEditOutlinerView()
    {
        return mpTextEditOutlinerView;
    }
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index f801a77..cd1dba8 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -517,6 +517,8 @@ $(eval $(call gb_Library_add_exception_objects,sd,\
	sd/source/ui/view/viewshe3 \
	sd/source/ui/view/viewshel \
	sd/source/ui/view/zoomlist \
	sd/source/ui/view/NotesPanelView \
	sd/source/ui/view/NotesPanelViewShell \
))

ifeq ($(ENABLE_SDREMOTE),TRUE)
diff --git a/sd/inc/app.hrc b/sd/inc/app.hrc
index 004b01c..45d20f8 100644
--- a/sd/inc/app.hrc
+++ b/sd/inc/app.hrc
@@ -421,7 +421,7 @@

#define SID_LEFT_PANE_IMPRESS               (SID_SD_START+414)
#define SID_LEFT_PANE_DRAW                  (SID_SD_START+415)
        // FREE
#define SID_BOTTOM_PANE_IMPRESS             (SID_SD_START+416)
#define SID_NOTES_WINDOW                    (SID_SD_START+417)
        // FREE
#define SID_NORMAL_MULTI_PANE_GUI           TypedWhichId<SfxBoolItem>(SID_SD_START+420)
diff --git a/sd/inc/glob.hxx b/sd/inc/glob.hxx
index a6ddf50..ad4ce9f 100644
--- a/sd/inc/glob.hxx
+++ b/sd/inc/glob.hxx
@@ -39,6 +39,8 @@
#define SD_IF_SDDRAWTABLEOBJECTBAR      SFX_INTERFACE_SD_START + SfxInterfaceId(27)
#define SD_IF_SDTOOLPANELPANESHELL      SFX_INTERFACE_SD_START + SfxInterfaceId(29)
#define SD_IF_SDTOOLPANELSHELL          SFX_INTERFACE_SD_START + SfxInterfaceId(30)
#define SD_IF_SDBOTTOMIMPRESSPANESHELL  SFX_INTERFACE_SD_START + SfxInterfaceId(31)
#define SD_IF_SDNOTESPANELVIEWSHELL     SFX_INTERFACE_SD_START + SfxInterfaceId(32)


// Object-Ids for StarDraw UserData
diff --git a/sd/sdi/NotesPanelView.sdi b/sd/sdi/NotesPanelView.sdi
new file mode 100644
index 0000000..90217ef
--- /dev/null
+++ b/sd/sdi/NotesPanelView.sdi
@@ -0,0 +1,514 @@
/*
 * 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/.
 */

interface NotesPanelView
{
    SID_CUT // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_COPY // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_PASTE // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_PASTE_UNFORMATTED // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_DELETE // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
        Asynchron ;
    ]
    SID_DRAWINGMODE // ole : no, status : play rec
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_ZOOM_NEXT // ole : no, status : play rec
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_ZOOM_PREV // ole : no, status : play rec
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_ZOOM_TOOLBOX // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetStatusBarState ;
    ]
    SID_ATTR_ZOOM // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetStatusBarState ;
    ]
    SID_ATTR_ZOOMSLIDER // status()
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetStatusBarState ;
    ]
    SID_ZOOM_OUT // ole : no, status : play rec
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_ZOOM_IN // ole : no, status : play rec
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_SIZE_REAL // ole : no, status : play rec
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_SIZE_VISAREA // ole : no, status : no
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_HYPERLINK_SETLINK // ole : no, status : no
    [
        ExecMethod = FuTemporaryModify ;
    ]
    SID_HYPERLINK_GETLINK // ole : no, status : no
    [
        StateMethod = GetCtrlState ;
    ]
    SID_READONLY_MODE // ole : no, status : no
    [
        StateMethod = GetCtrlState ;
    ]
    SID_CHARMAP // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_CHARMAP_CONTROL // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    FN_INSERT_SOFT_HYPHEN // status(final|play)
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    FN_INSERT_HARDHYPHEN // status()
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    FN_INSERT_HARD_SPACE // status(final|play)
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    FN_INSERT_NNBSP // status(final|play)
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_RLM
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_LRM
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_ZWSP
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_WJ
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    FN_SVX_SET_BULLET
    [
        ExecMethod = FuTemporaryModify ;
    ]
    FN_SVX_SET_NUMBER
    [
        ExecMethod = FuTemporaryModify ;
    ]
    SID_OUTLINE_BULLET // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_CHAR_DLG // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_CHAR_DLG_EFFECT // wj for sym2_1876
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_SELECTALL // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_INSERTFILE // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_PRESENTATION // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_PRESENTATION_CURRENT_SLIDE // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_EDIT_OUTLINER // ole : no, status : ?
    [
        ExecMethod = FuPermanent ;
        StateMethod = GetMenuState ;
    ]
    SID_SAVEDOC // ole : no, status : ?
    [
        ExecMethod = Execute ;
        StateMethod = GetMenuState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_SAVEASDOC // ole : no, status : ?
    [
        ExecMethod = Execute ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_RULER // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_STATUS_PAGE // ole : no, status : ?
    [
        ExecMethod = ExecStatusBar ;
        StateMethod = GetStatusBarState ;
    ]
    SID_STATUS_LAYOUT // ole : no, status : ?
    [
        ExecMethod = ExecStatusBar ;
        StateMethod = GetStatusBarState ;
    ]
    SID_SCALE // ole : no, status : ?
    [
        ExecMethod = ExecStatusBar ;
        StateMethod = GetStatusBarState ;
    ]
    SID_THESAURUS // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_SET_DEFAULT // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_PRESENTATIONOBJECT
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
     // Templates
     // no menu entry
    SID_STYLE_FAMILY2 // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_STYLE_FAMILY3 // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // Templates
     // no menu entry
    SID_STYLE_FAMILY5 // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
    ]
     // no menu entry
    SID_STYLE_EDIT // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // no menu entry
    SID_STYLE_UPDATE_BY_EXAMPLE // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // no menu entry
    SID_STYLE_WATERCAN // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // no menu entry
    SID_STYLE_NEW_BY_EXAMPLE // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // no menu entry
    SID_STYLE_NEW // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
     // no menu entry
    SID_STYLE_DELETE // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_STYLE_HIDE
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_STYLE_SHOW
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetAttrState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_AUTOSPELL_CHECK // ole : no, status : play rec
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_PREVIEW_STATE // ole : no, status : ?
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_PRESENTATION_DLG
    [
        ExecMethod = FuTemporary ;
    ]
    SID_REMOTE_DLG
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
    SID_CUSTOMSHOW_DLG
    [
        ExecMethod = FuTemporary ;
    ]
    SID_EXPAND_PAGE // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_SUMMARY_PAGE // ole : no, status : ?
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_DATE_FIX // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_DATE_VAR // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_TIME_FIX // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_TIME_VAR // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_PAGE_TITLE // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_PAGE // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_PAGES // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_FILE // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_INSERT_FLD_AUTHOR // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]
    SID_MODIFY_FIELD // ole : no, status : play rec
    [
        ExecMethod = FuTemporaryModify ;
        StateMethod = GetMenuState ;
    ]

    SID_MAIL_SCROLLBODY_PAGEDOWN // ole : no, status : ?
    [
        ExecMethod = ExecCtrl ;
        StateMethod = GetCtrlState ;
    ]
    SID_STYLE_FAMILY
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_TRANSLITERATE_SENTENCE_CASE // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_TITLE_CASE // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_TOGGLE_CASE // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_UPPER // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_LOWER // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_HALFWIDTH // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_FULLWIDTH // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_HIRAGANA // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_TRANSLITERATE_KATAKANA // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetCtrlState ;
    ]
    SID_OPT_LOCALE_CHANGED // ole : no, status : ?
    [
        ExecMethod = ExecCtrl ;
        StateMethod = GetCtrlState ;
    ]

    SID_GETUNDOSTRINGS // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_UNDO // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_GETREDOSTRINGS // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]
    SID_REDO // ole : no, status : ?
    [
        ExecMethod = FuSupport ;
        StateMethod = GetMenuState ;
    ]

    SID_SEARCH_OPTIONS // ole : ?, status : ?
    [
        ExecMethod = Execute ;
        StateMethod = GetState ;
        GroupId = SfxGroupId::Document ;
    ]
    SID_SEARCH_ITEM // ole : ?, status : ?
    [
        ExecMethod = Execute ;
        StateMethod = GetState ;
    ]
    SID_SPELL_DIALOG // ole : no, status : ?
    [
        ExecMethod = Execute ;
        StateMethod = GetMenuState ;
    ]
    SID_PHOTOALBUM
    [
        ExecMethod = FuTemporary ;
        StateMethod = GetMenuState ;
    ]
}

include "drtxtob.sdi"

shell NotesPanelViewShell
{
    import NotesPanelView;
    import TextObjectBar;
}
diff --git a/sd/sdi/sdslots.sdi b/sd/sdi/sdslots.sdi
index 751c099..95ed6d6 100644
--- a/sd/sdi/sdslots.sdi
+++ b/sd/sdi/sdslots.sdi
@@ -88,4 +88,5 @@ module StarDraw
        include "ViewShellBase.sdi"
        include "mediaob.sdi"
        include "tables.sdi"
        include "NotesPanelView.sdi"
        }
diff --git a/sd/source/ui/app/sddll.cxx b/sd/source/ui/app/sddll.cxx
index b21ce1c5..6701932 100644
--- a/sd/source/ui/app/sddll.cxx
+++ b/sd/source/ui/app/sddll.cxx
@@ -177,6 +177,7 @@ void SdDLL::RegisterControllers(SdModule* pMod)
    ::avmedia::MediaPlayer::RegisterChildWindow(false, pMod);
#endif
    ::sd::LeftPaneImpressChildWindow::RegisterChildWindow(false, pMod);
    ::sd::BottomPaneImpressChildWindow::RegisterChildWindow(false, pMod);
    ::sd::LeftPaneDrawChildWindow::RegisterChildWindow(false, pMod);
    ::sfx2::sidebar::SidebarChildWindow::RegisterChildWindow(false, pMod);
    ::sd::NotesChildWindow::RegisterChildWindow(false, pMod);
diff --git a/sd/source/ui/dlg/PaneChildWindows.cxx b/sd/source/ui/dlg/PaneChildWindows.cxx
index 320ce2a..5bbfa4e 100644
--- a/sd/source/ui/dlg/PaneChildWindows.cxx
+++ b/sd/source/ui/dlg/PaneChildWindows.cxx
@@ -32,6 +32,7 @@ namespace sd {


SFX_IMPL_DOCKINGWINDOW_WITHID(LeftPaneImpressChildWindow, SID_LEFT_PANE_IMPRESS)
SFX_IMPL_DOCKINGWINDOW_WITHID(BottomPaneImpressChildWindow, SID_BOTTOM_PANE_IMPRESS)
SFX_IMPL_DOCKINGWINDOW_WITHID(LeftPaneDrawChildWindow, SID_LEFT_PANE_DRAW)

//===== PaneChildWindow =======================================================
@@ -40,7 +41,8 @@ PaneChildWindow::PaneChildWindow (
    sal_uInt16 nId,
    SfxBindings* pBindings,
    SfxChildWinInfo* pInfo,
    TranslateId pTitleBarResId)
    TranslateId pTitleBarResId,
    SfxChildAlignment eAlignment)
    : SfxChildWindow (pParentWindow, nId)
{
    SetWindow( VclPtr<TitledDockingWindow>::Create(
@@ -48,7 +50,7 @@ PaneChildWindow::PaneChildWindow (
        this,
        pParentWindow,
        SdResId(pTitleBarResId)));
    SetAlignment(SfxChildAlignment::LEFT);
    SetAlignment(eAlignment);
    SfxDockingWindow* pDockingWindow = static_cast<SfxDockingWindow*>(GetWindow());
    pDockingWindow->EnableInput();
    pDockingWindow->Initialize(pInfo);
@@ -83,7 +85,24 @@ LeftPaneImpressChildWindow::LeftPaneImpressChildWindow (
        nId,
        pBindings,
        pInfo,
        STR_LEFT_PANE_IMPRESS_TITLE)
        STR_LEFT_PANE_IMPRESS_TITLE,
        SfxChildAlignment::LEFT)
{
}

//===== BottomPaneImpressChildWindow ============================================
BottomPaneImpressChildWindow::BottomPaneImpressChildWindow (
    vcl::Window* pParentWindow,
    sal_uInt16 nId,
    SfxBindings* pBindings,
    SfxChildWinInfo* pInfo)
    : PaneChildWindow(
        pParentWindow,
        nId,
        pBindings,
        pInfo,
        STR_NOTES_MODE, // TODO this isn't a specific translatable string for this view.
        SfxChildAlignment::BOTTOM)
{
}

@@ -98,7 +117,8 @@ LeftPaneDrawChildWindow::LeftPaneDrawChildWindow (
        nId,
        pBindings,
        pInfo,
        STR_LEFT_PANE_DRAW_TITLE)
        STR_LEFT_PANE_DRAW_TITLE,
        SfxChildAlignment::LEFT)
{
}

diff --git a/sd/source/ui/dlg/PaneShells.cxx b/sd/source/ui/dlg/PaneShells.cxx
index 77e411a..ab523bf 100644
--- a/sd/source/ui/dlg/PaneShells.cxx
+++ b/sd/source/ui/dlg/PaneShells.cxx
@@ -50,6 +50,23 @@ LeftImpressPaneShell::~LeftImpressPaneShell()
{
}

//===== BottomImpressPaneShell ==================================================

static SfxSlot aBottomImpressPaneShellSlots_Impl[]
    = { { 0, SfxGroupId::NONE, SfxSlotMode::NONE, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
          0, SfxDisableFlags::NONE, "" } };

SFX_IMPL_INTERFACE(BottomImpressPaneShell, SfxShell)

void BottomImpressPaneShell::InitInterface_Impl()
{
    GetStaticInterface()->RegisterChildWindow(::sd::BottomPaneImpressChildWindow::GetChildWindowId());
}

BottomImpressPaneShell::BottomImpressPaneShell() { SetName("BottomImpressPane"); }

BottomImpressPaneShell::~BottomImpressPaneShell() {}

//===== LeftDrawPaneShell =====================================================

static SfxSlot aLeftDrawPaneShellSlots_Impl[] =
diff --git a/sd/source/ui/framework/factories/BasicPaneFactory.cxx b/sd/source/ui/framework/factories/BasicPaneFactory.cxx
index 4ce694a..2168df8 100644
--- a/sd/source/ui/framework/factories/BasicPaneFactory.cxx
+++ b/sd/source/ui/framework/factories/BasicPaneFactory.cxx
@@ -46,6 +46,7 @@ namespace {
        CenterPaneId,
        FullScreenPaneId,
        LeftImpressPaneId,
        BottomImpressPaneId,
        LeftDrawPaneId
    };

@@ -119,6 +120,11 @@ BasicPaneFactory::BasicPaneFactory (
            mpPaneContainer->push_back(aDescriptor);
            xCC->addResourceFactory(aDescriptor.msPaneURL, this);

            aDescriptor.msPaneURL = FrameworkHelper::msBottomImpressPaneURL;
            aDescriptor.mePaneId = BottomImpressPaneId;
            mpPaneContainer->push_back(aDescriptor);
            xCC->addResourceFactory(aDescriptor.msPaneURL, this);

            aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
            aDescriptor.mePaneId = LeftDrawPaneId;
            mpPaneContainer->push_back(aDescriptor);
@@ -222,6 +228,7 @@ Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
                break;

            case LeftImpressPaneId:
            case BottomImpressPaneId:
            case LeftDrawPaneId:
                xPane = CreateChildWindowPane(
                    rxPaneId,
@@ -369,6 +376,11 @@ Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
                nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
                break;

            case BottomImpressPaneId:
                pShell.reset(new BottomImpressPaneShell());
                nChildWindowId = ::sd::BottomPaneImpressChildWindow::GetChildWindowId();
                break;

            case LeftDrawPaneId:
                pShell.reset(new LeftDrawPaneShell());
                nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
diff --git a/sd/source/ui/framework/factories/BasicViewFactory.cxx b/sd/source/ui/framework/factories/BasicViewFactory.cxx
index 3ea7e37..61118d6 100644
--- a/sd/source/ui/framework/factories/BasicViewFactory.cxx
+++ b/sd/source/ui/framework/factories/BasicViewFactory.cxx
@@ -31,6 +31,7 @@
#include <DrawViewShell.hxx>
#include <GraphicViewShell.hxx>
#include <OutlineViewShell.hxx>
#include <NotesPanelViewShell.hxx>
#include <PresentationViewShell.hxx>
#include <SlideSorterViewShell.hxx>
#include <FrameView.hxx>
@@ -106,6 +107,7 @@ BasicViewFactory::BasicViewFactory (const rtl::Reference<::sd::DrawController>& 
        mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
        mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
        mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
        mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesPanelViewURL, this);
    }
    catch (RuntimeException&)
    {
@@ -367,6 +369,11 @@ std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
            pFrameView);
        pViewShell->GetContentWindow()->set_id("slidesorter");
    }
    else if (rsViewURL == FrameworkHelper::msNotesPanelViewURL)
    {
        pViewShell = std::make_shared<NotesPanelViewShell>(&rFrame, *mpBase, &rWindow, pFrameView);
        pViewShell->GetContentWindow()->set_id("notes_panel_win");
    }

    return pViewShell;
}
diff --git a/sd/source/ui/framework/tools/FrameworkHelper.cxx b/sd/source/ui/framework/tools/FrameworkHelper.cxx
index 0a42649..d47ebc5 100644
--- a/sd/source/ui/framework/tools/FrameworkHelper.cxx
+++ b/sd/source/ui/framework/tools/FrameworkHelper.cxx
@@ -174,6 +174,7 @@ namespace {
const OUString FrameworkHelper::msCenterPaneURL( msPaneURLPrefix + "CenterPane");
const OUString FrameworkHelper::msFullScreenPaneURL( msPaneURLPrefix + "FullScreenPane");
const OUString FrameworkHelper::msLeftImpressPaneURL( msPaneURLPrefix + "LeftImpressPane");
const OUString FrameworkHelper::msBottomImpressPaneURL( msPaneURLPrefix + "BottomImpressPane");
const OUString FrameworkHelper::msLeftDrawPaneURL( msPaneURLPrefix + "LeftDrawPane");

// View URLs.
@@ -186,6 +187,7 @@ const OUString FrameworkHelper::msHandoutViewURL( msViewURLPrefix + "HandoutView
const OUString FrameworkHelper::msSlideSorterURL( msViewURLPrefix + "SlideSorter");
const OUString FrameworkHelper::msPresentationViewURL( msViewURLPrefix + "PresentationView");
const OUString FrameworkHelper::msSidebarViewURL( msViewURLPrefix + "SidebarView");
const OUString FrameworkHelper::msNotesPanelViewURL( msViewURLPrefix + "NotesPanelView");

// Tool bar URLs.

@@ -434,6 +436,7 @@ ViewShell::ShellType FrameworkHelper::GetViewId (const OUString& rsViewURL)
        maViewURLMap[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
        maViewURLMap[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
        maViewURLMap[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
        maViewURLMap[msNotesPanelViewURL] = ViewShell::ST_NOTESPANEL;
    }
    ViewURLMap::const_iterator iView (maViewURLMap.find(rsViewURL));
    if (iView != maViewURLMap.end())
@@ -454,6 +457,7 @@ OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
        case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
        case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
        case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
        case ViewShell::ST_NOTESPANEL: return msNotesPanelViewURL;
        default:
            return OUString();
    }
diff --git a/sd/source/ui/func/fuoltext.cxx b/sd/source/ui/func/fuoltext.cxx
index fe64cac..0068f77 100644
--- a/sd/source/ui/func/fuoltext.cxx
+++ b/sd/source/ui/func/fuoltext.cxx
@@ -82,25 +82,85 @@ const sal_uInt16 SidArray[] = {
                SID_SUMMARY_PAGE,
                0 };

void FuOutlineText::UpdateForKeyPress (const KeyEvent& rEvent)
{
    FuSimpleOutlinerText::UpdateForKeyPress(rEvent);

    bool bUpdatePreview = true;
    switch (rEvent.GetKeyCode().GetCode())
    {
        // When just the cursor has been moved the preview only changes when
        // it moved to entries of another page.  To prevent unnecessary
        // updates we check this here.  This is an early rejection test, so
        // missing a key is not a problem.
        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_HOME:
        case KEY_END:
        case KEY_PAGEUP:
        case KEY_PAGEDOWN:
        {
            SdPage* pCurrentPage = pOutlineViewShell->GetActualPage();
            bUpdatePreview = (pCurrentPage != pOutlineViewShell->GetActualPage());
        }
        break;
    }
    if (bUpdatePreview)
        pOutlineViewShell->UpdatePreview (pOutlineViewShell->GetActualPage());
}

/**
 * Process keyboard input
 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
 */
bool FuOutlineText::KeyInput(const KeyEvent& rKEvt)
{
    sal_uInt16 nKeyGroup = rKEvt.GetKeyCode().GetGroup();
    if( !mpDocSh->IsReadOnly() || nKeyGroup == KEYGROUP_CURSOR )
    {
        std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard;
        if( (nKeyGroup != KEYGROUP_CURSOR) && (nKeyGroup != KEYGROUP_FKEYS) )
            aGuard.reset( new OutlineViewModelChangeGuard( *static_cast<OutlineView*>(mpSimpleOutlinerView) ) );

        return FuSimpleOutlinerText::KeyInput(rKEvt);
    }

    return false;
}

rtl::Reference<FuPoor> FuOutlineText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
{
    rtl::Reference<FuPoor> xFunc( new FuOutlineText( pViewSh, pWin, pView, pDoc, rReq ) );
    xFunc->DoExecute( rReq );
    return xFunc;
}

FuOutlineText::FuOutlineText(ViewShell* pViewShell, ::sd::Window* pWindow,
                             ::sd::View* pView, SdDrawDocument* pDoc,
                             ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc,
                             SfxRequest& rReq)
       : FuSimpleOutlinerText(pViewShell, pWindow, pView, pDoc, rReq)
{}

FuSimpleOutlinerText::FuSimpleOutlinerText(ViewShell* pViewShell, ::sd::Window* pWindow,
                             ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc,
                             SfxRequest& rReq)
       : FuPoor(pViewShell, pWindow, pView, pDoc, rReq),
         pOutlineViewShell (static_cast<OutlineViewShell*>(pViewShell)),
         pOutlineView (static_cast<OutlineView*>(pView))
         pOutlineViewShell (pViewShell),
         mpSimpleOutlinerView (pView)
{
}

/**
 * forward to OutlinerView
 */
bool FuOutlineText::Command(const CommandEvent& rCEvt)
bool FuSimpleOutlinerText::Command(const CommandEvent& rCEvt)
{
    bool bResult = false;

    OutlinerView* pOlView =
        static_cast<OutlineView*>(mpView)->GetViewByWindow(mpWindow);
    OutlinerView* pOlView = mpSimpleOutlinerView->GetViewByWindow(mpWindow);

    DBG_ASSERT (pOlView, "no OutlineView found");

    if (pOlView)
@@ -112,18 +172,18 @@ bool FuOutlineText::Command(const CommandEvent& rCEvt)
}


rtl::Reference<FuPoor> FuOutlineText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
rtl::Reference<FuPoor> FuSimpleOutlinerText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc, SfxRequest& rReq )
{
    rtl::Reference<FuPoor> xFunc( new FuOutlineText( pViewSh, pWin, pView, pDoc, rReq ) );
    rtl::Reference<FuPoor> xFunc( new FuSimpleOutlinerText( pViewSh, pWin, pView, pDoc, rReq ) );
    xFunc->DoExecute( rReq );
    return xFunc;
}

bool FuOutlineText::MouseButtonDown(const MouseEvent& rMEvt)
bool FuSimpleOutlinerText::MouseButtonDown(const MouseEvent& rMEvt)
{
    mpWindow->GrabFocus();

    bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseButtonDown(rMEvt);
    bool bReturn = mpSimpleOutlinerView->GetViewByWindow(mpWindow)->MouseButtonDown(rMEvt);

    if (bReturn)
    {
@@ -138,9 +198,9 @@ bool FuOutlineText::MouseButtonDown(const MouseEvent& rMEvt)
    return bReturn;
}

bool FuOutlineText::MouseMove(const MouseEvent& rMEvt)
bool FuSimpleOutlinerText::MouseMove(const MouseEvent& rMEvt)
{
    bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseMove(rMEvt);
    bool bReturn = mpSimpleOutlinerView->GetViewByWindow(mpWindow)->MouseMove(rMEvt);

    if (!bReturn)
    {
@@ -150,9 +210,9 @@ bool FuOutlineText::MouseMove(const MouseEvent& rMEvt)
    return bReturn;
}

bool FuOutlineText::MouseButtonUp(const MouseEvent& rMEvt)
bool FuSimpleOutlinerText::MouseButtonUp(const MouseEvent& rMEvt)
{
    bool bReturn = pOutlineView->GetViewByWindow(mpWindow)->MouseButtonUp(rMEvt);
    bool bReturn = mpSimpleOutlinerView->GetViewByWindow(mpWindow)->MouseButtonUp(rMEvt);

    if (bReturn)
    {
@@ -161,7 +221,7 @@ bool FuOutlineText::MouseButtonUp(const MouseEvent& rMEvt)
    }
    else
    {
        const SvxFieldItem* pFieldItem = pOutlineView->GetViewByWindow( mpWindow )->GetFieldUnderMousePointer();
        const SvxFieldItem* pFieldItem = mpSimpleOutlinerView->GetViewByWindow( mpWindow )->GetFieldUnderMousePointer();
        if( pFieldItem )
        {
            const SvxFieldData* pField = pFieldItem->GetField();
@@ -204,7 +264,7 @@ bool FuOutlineText::MouseButtonUp(const MouseEvent& rMEvt)
 * Process keyboard input
 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
 */
bool FuOutlineText::KeyInput(const KeyEvent& rKEvt)
bool FuSimpleOutlinerText::KeyInput(const KeyEvent& rKEvt)
{
    bool bReturn = false;

@@ -213,11 +273,7 @@ bool FuOutlineText::KeyInput(const KeyEvent& rKEvt)
    {
        mpWindow->GrabFocus();

        std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard;
        if( (nKeyGroup != KEYGROUP_CURSOR) && (nKeyGroup != KEYGROUP_FKEYS) )
            aGuard.reset( new OutlineViewModelChangeGuard( *pOutlineView ) );

        bReturn = pOutlineView->GetViewByWindow(mpWindow)->PostKeyEvent(rKEvt);
        bReturn = mpSimpleOutlinerView->GetViewByWindow(mpWindow)->PostKeyEvent(rKEvt);

        if (bReturn)
        {
@@ -232,74 +288,49 @@ bool FuOutlineText::KeyInput(const KeyEvent& rKEvt)
    return bReturn;
}

void FuOutlineText::UpdateForKeyPress (const KeyEvent& rEvent)
void FuSimpleOutlinerText::UpdateForKeyPress (const KeyEvent& /*rEvent*/)
{
    // Attributes at the current text position may have changed.
    mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray);

    bool bUpdatePreview = true;
    switch (rEvent.GetKeyCode().GetCode())
    {
        // When just the cursor has been moved the preview only changes when
        // it moved to entries of another page.  To prevent unnecessary
        // updates we check this here.  This is an early rejection test, so
        // missing a key is not a problem.
        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_HOME:
        case KEY_END:
        case KEY_PAGEUP:
        case KEY_PAGEDOWN:
        {
            SdPage* pCurrentPage = pOutlineViewShell->GetActualPage();
            bUpdatePreview = (pCurrentPage != pOutlineViewShell->GetActualPage());
        }
        break;
    }
    if (bUpdatePreview)
        pOutlineViewShell->UpdatePreview (pOutlineViewShell->GetActualPage());
}

/**
 * Cut object to clipboard
 */
void FuOutlineText::DoCut()
void FuSimpleOutlinerText::DoCut()
{
    pOutlineView->GetViewByWindow(mpWindow)->Cut();
    mpSimpleOutlinerView->GetViewByWindow(mpWindow)->Cut();
}

/**
 * Copy object to clipboard
 */
void FuOutlineText::DoCopy()
void FuSimpleOutlinerText::DoCopy()
{
    pOutlineView->GetViewByWindow(mpWindow)->Copy();
    mpSimpleOutlinerView->GetViewByWindow(mpWindow)->Copy();
}

/**
 * Paste object from clipboard
 */
void FuOutlineText::DoPaste()
void FuSimpleOutlinerText::DoPaste()
{
    pOutlineView->GetViewByWindow(mpWindow)->PasteSpecial();
    mpSimpleOutlinerView->GetViewByWindow(mpWindow)->PasteSpecial();
}

/**
 * Paste object as unformatted text from clipboard
 */
void FuOutlineText::DoPasteUnformatted()
void FuSimpleOutlinerText::DoPasteUnformatted()
{
   TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewShell->GetActiveWindow() ) );
   if (aDataHelper.GetTransferable().is())
   {
       OUString aText;
       if (aDataHelper.GetString(SotClipboardFormatId::STRING, aText))
           pOutlineView->GetViewByWindow(mpWindow)->InsertText(aText);
           mpSimpleOutlinerView->GetViewByWindow(mpWindow)->InsertText(aText);
   }
}

} // end of namespace sd

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/inc/NotesPanelView.hxx b/sd/source/ui/inc/NotesPanelView.hxx
new file mode 100644
index 0000000..4bb9459
--- /dev/null
+++ b/sd/source/ui/inc/NotesPanelView.hxx
@@ -0,0 +1,96 @@
/* -*- 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 "OutlineView.hxx"
#include <Outliner.hxx>

class SdrTextObj;

namespace sd::tools
{
class EventMultiplexerEvent;
}

namespace sd
{
class DrawDocShell;
class NotesPanelViewShell;

/**
 * Derivative of ::sd::SimpleOutlinerView for the notes panel
|*
\************************************************************************/

class NotesPanelView final : public ::sd::SimpleOutlinerView
{
    NotesPanelViewShell& mrNotesPanelViewShell;
    SdOutliner maOutliner;
    OutlinerView maOutlinerView;

    Idle aModifyIdle;

    SdrTextObj* mpTextObj = nullptr;
    bool mbFirstPaint = true;
    bool mbIgnoreNotifications = false;

    /** stores the last used document color.
        this is changed in onUpdateStyleSettings()
    */
    Color maDocColor = COL_WHITE;

    void removeListener();
    void addListener();

    void setListenerIgnored(bool bIgnore);
    bool isListenerIgnored();

    void getNotesFromDoc();
    void setNotesToDoc();

public:
    NotesPanelView(DrawDocShell& rDocSh, vcl::Window* pWindow,
                   NotesPanelViewShell& rNotesPanelViewSh);
    virtual ~NotesPanelView() override;

    void Paint(const ::tools::Rectangle& rRect, ::sd::Window const* pWin);
    void onResize();

    OutlinerView* GetOutlinerView();
    OutlinerView* GetViewByWindow(vcl::Window const* pWin) const override;

    SdOutliner& GetOutliner() { return maOutliner; }

    void FillOutliner();
    void onUpdateStyleSettings(bool bForceUpdate);
    virtual SvtScriptType GetScriptType() const override;

    void SetLinks();
    void ResetLinks();
    virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;

    virtual void GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr = false) const override;
    virtual bool SetAttributes(const SfxItemSet& rSet, bool bReplaceAll = false,
                               bool bSlide = false, bool bMaster = false) override;

    // SdrObjEditView's Outliner access overrides to use TextObjectBar implementations.
    virtual const SdrOutliner* GetTextEditOutliner() const override { return &maOutliner; }
    virtual SdrOutliner* GetTextEditOutliner() override { return &maOutliner; }
    virtual const OutlinerView* GetTextEditOutlinerView() const override { return &maOutlinerView; }
    virtual OutlinerView* GetTextEditOutlinerView() override { return &maOutlinerView; }

    DECL_LINK(StatusEventHdl, EditStatus&, void);
    DECL_LINK(EditModifiedHdl, LinkParamNone*, void);
    DECL_LINK(ModifyTimerHdl, Timer*, void);
    DECL_LINK(EventMultiplexerListener, tools::EventMultiplexerEvent&, void);
};
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sd/source/ui/inc/NotesPanelViewShell.hxx b/sd/source/ui/inc/NotesPanelViewShell.hxx
new file mode 100644
index 0000000..e79ac89
--- /dev/null
+++ b/sd/source/ui/inc/NotesPanelViewShell.hxx
@@ -0,0 +1,101 @@
/* -*- 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 "ViewShell.hxx"
#include <glob.hxx>

class SdPage;

namespace sd
{
class NotesPanelView;

class NotesPanelViewShell final : public ViewShell
{
public:
    SFX_DECL_VIEWFACTORY(NotesPanelViewShell);
    SFX_DECL_INTERFACE(SD_IF_SDNOTESPANELVIEWSHELL)

private:
    /// SfxInterface initializer.
    static void InitInterface_Impl();

public:
    /** Create a new view shell for the notes panel.
        @param rViewShellBase
            The new object will be stacked on this view shell base.
        @param pFrameView
            The frame view that makes it possible to pass information from
            one view shell to the next.
    */
    NotesPanelViewShell(SfxViewFrame* pFrame, ViewShellBase& rViewShellBase,
                        vcl::Window* pParentWindow, FrameView* pFrameView);

    virtual ~NotesPanelViewShell() override;

    virtual void Paint(const ::tools::Rectangle& rRect, ::sd::Window* pWin) override;
    virtual bool PrepareClose(bool bUI = true) override;
    virtual void UpdateScrollBars() override;
    virtual void VirtHScrollHdl(ScrollAdaptor* pHScroll) override;
    virtual void VirtVScrollHdl(ScrollAdaptor* pVScroll) override;
    virtual void Activate(bool IsMDIActivate) override;
    /** this method is called when the visible area of the view from this viewshell is changed */
    virtual void VisAreaChanged(const ::tools::Rectangle& rRect) override;

    virtual void ArrangeGUIElements() override;
    virtual SdPage* GetActualPage() override;
    virtual SdPage* getCurrentPage() const override;
    virtual css::uno::Reference<css::drawing::XDrawSubController> CreateSubController() override;

    void ExecCtrl(SfxRequest& rReq);
    void GetCtrlState(SfxItemSet& rSet);
    void GetAttrState(SfxItemSet& rSet);
    void GetState(SfxItemSet& rSet);
    void GetCharState(SfxItemSet& rSet);

    static void ExecStatusBar(SfxRequest& rReq);
    void GetStatusBarState(SfxItemSet& rSet);

    void FuTemporary(SfxRequest& rReq);
    void FuTemporaryModify(SfxRequest& rReq);
    void FuPermanent(SfxRequest& rReq);
    void FuSupport(SfxRequest& rReq);
    void Execute(SfxRequest& rReq);
    void ExecChar(SfxRequest& rReq);

    virtual void Command(const CommandEvent& rCEvt, ::sd::Window* pWin) override;
    virtual bool KeyInput(const KeyEvent& rKEvt, ::sd::Window* pWin) override;
    virtual void MouseButtonUp(const MouseEvent& rMEvt, ::sd::Window* pWin) override;

    virtual void SetZoom(::tools::Long nZoom) override;
    virtual void SetZoomRect(const ::tools::Rectangle& rZoomRect) override;

    virtual void ReadFrameViewData(FrameView* pView) override;
    virtual void WriteFrameViewData() override;
    virtual css::uno::Reference<css::accessibility::XAccessible>
    CreateAccessibleDocumentView(::sd::Window* /*pWindow*/) override
    {
        // TODO
        return {};
    }

private:
    std::unique_ptr<NotesPanelView> mpNotesPanelView;
    bool mbInitialized = false;

    /** Initiates the shell with it's NotesPanelView instance
    */
    void Construct();
};

} // 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/OutlineView.hxx b/sd/source/ui/inc/OutlineView.hxx
index 43dadf0..75550bf 100644
--- a/sd/source/ui/inc/OutlineView.hxx
+++ b/sd/source/ui/inc/OutlineView.hxx
@@ -46,12 +46,24 @@ class OutlineViewModelChangeGuard;
const int MAX_OUTLINERVIEWS = 4;

/**
 * Derivative of ::sd::View for the outline mode
 *  Common base for OutlineView and NotesPanelView that only have a single Outliner in the view.
|*
\************************************************************************/
class SimpleOutlinerView : public ::sd::View
{
public:
    SimpleOutlinerView(SdDrawDocument& rDrawDoc, OutputDevice* pOutDev, ViewShell* pViewSh)
            : View(rDrawDoc, pOutDev, pViewSh) {}
    virtual OutlinerView* GetViewByWindow(vcl::Window const* pWin) const = 0;
};

/**
 * Derivative of ::sd::SimpleOutlinerView for the outline mode
|*
\************************************************************************/

class OutlineView final
    : public ::sd::View
    : public SimpleOutlinerView
{
    friend class OutlineViewModelChangeGuard;
public:
@@ -78,7 +90,7 @@ public:
    virtual void AddDeviceToPaintView(OutputDevice& rDev, vcl::Window* pWindow) override;
    virtual void DeleteDeviceFromPaintView(OutputDevice& rDev) override;

    OutlinerView*   GetViewByWindow(vcl::Window const * pWin) const;
    OutlinerView*   GetViewByWindow(vcl::Window const * pWin) const override;
    SdOutliner&     GetOutliner() { return mrOutliner; }

    Paragraph*      GetPrevTitle(const Paragraph* pPara);
diff --git a/sd/source/ui/inc/PaneChildWindows.hxx b/sd/source/ui/inc/PaneChildWindows.hxx
index f96ede4..68989f3 100644
--- a/sd/source/ui/inc/PaneChildWindows.hxx
+++ b/sd/source/ui/inc/PaneChildWindows.hxx
@@ -34,7 +34,8 @@ public:
        sal_uInt16 nId,
        SfxBindings* pBindings,
        SfxChildWinInfo* pInfo,
        TranslateId pTitleBarResId);
        TranslateId pTitleBarResId,
        SfxChildAlignment eAlignment);
    virtual ~PaneChildWindow() override;
};

@@ -49,6 +50,16 @@ public:
    SFX_DECL_CHILDWINDOW_WITHID(LeftPaneImpressChildWindow);
};

/// The notes panel (on the bottom) in Impress.
class BottomPaneImpressChildWindow final : public PaneChildWindow
{
public:
    BottomPaneImpressChildWindow(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings* pBindings,
                                 SfxChildWinInfo* pInfo);

    SFX_DECL_CHILDWINDOW_WITHID(BottomPaneImpressChildWindow);
};

/// The pages sidebar (on the left) in Draw.
class LeftPaneDrawChildWindow final
    : public PaneChildWindow
diff --git a/sd/source/ui/inc/PaneShells.hxx b/sd/source/ui/inc/PaneShells.hxx
index 73f2490..e15ce2d 100644
--- a/sd/source/ui/inc/PaneShells.hxx
+++ b/sd/source/ui/inc/PaneShells.hxx
@@ -41,6 +41,23 @@ public:
    virtual ~LeftImpressPaneShell() override;
};

/** Shell that displays the bottom pane for Impress. The shell does not do
    anything else and has especially no slots.
*/
class BottomImpressPaneShell final : public SfxShell
{
public:
    SFX_DECL_INTERFACE(SD_IF_SDBOTTOMIMPRESSPANESHELL)

private:
    /// SfxInterface initializer.
    static void InitInterface_Impl();

public:
    BottomImpressPaneShell();
    virtual ~BottomImpressPaneShell() override;
};

/** Shell that displays the left pane for Draw.  The shell does not do
    anything else and has especially no slots.
*/
diff --git a/sd/source/ui/inc/TextObjectBar.hxx b/sd/source/ui/inc/TextObjectBar.hxx
index 6139483..aaa008f 100644
--- a/sd/source/ui/inc/TextObjectBar.hxx
+++ b/sd/source/ui/inc/TextObjectBar.hxx
@@ -45,8 +45,11 @@ public:
    virtual ~TextObjectBar() override;

    void GetAttrState( SfxItemSet& rSet );
    static void GetAttrStateImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxItemSet& rSet, SfxShell* pTextObjectBar);
    void GetCharState( SfxItemSet& rSet );
    static void GetCharStateImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxItemSet& rSet);
    void Execute( SfxRequest &rReq );
    static void ExecuteImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxRequest& rReq, SfxShell* pTextObjectBar);

private:
    ViewShell* mpViewShell;
diff --git a/sd/source/ui/inc/ViewShell.hxx b/sd/source/ui/inc/ViewShell.hxx
index 8933253..85bc43e 100644
--- a/sd/source/ui/inc/ViewShell.hxx
+++ b/sd/source/ui/inc/ViewShell.hxx
@@ -100,7 +100,8 @@ public:
        ST_OUTLINE,
        ST_SLIDE_SORTER,
        ST_PRESENTATION,
        ST_SIDEBAR
        ST_SIDEBAR,
        ST_NOTESPANEL
    };
    static const int MAX_HSPLIT_CNT = 1;
    static const int MAX_VSPLIT_CNT = 1;
diff --git a/sd/source/ui/inc/framework/FrameworkHelper.hxx b/sd/source/ui/inc/framework/FrameworkHelper.hxx
index e5fe6f7..f25e588 100644
--- a/sd/source/ui/inc/framework/FrameworkHelper.hxx
+++ b/sd/source/ui/inc/framework/FrameworkHelper.hxx
@@ -60,6 +60,7 @@ public:
    static const OUString msCenterPaneURL;
    static const OUString msFullScreenPaneURL;
    static const OUString msLeftImpressPaneURL;
    static const OUString msBottomImpressPaneURL;
    static const OUString msLeftDrawPaneURL;

    // URLs of frequently used views.
@@ -72,6 +73,7 @@ public:
    static const OUString msSlideSorterURL;
    static const OUString msPresentationViewURL;
    static const OUString msSidebarViewURL;
    static const OUString msNotesPanelViewURL;

    // URLs of frequently used tool bars.
    static constexpr OUString msToolBarURLPrefix = u"private:resource/toolbar/"_ustr;
diff --git a/sd/source/ui/inc/fuoltext.hxx b/sd/source/ui/inc/fuoltext.hxx
index 288bcf1..ddbada5 100644
--- a/sd/source/ui/inc/fuoltext.hxx
+++ b/sd/source/ui/inc/fuoltext.hxx
@@ -24,22 +24,19 @@
class SdDrawDocument;
class SfxRequest;

namespace sd {
namespace sd
{

class View;
class ViewShell;
class OutlineView;
class OutlineViewShell;
class SimpleOutlinerView;

/**
 * text functions in outline mode
 * Functions class for shells that host only an Outliner e.g. NotesPanel
 *
 */
class FuOutlineText final
    : public FuPoor
class FuSimpleOutlinerText : public FuPoor
{
public:

    static rtl::Reference<FuPoor> Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq );
    static rtl::Reference<FuPoor> Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc, SfxRequest& rReq );

    virtual bool Command(const CommandEvent& rCEvt) override;

@@ -53,22 +50,42 @@ public:
    virtual void DoPaste() override;
    virtual void DoPasteUnformatted() override;

    /** Call this method when the text in the outliner (may) has changed.
        It will invalidate some slots of the view frame and update the
        preview in the slide sorter.
    /** Call this method when the text in the outliner (may) have changed.
        It will invalidate some slots of the view frame.
    */
    void UpdateForKeyPress (const KeyEvent& rEvent);
    virtual void UpdateForKeyPress (const KeyEvent& rEvent);

private:
    FuOutlineText (
protected:
    FuSimpleOutlinerText(
        ViewShell* pViewShell,
        ::sd::Window* pWin,
        ::sd::View* pView,
        ::sd::SimpleOutlinerView* pView,
        SdDrawDocument* pDoc,
        SfxRequest& rReq);

    OutlineViewShell* pOutlineViewShell;
    OutlineView* pOutlineView;
    ViewShell* pOutlineViewShell;
    SimpleOutlinerView* mpSimpleOutlinerView;
};

class FuOutlineText final : public FuSimpleOutlinerText
{
public:
    static rtl::Reference<FuPoor> Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView, SdDrawDocument* pDoc, SfxRequest& rReq );

    virtual bool KeyInput(const KeyEvent& rKEvt) override;
    /** Call this method when the text in the outliner (may) have changed.
        It will invalidate some slots of the view frame and update the
        preview in the slide sorter.
    */
    virtual void UpdateForKeyPress(const KeyEvent& rEvent) override;

private:
    FuOutlineText(
        ViewShell* pViewShell,
        ::sd::Window* pWin,
        ::sd::SimpleOutlinerView* pView,
        SdDrawDocument* pDoc,
        SfxRequest& rReq);
};

} // end of namespace sd
diff --git a/sd/source/ui/view/NotesPanelView.cxx b/sd/source/ui/view/NotesPanelView.cxx
new file mode 100644
index 0000000..0cbc714
--- /dev/null
+++ b/sd/source/ui/view/NotesPanelView.cxx
@@ -0,0 +1,320 @@
/* -*- 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 <NotesPanelViewShell.hxx>
#include <NotesPanelView.hxx>
#include <OutlineView.hxx>
#include <ViewShellBase.hxx>
#include <editeng/editeng.hxx>
#include <editeng/outliner.hxx>
#include <sdresid.hxx>
#include <editeng/editund2.hxx>
#include <sdpage.hxx>
#include <DrawViewShell.hxx>
#include <DrawDocShell.hxx>
#include <Window.hxx>
#include <drawdoc.hxx>
#include <sdmod.hxx>
#include <officecfg/Office/Common.hxx>
#include <EventMultiplexer.hxx>
#include <app.hrc>
#include <strings.hrc>

namespace sd
{
NotesPanelView::NotesPanelView(DrawDocShell& rDocSh, vcl::Window* pWindow,
                               NotesPanelViewShell& rNotesPanelViewShell)
    : ::sd::SimpleOutlinerView(*rDocSh.GetDoc(), pWindow->GetOutDev(), &rNotesPanelViewShell)
    , mrNotesPanelViewShell(rNotesPanelViewShell)
    , maOutliner(&mrDoc, OutlinerMode::TextObject)
    , maOutlinerView(&maOutliner, pWindow)
    , aModifyIdle("NotesEditWindow ModifyIdle")
{
    aModifyIdle.SetInvokeHandler(LINK(this, NotesPanelView, ModifyTimerHdl));
    aModifyIdle.SetPriority(TaskPriority::LOWEST);

    maOutliner.Init(OutlinerMode::OutlineView);
    maOutliner.SetRefDevice(SD_MOD()->GetVirtualRefDevice());
    maOutliner.SetPaperSize(mrNotesPanelViewShell.GetActiveWindow()->GetViewSize());

    maOutlinerView.SetOutputArea(
        ::tools::Rectangle{ Point(0, 0), mrNotesPanelViewShell.GetActiveWindow()->GetViewSize() });
    maOutliner.InsertView(&maOutlinerView, EE_APPEND);

    onUpdateStyleSettings(true);

    // fill Outliner with contents
    FillOutliner();

    // TODO: UNDO
    // sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
    // if (pDocUndoMgr != nullptr)
    //     pDocUndoMgr->SetLinkedUndoManager(&maOutliner.GetUndoManager());
}

NotesPanelView::~NotesPanelView()
{
    ResetLinks();

    // DisconnectFromApplication();
    // mpProgress.reset();
}

void NotesPanelView::FillOutliner()
{
    maOutliner.GetUndoManager().Clear();
    maOutliner.EnableUndo(false);
    ResetLinks();
    removeListener();
    mpTextObj = nullptr;
    maOutliner.Clear();

    SdPage* pNotesPage = mrNotesPanelViewShell.getCurrentPage();
    if (!pNotesPage)
        return;

    SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
    if (!pNotesObj)
        return;

    mpTextObj = dynamic_cast<SdrTextObj*>(pNotesObj);
    addListener();
    getNotesFromDoc();
    SetLinks();
    maOutliner.EnableUndo(true);
}

void NotesPanelView::SetLinks()
{
    maOutliner.SetStatusEventHdl(LINK(this, NotesPanelView, StatusEventHdl));
    mrNotesPanelViewShell.GetViewShellBase().GetEventMultiplexer()->AddEventListener(
        LINK(this, NotesPanelView, EventMultiplexerListener));
}

void NotesPanelView::ResetLinks()
{
    maOutliner.SetStatusEventHdl(Link<EditStatus&, void>());
    mrNotesPanelViewShell.GetViewShellBase().GetEventMultiplexer()->RemoveEventListener(
        LINK(this, NotesPanelView, EventMultiplexerListener));
}

void NotesPanelView::removeListener()
{
    if (mpTextObj)
        mpTextObj->RemoveListener(*this);
}
void NotesPanelView::addListener()
{
    if (mpTextObj)
        mpTextObj->AddListener(*this);
}

void NotesPanelView::setListenerIgnored(bool bIgnore) { mbIgnoreNotifications = bIgnore; }
bool NotesPanelView::isListenerIgnored() { return mbIgnoreNotifications; }

void NotesPanelView::getNotesFromDoc()
{
    if (!mpTextObj)
        return;

    // Ignore notifications that will rebound from updating the text
    maOutliner.SetModifyHdl(Link<LinkParamNone*, void>());
    setListenerIgnored(true);

    if (OutlinerParaObject* pPara = mpTextObj->GetOutlinerParaObject())
        maOutliner.SetText(*pPara);

    setListenerIgnored(false);
    maOutliner.SetModifyHdl(LINK(this, NotesPanelView, EditModifiedHdl));
}

void NotesPanelView::setNotesToDoc()
{
    if (!mpTextObj)
        return;

    setListenerIgnored(true);

    std::optional<OutlinerParaObject> pNewText = maOutliner.CreateParaObject();
    mpTextObj->SetOutlinerParaObject(std::move(pNewText));
    if (mpTextObj->IsEmptyPresObj())
        mpTextObj->SetEmptyPresObj(false);

    setListenerIgnored(false);
}

void NotesPanelView::Paint(const ::tools::Rectangle& rRect, ::sd::Window const* /*pWin*/)
{
    OutlinerView* pOlView = GetOutlinerView();

    if (pOlView)
    {
        pOlView->HideCursor();
        pOlView->Paint(rRect);

        pOlView->ShowCursor(mbFirstPaint);
        mbFirstPaint = false;
    }
}

void NotesPanelView::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:
                FillOutliner();
                break;
            case SdrHintKind::ObjectChange:
            case SdrHintKind::EndEdit:
                FillOutliner();
                break;
            default:
                break;
        }
    }
}

OutlinerView* NotesPanelView::GetOutlinerView() { return &maOutlinerView; }

void NotesPanelView::onUpdateStyleSettings(bool bForceUpdate /* = false */)
{
    svtools::ColorConfig aColorConfig;
    const Color aDocColor(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
    if (!(bForceUpdate || (maDocColor != aDocColor)))
        return;

    maOutlinerView.SetBackgroundColor(aDocColor);
    if (vcl::Window* pWindow = maOutlinerView.GetWindow())
        pWindow->SetBackground(Wallpaper(aDocColor));

    maOutliner.SetBackgroundColor(aDocColor);
    maDocColor = aDocColor;
}

void NotesPanelView::onResize()
{
    ::sd::Window* pWin = mrNotesPanelViewShell.GetActiveWindow();
    OutlinerView* pOutlinerView = GetOutlinerView();

    Size aOutputSize = pWin->PixelToLogic(pWin->GetOutputSizePixel());

    pOutlinerView->SetOutputArea({ Point(0, 0), aOutputSize });
    maOutliner.SetPaperSize(aOutputSize);
    pOutlinerView->ShowCursor();

    const ::tools::Long nMaxVisAreaStart = maOutliner.GetTextHeight() - aOutputSize.Height();

    ::tools::Rectangle aVisArea(pOutlinerView->GetVisArea());

    if (aVisArea.Top() > nMaxVisAreaStart)
    {
        aVisArea.SetTop(std::max<::tools::Long>(nMaxVisAreaStart, 0));
        aVisArea.SetSize(aOutputSize);
        pOutlinerView->SetVisArea(aVisArea);
        pOutlinerView->ShowCursor();
    }

    if (!aVisArea.IsEmpty()) // not when opening
    {
        mrNotesPanelViewShell.InitWindows(Point(0, 0), aVisArea.GetSize(), aVisArea.TopLeft());
        mrNotesPanelViewShell.UpdateScrollBars();
    }
}

/**
 * Handler for StatusEvents
 */
IMPL_LINK_NOARG(NotesPanelView, StatusEventHdl, EditStatus&, void) { onResize(); }

IMPL_LINK_NOARG(NotesPanelView, 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(NotesPanelView, ModifyTimerHdl, Timer*, void)
{
    setNotesToDoc();
    aModifyIdle.Stop();
}

IMPL_LINK(NotesPanelView, EventMultiplexerListener, tools::EventMultiplexerEvent&, rEvent, void)
{
    switch (rEvent.meEventId)
    {
        case EventMultiplexerEventId::CurrentPageChanged:
        case EventMultiplexerEventId::MainViewRemoved:
        case EventMultiplexerEventId::MainViewAdded:
            FillOutliner();
            break;
        default:
            break;
    }
}

OutlinerView* NotesPanelView::GetViewByWindow(vcl::Window const* /*pWin*/) const
{
    return const_cast<NotesPanelView*>(this)->GetOutlinerView();
}

/**
 * Set attributes of the selected text
 */
bool NotesPanelView::SetAttributes(const SfxItemSet& rSet, bool /*bSlide*/, bool /*bReplaceAll*/,
                                   bool /*bMaster*/)
{
    bool bOk = false;

    OutlinerView* pOlView = GetOutlinerView();

    if (pOlView)
    {
        pOlView->SetAttribs(rSet);
        bOk = true;
    }

    mrNotesPanelViewShell.Invalidate(SID_PREVIEW_STATE);

    return bOk;
}

/**
 * Get attributes of the selected text
 */
void NotesPanelView::GetAttributes(SfxItemSet& rTargetSet, bool) const
{
    rTargetSet.Put(const_cast<OutlinerView&>(maOutlinerView).GetAttribs(), false);
}

SvtScriptType NotesPanelView::GetScriptType() const
{
    SvtScriptType nScriptType = ::sd::View::GetScriptType();

    std::optional<OutlinerParaObject> pTempOPObj = maOutliner.CreateParaObject();
    if (pTempOPObj)
    {
        nScriptType = pTempOPObj->GetTextObject().GetScriptType();
    }

    return nScriptType;
}

} // 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/NotesPanelViewShell.cxx b/sd/source/ui/view/NotesPanelViewShell.cxx
new file mode 100644
index 0000000..ec849a2
--- /dev/null
+++ b/sd/source/ui/view/NotesPanelViewShell.cxx
@@ -0,0 +1,1448 @@
/* -*- 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 <NotesPanelViewShell.hxx>
#include <NotesPanelView.hxx>
#include <sal/log.hxx>

#include <DrawController.hxx>
#include <DrawDocShell.hxx>
#include <DrawViewShell.hxx>
#include <FrameView.hxx>
#include <SpellDialogChildWindow.hxx>
#include <ViewShellBase.hxx>
#include <Window.hxx>
#include <app.hrc>
#include <com/sun/star/linguistic2/XThesaurus.hpp>
#include <drawdoc.hxx>
#include <editeng/editobj.hxx>
#include <editeng/editstat.hxx>
#include <editeng/editund2.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/unolingu.hxx>
#include <framework/FrameworkHelper.hxx>
#include <fubullet.hxx>
#include <fuchar.hxx>
#include <fucushow.hxx>
#include <fuexpand.hxx>
#include <fuinsfil.hxx>
#include <fuolbull.hxx>
#include <fuoltext.hxx>
#include <fuprobjs.hxx>
#include <fuscale.hxx>
#include <fusldlg.hxx>
#include <fusumry.hxx>
#include <futempl.hxx>
#include <futhes.hxx>
#include <memory>
#include <sdabstdlg.hxx>
#include <sdpage.hxx>
#include <sdresid.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/request.hxx>
#include <sfx2/sidebar/SidebarChildWindow.hxx>
#include <sfx2/tplpitem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/zoomitem.hxx>
#include <slideshow.hxx>
#include <sot/formats.hxx>
#include <stlsheet.hxx>
#include <strings.hrc>
#include <svl/cjkoptions.hxx>
#include <svl/srchitem.hxx>
#include <svl/stritem.hxx>
#include <svl/whiter.hxx>
#include <svtools/cliplistener.hxx>
#include <svx/hlnkitem.hxx>
#include <svx/hyperdlg.hxx>
#include <svx/svdoutl.hxx>
#include <svx/svxids.hrc>
#include <svx/zoomslideritem.hxx>
#include <unotools/useroptions.hxx>
#include <vcl/EnumContext.hxx>
#include <vcl/commandevent.hxx>
#include <zoomlist.hxx>

#include <TextObjectBar.hxx>

#include <memory>

#define ShellClass_NotesPanelViewShell
using namespace sd;
#include <sdslots.hxx>

namespace sd
{
#define MIN_ZOOM 10 // minimum zoom factor
#define MAX_ZOOM 1000 // maximum zoom factor

/**
 * Declare SFX-Slotmap and standard interface
 */
SFX_IMPL_INTERFACE(NotesPanelViewShell, SfxShell)

void NotesPanelViewShell::InitInterface_Impl()
{
    GetStaticInterface()->RegisterPopupMenu("drawtext");

    GetStaticInterface()->RegisterChildWindow(SvxHlinkDlgWrapper::GetChildWindowId());
    GetStaticInterface()->RegisterChildWindow(::sd::SpellDialogChildWindow::GetChildWindowId());
    GetStaticInterface()->RegisterChildWindow(SID_SEARCH_DLG);
    GetStaticInterface()->RegisterChildWindow(
        sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
    GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
}

/**
 * Default constructor, windows must not center themselves automatically
 */
NotesPanelViewShell::NotesPanelViewShell(SfxViewFrame* /*pFrame*/, ViewShellBase& rViewShellBase,
                                         vcl::Window* pParentWindow, FrameView* pFrameViewArgument)
    : ViewShell(pParentWindow, rViewShellBase)
{
    if (pFrameViewArgument != nullptr)
        mpFrameView = pFrameViewArgument;
    else
        mpFrameView = new FrameView(GetDoc());

    mpFrameView->Connect();

    Construct();

    SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::DrawText));

    doShow();
    mpHorizontalScrollBar->Hide();
}

NotesPanelViewShell::~NotesPanelViewShell()
{
    DisposeFunctions();
    mpFrameView->Disconnect();
    // if ( mxClipEvtLstnr.is() )
    // {
    //     mxClipEvtLstnr->RemoveListener( GetActiveWindow() );
    //     mxClipEvtLstnr->ClearCallbackLink();     // prevent callback if another thread is waiting
    // }
}

void NotesPanelViewShell::Construct()
{
    meShellType = ST_NOTESPANEL;

    Size aSize(29700, 21000);
    Point aWinPos(0, 0);
    Point aViewOrigin(0, 0);
    GetActiveWindow()->SetMinZoomAutoCalc(false);
    GetActiveWindow()->SetMinZoom(MIN_ZOOM);
    GetActiveWindow()->SetMaxZoom(MAX_ZOOM);
    InitWindows(aViewOrigin, aSize, aWinPos);

    mpNotesPanelView = std::make_unique<NotesPanelView>(*GetDocSh(), GetActiveWindow(), *this);
    mpView = mpNotesPanelView.get();

    SetPool(&GetDoc()->GetPool());
    SetZoom(70);

    // Apply settings of FrameView
    ReadFrameViewData(mpFrameView);

    SetName("NotesPanelViewShell");
    // TODO: Help ID
    // GetActiveWindow()->SetHelpId(HID_SDNOTESPANEL);
}

void NotesPanelViewShell::Paint(const ::tools::Rectangle& rRect, ::sd::Window* pWin)
{
    if (mpNotesPanelView)
        mpNotesPanelView->Paint(rRect, pWin);
}

bool NotesPanelViewShell::PrepareClose(bool bUI)
{
    if (!ViewShell::PrepareClose(bUI))
        return false;

    return true;
}

void NotesPanelViewShell::VirtHScrollHdl(ScrollAdaptor* /*pHScroll*/)
{
    // no horizontal scroll
    return;
}

void NotesPanelViewShell::UpdateScrollBars()
{
    if (!mpVerticalScrollBar)
        return;

    OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();
    const SdOutliner& rOutliner = mpNotesPanelView->GetOutliner();

    int nVUpper = rOutliner.GetTextHeight();
    int nVCurrentDocPos = pOutlinerView->GetVisArea().Top();
    const Size aOut(pOutlinerView->GetOutputArea().GetSize());
    int nVStepIncrement = aOut.Height() * 2 / 10;
    int nVPageIncrement = aOut.Height() * 8 / 10;
    int nVPageSize = aOut.Height();

    nVPageSize = std::min(nVPageSize, nVUpper);

    mpVerticalScrollBar->SetRange({ 0, nVUpper });
    mpVerticalScrollBar->SetVisibleSize(nVPageSize);
    mpVerticalScrollBar->SetThumbPos(nVCurrentDocPos);
    mpVerticalScrollBar->SetLineSize(nVStepIncrement);
    mpVerticalScrollBar->SetPageSize(nVPageIncrement);

    // TODO: This is a workaround for the view going blank when overflow the current view with text.
    // The extra faulty draw call still happens.. Should get rid of that before removing this.
    VirtVScrollHdl(mpVerticalScrollBar);
}

void NotesPanelViewShell::VirtVScrollHdl(ScrollAdaptor* /*pVScroll*/)
{
    OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();

    if (pOutlinerView)
    {
        pOutlinerView->SetVisArea({ Point(0, mpVerticalScrollBar->GetThumbPos()),
                                    pOutlinerView->GetVisArea().GetSize() });
        pOutlinerView->GetEditView().Invalidate();

        auto currentDocPos = pOutlinerView->GetVisArea().Top();
        auto nDiff = currentDocPos - mpVerticalScrollBar->GetThumbPos();
        pOutlinerView->Scroll(0, nDiff);
    }
}

void NotesPanelViewShell::VisAreaChanged(const ::tools::Rectangle& rRect)
{
    ViewShell::VisAreaChanged(rRect);
    GetViewShellBase().GetDrawController()->FireVisAreaChanged(rRect);
}

void NotesPanelViewShell::ArrangeGUIElements()
{
    // Retrieve the current size (thickness) of the scroll bars.  That is
    // the width of the vertical and the height of the horizontal scroll
    // bar.
    int nScrollBarSize = GetParentWindow()->GetSettings().GetStyleSettings().GetScrollBarSize();
    maScrBarWH = Size(nScrollBarSize, nScrollBarSize);

    ViewShell::ArrangeGUIElements();

    ::sd::Window* pWindow = mpContentWindow.get();
    if (pWindow == nullptr)
        return;

    pWindow->SetMinZoomAutoCalc(false);
    mpNotesPanelView->onResize();
}

SdPage* NotesPanelViewShell::GetActualPage() { return getCurrentPage(); }

SdPage* NotesPanelViewShell::getCurrentPage() const
{
    SdPage* pCurrentPage = nullptr;

    std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
    if (pMainViewShell)
        pCurrentPage = pMainViewShell->GetActualPage();

    if (!pCurrentPage)
        return nullptr;

    switch (pCurrentPage->GetPageKind())
    {
        case PageKind::Standard:
            return GetDoc()->GetSdPage((pCurrentPage->GetPageNum() - 1) >> 1, PageKind::Notes);
        case PageKind::Notes:
            return pCurrentPage;
        case PageKind::Handout:
        default:
            return nullptr;
    }
}

css::uno::Reference<css::drawing::XDrawSubController> NotesPanelViewShell::CreateSubController()
{
    // SubController appears is only relevant for MainViewShell
    // NotesPanel isn't meant as a MainViewShell
    return {};
}

void NotesPanelViewShell::ReadFrameViewData(FrameView* /*pView*/)
{
    DrawController& rController(*GetViewShellBase().GetDrawController());
    rController.FireSelectionChangeListener();
}

void NotesPanelViewShell::WriteFrameViewData() {}

/**
 * Activate(): during the first invocation the fields get updated
 */
void NotesPanelViewShell::Activate(bool bIsMDIActivate)
{
    if (!mbInitialized)
    {
        mbInitialized = true;
        SfxRequest aRequest(SID_EDIT_OUTLINER, SfxCallMode::SLOT, GetDoc()->GetItemPool());
        FuPermanent(aRequest);
    }

    ViewShell::Activate(bIsMDIActivate);
    SfxShell::BroadcastContextForActivation(true);

    if (bIsMDIActivate)
    {
        OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();
        ::Outliner* pOutl = pOutlinerView->GetOutliner();
        pOutl->UpdateFields();
    }
}

/**
 * SfxRequests for permanent functions
 */
void NotesPanelViewShell::FuPermanent(SfxRequest& rReq)
{
    if (HasCurrentFunction())
    {
        DeactivateCurrentFunction(true);
    }

    switch (rReq.GetSlot())
    {
        case SID_EDIT_OUTLINER:
        {
            ::Outliner& rOutl = mpNotesPanelView->GetOutliner();
            rOutl.GetUndoManager().Clear();
            rOutl.UpdateFields();

            SetCurrentFunction(FuSimpleOutlinerText::Create(
                this, GetActiveWindow(), mpNotesPanelView.get(), GetDoc(), rReq));

            rReq.Done();
        }
        break;

        default:
            break;
    }

    if (HasOldFunction())
    {
        GetOldFunction()->Deactivate();
        SetOldFunction(nullptr);
    }

    if (HasCurrentFunction())
    {
        GetCurrentFunction()->Activate();
        SetOldFunction(GetCurrentFunction());
    }
}

/**
 * Zoom with zoom factor. Inform OutlinerView
 */
void NotesPanelViewShell::SetZoom(::tools::Long nZoom)
{
    ViewShell::SetZoom(nZoom);

    ::sd::Window* pWindow = mpContentWindow.get();
    if (pWindow)
        mpNotesPanelView->onResize();

    GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM);
    GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER);
}

/**
 * Zoom with zoom rectangle. Inform OutlinerView
 */
void NotesPanelViewShell::SetZoomRect(const ::tools::Rectangle& rZoomRect)
{
    ViewShell::SetZoomRect(rZoomRect);

    ::sd::Window* pWindow = mpContentWindow.get();
    if (pWindow)
        mpNotesPanelView->onResize();

    GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM);
    GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER);
}

void NotesPanelViewShell::ExecCtrl(SfxRequest& rReq)
{
    sal_uInt16 nSlot = rReq.GetSlot();
    switch (nSlot)
    {
        case SID_MAIL_SCROLLBODY_PAGEDOWN:
        {
            ExecReq(rReq);
            break;
        }

        case SID_OPT_LOCALE_CHANGED:
        {
            mpNotesPanelView->GetOutliner().UpdateFields();
            rReq.Done();
            break;
        }

        default:
            break;
    }
}

void NotesPanelViewShell::GetCtrlState(SfxItemSet& rSet)
{
    if (SfxItemState::DEFAULT == rSet.GetItemState(SID_HYPERLINK_GETLINK))
    {
        SvxHyperlinkItem aHLinkItem;

        OutlinerView* pOLV = mpNotesPanelView->GetOutlinerView();
        if (pOLV)
        {
            const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection();
            if (pFieldItem)
            {
                ESelection aSel = pOLV->GetSelection();
                if (abs(aSel.nEndPos - aSel.nStartPos) == 1)
                {
                    const SvxFieldData* pField = pFieldItem->GetField();
                    if (auto pUrlField = dynamic_cast<const SvxURLField*>(pField))
                    {
                        aHLinkItem.SetName(pUrlField->GetRepresentation());
                        aHLinkItem.SetURL(pUrlField->GetURL());
                        aHLinkItem.SetTargetFrame(pUrlField->GetTargetFrame());
                    }
                }
            }
        }
        rSet.Put(aHLinkItem);
    }
    rSet.Put(SfxBoolItem(SID_READONLY_MODE, GetDocSh()->IsReadOnly()));

    if (SfxItemState::DEFAULT == rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN))
        rSet.Put(SfxBoolItem(SID_MAIL_SCROLLBODY_PAGEDOWN, true));

    if (!(SfxItemState::DEFAULT == rSet.GetItemState(SID_TRANSLITERATE_HALFWIDTH)
          || SfxItemState::DEFAULT == rSet.GetItemState(SID_TRANSLITERATE_FULLWIDTH)
          || SfxItemState::DEFAULT == rSet.GetItemState(SID_TRANSLITERATE_HIRAGANA)
          || SfxItemState::DEFAULT == rSet.GetItemState(SID_TRANSLITERATE_KATAKANA)))
        return;

    if (!SvtCJKOptions::IsChangeCaseMapEnabled())
    {
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_HALFWIDTH, false);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_FULLWIDTH, false);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_HIRAGANA, false);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_KATAKANA, false);
        rSet.DisableItem(SID_TRANSLITERATE_HALFWIDTH);
        rSet.DisableItem(SID_TRANSLITERATE_FULLWIDTH);
        rSet.DisableItem(SID_TRANSLITERATE_HIRAGANA);
        rSet.DisableItem(SID_TRANSLITERATE_KATAKANA);
    }
    else
    {
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_HALFWIDTH, true);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_FULLWIDTH, true);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_HIRAGANA, true);
        GetViewFrame()->GetBindings().SetVisibleState(SID_TRANSLITERATE_KATAKANA, true);
    }
}

void NotesPanelViewShell::GetAttrState(SfxItemSet& rSet)
{
    SfxWhichIter aIter(rSet);
    sal_uInt16 nWhich = aIter.FirstWhich();
    SfxAllItemSet aAllSet(*rSet.GetPool());

    while (nWhich)
    {
        sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich) ? GetPool().GetSlotId(nWhich) : nWhich;

        switch (nSlotId)
        {
            case SID_STYLE_FAMILY2:
            case SID_STYLE_FAMILY3:
            {
                rSet.DisableItem(nWhich);
            }
            break;

            case SID_STYLE_FAMILY5:
            {
                SfxStyleSheet* pStyleSheet = mpNotesPanelView->GetOutlinerView()->GetStyleSheet();

                if (pStyleSheet)
                {
                    pStyleSheet = static_cast<SdStyleSheet*>(pStyleSheet)->GetPseudoStyleSheet();

                    if (pStyleSheet)
                    {
                        SfxTemplateItem aItem(nWhich, pStyleSheet->GetName());
                        aAllSet.Put(aItem);
                    }
                }

                if (!pStyleSheet)
                {
                    SfxTemplateItem aItem(nWhich, OUString());
                    aAllSet.Put(aItem);
                }
            }
            break;

            case SID_STYLE_EDIT:
            {
                std::unique_ptr<SfxUInt16Item> pFamilyItem;
                GetViewFrame()->GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem);
                if (pFamilyItem
                    && static_cast<SfxStyleFamily>(pFamilyItem->GetValue())
                           == SfxStyleFamily::Pseudo)
                {
                    rSet.DisableItem(nWhich);
                }
            }
            break;

            case SID_STYLE_UPDATE_BY_EXAMPLE:
            {
                OutlinerView* pOV = mpNotesPanelView->GetOutlinerView();
                ESelection aESel(pOV->GetSelection());

                if (aESel.nStartPara != aESel.nEndPara || aESel.nStartPos != aESel.nEndPos)
                    // spanned selection, i.e. StyleSheet and/or
                    // attribution not necessarily unique
                    rSet.DisableItem(nWhich);
            }
            break;

            case SID_STYLE_NEW:
            case SID_STYLE_DELETE:
            case SID_STYLE_HIDE:
            case SID_STYLE_SHOW:
            case SID_STYLE_NEW_BY_EXAMPLE:
            case SID_STYLE_WATERCAN:
            {
                rSet.DisableItem(nWhich);
            }
            break;

            default:
                break;
        }

        nWhich = aIter.NextWhich();
    }

    rSet.Put(aAllSet, false);
    TextObjectBar::GetAttrStateImpl(this, mpView, rSet, nullptr);
}

void NotesPanelViewShell::GetState(SfxItemSet& rSet)
{
    // Iterate over all requested items in the set.
    SfxWhichIter aIter(rSet);
    sal_uInt16 nWhich = aIter.FirstWhich();
    while (nWhich)
    {
        switch (nWhich)
        {
            case SID_SEARCH_ITEM:
            case SID_SEARCH_OPTIONS:
                // Call common (old) implementation in the document shell.
                GetDocSh()->GetState(rSet);
                break;
            default:
                SAL_WARN("sd",
                         "NotesPanelViewShell::GetState(): can not handle which id " << nWhich);
                break;
        }
        nWhich = aIter.NextWhich();
    }
}

void NotesPanelViewShell::GetCharState(SfxItemSet& rSet)
{
    TextObjectBar::GetCharStateImpl(this, mpView, rSet);
}

void NotesPanelViewShell::ExecStatusBar(SfxRequest& /*rReq*/) {}

void NotesPanelViewShell::GetStatusBarState(SfxItemSet& rSet)
{
    // Zoom-Item
    if (SfxItemState::DEFAULT == rSet.GetItemState(SID_ATTR_ZOOM))
    {
        sal_uInt16 nZoom = static_cast<sal_uInt16>(GetActiveWindow()->GetZoom());

        std::unique_ptr<SvxZoomItem> pZoomItem(new SvxZoomItem(SvxZoomType::PERCENT, nZoom));

        // limit area
        SvxZoomEnableFlags nZoomValues = SvxZoomEnableFlags::ALL;
        nZoomValues &= ~SvxZoomEnableFlags::OPTIMAL;
        nZoomValues &= ~SvxZoomEnableFlags::WHOLEPAGE;
        nZoomValues &= ~SvxZoomEnableFlags::PAGEWIDTH;

        pZoomItem->SetValueSet(nZoomValues);
        rSet.Put(std::move(pZoomItem));
    }

    if (SfxItemState::DEFAULT == rSet.GetItemState(SID_ATTR_ZOOMSLIDER))
    {
        if (GetDocSh()->IsUIActive() || !GetActiveWindow())
        {
            rSet.DisableItem(SID_ATTR_ZOOMSLIDER);
        }
        else
        {
            sd::Window* pActiveWindow = GetActiveWindow();
            SvxZoomSliderItem aZoomItem(static_cast<sal_uInt16>(pActiveWindow->GetZoom()),
                                        static_cast<sal_uInt16>(pActiveWindow->GetMinZoom()),
                                        static_cast<sal_uInt16>(pActiveWindow->GetMaxZoom()));
            aZoomItem.AddSnappingPoint(100);
            rSet.Put(aZoomItem);
        }
    }

    // TODO: page view and layout strings
    // rSet.Put( SfxStringItem( SID_STATUS_PAGE, aPageStr ) );
    // rSet.Put( SfxStringItem( SID_STATUS_LAYOUT, aLayoutStr ) );
}

void NotesPanelViewShell::FuTemporary(SfxRequest& rReq)
{
    DeactivateCurrentFunction();

    OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();
    sal_uInt16 nSId = rReq.GetSlot();

    switch (nSId)
    {
        case SID_ATTR_ZOOM:
        {
            const SfxItemSet* pArgs = rReq.GetArgs();

            if (pArgs)
            {
                SvxZoomType eZT = pArgs->Get(SID_ATTR_ZOOM).GetType();
                switch (eZT)
                {
                    case SvxZoomType::PERCENT:
                        SetZoom(static_cast<::tools::Long>(pArgs->Get(SID_ATTR_ZOOM).GetValue()));
                        Invalidate(SID_ATTR_ZOOM);
                        Invalidate(SID_ATTR_ZOOMSLIDER);
                        break;
                    default:
                        break;
                }
                rReq.Done();
            }
            else
            {
                // open the zoom dialog here
                SetCurrentFunction(FuScale::Create(this, GetActiveWindow(), mpNotesPanelView.get(),
                                                   GetDoc(), rReq));
            }
            Cancel();
        }
        break;

        case SID_ATTR_ZOOMSLIDER:
        {
            const SfxItemSet* pArgs = rReq.GetArgs();

            const SfxUInt16Item* pScale
                = (pArgs && pArgs->Count() == 1) ? rReq.GetArg(SID_ATTR_ZOOMSLIDER) : nullptr;
            if (pScale && CHECK_RANGE(5, pScale->GetValue(), 3000))
            {
                SetZoom(pScale->GetValue());

                SfxBindings& rBindings = GetViewFrame()->GetBindings();
                rBindings.Invalidate(SID_ATTR_ZOOM);
                rBindings.Invalidate(SID_ZOOM_IN);
                rBindings.Invalidate(SID_ZOOM_OUT);
                rBindings.Invalidate(SID_ATTR_ZOOMSLIDER);
            }

            Cancel();
            rReq.Done();
            break;
        }

        case SID_ZOOM_IN:
        {
            SetZoom(std::min<::tools::Long>(GetActiveWindow()->GetZoom() * 2,
                                            GetActiveWindow()->GetMaxZoom()));
            ::tools::Rectangle aVisAreaWin = GetActiveWindow()->PixelToLogic(
                ::tools::Rectangle(Point(0, 0), GetActiveWindow()->GetOutputSizePixel()));
            mpZoomList->InsertZoomRect(aVisAreaWin);
            Invalidate(SID_ATTR_ZOOM);
            Invalidate(SID_ZOOM_IN);
            Invalidate(SID_ZOOM_OUT);
            Invalidate(SID_ATTR_ZOOMSLIDER);
            Cancel();
            rReq.Done();
        }
        break;

        case SID_SIZE_REAL:
        {
            SetZoom(100);
            ::tools::Rectangle aVisAreaWin = GetActiveWindow()->PixelToLogic(
                ::tools::Rectangle(Point(0, 0), GetActiveWindow()->GetOutputSizePixel()));
            mpZoomList->InsertZoomRect(aVisAreaWin);
            Invalidate(SID_ATTR_ZOOM);
            Invalidate(SID_ATTR_ZOOMSLIDER);
            Cancel();
            rReq.Done();
        }
        break;

        case SID_ZOOM_OUT:
        {
            SetZoom(std::max<::tools::Long>(GetActiveWindow()->GetZoom() / 2,
                                            GetActiveWindow()->GetMinZoom()));
            ::tools::Rectangle aVisAreaWin = GetActiveWindow()->PixelToLogic(
                ::tools::Rectangle(Point(0, 0), GetActiveWindow()->GetOutputSizePixel()));
            mpZoomList->InsertZoomRect(aVisAreaWin);
            Invalidate(SID_ATTR_ZOOM);
            Invalidate(SID_ZOOM_OUT);
            Invalidate(SID_ZOOM_IN);
            Invalidate(SID_ATTR_ZOOMSLIDER);
            Cancel();
            rReq.Done();
        }
        break;

        case SID_SELECTALL:
        {
            ::Outliner& rOutl = mpNotesPanelView->GetOutliner();
            sal_Int32 nParaCount = rOutl.GetParagraphCount();
            if (nParaCount > 0)
            {
                pOutlinerView->SelectRange(0, nParaCount);
            }
            Cancel();
        }
        break;

        case SID_PRESENTATION:
        case SID_PRESENTATION_CURRENT_SLIDE:
        case SID_REHEARSE_TIMINGS:
        {
            slideshowhelp::ShowSlideShow(rReq, *GetDoc());
            Cancel();
            rReq.Done();
        }
        break;

        case SID_STYLE_EDIT:
        case SID_STYLE_UPDATE_BY_EXAMPLE:
        {
            if (rReq.GetArgs())
            {
                SetCurrentFunction(FuTemplate::Create(this, GetActiveWindow(),
                                                      mpNotesPanelView.get(), GetDoc(), rReq));
                Cancel();
            }

            rReq.Ignore();
        }
        break;

        case SID_PRESENTATION_DLG:
        {
            SetCurrentFunction(FuSlideShowDlg::Create(this, GetActiveWindow(),
                                                      mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_REMOTE_DLG:
        {
#ifdef ENABLE_SDREMOTE
            SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
            ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateRemoteDialog(GetFrameWeld()));
            pDlg->Execute();
#endif
        }
        break;

        case SID_CUSTOMSHOW_DLG:
        {
            SetCurrentFunction(FuCustomShowDlg::Create(this, GetActiveWindow(),
                                                       mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_PHOTOALBUM:
        {
            SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
            vcl::Window* pWin = GetActiveWindow();
            ScopedVclPtr<VclAbstractDialog> pDlg(
                pFact->CreateSdPhotoAlbumDialog(pWin ? pWin->GetFrameWeld() : nullptr, GetDoc()));

            pDlg->Execute();

            Cancel();
            rReq.Ignore();
        }
        break;
    }

    if (HasCurrentFunction())
        GetCurrentFunction()->Activate();

    Invalidate(SID_CUT);
    Invalidate(SID_COPY);
    Invalidate(SID_PASTE);
    Invalidate(SID_PASTE_UNFORMATTED);
}

void NotesPanelViewShell::FuTemporaryModify(SfxRequest& rReq)
{
    DeactivateCurrentFunction();

    OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();

    sal_uInt16 nSId = rReq.GetSlot();
    switch (nSId)
    {
        case SID_HYPERLINK_SETLINK:
        {
            const SfxItemSet* pReqArgs = rReq.GetArgs();

            if (pReqArgs)
            {
                const SvxHyperlinkItem* pHLItem = &pReqArgs->Get(SID_HYPERLINK_SETLINK);

                SvxFieldItem aURLItem(
                    SvxURLField(pHLItem->GetURL(), pHLItem->GetName(), SvxURLFormat::Repr),
                    EE_FEATURE_FIELD);
                ESelection aSel(pOutlinerView->GetSelection());
                pOutlinerView->InsertField(aURLItem);
                if (aSel.nStartPos <= aSel.nEndPos)
                    aSel.nEndPos = aSel.nStartPos + 1;
                else
                    aSel.nStartPos = aSel.nEndPos + 1;
                pOutlinerView->SetSelection(aSel);
            }

            Cancel();
            rReq.Ignore();
        }
        break;

        case FN_INSERT_SOFT_HYPHEN:
        case FN_INSERT_HARDHYPHEN:
        case FN_INSERT_HARD_SPACE:
        case FN_INSERT_NNBSP:
        case SID_INSERT_RLM:
        case SID_INSERT_LRM:
        case SID_INSERT_WJ:
        case SID_INSERT_ZWSP:
        case SID_CHARMAP:
        {
            SetCurrentFunction(
                FuBullet::Create(this, GetActiveWindow(), mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_OUTLINE_BULLET:
        case FN_SVX_SET_BULLET:
        case FN_SVX_SET_NUMBER:
        {
            SetCurrentFunction(FuBulletAndPosition::Create(this, GetActiveWindow(),
                                                           mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_THESAURUS:
        {
            SetCurrentFunction(FuThesaurus::Create(this, GetActiveWindow(), mpNotesPanelView.get(),
                                                   GetDoc(), rReq));
            Cancel();
            rReq.Ignore();
        }
        break;

        case SID_CHAR_DLG_EFFECT:
        case SID_CHAR_DLG:
        {
            SetCurrentFunction(
                FuChar::Create(this, GetActiveWindow(), mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_INSERTFILE:
        {
            SetCurrentFunction(FuInsertFile::Create(this, GetActiveWindow(), mpNotesPanelView.get(),
                                                    GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_PRESENTATIONOBJECT:
        {
            SetCurrentFunction(FuPresentationObjects::Create(
                this, GetActiveWindow(), mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_SET_DEFAULT:
        {
            pOutlinerView->RemoveAttribs(true); // sal_True = also paragraph attributes
            Cancel();
            rReq.Done();
        }
        break;

        case SID_SUMMARY_PAGE:
        {
            SetCurrentFunction(FuSummaryPage::Create(this, GetActiveWindow(),
                                                     mpNotesPanelView.get(), GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_EXPAND_PAGE:
        {
            SetCurrentFunction(FuExpandPage::Create(this, GetActiveWindow(), mpNotesPanelView.get(),
                                                    GetDoc(), rReq));
            Cancel();
        }
        break;

        case SID_INSERT_FLD_DATE_FIX:
        case SID_INSERT_FLD_DATE_VAR:
        case SID_INSERT_FLD_TIME_FIX:
        case SID_INSERT_FLD_TIME_VAR:
        case SID_INSERT_FLD_AUTHOR:
        case SID_INSERT_FLD_PAGE:
        case SID_INSERT_FLD_PAGE_TITLE:
        case SID_INSERT_FLD_PAGES:
        case SID_INSERT_FLD_FILE:
        {
            std::unique_ptr<SvxFieldItem> pFieldItem;

            switch (nSId)
            {
                case SID_INSERT_FLD_DATE_FIX:
                    pFieldItem.reset(new SvxFieldItem(
                        SvxDateField(Date(Date::SYSTEM), SvxDateType::Fix), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_DATE_VAR:
                    pFieldItem.reset(new SvxFieldItem(SvxDateField(), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_TIME_FIX:
                    pFieldItem.reset(new SvxFieldItem(
                        SvxExtTimeField(::tools::Time(::tools::Time::SYSTEM), SvxTimeType::Fix),
                        EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_TIME_VAR:
                    pFieldItem.reset(new SvxFieldItem(SvxExtTimeField(), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_AUTHOR:
                {
                    SvtUserOptions aUserOptions;
                    pFieldItem.reset(new SvxFieldItem(SvxAuthorField(aUserOptions.GetFirstName(),
                                                                     aUserOptions.GetLastName(),
                                                                     aUserOptions.GetID()),
                                                      EE_FEATURE_FIELD));
                }
                break;

                case SID_INSERT_FLD_PAGE:
                    pFieldItem.reset(new SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_PAGE_TITLE:
                    pFieldItem.reset(new SvxFieldItem(SvxPageTitleField(), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_PAGES:
                    pFieldItem.reset(new SvxFieldItem(SvxPagesField(), EE_FEATURE_FIELD));
                    break;

                case SID_INSERT_FLD_FILE:
                {
                    OUString aName;
                    if (GetDocSh()->HasName())
                        aName = GetDocSh()->GetMedium()->GetName();
                    pFieldItem.reset(new SvxFieldItem(SvxExtFileField(aName), EE_FEATURE_FIELD));
                }
                break;
            }

            const SvxFieldItem* pOldFldItem = pOutlinerView->GetFieldAtSelection();

            if (pOldFldItem
                && (nullptr != dynamic_cast<const SvxURLField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxDateField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxTimeField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxExtTimeField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxExtFileField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxAuthorField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxPageField*>(pOldFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxPagesField*>(pOldFldItem->GetField())))
            {
                // select field, so it gets deleted on Insert
                ESelection aSel = pOutlinerView->GetSelection();
                if (aSel.nStartPos == aSel.nEndPos)
                    aSel.nEndPos++;
                pOutlinerView->SetSelection(aSel);
            }

            if (pFieldItem)
                pOutlinerView->InsertField(*pFieldItem);

            pFieldItem.reset();

            Cancel();
            rReq.Ignore();
        }
        break;

        case SID_MODIFY_FIELD:
        {
            const SvxFieldItem* pFldItem = pOutlinerView->GetFieldAtSelection();

            if (pFldItem
                && (nullptr != dynamic_cast<const SvxDateField*>(pFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxAuthorField*>(pFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxExtFileField*>(pFldItem->GetField())
                    || nullptr != dynamic_cast<const SvxExtTimeField*>(pFldItem->GetField())))
            {
                // Dialog...
                SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
                vcl::Window* pWin = GetActiveWindow();
                ScopedVclPtr<AbstractSdModifyFieldDlg> pDlg(pFact->CreateSdModifyFieldDlg(
                    pWin ? pWin->GetFrameWeld() : nullptr, pFldItem->GetField(),
                    pOutlinerView->GetAttribs()));
                if (pDlg->Execute() == RET_OK)
                {
                    std::unique_ptr<SvxFieldData> pField(pDlg->GetField());
                    if (pField)
                    {
                        SvxFieldItem aFieldItem(*pField, EE_FEATURE_FIELD);
                        //pOLV->DeleteSelected(); <-- unfortunately missing!
                        // select field, so it gets deleted on Insert
                        ESelection aSel = pOutlinerView->GetSelection();
                        bool bSel = true;
                        if (aSel.nStartPos == aSel.nEndPos)
                        {
                            bSel = false;
                            aSel.nEndPos++;
                        }
                        pOutlinerView->SetSelection(aSel);

                        pOutlinerView->InsertField(aFieldItem);

                        // reset selection to original state
                        if (!bSel)
                            aSel.nEndPos--;
                        pOutlinerView->SetSelection(aSel);

                        pField.reset();
                    }

                    SfxItemSet aSet(pDlg->GetItemSet());
                    if (aSet.Count())
                    {
                        pOutlinerView->SetAttribs(aSet);

                        ::Outliner* pOutliner = pOutlinerView->GetOutliner();
                        if (pOutliner)
                            pOutliner->UpdateFields();
                    }
                }
            }

            Cancel();
            rReq.Ignore();
        }
        break;
    }

    if (HasCurrentFunction())
        GetCurrentFunction()->Activate();

    Invalidate(SID_CUT);
    Invalidate(SID_COPY);
    Invalidate(SID_PASTE);
    Invalidate(SID_PASTE_UNFORMATTED);
}

void NotesPanelViewShell::FuSupport(SfxRequest& rReq)
{
    if (rReq.GetSlot() == SID_STYLE_FAMILY && rReq.GetArgs())
        GetDocSh()->SetStyleFamily(
            static_cast<SfxStyleFamily>(rReq.GetArgs()->Get(SID_STYLE_FAMILY).GetValue()));

    bool bPreviewState = false;
    sal_uInt16 nSlot = rReq.GetSlot();

    switch (nSlot)
    {
        case SID_CUT:
        {
            if (HasCurrentFunction())
            {
                GetCurrentFunction()->DoCut();
            }
            else if (mpNotesPanelView)
            {
                mpNotesPanelView->DoCut();
            }
            rReq.Done();
            bPreviewState = true;
        }
        break;

        case SID_COPY:
        {
            if (HasCurrentFunction())
            {
                GetCurrentFunction()->DoCopy();
            }
            else if (mpNotesPanelView)
            {
                mpNotesPanelView->DoCopy();
            }
            rReq.Done();
            bPreviewState = true;
        }
        break;

        case SID_PASTE:
        {
            if (HasCurrentFunction())
            {
                GetCurrentFunction()->DoPaste();
            }
            else if (mpNotesPanelView)
            {
                mpNotesPanelView->DoPaste();
            }
            rReq.Done();
            bPreviewState = true;
        }
        break;

        case SID_PASTE_UNFORMATTED:
        {
            if (HasCurrentFunction())
            {
                GetCurrentFunction()->DoPasteUnformatted();
            }
            else if (mpNotesPanelView)
            {
                TransferableDataHelper aDataHelper(
                    TransferableDataHelper::CreateFromSystemClipboard(GetActiveWindow()));
                if (aDataHelper.GetTransferable().is())
                {
                    sal_Int8 nAction = DND_ACTION_COPY;
                    mpNotesPanelView->InsertData(
                        aDataHelper,
                        GetActiveWindow()->PixelToLogic(
                            ::tools::Rectangle(Point(), GetActiveWindow()->GetOutputSizePixel())
                                .Center()),
                        nAction, false, SotClipboardFormatId::STRING);
                }
            }

            rReq.Ignore();
        }
        break;
        case SID_DELETE:
        {
            if (mpNotesPanelView)
            {
                OutlinerView* pOutlView = mpNotesPanelView->GetOutlinerView();
                if (pOutlView)
                {
                    vcl::KeyCode aKCode(KEY_DELETE);
                    KeyEvent aKEvt(0, aKCode);
                    pOutlView->PostKeyEvent(aKEvt);

                    rtl::Reference<FuPoor> xFunc(GetCurrentFunction());
                    FuOutlineText* pFuOutlineText = dynamic_cast<FuOutlineText*>(xFunc.get());
                    if (pFuOutlineText)
                        pFuOutlineText->UpdateForKeyPress(aKEvt);
                }
            }
            rReq.Done();
            bPreviewState = true;
        }
        break;

        case SID_DRAWINGMODE:
        case SID_SLIDE_MASTER_MODE:
        case SID_NOTES_MODE:
        case SID_NOTES_MASTER_MODE:
        case SID_HANDOUT_MASTER_MODE:
        case SID_SLIDE_SORTER_MODE:
        case SID_OUTLINE_MODE:
            framework::FrameworkHelper::Instance(GetViewShellBase())
                ->HandleModeChangeSlot(nSlot, rReq);
            rReq.Done();
            break;

        case SID_RULER:
            SetRuler(!HasRuler());
            Invalidate(SID_RULER);
            rReq.Done();
            break;

        case SID_ZOOM_PREV:
        {
            if (mpZoomList->IsPreviousPossible())
            {
                SetZoomRect(mpZoomList->GetPreviousZoomRect());
            }
            rReq.Done();
        }
        break;

        case SID_ZOOM_NEXT:
        {
            if (mpZoomList->IsNextPossible())
            {
                SetZoomRect(mpZoomList->GetNextZoomRect());
            }
            rReq.Done();
        }
        break;

        case SID_AUTOSPELL_CHECK:
        {
            GetDoc()->SetOnlineSpell(!GetDoc()->GetOnlineSpell());
            rReq.Done();
        }
        break;

        case SID_TRANSLITERATE_SENTENCE_CASE:
        case SID_TRANSLITERATE_TITLE_CASE:
        case SID_TRANSLITERATE_TOGGLE_CASE:
        case SID_TRANSLITERATE_UPPER:
        case SID_TRANSLITERATE_LOWER:
        case SID_TRANSLITERATE_HALFWIDTH:
        case SID_TRANSLITERATE_FULLWIDTH:
        case SID_TRANSLITERATE_HIRAGANA:
        case SID_TRANSLITERATE_KATAKANA:
        {
            OutlinerView* pOLV = mpNotesPanelView ? mpNotesPanelView->GetOutlinerView() : nullptr;
            if (pOLV)
            {
                TransliterationFlags nType = TransliterationFlags::NONE;

                switch (nSlot)
                {
                    case SID_TRANSLITERATE_SENTENCE_CASE:
                        nType = TransliterationFlags::SENTENCE_CASE;
                        break;
                    case SID_TRANSLITERATE_TITLE_CASE:
                        nType = TransliterationFlags::TITLE_CASE;
                        break;
                    case SID_TRANSLITERATE_TOGGLE_CASE:
                        nType = TransliterationFlags::TOGGLE_CASE;
                        break;
                    case SID_TRANSLITERATE_UPPER:
                        nType = TransliterationFlags::LOWERCASE_UPPERCASE;
                        break;
                    case SID_TRANSLITERATE_LOWER:
                        nType = TransliterationFlags::UPPERCASE_LOWERCASE;
                        break;
                    case SID_TRANSLITERATE_HALFWIDTH:
                        nType = TransliterationFlags::FULLWIDTH_HALFWIDTH;
                        break;
                    case SID_TRANSLITERATE_FULLWIDTH:
                        nType = TransliterationFlags::HALFWIDTH_FULLWIDTH;
                        break;
                    case SID_TRANSLITERATE_HIRAGANA:
                        nType = TransliterationFlags::KATAKANA_HIRAGANA;
                        break;
                    case SID_TRANSLITERATE_KATAKANA:
                        nType = TransliterationFlags::HIRAGANA_KATAKANA;
                        break;
                }

                pOLV->TransliterateText(nType);
            }

            rReq.Done();
            bPreviewState = true;
        }
        break;

        // added Undo/Redo handling
        case SID_UNDO:
        {
            ImpSidUndo(rReq);
        }
        break;
        case SID_REDO:
        {
            ImpSidRedo(rReq);
        }
        break;

        default:
            break;
    }

    if (bPreviewState)
        Invalidate(SID_PREVIEW_STATE);

    Invalidate(SID_CUT);
    Invalidate(SID_COPY);
    Invalidate(SID_PASTE);
}

void NotesPanelViewShell::Execute(SfxRequest& rReq)
{
    bool bForwardCall = true;

    switch (rReq.GetSlot())
    {
        case SID_SAVEDOC:
        case SID_SAVEASDOC:
            PrepareClose();
            break;

        case SID_SEARCH_ITEM:
            // Forward this request to the common (old) code of the
            // document shell.
            GetDocSh()->Execute(rReq);
            bForwardCall = false;
            break;

        case SID_SPELL_DIALOG:
        {
            SfxViewFrame* pViewFrame = GetViewFrame();
            if (rReq.GetArgs() != nullptr)
                pViewFrame->SetChildWindow(
                    SID_SPELL_DIALOG,
                    static_cast<const SfxBoolItem&>(rReq.GetArgs()->Get(SID_SPELL_DIALOG))
                        .GetValue());
            else
                pViewFrame->ToggleChildWindow(SID_SPELL_DIALOG);

            pViewFrame->GetBindings().Invalidate(SID_SPELL_DIALOG);
            rReq.Done();
            bForwardCall = false;
        }
        break;

        default:
            break;
    }

    if (bForwardCall)
        TextObjectBar::ExecuteImpl(this, mpView, rReq, nullptr);
}

void NotesPanelViewShell::MouseButtonUp(const MouseEvent& rMEvt, ::sd::Window* pWin)
{
    // first the base classes
    ViewShell::MouseButtonUp(rMEvt, pWin);

    Invalidate(SID_STYLE_EDIT);
    Invalidate(SID_STYLE_NEW);
    Invalidate(SID_STYLE_DELETE);
    Invalidate(SID_STYLE_HIDE);
    Invalidate(SID_STYLE_SHOW);
    Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE);
    Invalidate(SID_STYLE_NEW_BY_EXAMPLE);
    Invalidate(SID_STYLE_WATERCAN);
    Invalidate(SID_STYLE_FAMILY5);
}

void NotesPanelViewShell::Command(const CommandEvent& rCEvt, ::sd::Window* pWin)
{
    if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
    {
        GetActiveWindow()->ReleaseMouse();

        OutlinerView* pOLV = mpNotesPanelView->GetOutlinerView();
        Point aPos(rCEvt.GetMousePosPixel());

        if (pOLV && pOLV->IsWrongSpelledWordAtPos(aPos))
        {
            // Popup for Online-Spelling now handled by DrawDocShell
            Link<SpellCallbackInfo&, void> aLink
                = LINK(GetDocSh(), DrawDocShell, OnlineSpellCallback);

            pOLV->ExecuteSpellPopup(aPos, aLink);
            pOLV->GetEditView().Invalidate();
        }
        else
        {
            GetViewFrame()->GetDispatcher()->ExecutePopup("drawtext");
        }
    }
    else
    {
        ViewShell::Command(rCEvt, pWin);
    }
}

bool NotesPanelViewShell::KeyInput(const KeyEvent& rKEvt, ::sd::Window* pWin)
{
    bool bReturn = false;

    if (pWin == nullptr && HasCurrentFunction())
    {
        bReturn = GetCurrentFunction()->KeyInput(rKEvt);
    }
    else
    {
        bReturn = ViewShell::KeyInput(rKEvt, pWin);
    }

    Invalidate(SID_STYLE_EDIT);
    Invalidate(SID_STYLE_NEW);
    Invalidate(SID_STYLE_DELETE);
    Invalidate(SID_STYLE_HIDE);
    Invalidate(SID_STYLE_SHOW);
    Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE);
    Invalidate(SID_STYLE_NEW_BY_EXAMPLE);
    Invalidate(SID_STYLE_WATERCAN);
    Invalidate(SID_STYLE_FAMILY5);

    vcl::KeyCode aKeyGroup(rKEvt.GetKeyCode().GetGroup());
    return bReturn;
}

} // 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/ToolBarManager.cxx b/sd/source/ui/view/ToolBarManager.cxx
index 4be073b..7dd95c9 100644
--- a/sd/source/ui/view/ToolBarManager.cxx
+++ b/sd/source/ui/view/ToolBarManager.cxx
@@ -993,6 +993,7 @@ void ToolBarRules::MainViewShellChanged (ViewShell::ShellType nShellType)
                ToolBarManager::msSlideSorterObjectBar);
            break;

        case ViewShell::ST_NOTESPANEL:
        case ViewShell::ST_NONE:
        case ViewShell::ST_PRESENTATION:
        case ViewShell::ST_SIDEBAR:
diff --git a/sd/source/ui/view/ViewShellBase.cxx b/sd/source/ui/view/ViewShellBase.cxx
index 115beb9..eb9a1d4 100644
--- a/sd/source/ui/view/ViewShellBase.cxx
+++ b/sd/source/ui/view/ViewShellBase.cxx
@@ -632,13 +632,11 @@ void ViewShellBase::Execute (SfxRequest& rRequest)
            break;

        case SID_NOTES_WINDOW:
        {
            SfxViewShell* pViewShell = SfxViewShell::Current();
            SfxViewFrame& rViewFrame = pViewShell->GetViewFrame();
            auto nID = rRequest.GetSlot();
            rViewFrame.ToggleChildWindow(nID);
            mpImpl->SetPaneVisibility(
                rRequest,
                framework::FrameworkHelper::msBottomImpressPaneURL,
                framework::FrameworkHelper::msNotesPanelViewURL);
            break;
        }

        case SID_TOGGLE_TABBAR_VISIBILITY:
        {
@@ -1344,19 +1342,10 @@ void ViewShellBase::Implementation::GetSlotState (SfxItemSet& rSet)
                        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);
                            }
                        }
                        xResourceId = ResourceId::create(
                            xContext, FrameworkHelper::msBottomImpressPaneURL);
                        bState = xConfiguration->hasResource(xResourceId);
                        break;
                    }

                    case SID_DRAWINGMODE:
                    case SID_NORMAL_MULTI_PANE_GUI:
diff --git a/sd/source/ui/view/ViewShellImplementation.cxx b/sd/source/ui/view/ViewShellImplementation.cxx
index 27d003c..b894d4e 100644
--- a/sd/source/ui/view/ViewShellImplementation.cxx
+++ b/sd/source/ui/view/ViewShellImplementation.cxx
@@ -293,6 +293,7 @@ SfxInterfaceId ViewShell::Implementation::GetViewId() const
        // Since we have to return a view id for every possible shell type
        // and there is not (yet) a proper ViewShellBase sub class for the
        // remaining types we chose the Impress factory as a fall back.
        case ViewShell::ST_NOTESPANEL:
        case ViewShell::ST_SIDEBAR:
        case ViewShell::ST_NONE:
        default:
diff --git a/sd/source/ui/view/drtxtob.cxx b/sd/source/ui/view/drtxtob.cxx
index 0a75f4d..a5b62e4 100644
--- a/sd/source/ui/view/drtxtob.cxx
+++ b/sd/source/ui/view/drtxtob.cxx
@@ -121,6 +121,11 @@ TextObjectBar::~TextObjectBar()

void TextObjectBar::GetCharState( SfxItemSet& rSet )
{
    GetCharStateImpl(mpViewShell, mpView, rSet);
}

void TextObjectBar::GetCharStateImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxItemSet& rSet)
{
    SfxItemSet  aCharAttrSet( mpView->GetDoc().GetPool() );
    mpView->GetAttributes( aCharAttrSet );

@@ -140,10 +145,15 @@ void TextObjectBar::GetCharState( SfxItemSet& rSet )
    }
}

void TextObjectBar::GetAttrState( SfxItemSet& rSet )
{
    GetAttrStateImpl(mpViewShell, mpView, rSet, this);
}

/**
 * Status of attribute items.
 */
void TextObjectBar::GetAttrState( SfxItemSet& rSet )
void TextObjectBar::GetAttrStateImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxItemSet& rSet, SfxShell* pTextObjectBar)
{
    SfxWhichIter        aIter( rSet );
    sal_uInt16              nWhich = aIter.FirstWhich();
@@ -156,7 +166,7 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet )
    while ( nWhich )
    {
        sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich)
            ? GetPool().GetSlotId(nWhich)
            ? mpView->GetDoc().GetPool().GetSlotId(nWhich)
            : nWhich;

        switch ( nSlotId )
@@ -170,7 +180,7 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet )
            case SID_ATTR_CHAR_CASEMAP:
            {
                double stretchY = 1.0;
                SvxScriptSetItem aSetItem( nSlotId, GetPool() );
                SvxScriptSetItem aSetItem( nSlotId, mpView->GetDoc().GetPool() );
                aSetItem.GetItemSet().Put( aAttrSet, false );

                SvtScriptType nScriptType = mpView->GetScriptType();
@@ -528,12 +538,15 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet )
            break;
        }

        Invalidate(SID_ATTR_PARA_ADJUST_LEFT);
        Invalidate(SID_ATTR_PARA_ADJUST_CENTER);
        Invalidate(SID_ATTR_PARA_ADJUST_RIGHT);
        Invalidate(SID_ATTR_PARA_ADJUST_BLOCK);
        Invalidate(SID_ATTR_PARA_LINESPACE);
        Invalidate(SID_ATTR_PARA_ULSPACE);
        if(pTextObjectBar)
        {
            pTextObjectBar->Invalidate(SID_ATTR_PARA_ADJUST_LEFT);
            pTextObjectBar->Invalidate(SID_ATTR_PARA_ADJUST_CENTER);
            pTextObjectBar->Invalidate(SID_ATTR_PARA_ADJUST_RIGHT);
            pTextObjectBar->Invalidate(SID_ATTR_PARA_ADJUST_BLOCK);
            pTextObjectBar->Invalidate(SID_ATTR_PARA_LINESPACE);
            pTextObjectBar->Invalidate(SID_ATTR_PARA_ULSPACE);
        }

        // paragraph text direction
        if( bDisableParagraphTextDirection )
@@ -587,7 +600,8 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet )
        SvxLRSpaceItem aLRSpace = aAttrSet.Get( EE_PARA_LRSPACE );
        aLRSpace.SetWhich(SID_ATTR_PARA_LRSPACE);
        rSet.Put(aLRSpace);
        Invalidate(SID_ATTR_PARA_LRSPACE);
        if (pTextObjectBar)
            pTextObjectBar->Invalidate(SID_ATTR_PARA_LRSPACE);

        //Added by xuxu
        SfxItemState eState = aAttrSet.GetItemState( EE_PARA_LRSPACE );
diff --git a/sd/source/ui/view/drtxtob1.cxx b/sd/source/ui/view/drtxtob1.cxx
index e7deb15..44a63a3 100644
--- a/sd/source/ui/view/drtxtob1.cxx
+++ b/sd/source/ui/view/drtxtob1.cxx
@@ -71,8 +71,12 @@ namespace sd {
/**
 * Process SfxRequests
 */
void TextObjectBar::Execute(SfxRequest& rReq)
{
    ExecuteImpl(mpViewShell, mpView, rReq, this);
}

void TextObjectBar::Execute( SfxRequest &rReq )
void TextObjectBar::ExecuteImpl(ViewShell* mpViewShell, ::sd::View* mpView, SfxRequest& rReq, SfxShell* pTextObjectBar)
{
    const SfxItemSet* pArgs = rReq.GetArgs();
    sal_uInt16 nSlot = rReq.GetSlot();
@@ -169,7 +173,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
            }
            rReq.Done();

            Invalidate();
            if(pTextObjectBar)
                pTextObjectBar->Invalidate();
            // to refresh preview (in outline mode), slot has to be invalidated:
            mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );

@@ -274,7 +279,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
            }
            rReq.Done();

            Invalidate();
            if (pTextObjectBar)
                pTextObjectBar->Invalidate();
            // to refresh preview (in outline mode), slot has to be invalidated:
            mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );
            mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_PARA_ULSPACE, true );
@@ -288,7 +294,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
                pOLV->AdjustDepth( -1 );

                // Ensure bold/italic etc. icon state updates
                Invalidate();
                if (pTextObjectBar)
                    pTextObjectBar->Invalidate();
                // trigger preview refresh
                mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );
            }
@@ -303,7 +310,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
                pOLV->AdjustDepth( 1 );

                // Ensure bold/italic etc. icon state updates
                Invalidate();
                if (pTextObjectBar)
                    pTextObjectBar->Invalidate();
                // trigger preview refresh
                mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );
            }
@@ -316,19 +324,20 @@ void TextObjectBar::Execute( SfxRequest &rReq )
            SvxLRSpaceItem aLRSpace = static_cast<const SvxLRSpaceItem&>(pArgs->Get(
                SID_ATTR_PARA_LRSPACE));

            SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aEditAttr( GetPool() );
            SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aEditAttr(mpView->GetDoc().GetPool());
            aLRSpace.SetWhich( EE_PARA_LRSPACE );

            aEditAttr.Put( aLRSpace );
            mpView->SetAttributes( aEditAttr );

            Invalidate(SID_ATTR_PARA_LRSPACE);
            if (pTextObjectBar)
                pTextObjectBar->Invalidate(SID_ATTR_PARA_LRSPACE);
        }
        break;

        case SID_HANGING_INDENT:
        {
            SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aLRSpaceSet( GetPool() );
            SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aLRSpaceSet(mpView->GetDoc().GetPool());
            mpView->GetAttributes( aLRSpaceSet );
            SvxLRSpaceItem aParaMargin( aLRSpaceSet.Get( EE_PARA_LRSPACE ) );

@@ -339,7 +348,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
            aLRSpaceSet.Put( aNewMargin );
            mpView->SetAttributes( aLRSpaceSet );

            Invalidate(SID_ATTR_PARA_LRSPACE);
            if (pTextObjectBar)
                pTextObjectBar->Invalidate(SID_ATTR_PARA_LRSPACE);
        }
        break;

@@ -383,7 +393,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
                    SDRATTR_TEXTDIRECTION ) );
            rReq.Done( aAttr );
            mpView->SetAttributes( aAttr );
            Invalidate();
            if (pTextObjectBar)
                pTextObjectBar->Invalidate();
            mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );
        }
        break;
@@ -700,7 +711,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )
                rReq.Done( aNewAttr );
                pArgs = rReq.GetArgs();

                Invalidate( SID_RULER_TEXT_RIGHT_TO_LEFT );
                if (pTextObjectBar)
                    pTextObjectBar->Invalidate(SID_RULER_TEXT_RIGHT_TO_LEFT);
            }
            else if ( nSlot == SID_ATTR_CHAR_FONT       ||
                      nSlot == SID_ATTR_CHAR_FONTHEIGHT ||
@@ -788,7 +800,8 @@ void TextObjectBar::Execute( SfxRequest &rReq )

            // invalidate entire shell because of performance and
            // extension reasons
            Invalidate();
            if (pTextObjectBar)
                pTextObjectBar->Invalidate();

            // to refresh preview (in outline mode), slot has to be invalidated:
            mpViewShell->GetViewFrame()->GetBindings().Invalidate( SID_PREVIEW_STATE, true );
@@ -802,10 +815,13 @@ void TextObjectBar::Execute( SfxRequest &rReq )
        pOLV->GetWindow()->GrabFocus();
    }

    Invalidate( SID_OUTLINE_LEFT );
    Invalidate( SID_OUTLINE_RIGHT );
    Invalidate( SID_OUTLINE_UP );
    Invalidate( SID_OUTLINE_DOWN );
    if (pTextObjectBar)
    {
        pTextObjectBar->Invalidate(SID_OUTLINE_LEFT);
        pTextObjectBar->Invalidate(SID_OUTLINE_RIGHT);
        pTextObjectBar->Invalidate(SID_OUTLINE_UP);
        pTextObjectBar->Invalidate(SID_OUTLINE_DOWN);
    }
}

} // end of namespace sd
diff --git a/sd/source/ui/view/outlview.cxx b/sd/source/ui/view/outlview.cxx
index 087aa50..ddcbf36 100644
--- a/sd/source/ui/view/outlview.cxx
+++ b/sd/source/ui/view/outlview.cxx
@@ -71,7 +71,7 @@ namespace sd {
#define PROCESS_WITH_PROGRESS_THRESHOLD  5

OutlineView::OutlineView( DrawDocShell& rDocSh, vcl::Window* pWindow, OutlineViewShell& rOutlineViewShell)
: ::sd::View(*rDocSh.GetDoc(), pWindow->GetOutDev(), &rOutlineViewShell)
: ::sd::SimpleOutlinerView(*rDocSh.GetDoc(), pWindow->GetOutDev(), &rOutlineViewShell)
, mrOutlineViewShell(rOutlineViewShell)
, mrOutliner(*mrDoc.GetOutliner())
, mnPagesToProcess(0)