/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <OutlineViewShell.hxx>
#include <Outliner.hxx>
#include <helpids.h>
#include <app.hrc>
#include <svx/hyperdlg.hxx>
#include <svx/zoomslideritem.hxx>
#include <svx/svdundo.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/zoomitem.hxx>
#include <editeng/editview.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include <editeng/editund2.hxx>
#include <sfx2/shell.hxx>
#include <sfx2/request.hxx>
#include <svx/hlnkitem.hxx>
#include <svx/svdotext.hxx>
#include <svx/svdoutl.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/settings.hxx>
#include <sal/log.hxx>
#include <svl/stritem.hxx>
#include <svl/whiter.hxx>
#include <editeng/editstat.hxx>
#include <svl/itempool.hxx>
#include <sfx2/tplpitem.hxx>
#include <sfx2/sidebar/SidebarChildWindow.hxx>
#include <vcl/EnumContext.hxx>
#include <sot/formats.hxx>
#include <com/sun/star/linguistic2/XThesaurus.hpp>
#include <editeng/unolingu.hxx>
#include <editeng/outlobj.hxx>
#include <svl/cjkoptions.hxx>
#include <svtools/cliplistener.hxx>
#include <svl/srchitem.hxx>
#include <editeng/editobj.hxx>
#include <fubullet.hxx>
#include <strings.hrc>
#include <Window.hxx>
#include <drawdoc.hxx>
#include <sdresid.hxx>
#include <sdpage.hxx>
#include <fuoltext.hxx>
#include <FrameView.hxx>
#include <zoomlist.hxx>
#include <stlsheet.hxx>
#include <SdUnoOutlineView.hxx>
#include <SpellDialogChildWindow.hxx>
#include <AccessibleOutlineView.hxx>
#include <ViewShellBase.hxx>
#include <DrawController.hxx>
#include <DrawDocShell.hxx>
#include <OutlineView.hxx>
#include <framework/FrameworkHelper.hxx>
#include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
#include <memory>
#define ShellClass_OutlineViewShell
using namespace sd;
#include <sdslots.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::linguistic2;
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(OutlineViewShell, SfxShell)
void OutlineViewShell::InitInterface_Impl()
{
GetStaticInterface()->RegisterPopupMenu(u"outline"_ustr);
GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS, SfxVisibilityFlags::Standard | SfxVisibilityFlags::FullScreen | SfxVisibilityFlags::Server,
ToolbarId::Outline_Toolbox);
GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, SfxVisibilityFlags::Standard | SfxVisibilityFlags::Client | SfxVisibilityFlags::Viewer | SfxVisibilityFlags::ReadonlyDoc,
ToolbarId::Draw_Viewer_Toolbox);
GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(SvxHlinkDlgWrapper::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(::sd::SpellDialogChildWindow::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(SID_SEARCH_DLG);
GetStaticInterface()->RegisterChildWindow(sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
}
/**
* common initialization part of both constructors
*/
void OutlineViewShell::Construct()
{
bool bModified = GetDoc()->IsChanged();
meShellType = ST_OUTLINE;
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);
pOlView.reset( new OutlineView(*GetDocSh(), GetActiveWindow(), *this) );
mpView = pOlView.get(); // Pointer of base class ViewShell
SetPool( &GetDoc()->GetPool() );
SetZoom(69);
// Apply settings of FrameView
ReadFrameViewData(mpFrameView);
::Outliner& rOutl = pOlView->GetOutliner();
rOutl.SetUpdateLayout(true);
if (!bModified)
{
rOutl.ClearModifyFlag();
}
pLastPage = GetActualPage();
SetName( u"OutlineViewShell"_ustr );
GetActiveWindow()->SetHelpId( HID_SDOUTLINEVIEWSHELL );
}
Reference<drawing::XDrawSubController> OutlineViewShell::CreateSubController()
{
Reference<drawing::XDrawSubController> xSubController;
if (IsMainViewShell())
{
// Create uno sub controller for the main view shell.
xSubController.set( new SdUnoOutlineView(*this) );
}
return xSubController;
}
/**
* Default constructor, windows must not center themselves automatically
*/
OutlineViewShell::OutlineViewShell (
SfxViewFrame* /*pFrame*/,
ViewShellBase& rViewShellBase,
vcl::Window* pParentWindow,
FrameView* pFrameViewArgument)
: ViewShell(pParentWindow, rViewShellBase),
pLastPage( nullptr ),
bPastePossible(false),
mbInitialized(false)
{
if (pFrameViewArgument != nullptr)
mpFrameView = pFrameViewArgument;
else
mpFrameView = new FrameView(GetDoc());
mpFrameView->Connect();
Construct();
SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::OutlineText));
m_StrOldPageName.clear();
doShow();
}
OutlineViewShell::~OutlineViewShell()
{
DisposeFunctions();
pOlView.reset();
mpFrameView->Disconnect();
if ( mxClipEvtLstnr.is() )
{
mxClipEvtLstnr->RemoveListener( GetActiveWindow() );
mxClipEvtLstnr->ClearCallbackLink(); // prevent callback if another thread is waiting
}
}
void OutlineViewShell::Shutdown()
{
ViewShell::Shutdown();
PrepareClose();
}
/**
* Paint method: the event gets forwarded from pWindow to the Viewshell
* and the current function
*/
void OutlineViewShell::Paint(const ::tools::Rectangle& rRect, ::sd::Window* pWin)
{
if (pOlView)
{
pOlView->Paint(rRect, pWin);
}
}
void OutlineViewShell::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);
// change OutputArea of the OutlinerView
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(pWindow);
::tools::Rectangle aWin(Point(0,0), pWindow->GetOutputSizePixel());
aWin = pWindow->PixelToLogic(aWin);
pOutlinerView->SetOutputArea(aWin);
::tools::Rectangle aVis = pOutlinerView->GetVisArea();
::tools::Rectangle aText(Point(0,0),
Size(pOlView->GetPaperWidth(),
pOlView->GetOutliner().GetTextHeight()));
if (aWin.GetHeight() > aText.Bottom())
aText.SetBottom( aWin.GetHeight() );
if (!aWin.IsEmpty()) // not when opening
{
InitWindows(Point(0,0), aText.GetSize(), aVis.TopLeft());
UpdateScrollBars();
}
}
/**
* Handle SfxRequest for the Controller
*/
void OutlineViewShell::ExecCtrl(SfxRequest &rReq)
{
sal_uInt16 nSlot = rReq.GetSlot();
switch ( nSlot )
{
case SID_MAIL_SCROLLBODY_PAGEDOWN:
{
ExecReq( rReq );
break;
}
case SID_OPT_LOCALE_CHANGED:
{
pOlView->GetOutliner().UpdateFields();
UpdatePreview( GetActualPage() );
rReq.Done();
break;
}
default:
break;
}
}
/**
* Activate(): during the first invocation the fields get updated
*/
void OutlineViewShell::Activate( bool bIsMDIActivate )
{
if ( ! mbInitialized)
{
mbInitialized = true;
SfxRequest aRequest (SID_EDIT_OUTLINER, SfxCallMode::SLOT, GetDoc()->GetItemPool());
FuPermanent (aRequest);
}
ViewShell::Activate( bIsMDIActivate );
BroadcastContextForActivation(true);
pOlView->SetLinks();
pOlView->ConnectToApplication();
if( bIsMDIActivate )
{
OutlinerView* pOutlinerView = pOlView->GetViewByWindow( GetActiveWindow() );
::Outliner* pOutl = pOutlinerView->GetOutliner();
pOutl->UpdateFields();
}
}
void OutlineViewShell::Deactivate( bool bIsMDIActivate )
{
pOlView->DisconnectFromApplication();
// Links must be kept also on deactivated viewshell, to allow drag'n'drop
// to function properly
ViewShell::Deactivate( bIsMDIActivate );
}
/**
* Set status of Controller-SfxSlots
*/
void OutlineViewShell::GetCtrlState(SfxItemSet &rSet)
{
if (SfxItemState::DEFAULT == rSet.GetItemState(SID_HYPERLINK_GETLINK))
{
SvxHyperlinkItem aHLinkItem;
OutlinerView* pOLV = pOlView->GetViewByWindow(GetActiveWindow());
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 );
}
}
/**
* SfxRequests for support functions
*/
void OutlineViewShell::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();
std::unique_ptr<OutlineViewModelChangeGuard, o3tl::default_delete<OutlineViewModelChangeGuard>> aGuard;
if( pOlView && (
(nSlot == SID_TRANSLITERATE_SENTENCE_CASE) ||
(nSlot == SID_TRANSLITERATE_TITLE_CASE) ||
(nSlot == SID_TRANSLITERATE_TOGGLE_CASE) ||
(nSlot == SID_TRANSLITERATE_UPPER) ||
(nSlot == SID_TRANSLITERATE_LOWER) ||
(nSlot == SID_TRANSLITERATE_HALFWIDTH) ||
(nSlot == SID_TRANSLITERATE_FULLWIDTH) ||
(nSlot == SID_TRANSLITERATE_HIRAGANA) ||
(nSlot == SID_TRANSLITERATE_KATAKANA) ||
(nSlot == SID_CUT) ||
(nSlot == SID_PASTE) ||
(nSlot == SID_PASTE_UNFORMATTED) ||
(nSlot == SID_DELETE)))
{
aGuard.reset( new OutlineViewModelChangeGuard( *pOlView ) );
}
switch ( nSlot )
{
case SID_CUT:
{
if(HasCurrentFunction())
{
GetCurrentFunction()->DoCut();
}
else if (pOlView)
{
pOlView->DoCut();
}
rReq.Done();
bPreviewState = true;
}
break;
case SID_COPY:
{
if(HasCurrentFunction())
{
GetCurrentFunction()->DoCopy();
}
else if (pOlView)
{
pOlView->DoCopy();
}
rReq.Done();
bPreviewState = true;
}
break;
case SID_PASTE:
{
OutlineViewPageChangesGuard aGuard2(pOlView.get());
if(HasCurrentFunction())
{
GetCurrentFunction()->DoPaste();
}
else if (pOlView)
{
pOlView->DoPaste();
}
rReq.Done();
bPreviewState = true;
}
break;
case SID_PASTE_UNFORMATTED:
{
OutlineViewPageChangesGuard aGuard2(pOlView.get());
if(HasCurrentFunction())
{
GetCurrentFunction()->DoPasteUnformatted();
}
else if(pOlView)
{
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( GetActiveWindow() ) );
if (aDataHelper.GetTransferable().is())
{
sal_Int8 nAction = DND_ACTION_COPY;
pOlView->InsertData( aDataHelper,
GetActiveWindow()->PixelToLogic( ::tools::Rectangle( Point(), GetActiveWindow()->GetOutputSizePixel() ).Center() ),
nAction, false, SotClipboardFormatId::STRING);
}
}
rReq.Ignore ();
}
break;
case SID_DELETE:
{
if( pOlView )
{
OutlinerView* pOutlView = pOlView->GetViewByWindow(GetActiveWindow());
if (pOutlView)
{
OutlineViewPageChangesGuard aGuard2(pOlView.get());
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 = pOlView ? pOlView->GetViewByWindow( GetActiveWindow() ) : 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 :
{
OutlineViewPageChangesGuard aGuard2(pOlView.get());
ImpSidUndo(rReq);
}
break;
case SID_REDO :
{
OutlineViewPageChangesGuard aGuard2(pOlView.get());
ImpSidRedo(rReq);
}
break;
default:
break;
}
if( bPreviewState )
Invalidate( SID_PREVIEW_STATE );
Invalidate(SID_CUT);
Invalidate(SID_COPY);
Invalidate(SID_PASTE);
}
/**
* SfxRequests for permanent functions
*/
void OutlineViewShell::FuPermanent(SfxRequest &rReq)
{
if(HasCurrentFunction())
{
DeactivateCurrentFunction(true);
}
switch ( rReq.GetSlot() )
{
case SID_EDIT_OUTLINER:
{
::Outliner& rOutl = pOlView->GetOutliner();
rOutl.GetUndoManager().Clear();
rOutl.UpdateFields();
SetCurrentFunction( FuOutlineText::Create(this,GetActiveWindow(),pOlView.get(),GetDoc(),rReq) );
rReq.Done();
}
break;
default:
break;
}
if(HasOldFunction())
{
GetOldFunction()->Deactivate();
SetOldFunction(nullptr);
}
if(HasCurrentFunction())
{
GetCurrentFunction()->Activate();
SetOldFunction(GetCurrentFunction());
}
}
IMPL_LINK( OutlineViewShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
{
bPastePossible = pDataHelper->GetFormatCount() != 0 &&
( pDataHelper->HasFormat( SotClipboardFormatId::STRING ) ||
pDataHelper->HasFormat( SotClipboardFormatId::RTF ) ||
pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT ) ||
pDataHelper->HasFormat( SotClipboardFormatId::HTML ) );
SfxBindings& rBindings = GetViewFrame()->GetBindings();
rBindings.Invalidate( SID_PASTE );
rBindings.Invalidate( SID_PASTE_SPECIAL );
rBindings.Invalidate( SID_PASTE_UNFORMATTED );
rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
}
/**
* Set Status (Enabled/Disabled) of Menu-SfxSlots
*/
void OutlineViewShell::GetMenuState( SfxItemSet &rSet )
{
ViewShell::GetMenuState(rSet);
rSet.Put(SfxBoolItem(SID_SLIDE_SORTER_MODE, false));
rSet.Put(SfxBoolItem(SID_DRAWINGMODE, false));
rSet.Put(SfxBoolItem(SID_SLIDE_MASTER_MODE, false));
rSet.Put(SfxBoolItem(SID_OUTLINE_MODE, true));
rSet.Put(SfxBoolItem(SID_NOTES_MODE, false));
rSet.Put(SfxBoolItem(SID_NOTES_MASTER_MODE, false));
rSet.Put(SfxBoolItem(SID_HANDOUT_MASTER_MODE, false));
if (!mpZoomList->IsNextPossible())
{
rSet.DisableItem(SID_ZOOM_NEXT);
}
if (!mpZoomList->IsPreviousPossible())
{
rSet.DisableItem(SID_ZOOM_PREV);
}
if( SfxItemState::DEFAULT == rSet.GetItemState( SID_ZOOM_IN ) ||
SfxItemState::DEFAULT == rSet.GetItemState( SID_ZOOM_OUT ) )
{
if( GetActiveWindow()->GetZoom() <= GetActiveWindow()->GetMinZoom() || GetDocSh()->IsUIActive() )
rSet.DisableItem( SID_ZOOM_OUT );
if( GetActiveWindow()->GetZoom() >= GetActiveWindow()->GetMaxZoom() || GetDocSh()->IsUIActive() )
rSet.DisableItem( SID_ZOOM_IN );
}
::Outliner& rOutl = pOlView->GetOutliner();
// allow 'Select All'?
if( SfxItemState::DEFAULT == rSet.GetItemState( SID_SELECTALL ) )
{
sal_Int32 nParaCount = rOutl.GetParagraphCount();
bool bDisable = nParaCount == 0;
if (!bDisable && nParaCount == 1)
{
OUString aTest = rOutl.GetText(rOutl.GetParagraph(0));
if (aTest.isEmpty())
{
bDisable = true;
}
}
if (bDisable)
rSet.DisableItem(SID_SELECTALL);
}
// set status of Ruler
rSet.Put( SfxBoolItem( SID_RULER, HasRuler() ) );
// Enable formatting?
rSet.Put( SfxBoolItem( SID_OUTLINE_FORMAT, !rOutl.IsFlatMode() ) );
if( rOutl.IsFlatMode() )
rSet.DisableItem( SID_COLORVIEW );
else
{
// Enable color view?
EEControlBits nCntrl = rOutl.GetControlWord();
bool bNoColor = false;
if (nCntrl & EEControlBits::NOCOLORS)
bNoColor = true;
rSet.Put( SfxBoolItem( SID_COLORVIEW, bNoColor ) );
}
// Buttons of toolbar
// first the selection dependent ones: COLLAPSE, EXPAND
bool bDisableCollapse = true;
bool bDisableExpand = true;
bool bUnique = true;
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(GetActiveWindow());
std::vector<Paragraph*> aSelList;
pOutlinerView->CreateSelectionList(aSelList);
if (!aSelList.empty())
{
sal_Int16 nTmpDepth = rOutl.GetDepth( rOutl.GetAbsPos( aSelList.front() ) );
bool bPage = ::Outliner::HasParaFlag( aSelList.front(), ParaFlag::ISPAGE );
for (const Paragraph* pPara : aSelList)
{
sal_Int16 nDepth = rOutl.GetDepth( rOutl.GetAbsPos( pPara ) );
if( nDepth != nTmpDepth || bPage != ::Outliner::HasParaFlag( pPara, ParaFlag::ISPAGE ))
bUnique = false;
if (rOutl.HasChildren(pPara))
{
if (!rOutl.IsExpanded(pPara))
bDisableExpand = false;
else
bDisableCollapse = false;
}
}
}
if (bDisableExpand)
rSet.DisableItem(SID_OUTLINE_EXPAND);
if (bDisableCollapse)
rSet.DisableItem(SID_OUTLINE_COLLAPSE);
// does the selection provide a unique presentation layout?
// if not, the templates must not be edited
SfxItemSetFixed<SID_STATUS_LAYOUT, SID_STATUS_LAYOUT> aSet(*rSet.GetPool());
GetStatusBarState(aSet);
OUString aTest = aSet.Get(SID_STATUS_LAYOUT).GetValue();
if (aTest.isEmpty())
{
bUnique = false;
}
if (!bUnique)
rSet.DisableItem( SID_PRESENTATIONOBJECT );
// now the selection independent ones: COLLAPSE_ALL, EXPAND_ALL
bool bDisableCollapseAll = true;
bool bDisableExpandAll = true;
// does the selection contain something collapsible/expandable?
if (!bDisableCollapse)
bDisableCollapseAll = false;
if (!bDisableExpand)
bDisableExpandAll = false;
// otherwise look through all paragraphs
if (bDisableCollapseAll || bDisableExpandAll)
{
sal_Int32 nParaPos = 0;
Paragraph* pPara = rOutl.GetParagraph( nParaPos );
while (pPara && (bDisableCollapseAll || bDisableExpandAll))
{
if (!rOutl.IsExpanded(pPara) && rOutl.HasChildren(pPara))
bDisableExpandAll = false;
if (rOutl.IsExpanded(pPara) && rOutl.HasChildren(pPara))
bDisableCollapseAll = false;
pPara = rOutl.GetParagraph( ++nParaPos );
}
}
if (bDisableExpandAll)
rSet.DisableItem(SID_OUTLINE_EXPAND_ALL);
if (bDisableCollapseAll)
rSet.DisableItem(SID_OUTLINE_COLLAPSE_ALL);
if( SfxItemState::DEFAULT == rSet.GetItemState( SID_PASTE ) )
{
if ( !mxClipEvtLstnr.is() )
{
// create listener
mxClipEvtLstnr = new TransferableClipboardListener( LINK( this, OutlineViewShell, ClipboardChanged ) );
mxClipEvtLstnr->AddListener( GetActiveWindow() );
// get initial state
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( GetActiveWindow() ) );
bPastePossible = ( aDataHelper.GetFormatCount() != 0 &&
( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) ||
aDataHelper.HasFormat( SotClipboardFormatId::RTF ) ||
aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) ||
aDataHelper.HasFormat( SotClipboardFormatId::HTML ) ) );
}
if( !bPastePossible )
{
rSet.DisableItem( SID_PASTE );
}
}
if (!pOlView->GetViewByWindow(GetActiveWindow())->HasSelection()
|| GetObjectShell()->isContentExtractionLocked())
{
rSet.DisableItem(SID_CUT);
rSet.DisableItem(SID_COPY);
}
if (pOlView->GetOutliner().IsModified())
{
GetDoc()->SetChanged();
}
// the status has to be set here because of overriding
if( !GetDocSh()->IsModified() )
{
rSet.DisableItem( SID_SAVEDOC );
}
if ( GetDocSh()->IsReadOnly() )
{
rSet.DisableItem( SID_AUTOSPELL_CHECK );
}
else
{
if (GetDoc()->GetOnlineSpell())
{
rSet.Put(SfxBoolItem(SID_AUTOSPELL_CHECK, true));
}
else
{
rSet.Put(SfxBoolItem(SID_AUTOSPELL_CHECK, false));
}
}
// field commands
if( SfxItemState::DEFAULT == rSet.GetItemState( 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() ) ) ) )
{
rSet.DisableItem( SID_MODIFY_FIELD );
}
}
if (SfxItemState::DEFAULT == rSet.GetItemState(SID_EXPAND_PAGE))
{
bool bDisable = true;
sal_uInt16 i = 0;
sal_uInt16 nCount = GetDoc()->GetSdPageCount(PageKind::Standard);
pOlView->SetSelectedPages();
while (i < nCount && bDisable)
{
SdPage* pPage = GetDoc()->GetSdPage(i, PageKind::Standard);
if (pPage->IsSelected())
{
SdrObject* pObj = pPage->GetPresObj(PresObjKind::Outline);
if (pObj!=nullptr )
{
if( !pObj->IsEmptyPresObj() )
{
bDisable = false;
}
else
{
// check if the object is in edit, then if it's temporarily not empty
SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );
if( pTextObj )
{
if( pTextObj->CanCreateEditOutlinerParaObject() )
{
bDisable = false;
}
}
}
}
}
i++;
}
if (bDisable)
{
rSet.DisableItem(SID_EXPAND_PAGE);
}
}
if (SfxItemState::DEFAULT == rSet.GetItemState(SID_SUMMARY_PAGE))
{
bool bDisable = true;
sal_uInt16 i = 0;
sal_uInt16 nCount = GetDoc()->GetSdPageCount(PageKind::Standard);
pOlView->SetSelectedPages();
while (i < nCount && bDisable)
{
SdPage* pPage = GetDoc()->GetSdPage(i, PageKind::Standard);
if (pPage->IsSelected())
{
SdrObject* pObj = pPage->GetPresObj(PresObjKind::Title);
if (pObj && !pObj->IsEmptyPresObj())
{
bDisable = false;
}
}
i++;
}
if (bDisable)
{
rSet.DisableItem(SID_SUMMARY_PAGE);
}
}
if( SfxItemState::DEFAULT == rSet.GetItemState( SID_THESAURUS ) )
{
if ( !pOlView->IsTextEdit() )
{
rSet.DisableItem( SID_THESAURUS );
}
else
{
LanguageType eLang = GetDoc()->GetLanguage( EE_CHAR_LANGUAGE );
Reference< XThesaurus > xThesaurus( LinguMgr::GetThesaurus() );
if (!xThesaurus.is() || eLang == LANGUAGE_NONE || !xThesaurus->hasLocale( LanguageTag::convertToLocale( eLang)))
rSet.DisableItem( SID_THESAURUS );
}
}
// is starting the presentation possible?
if( SfxItemState::DEFAULT == rSet.GetItemState( SID_PRESENTATION ) )
{
bool bDisable = true;
sal_uInt16 nCount = GetDoc()->GetSdPageCount( PageKind::Standard );
for( sal_uInt16 i = 0; i < nCount && bDisable; i++ )
{
SdPage* pPage = GetDoc()->GetSdPage(i, PageKind::Standard);
if( !pPage->IsExcluded() )
bDisable = false;
}
if( bDisable || GetDocSh()->IsPreview())
{
rSet.DisableItem( SID_PRESENTATION );
}
}
FuBullet::GetSlotState( rSet, this, GetViewFrame() );
}
/**
* gets invoked when ScrollBar is used
*/
void OutlineViewShell::VirtHScrollHdl(ScrollAdaptor* pHScroll)
{
::tools::Long nThumb = pHScroll->GetThumbPos();
::tools::Long nRange = pHScroll->GetRange().Len();
double fX = static_cast<double>(nThumb) / nRange;
Window* pWin = mpContentWindow.get();
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(pWin);
::tools::Long nViewWidth = pWin->PixelToLogic(
pWin->GetSizePixel()).Width();
::tools::Long nTextWidth = pOlView->GetPaperWidth();
nViewWidth = std::max(nViewWidth, nTextWidth);
::tools::Long nCurrentPos = pOutlinerView->GetVisArea().Left();
::tools::Long nTargetPos = static_cast<::tools::Long>(fX * nViewWidth);
::tools::Long nDelta = nTargetPos - nCurrentPos;
pOutlinerView->HideCursor();
pOutlinerView->Scroll(-nDelta, 0);
pOutlinerView->ShowCursor(false);
}
void OutlineViewShell::VirtVScrollHdl(ScrollAdaptor* pVScroll)
{
::tools::Long nThumb = pVScroll->GetThumbPos();
::tools::Long nRange = pVScroll->GetRange().Len();
double fY = static_cast<double>(nThumb) / nRange;
Window* pWin = mpContentWindow.get();
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(pWin);
::tools::Long nViewHeight = pWin->PixelToLogic(
pWin->GetSizePixel()).Height();
::tools::Long nTextHeight = pOlView->GetOutliner().GetTextHeight();
nViewHeight += nTextHeight;
::tools::Long nCurrentPos = pOutlinerView->GetVisArea().Top();
::tools::Long nTargetPos = static_cast<::tools::Long>(fY * nViewHeight);
::tools::Long nDelta = nTargetPos - nCurrentPos;
pOutlinerView->HideCursor();
pOutlinerView->Scroll(0, -nDelta);
pOutlinerView->ShowCursor(false);
}
/**
* PrepareClose, gets called when the Shell shall be destroyed.
* Forwards the invocation to the View
*/
bool OutlineViewShell::PrepareClose( bool bUI )
{
if( !ViewShell::PrepareClose(bUI) )
return false;
if (pOlView)
pOlView->PrepareClose();
return true;
}
/**
* Zoom with zoom factor. Inform OutlinerView
*/
void OutlineViewShell::SetZoom(::tools::Long nZoom)
{
ViewShell::SetZoom(nZoom);
::sd::Window* pWindow = mpContentWindow.get();
if (pWindow)
{
// change OutputArea of OutlinerView
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(pWindow);
::tools::Rectangle aWin(Point(0,0), pWindow->GetOutputSizePixel());
aWin = pWindow->PixelToLogic(aWin);
pOutlinerView->SetOutputArea(aWin);
}
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
}
/**
* Zoom with zoom rectangle. Inform OutlinerView
*/
void OutlineViewShell::SetZoomRect(const ::tools::Rectangle& rZoomRect)
{
ViewShell::SetZoomRect(rZoomRect);
::sd::Window* pWindow = mpContentWindow.get();
if (pWindow)
{
// change OutputArea of OutlinerView
OutlinerView* pOutlinerView = pOlView->GetViewByWindow(pWindow);
::tools::Rectangle aWin(Point(0,0), pWindow->GetOutputSizePixel());
aWin = pWindow->PixelToLogic(aWin);
pOutlinerView->SetOutputArea(aWin);
}
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
}
/**
* Before saving: Update Model of the Drawing Engine, then forward the
* invocation to the ObjectShell.
*/
void OutlineViewShell::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:
SAL_WARN("sd", "OutlineViewShell::Execute(): can not handle slot " << rReq.GetSlot());
break;
}
if (bForwardCall)
static_cast<DrawDocShell*>(GetViewFrame()->GetObjectShell())->ExecuteSlot( rReq );
}
/**
* Read FrameViews data and set actual views data
*/
void OutlineViewShell::ReadFrameViewData(FrameView* pView)
{
::Outliner& rOutl = pOlView->GetOutliner();
rOutl.SetFlatMode( pView->IsNoAttribs() );
EEControlBits nCntrl = rOutl.GetControlWord();
if ( pView->IsNoColors() )
rOutl.SetControlWord(nCntrl | EEControlBits::NOCOLORS);
else
rOutl.SetControlWord(nCntrl & ~EEControlBits::NOCOLORS);
sal_uInt16 nPage = mpFrameView->GetSelectedPage();
pLastPage = GetDoc()->GetSdPage( nPage, PageKind::Standard );
pOlView->SetActualPage(pLastPage);
}
/**
* Write actual views data to FrameView
*/
void OutlineViewShell::WriteFrameViewData()
{
::Outliner& rOutl = pOlView->GetOutliner();
EEControlBits nCntrl = rOutl.GetControlWord();
bool bNoColor = false;
if (nCntrl & EEControlBits::NOCOLORS)
bNoColor = true;
mpFrameView->SetNoColors(bNoColor);
mpFrameView->SetNoAttribs( rOutl.IsFlatMode() );
SdPage* pActualPage = pOlView->GetActualPage();
DBG_ASSERT(pActualPage, "No current page");
if( pActualPage )
mpFrameView->SetSelectedPage((pActualPage->GetPageNum() - 1) / 2);
}
/**
* Handle SfxRequests for the StatusBar
*/
void OutlineViewShell::ExecStatusBar(SfxRequest&)
{
}
void OutlineViewShell::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 );
}
}
// page view and layout
sal_uInt16 nPageCount = GetDoc()->GetSdPageCount( PageKind::Standard );
OUString aPageStr, aLayoutStr;
::sd::Window* pWin = GetActiveWindow();
OutlinerView* pActiveView = pOlView->GetViewByWindow( pWin );
std::vector<Paragraph*> aSelList;
pActiveView->CreateSelectionList(aSelList);
Paragraph *pFirstPara = nullptr;
Paragraph *pLastPara = nullptr;
if (!aSelList.empty())
{
pFirstPara = *(aSelList.begin());
pLastPara = *(aSelList.rbegin());
}
if( !::Outliner::HasParaFlag(pFirstPara,ParaFlag::ISPAGE) )
pFirstPara = pOlView->GetPrevTitle( pFirstPara );
if( !::Outliner::HasParaFlag(pLastPara, ParaFlag::ISPAGE) )
pLastPara = pOlView->GetPrevTitle( pLastPara );
// only one page selected?
if( pFirstPara == pLastPara )
{
// how many pages are we before the selected page?
sal_uLong nPos = 0;
while( pFirstPara )
{
pFirstPara = pOlView->GetPrevTitle( pFirstPara );
if( pFirstPara )
nPos++;
}
if( nPos >= GetDoc()->GetSdPageCount( PageKind::Standard ) )
nPos = 0;
SdPage* pPage = GetDoc()->GetSdPage( static_cast<sal_uInt16>(nPos), PageKind::Standard );
if (GetDoc()->GetDocumentType() == DocumentType::Draw)
aPageStr = SdResId(STR_SD_PAGE_COUNT_DRAW);
else
aPageStr = SdResId(STR_SD_PAGE_COUNT);
aPageStr = aPageStr.replaceFirst("%1", OUString::number(static_cast<sal_Int32>(nPos + 1)));
aPageStr = aPageStr.replaceFirst("%2", OUString::number(nPageCount));
aLayoutStr = pPage->GetLayoutName();
sal_Int32 nIndex = aLayoutStr.indexOf(SD_LT_SEPARATOR);
if (nIndex != -1)
aLayoutStr = aLayoutStr.copy(0, nIndex);
//Now, CurrentPage property change is already sent for DrawView and OutlineView, so it is not necessary to send again here
if(m_StrOldPageName!=aPageStr)
{
GetViewShellBase().GetDrawController()->fireSwitchCurrentPage(nPos);
m_StrOldPageName = aPageStr;
}
}
rSet.Put( SfxStringItem( SID_STATUS_PAGE, aPageStr ) );
rSet.Put( SfxStringItem( SID_STATUS_LAYOUT, aLayoutStr ) );
}
void OutlineViewShell::Command( const CommandEvent& rCEvt, ::sd::Window* pWin )
{
if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
{
GetActiveWindow()->ReleaseMouse();
OutlinerView* pOLV = pOlView->GetViewByWindow(GetActiveWindow());
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(u"outline"_ustr);
}
}
else
{
ViewShell::Command( rCEvt, pWin );
// if necessary communicate the new context to the Preview
Invalidate( SID_PREVIEW_STATE );
}
}
bool OutlineViewShell::KeyInput(const KeyEvent& rKEvt, ::sd::Window* pWin)
{
bool bReturn = false;
OutlineViewPageChangesGuard aGuard(pOlView.get());
if (pWin == nullptr && HasCurrentFunction())
{
bReturn = GetCurrentFunction()->KeyInput(rKEvt);
}
// no, forward to base class
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);
// check and distinguish cursor movements- or input-keys
vcl::KeyCode aKeyGroup( rKEvt.GetKeyCode().GetGroup() );
if( (aKeyGroup != KEYGROUP_CURSOR && aKeyGroup != KEYGROUP_FKEYS) ||
(GetActualPage() != pLastPage) )
{
Invalidate( SID_PREVIEW_STATE );
}
return bReturn;
}
/**
* Status of Attribute-Items
*/
void OutlineViewShell::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 = pOlView->GetViewByWindow(GetActiveWindow())->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 );
// rSet.DisableItem( nWhich );
}
}
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)
{
SfxItemSetFixed<SID_STATUS_LAYOUT, SID_STATUS_LAYOUT> aSet(*rSet.GetPool());
GetStatusBarState(aSet);
OUString aRealStyle = aSet.Get(SID_STATUS_LAYOUT).GetValue();
if (aRealStyle.isEmpty())
{
// no unique layout name found
rSet.DisableItem(nWhich);
}
}
}
break;
case SID_STYLE_UPDATE_BY_EXAMPLE:
{
::sd::Window* pActWin = GetActiveWindow();
OutlinerView* pOV = pOlView->GetViewByWindow(pActWin);
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;
}
nWhich = aIter.NextWhich();
}
rSet.Put( aAllSet, false );
}
void OutlineViewShell::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);
// if necessary communicate the new context to the Preview
if( GetActualPage() != pLastPage )
Invalidate( SID_PREVIEW_STATE );
}
SdPage* OutlineViewShell::getCurrentPage() const
{
// since there are no master pages in outline view, we can
// for now use the GetActualPage method
return const_cast<OutlineViewShell*>(this)->GetActualPage();
}
/**
* Returns the first selected page.
* If nothing is selected, the first page is returned.
*/
SdPage* OutlineViewShell::GetActualPage()
{
return pOlView->GetActualPage();
}
void OutlineViewShell::UpdatePreview( SdPage* pPage )
{
const bool bNewPage = pPage != pLastPage;
pLastPage = pPage;
if (bNewPage)
{
OutlineViewPageChangesGuard aGuard(pOlView.get());
SetCurrentPage(pPage);
}
}
void OutlineViewShell::UpdateTitleObject( SdPage* pPage, Paragraph const * pPara )
{
DBG_ASSERT( pPage, "sd::OutlineViewShell::UpdateTitleObject(), pPage == 0?" );
DBG_ASSERT( pPara, "sd::OutlineViewShell::UpdateTitleObject(), pPara == 0?" );
if( !pPage || !pPara )
return;
::Outliner& rOutliner = pOlView->GetOutliner();
SdrTextObj* pTO = OutlineView::GetTitleTextObject( pPage );
OUString aTest = rOutliner.GetText(pPara);
bool bText = !aTest.isEmpty();
if( bText )
{
bool bNewObject = false;
// create a title object if we don't have one but have text
if( !pTO )
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateTitleObject(), no undo for model change!?" );
pTO = OutlineView::CreateTitleTextObject(pPage);
bNewObject = true;
}
// if we have a title object and a text, set the text
std::optional<OutlinerParaObject> pOPO;
if (pTO)
pOPO = rOutliner.CreateParaObject(rOutliner.GetAbsPos(pPara), 1);
if (pOPO)
{
pOPO->SetOutlinerMode( OutlinerMode::TitleObject );
assert(pTO);
pOPO->SetVertical( pTO->IsVerticalWriting() );
if( pTO->GetOutlinerParaObject() && (pOPO->GetTextObject() == pTO->GetOutlinerParaObject()->GetTextObject()) )
{
// do nothing, same text already set
}
else
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateTitleObject(), no undo for model change!?" );
if( !bNewObject && pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
pTO->SetOutlinerParaObject( std::move(pOPO) );
pTO->SetEmptyPresObj( false );
pTO->ActionChanged();
}
}
}
else if( pTO )
{
// no text but object available?
// outline object available, but we have no text
if(pPage->IsPresObj(pTO))
{
// if it is not already empty
if( !pTO->IsEmptyPresObj() )
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateTitleObject(), no undo for model change!?" );
// make it empty
if( pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
pPage->RestoreDefaultText( pTO );
pTO->SetEmptyPresObj(true);
pTO->ActionChanged();
}
}
else
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateTitleObject(), no undo for model change!?" );
// outline object is not part of the layout, delete it
if( pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoRemoveObject(*pTO));
pPage->RemoveObject(pTO->GetOrdNum());
}
}
}
void OutlineViewShell::UpdateOutlineObject( SdPage* pPage, Paragraph* pPara )
{
DBG_ASSERT( pPage, "sd::OutlineViewShell::UpdateOutlineObject(), pPage == 0?" );
DBG_ASSERT( pPara, "sd::OutlineViewShell::UpdateOutlineObject(), pPara == 0?" );
if( !pPage || !pPara )
return;
::Outliner& rOutliner = pOlView->GetOutliner();
std::optional<OutlinerParaObject> pOPO;
SdrTextObj* pTO = nullptr;
OutlinerMode eOutlinerMode = OutlinerMode::TitleObject;
pTO = static_cast<SdrTextObj*>(pPage->GetPresObj( PresObjKind::Text ));
if( !pTO )
{
eOutlinerMode = OutlinerMode::OutlineObject;
pTO = OutlineView::GetOutlineTextObject( pPage );
}
// how many paragraphs in the outline?
sal_Int32 nTitlePara = rOutliner.GetAbsPos( pPara );
sal_Int32 nPara = nTitlePara + 1;
sal_Int32 nParasInLayout = 0;
pPara = rOutliner.GetParagraph( nPara );
while( pPara && !::Outliner::HasParaFlag(pPara, ParaFlag::ISPAGE) )
{
nParasInLayout++;
pPara = rOutliner.GetParagraph( ++nPara );
}
if( nParasInLayout )
{
// create an OutlinerParaObject
pOPO = rOutliner.CreateParaObject( nTitlePara + 1, nParasInLayout );
}
if( pOPO )
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateOutlineObject(), no undo for model change!?" );
bool bNewObject = false;
// do we need an outline text object?
if( !pTO )
{
pTO = OutlineView::CreateOutlineTextObject( pPage );
bNewObject = true;
}
// page object, outline text in Outliner:
// apply text
if( pTO )
{
pOPO->SetVertical( pTO->IsVerticalWriting() );
pOPO->SetOutlinerMode( eOutlinerMode );
if( pTO->GetOutlinerParaObject() && (pOPO->GetTextObject() == pTO->GetOutlinerParaObject()->GetTextObject()) )
{
// do nothing, same text already set
}
else
{
if( !bNewObject && pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
pTO->SetOutlinerParaObject( std::move(pOPO) );
pTO->SetEmptyPresObj( false );
pTO->ActionChanged();
}
}
}
else if( pTO )
{
// page object but no outline text:
// if the object is in the outline of the page -> default text
// otherwise delete object
if( pPage->IsPresObj(pTO) )
{
if( !pTO->IsEmptyPresObj() )
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateOutlineObject(), no undo for model change!?" );
// delete old OutlinerParaObject, too
if( pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
pPage->RestoreDefaultText( pTO );
pTO->SetEmptyPresObj(true);
pTO->ActionChanged();
}
}
else
{
DBG_ASSERT( pOlView->isRecordingUndo(), "sd::OutlineViewShell::UpdateOutlineObject(), no undo for model change!?" );
if( pOlView->isRecordingUndo() )
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoRemoveObject(*pTO));
pPage->RemoveObject(pTO->GetOrdNum());
}
}
}
/**
* Fill Outliner from Stream
*/
ErrCode OutlineViewShell::ReadRtf(SvStream& rInput)
{
ErrCode bRet = ERRCODE_NONE;
::Outliner& rOutl = pOlView->GetOutliner();
OutlineViewPageChangesGuard aGuard( pOlView.get() );
OutlineViewModelChangeGuard aGuard2( *pOlView );
bRet = rOutl.Read( rInput, OUString(), EETextFormat::Rtf, GetDocSh()->GetHeaderAttributes() );
SdPage* pPage = GetDoc()->GetSdPage( GetDoc()->GetSdPageCount(PageKind::Standard) - 1, PageKind::Standard );
SfxStyleSheet* pTitleSheet = pPage->GetStyleSheetForPresObj( PresObjKind::Title );
SfxStyleSheet* pOutlSheet = pPage->GetStyleSheetForPresObj( PresObjKind::Outline );
sal_Int32 nParaCount = rOutl.GetParagraphCount();
if ( nParaCount > 0 )
{
for ( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
{
pOlView->UpdateParagraph( nPara );
sal_Int16 nDepth = rOutl.GetDepth( nPara );
if( (nDepth == 0) || !nPara )
{
Paragraph* pPara = rOutl.GetParagraph( nPara );
rOutl.SetDepth(pPara, -1);
rOutl.SetParaFlag(pPara, ParaFlag::ISPAGE);
rOutl.SetStyleSheet( nPara, pTitleSheet );
if( nPara ) // first slide already exists
pOlView->InsertSlideForParagraph( pPara );
}
else
{
rOutl.SetDepth( rOutl.GetParagraph( nPara ), nDepth - 1 );
OUString aStyleSheetName = pOutlSheet->GetName();
if (!aStyleSheetName.isEmpty())
aStyleSheetName = aStyleSheetName.copy(0, aStyleSheetName.getLength() - 1);
aStyleSheetName += OUString::number( nDepth );
SfxStyleSheetBasePool* pStylePool = GetDoc()->GetStyleSheetPool();
SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStylePool->Find( aStyleSheetName, pOutlSheet->GetFamily() ) );
DBG_ASSERT( pStyle, "AutoStyleSheetName - Style not found!" );
if ( pStyle )
rOutl.SetStyleSheet( nPara, pStyle );
}
}
}
rOutl.GetUndoManager().Clear();
return bRet;
}
void OutlineViewShell::WriteUserDataSequence ( css::uno::Sequence < css::beans::PropertyValue >& rSequence )
{
WriteFrameViewData();
ViewShell::WriteUserDataSequence( rSequence );
}
void OutlineViewShell::ReadUserDataSequence ( const css::uno::Sequence < css::beans::PropertyValue >& rSequence )
{
WriteFrameViewData();
ViewShell::ReadUserDataSequence( rSequence );
ReadFrameViewData( mpFrameView );
}
void OutlineViewShell::VisAreaChanged(const ::tools::Rectangle& rRect)
{
ViewShell::VisAreaChanged( rRect );
GetViewShellBase().GetDrawController()->FireVisAreaChanged(rRect);
}
/** If there is a valid controller then create a new instance of
<type>AccessibleDrawDocumentView</type>. Otherwise return an empty
reference.
*/
css::uno::Reference<css::accessibility::XAccessible>
OutlineViewShell::CreateAccessibleDocumentView (::sd::Window* pWindow)
{
OSL_ASSERT (GetViewShell()!=nullptr);
if (GetViewShell()->GetController() != nullptr)
{
rtl::Reference<::accessibility::AccessibleOutlineView> pDocumentView =
new ::accessibility::AccessibleOutlineView (
pWindow,
this,
GetViewShell()->GetController(),
pWindow->GetAccessibleParentWindow()->GetAccessible());
pDocumentView->Init();
return pDocumentView;
}
SAL_WARN("sd", "OutlineViewShell::CreateAccessibleDocumentView: no controller");
return css::uno::Reference< css::accessibility::XAccessible >();
}
void OutlineViewShell::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", "OutlineViewShell::GetState(): can not handle which id " << nWhich);
break;
}
nWhich = aIter.NextWhich();
}
}
void OutlineViewShell::SetCurrentPage (SdPage* pPage)
{
// Adapt the selection of the model.
for (sal_uInt16 i=0; i<GetDoc()->GetSdPageCount(PageKind::Standard); i++)
GetDoc()->SetSelected(
GetDoc()->GetSdPage(i, PageKind::Standard),
false);
GetDoc()->SetSelected (pPage, true);
DrawController& rController(*GetViewShellBase().GetDrawController());
rController.FireSelectionChangeListener();
rController.FireSwitchCurrentPage (pPage);
pOlView->SetActualPage(pPage);
}
} // end of namespace sd
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V595 The 'GetActiveWindow()' pointer was utilized before it was verified against nullptr. Check lines: 1251, 1267.
↑ V1053 Calling the 'SetZoom' virtual function indirectly in the constructor may lead to unexpected result at runtime. Check lines: 'outlnvsh.cxx:197', 'outlnvsh.cxx:143', 'OutlineViewShell.hxx:102'.
↑ V1037 Two or more case-branches perform the same actions. Check lines: 1435, 1502