/* -*- 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 <fuinsert.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 <sdmod.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>

#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(u"drawtext"_ustr);

    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(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(u"NotesPanelViewShell"_ustr);
    // 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::onGrabFocus() { mpNotesPanelView->onGrabFocus(); }

void NotesPanelViewShell::onLoseFocus() { mpNotesPanelView->onLoseFocus(); }

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);

    if (bIsMDIActivate)
    {
        OutlinerView* pOutlinerView = mpNotesPanelView->GetOutlinerView();
        ::Outliner& rOutl = pOutlinerView->GetOutliner();
        rOutl.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(FuNotesPane::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.end.nIndex - aSel.start.nIndex) == 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.HasRange())
                    // 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;
            case FN_NUM_BULLET_ON:
            case FN_NUM_NUMBERING_ON:
            {
                bool bIsBullet = false;
                bool bIsNumbering = false;
                OutlinerView* pOlView = mpNotesPanelView->GetTextEditOutlinerView();
                if (pOlView)
                {
                    pOlView->IsBulletOrNumbering(bIsBullet, bIsNumbering);
                }
                rSet.Put(SfxBoolItem(FN_NUM_BULLET_ON, bIsBullet));
                rSet.Put(SfxBoolItem(FN_NUM_NUMBERING_ON, bIsNumbering));
            }
            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 FID_SEARCH_NOW:
            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;

        case SID_PASTE_SPECIAL:
        {
            SetCurrentFunction(FuInsertClipboard::Create(*this, GetActiveWindow(),
                                                         mpNotesPanelView.get(), *GetDoc(), rReq));
            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.start.nIndex <= aSel.end.nIndex)
                    aSel.end.nIndex = aSel.start.nIndex + 1;
                else
                    aSel.start.nIndex = aSel.end.nIndex + 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 FN_NUM_BULLET_ON:
        {
            // The value (sal_uInt16)0xFFFF means set bullet on/off.
            SfxUInt16Item aItem(FN_SVX_SET_BULLET, sal_uInt16(0xFFFF));
            GetViewFrame()->GetDispatcher()->ExecuteList(FN_SVX_SET_BULLET, SfxCallMode::RECORD,
                                                         { &aItem });
        }
        break;

        case FN_NUM_NUMBERING_ON:
        {
            // The value (sal_uInt16)0xFFFF means set bullet on/off.
            SfxUInt16Item aItem(FN_SVX_SET_NUMBER, sal_uInt16(0xFFFF));
            GetViewFrame()->GetDispatcher()->ExecuteList(FN_SVX_SET_NUMBER, SfxCallMode::RECORD,
                                                         { &aItem });
        }
        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();
            SfxBindings& rBindings = GetViewFrame()->GetBindings();
            rBindings.Invalidate(FN_NUM_BULLET_ON);
            rBindings.Invalidate(FN_NUM_NUMBERING_ON);
        }
        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.start.nIndex == aSel.end.nIndex)
                    aSel.end.nIndex++;
                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.start.nIndex == aSel.end.nIndex)
                        {
                            bSel = false;
                            aSel.end.nIndex++;
                        }
                        pOutlinerView->SetSelection(aSel);

                        pOutlinerView->InsertField(aFieldItem);

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

                        pField.reset();
                    }

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

                        ::Outliner& rOutliner = pOutlinerView->GetOutliner();
                        rOutliner.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)
{
    switch (rReq.GetSlot())
    {
        case FID_SEARCH_NOW:
        {
            const SfxItemSet* pReqArgs = rReq.GetArgs();

            sd::View* pView = nullptr;
            if (auto pMainViewSh = GetViewShellBase().GetMainViewShell())
                pView = pMainViewSh->GetView();

            if (pReqArgs)
            {
                if (pView)
                {
                    rtl::Reference<FuSearch>& xFuSearch
                        = pView->getSearchContext().getFunctionSearch();

                    if (!xFuSearch.is())
                    {
                        xFuSearch = rtl::Reference<FuSearch>(FuSearch::createPtr(
                            *this, this->GetActiveWindow(), pView, *GetDoc(), rReq));

                        pView->getSearchContext().setSearchFunction(xFuSearch);
                    }

                    if (xFuSearch.is())
                    {
                        const SvxSearchItem& rSearchItem = pReqArgs->Get(SID_SEARCH_ITEM);

                        SdModule::get()->SetSearchItem(
                            std::unique_ptr<SvxSearchItem>(rSearchItem.Clone()));
                        xFuSearch->SearchAndReplace(&rSearchItem);
                    }
                }
            }
            rReq.Done();
        }
        break;

        case SID_SEARCH_ITEM:
            // Forward this request to the common (old) code of the
            // document shell.
            GetDocSh()->Execute(rReq);
            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();
        }
        break;

        default:
            break;
    }
}

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());

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

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

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

    if (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);

    return bReturn;
}

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

bool FuNotesPane::KeyInput(const KeyEvent& rKEvt)
{
    sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
    switch (nCode)
    {
        case KEY_PAGEUP:
        case KEY_PAGEDOWN:
        {
            // do not consume the input and let Accelerators handle Ctrl+PgUp/PgDown
            if (rKEvt.GetKeyCode().IsMod1())
                return false;
            break;
        }
        default:
            break;
    }
    return FuSimpleOutlinerText::KeyInput(rKEvt);
}

FuNotesPane::FuNotesPane(ViewShell& rViewShell, ::sd::Window* pWin, ::sd::SimpleOutlinerView* pView,
                         SdDrawDocument& rDoc, SfxRequest& rReq)
    : sd::FuSimpleOutlinerText(rViewShell, pWin, pView, rDoc, rReq)
{
}

} // end of namespace sd

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
