the "end" call will close the shell, which is deleted directly so the local shared_ptr remains pointed to something which is already deleted. So: a) Have activate return true/false to indicate the failure and require the caller to call 'end' in response to failure. b) A bunch of stuff in the call-stack expects the ViewShell not to get deleted while they are calling it, so additionally launch that 'end' to happen in the next event loop. ==2838867== Invalid read of size 8 ==2838867== at 0x32F4B83C: sd::ViewShellBase::GetDocShell() const (ViewShellBase.hxx:97) ==2838867== by 0x335BBCFC: sd::ViewShell::GetDocSh() const (viewshel.cxx:1389) ==2838867== by 0x3357CAC1: sd::PresentationViewShell::~PresentationViewShell() (presvish.cxx:73) ==2838867== by 0x330AA34B: void __gnu_cxx::new_allocator<sd::PresentationViewShell>::destroy<sd::PresentationViewShell>(sd::PresentationViewShell*) (new_allocator.h:156) ==2838867== by 0x330AA2DF: void std::allocator_traits<std::allocator<sd::PresentationViewShell> >::destroy<sd::PresentationViewShell>(std::allocator<sd::PresentationViewShell>&, sd::PresentationViewShell*) (alloc_traits.h:531) ==2838867== by 0x330AA0BE: std::_Sp_counted_ptr_inplace<sd::PresentationViewShell, std::allocator<sd::PresentationViewShell>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:560) ==2838867== by 0x32D10D33: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:158) ==2838867== by 0x32D10C79: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:733) ==2838867== by 0x330A03BD: std::__shared_ptr<sd::PresentationViewShell, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1183) ==2838867== by 0x3309F847: std::shared_ptr<sd::PresentationViewShell>::~shared_ptr() (shared_ptr.h:121) ==2838867== by 0x3320E1E8: sd::SlideShow::activate(sd::ViewShellBase&) (slideshow.cxx:999) ==2838867== by 0x3357CF33: sd::PresentationViewShell::Activate(bool) (presvish.cxx:118) ==2838867== Address 0x2fb5f320 is 256 bytes inside a block of size 272 free'd ==2838867== at 0x483BEDD: operator delete(void*) (vg_replace_malloc.c:584) ==2838867== by 0x33466537: sd::PresentationViewShellBase::~PresentationViewShellBase() (PresentationViewShellBase.cxx:82) ==2838867== by 0x823076C: SfxViewFrame::ReleaseObjectShell_Impl() (viewfrm.cxx:1113) ==2838867== by 0x8234B1C: SfxViewFrame::~SfxViewFrame() (viewfrm.cxx:1652) ==2838867== by 0x8234FEB: SfxViewFrame::~SfxViewFrame() (viewfrm.cxx:1646) ==2838867== by 0x8230D6C: SfxViewFrame::Close() (viewfrm.cxx:1165) ==2838867== by 0x81E4217: SfxFrame::DoClose_Impl() (frame.cxx:142) ==2838867== by 0x821709A: SfxBaseController::dispose() (sfxbasecontroller.cxx:982) ==2838867== by 0x3337A59F: sd::DrawController::dispose() (DrawController.cxx:164) ==2838867== by 0x6F35CC0: (anonymous namespace)::XFrameImpl::setComponent(com::sun:⭐:uno::Reference<com::sun:⭐:awt::XWindow> const&, com::sun:⭐:uno::Reference<com::sun:⭐:frame::XController> const&) (frame.cxx:1485) ==2838867== by 0x6F3834E: (anonymous namespace)::XFrameImpl::close(unsigned char) (frame.cxx:1692) ==2838867== by 0x81E3CFA: SfxFrame::DoClose() (frame.cxx:108) ==2838867== by 0x823802C: SfxViewFrame::DoClose() (viewfrm.cxx:2525) ==2838867== by 0x3320B971: sd::SlideShow::end() (slideshow.cxx:696) ==2838867== by 0x3320E1C2: sd::SlideShow::activate(sd::ViewShellBase&) (slideshow.cxx:995) ==2838867== by 0x3357CF33: sd::PresentationViewShell::Activate(bool) (presvish.cxx:118) Change-Id: Ida91228b7584491c9a5dc9c0b3f76ce63218a92a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103319 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
1646 lines
50 KiB
C++
1646 lines
50 KiB
C++
/* -*- 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 <memory>
|
|
#include <ViewShell.hxx>
|
|
#include <ViewShellImplementation.hxx>
|
|
#include <createtableobjectbar.hxx>
|
|
|
|
#include <ViewShellBase.hxx>
|
|
#include <ShellFactory.hxx>
|
|
#include <DrawController.hxx>
|
|
#include <LayerTabBar.hxx>
|
|
|
|
#include <sal/log.hxx>
|
|
#include <sfx2/viewfrm.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <sfx2/dispatch.hxx>
|
|
#include <vcl/commandevent.hxx>
|
|
#include <vcl/scrbar.hxx>
|
|
#include <svl/eitem.hxx>
|
|
#include <svx/ruler.hxx>
|
|
#include <svx/svxids.hrc>
|
|
#include <svx/fmshell.hxx>
|
|
#include <WindowUpdater.hxx>
|
|
#include <sdxfer.hxx>
|
|
|
|
#include <app.hrc>
|
|
|
|
#include <OutlineView.hxx>
|
|
#include <DrawViewShell.hxx>
|
|
#include <DrawDocShell.hxx>
|
|
#include <slideshow.hxx>
|
|
#include <drawdoc.hxx>
|
|
#include <sdpage.hxx>
|
|
#include <zoomlist.hxx>
|
|
#include <FrameView.hxx>
|
|
#include <BezierObjectBar.hxx>
|
|
#include <TextObjectBar.hxx>
|
|
#include <GraphicObjectBar.hxx>
|
|
#include <MediaObjectBar.hxx>
|
|
#include <SlideSorter.hxx>
|
|
#include <SlideSorterViewShell.hxx>
|
|
#include <ViewShellManager.hxx>
|
|
#include <FormShellManager.hxx>
|
|
#include <svx/extrusionbar.hxx>
|
|
#include <svx/fontworkbar.hxx>
|
|
#include <svx/svdoutl.hxx>
|
|
#include <tools/svborder.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
|
|
#include <svl/slstitm.hxx>
|
|
#include <sfx2/request.hxx>
|
|
#include <SpellDialogChildWindow.hxx>
|
|
#include <controller/SlideSorterController.hxx>
|
|
#include <controller/SlsPageSelector.hxx>
|
|
#include <controller/SlsSelectionObserver.hxx>
|
|
#include <view/SlideSorterView.hxx>
|
|
|
|
#include <basegfx/utils/zoomtools.hxx>
|
|
|
|
#include <Window.hxx>
|
|
#include <fupoor.hxx>
|
|
#include <futext.hxx>
|
|
|
|
#include <editeng/numitem.hxx>
|
|
#include <editeng/eeitem.hxx>
|
|
#include <editeng/editview.hxx>
|
|
#include <editeng/editeng.hxx>
|
|
#include <svl/intitem.hxx>
|
|
#include <svl/poolitem.hxx>
|
|
#include <strings.hxx>
|
|
#include <sdmod.hxx>
|
|
#include <AccessibleDocumentViewBase.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::presentation;
|
|
|
|
namespace {
|
|
|
|
class ViewShellObjectBarFactory
|
|
: public ::sd::ShellFactory<SfxShell>
|
|
{
|
|
public:
|
|
explicit ViewShellObjectBarFactory (::sd::ViewShell& rViewShell);
|
|
virtual SfxShell* CreateShell( ::sd::ShellId nId ) override;
|
|
virtual void ReleaseShell (SfxShell* pShell) override;
|
|
private:
|
|
::sd::ViewShell& mrViewShell;
|
|
};
|
|
|
|
} // end of anonymous namespace
|
|
|
|
namespace sd {
|
|
|
|
bool ViewShell::IsPageFlipMode() const
|
|
{
|
|
return dynamic_cast< const DrawViewShell *>( this ) != nullptr && mpContentWindow &&
|
|
mpContentWindow->GetVisibleHeight() >= 1.0;
|
|
}
|
|
|
|
SfxViewFrame* ViewShell::GetViewFrame() const
|
|
{
|
|
const SfxViewShell* pViewShell = GetViewShell();
|
|
if (pViewShell != nullptr)
|
|
{
|
|
return pViewShell->GetViewFrame();
|
|
}
|
|
else
|
|
{
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/// declare SFX-Slotmap and standard interface
|
|
|
|
ViewShell::ViewShell( vcl::Window* pParentWindow, ViewShellBase& rViewShellBase)
|
|
: SfxShell(&rViewShellBase)
|
|
, mpParentWindow(pParentWindow)
|
|
{
|
|
construct();
|
|
}
|
|
|
|
ViewShell::~ViewShell()
|
|
{
|
|
// Keep the content window from accessing in its destructor the
|
|
// WindowUpdater.
|
|
if (mpContentWindow)
|
|
mpContentWindow->SetViewShell(nullptr);
|
|
|
|
mpZoomList.reset();
|
|
|
|
mpLayerTabBar.disposeAndClear();
|
|
|
|
if (mpImpl->mpSubShellFactory)
|
|
GetViewShellBase().GetViewShellManager()->RemoveSubShellFactory(
|
|
this,mpImpl->mpSubShellFactory);
|
|
|
|
if (mpContentWindow)
|
|
{
|
|
SAL_INFO(
|
|
"sd.view",
|
|
"destroying mpContentWindow at " << mpContentWindow.get()
|
|
<< " with parent " << mpContentWindow->GetParent());
|
|
mpContentWindow.disposeAndClear();
|
|
}
|
|
|
|
mpScrollBarBox.disposeAndClear();
|
|
mpVerticalRuler.disposeAndClear();
|
|
mpHorizontalRuler.disposeAndClear();
|
|
mpVerticalScrollBar.disposeAndClear();
|
|
mpHorizontalScrollBar.disposeAndClear();
|
|
}
|
|
|
|
/**
|
|
* common initialization part of both constructors
|
|
*/
|
|
void ViewShell::construct()
|
|
{
|
|
mbHasRulers = false;
|
|
mpActiveWindow = nullptr;
|
|
mpView = nullptr;
|
|
mpFrameView = nullptr;
|
|
mpZoomList = nullptr;
|
|
mbStartShowWithDialog = false;
|
|
mnPrintedHandoutPageNum = 1;
|
|
mnPrintedHandoutPageCount = 0;
|
|
mpWindowUpdater.reset( new ::sd::WindowUpdater() );
|
|
mpImpl.reset(new Implementation(*this));
|
|
meShellType = ST_NONE;
|
|
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
|
|
if (IsMainViewShell())
|
|
GetDocSh()->Connect (this);
|
|
|
|
mpZoomList.reset( new ZoomList( this ) );
|
|
|
|
mpContentWindow.reset(VclPtr< ::sd::Window >::Create(GetParentWindow()));
|
|
SetActiveWindow (mpContentWindow.get());
|
|
|
|
GetParentWindow()->SetBackground (Wallpaper());
|
|
mpContentWindow->SetBackground (Wallpaper());
|
|
mpContentWindow->SetCenterAllowed(true);
|
|
mpContentWindow->SetViewShell(this);
|
|
mpContentWindow->SetPosSizePixel(
|
|
GetParentWindow()->GetPosPixel(),GetParentWindow()->GetSizePixel());
|
|
|
|
if ( ! GetDocSh()->IsPreview())
|
|
{
|
|
// Create scroll bars and the filler between the scroll bars.
|
|
mpHorizontalScrollBar.reset (VclPtr<ScrollBar>::Create(GetParentWindow(), WinBits(WB_HSCROLL | WB_DRAG)));
|
|
mpHorizontalScrollBar->EnableRTL (false);
|
|
mpHorizontalScrollBar->SetRange(Range(0, 32000));
|
|
mpHorizontalScrollBar->SetScrollHdl(LINK(this, ViewShell, HScrollHdl));
|
|
|
|
mpVerticalScrollBar.reset (VclPtr<ScrollBar>::Create(GetParentWindow(), WinBits(WB_VSCROLL | WB_DRAG)));
|
|
mpVerticalScrollBar->SetRange(Range(0, 32000));
|
|
mpVerticalScrollBar->SetScrollHdl(LINK(this, ViewShell, VScrollHdl));
|
|
|
|
mpScrollBarBox.reset(VclPtr<ScrollBarBox>::Create(GetParentWindow(), WB_SIZEABLE));
|
|
}
|
|
|
|
SetName ("ViewShell");
|
|
|
|
GetDoc()->StartOnlineSpelling(false);
|
|
|
|
mpWindowUpdater->SetDocument (GetDoc());
|
|
|
|
// Re-initialize the spell dialog.
|
|
::sd::SpellDialogChildWindow* pSpellDialog =
|
|
static_cast< ::sd::SpellDialogChildWindow*> (
|
|
GetViewFrame()->GetChildWindow (
|
|
::sd::SpellDialogChildWindow::GetChildWindowId()));
|
|
if (pSpellDialog != nullptr)
|
|
pSpellDialog->InvalidateSpellDialog();
|
|
|
|
// Register the sub shell factory.
|
|
mpImpl->mpSubShellFactory = std::make_shared<ViewShellObjectBarFactory>(*this);
|
|
GetViewShellBase().GetViewShellManager()->AddSubShellFactory(this,mpImpl->mpSubShellFactory);
|
|
}
|
|
|
|
void ViewShell::doShow()
|
|
{
|
|
mpContentWindow->Show();
|
|
static_cast< vcl::Window*>(mpContentWindow.get())->Resize();
|
|
SAL_INFO(
|
|
"sd.view",
|
|
"content window has size " << mpContentWindow->GetSizePixel().Width()
|
|
<< " " << mpContentWindow->GetSizePixel().Height());
|
|
|
|
if ( ! GetDocSh()->IsPreview())
|
|
{
|
|
// Show scroll bars
|
|
mpHorizontalScrollBar->Show();
|
|
|
|
mpVerticalScrollBar->Show();
|
|
maScrBarWH = Size(
|
|
mpVerticalScrollBar->GetSizePixel().Width(),
|
|
mpHorizontalScrollBar->GetSizePixel().Height());
|
|
|
|
mpScrollBarBox->Show();
|
|
}
|
|
|
|
GetParentWindow()->Show();
|
|
}
|
|
|
|
void ViewShell::Init (bool bIsMainViewShell)
|
|
{
|
|
mpImpl->mbIsInitialized = true;
|
|
SetIsMainViewShell(bIsMainViewShell);
|
|
if (bIsMainViewShell)
|
|
SetActiveWindow (mpContentWindow.get());
|
|
}
|
|
|
|
void ViewShell::Exit()
|
|
{
|
|
sd::View* pView = GetView();
|
|
if (pView!=nullptr && pView->IsTextEdit())
|
|
{
|
|
pView->SdrEndTextEdit();
|
|
pView->UnmarkAll();
|
|
}
|
|
|
|
Deactivate (true);
|
|
|
|
if (IsMainViewShell())
|
|
GetDocSh()->Disconnect(this);
|
|
|
|
SetIsMainViewShell(false);
|
|
}
|
|
|
|
/**
|
|
* set focus to working window
|
|
*/
|
|
void ViewShell::Activate(bool bIsMDIActivate)
|
|
{
|
|
// Do not forward to SfxShell::Activate()
|
|
|
|
/* According to MI, nobody is allowed to call GrabFocus, who does not
|
|
exactly know from which window the focus is grabbed. Since Activate()
|
|
is sent sometimes asynchronous, it can happen, that the wrong window
|
|
gets the focus. */
|
|
|
|
if (mpHorizontalRuler)
|
|
mpHorizontalRuler->SetActive();
|
|
if (mpVerticalRuler)
|
|
mpVerticalRuler->SetActive();
|
|
|
|
if (bIsMDIActivate)
|
|
{
|
|
// thus, the Navigator will also get a current status
|
|
SfxBoolItem aItem( SID_NAVIGATOR_INIT, true );
|
|
if (GetDispatcher() != nullptr)
|
|
GetDispatcher()->ExecuteList(
|
|
SID_NAVIGATOR_INIT,
|
|
SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
|
|
{ &aItem });
|
|
|
|
SfxViewShell* pViewShell = GetViewShell();
|
|
OSL_ASSERT (pViewShell!=nullptr);
|
|
SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
|
|
rBindings.Invalidate( SID_3D_STATE, true );
|
|
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
if (xSlideShow.is() && xSlideShow->isRunning())
|
|
{
|
|
bool bSuccess = xSlideShow->activate(GetViewShellBase());
|
|
assert(bSuccess && "can only return false with a PresentationViewShell"); (void)bSuccess;
|
|
}
|
|
|
|
if(HasCurrentFunction())
|
|
GetCurrentFunction()->Activate();
|
|
|
|
if(!GetDocSh()->IsUIActive())
|
|
UpdatePreview( GetActualPage() );
|
|
}
|
|
|
|
ReadFrameViewData( mpFrameView );
|
|
|
|
if (IsMainViewShell())
|
|
GetDocSh()->Connect(this);
|
|
}
|
|
|
|
void ViewShell::UIActivating( SfxInPlaceClient* )
|
|
{
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
GetViewShellBase().GetToolBarManager()->ToolBarsDestroyed();
|
|
}
|
|
|
|
void ViewShell::UIDeactivated( SfxInPlaceClient* )
|
|
{
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
GetViewShellBase().GetToolBarManager()->ToolBarsDestroyed();
|
|
if ( GetDrawView() )
|
|
GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*this, *GetDrawView());
|
|
}
|
|
|
|
void ViewShell::Deactivate(bool bIsMDIActivate)
|
|
{
|
|
// remove view from a still active drag'n'drop session
|
|
SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
|
|
|
|
if (IsMainViewShell())
|
|
GetDocSh()->Disconnect(this);
|
|
|
|
if( pDragTransferable )
|
|
pDragTransferable->SetView( nullptr );
|
|
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
|
|
// remember view attributes of FrameView
|
|
WriteFrameViewData();
|
|
|
|
if (bIsMDIActivate)
|
|
{
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
if(xSlideShow.is() && xSlideShow->isRunning() )
|
|
xSlideShow->deactivate();
|
|
|
|
if(HasCurrentFunction())
|
|
GetCurrentFunction()->Deactivate();
|
|
}
|
|
|
|
if (mpHorizontalRuler)
|
|
mpHorizontalRuler->SetActive(false);
|
|
if (mpVerticalRuler)
|
|
mpVerticalRuler->SetActive(false);
|
|
|
|
SfxShell::Deactivate(bIsMDIActivate);
|
|
}
|
|
|
|
void ViewShell::Shutdown()
|
|
{
|
|
Exit ();
|
|
}
|
|
|
|
bool ViewShell::KeyInput(const KeyEvent& rKEvt, ::sd::Window* pWin)
|
|
{
|
|
bool bReturn(false);
|
|
|
|
if(pWin)
|
|
SetActiveWindow(pWin);
|
|
|
|
// give key input first to SfxViewShell to give CTRL+Key
|
|
// (e.g. CTRL+SHIFT+'+', to front) priority.
|
|
OSL_ASSERT(GetViewShell() != nullptr);
|
|
bReturn = GetViewShell()->KeyInput(rKEvt);
|
|
|
|
const size_t OriCount = GetView()->GetMarkedObjectList().GetMarkCount();
|
|
if(!bReturn)
|
|
{
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
if(xSlideShow.is() && xSlideShow->isRunning())
|
|
{
|
|
bReturn = xSlideShow->keyInput(rKEvt);
|
|
}
|
|
else
|
|
{
|
|
bool bConsumed = false;
|
|
if( GetView() )
|
|
bConsumed = GetView()->getSmartTags().KeyInput(rKEvt);
|
|
|
|
if( !bConsumed )
|
|
{
|
|
rtl::Reference< sdr::SelectionController > xSelectionController( GetView()->getSelectionController() );
|
|
if( !xSelectionController.is() || !xSelectionController->onKeyInput( rKEvt, pWin ) )
|
|
{
|
|
if(HasCurrentFunction())
|
|
bReturn = GetCurrentFunction()->KeyInput(rKEvt);
|
|
}
|
|
else
|
|
{
|
|
bReturn = true;
|
|
if (HasCurrentFunction())
|
|
{
|
|
FuText* pTextFunction = dynamic_cast<FuText*>(GetCurrentFunction().get());
|
|
if(pTextFunction != nullptr)
|
|
pTextFunction->InvalidateBindings();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const size_t EndCount = GetView()->GetMarkedObjectList().GetMarkCount();
|
|
// Here, oriCount or endCount must have one value=0, another value > 0, then to switch focus between Document and shape objects
|
|
if(bReturn && (OriCount + EndCount > 0) && (OriCount * EndCount == 0))
|
|
SwitchActiveViewFireFocus();
|
|
|
|
if(!bReturn && GetActiveWindow())
|
|
{
|
|
vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
|
|
|
|
if (aKeyCode.IsMod1() && aKeyCode.IsShift()
|
|
&& aKeyCode.GetCode() == KEY_R)
|
|
{
|
|
InvalidateWindows();
|
|
bReturn = true;
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
void ViewShell::MouseButtonDown(const MouseEvent& rMEvt, ::sd::Window* pWin)
|
|
{
|
|
// We have to lock tool bar updates while the mouse button is pressed in
|
|
// order to prevent the shape under the mouse to be moved (this happens
|
|
// when the number of docked tool bars changes as result of a changed
|
|
// selection; this changes the window size and thus the mouse position
|
|
// in model coordinates: with respect to model coordinates the mouse
|
|
// moves.)
|
|
OSL_ASSERT(mpImpl->mpUpdateLockForMouse.expired());
|
|
mpImpl->mpUpdateLockForMouse = ViewShell::Implementation::ToolBarManagerLock::Create(
|
|
GetViewShellBase().GetToolBarManager());
|
|
|
|
if ( pWin && !pWin->HasFocus() )
|
|
{
|
|
pWin->GrabFocus();
|
|
SetActiveWindow(pWin);
|
|
}
|
|
|
|
// insert MouseEvent into E3dView
|
|
if (GetView() != nullptr)
|
|
GetView()->SetMouseEvent(rMEvt);
|
|
|
|
bool bConsumed = false;
|
|
if( GetView() )
|
|
bConsumed = GetView()->getSmartTags().MouseButtonDown( rMEvt );
|
|
|
|
if( bConsumed )
|
|
return;
|
|
|
|
rtl::Reference< sdr::SelectionController > xSelectionController( GetView()->getSelectionController() );
|
|
if( !xSelectionController.is() || !xSelectionController->onMouseButtonDown( rMEvt, pWin ) )
|
|
{
|
|
if(HasCurrentFunction())
|
|
GetCurrentFunction()->MouseButtonDown(rMEvt);
|
|
}
|
|
else
|
|
{
|
|
if (HasCurrentFunction())
|
|
{
|
|
FuText* pTextFunction = dynamic_cast<FuText*>(GetCurrentFunction().get());
|
|
if (pTextFunction != nullptr)
|
|
pTextFunction->InvalidateBindings();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ViewShell::SetCursorMm100Position(const Point& rPosition, bool bPoint, bool bClearMark)
|
|
{
|
|
if (SdrView* pSdrView = GetView())
|
|
{
|
|
rtl::Reference<sdr::SelectionController> xSelectionController(GetView()->getSelectionController());
|
|
if (!xSelectionController.is() || !xSelectionController->setCursorLogicPosition(rPosition, bPoint))
|
|
{
|
|
if (pSdrView->GetTextEditObject())
|
|
{
|
|
EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
|
|
rEditView.SetCursorLogicPosition(rPosition, bPoint, bClearMark);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uno::Reference<datatransfer::XTransferable> ViewShell::GetSelectionTransferrable() const
|
|
{
|
|
SdrView* pSdrView = GetView();
|
|
if (!pSdrView)
|
|
return uno::Reference<datatransfer::XTransferable>();
|
|
|
|
if (!pSdrView->GetTextEditObject())
|
|
return uno::Reference<datatransfer::XTransferable>();
|
|
|
|
EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
|
|
return rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection());
|
|
}
|
|
|
|
void ViewShell::SetGraphicMm100Position(bool bStart, const Point& rPosition)
|
|
{
|
|
if (bStart)
|
|
{
|
|
MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
|
|
MouseButtonDown(aClickEvent, mpActiveWindow);
|
|
MouseEvent aMoveEvent(Point(rPosition.getX(), rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
|
|
MouseMove(aMoveEvent, mpActiveWindow);
|
|
}
|
|
else
|
|
{
|
|
MouseEvent aMoveEvent(Point(rPosition.getX(), rPosition.getY()), 0, MouseEventModifiers::SIMPLEMOVE, MOUSE_LEFT);
|
|
MouseMove(aMoveEvent, mpActiveWindow);
|
|
MouseEvent aClickEvent(rPosition, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT);
|
|
MouseButtonUp(aClickEvent, mpActiveWindow);
|
|
}
|
|
}
|
|
|
|
void ViewShell::MouseMove(const MouseEvent& rMEvt, ::sd::Window* pWin)
|
|
{
|
|
if (rMEvt.IsLeaveWindow())
|
|
{
|
|
if ( ! mpImpl->mpUpdateLockForMouse.expired())
|
|
{
|
|
std::shared_ptr<ViewShell::Implementation::ToolBarManagerLock> pLock(
|
|
mpImpl->mpUpdateLockForMouse);
|
|
if (pLock != nullptr)
|
|
pLock->Release();
|
|
}
|
|
}
|
|
|
|
if ( pWin )
|
|
{
|
|
SetActiveWindow(pWin);
|
|
}
|
|
|
|
// insert MouseEvent into E3dView
|
|
if (GetView() != nullptr)
|
|
GetView()->SetMouseEvent(rMEvt);
|
|
|
|
if(HasCurrentFunction())
|
|
{
|
|
rtl::Reference< sdr::SelectionController > xSelectionController( GetView()->getSelectionController() );
|
|
if( !xSelectionController.is() || !xSelectionController->onMouseMove( rMEvt, pWin ) )
|
|
{
|
|
if(HasCurrentFunction())
|
|
GetCurrentFunction()->MouseMove(rMEvt);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ViewShell::MouseButtonUp(const MouseEvent& rMEvt, ::sd::Window* pWin)
|
|
{
|
|
if ( pWin )
|
|
SetActiveWindow(pWin);
|
|
|
|
// insert MouseEvent into E3dView
|
|
if (GetView() != nullptr)
|
|
GetView()->SetMouseEvent(rMEvt);
|
|
|
|
if( HasCurrentFunction())
|
|
{
|
|
rtl::Reference< sdr::SelectionController > xSelectionController( GetView()->getSelectionController() );
|
|
if( !xSelectionController.is() || !xSelectionController->onMouseButtonUp( rMEvt, pWin ) )
|
|
{
|
|
if(HasCurrentFunction())
|
|
GetCurrentFunction()->MouseButtonUp(rMEvt);
|
|
}
|
|
else
|
|
{
|
|
if (HasCurrentFunction())
|
|
{
|
|
FuText* pTextFunction = dynamic_cast<FuText*>(GetCurrentFunction().get());
|
|
if (pTextFunction != nullptr)
|
|
pTextFunction->InvalidateBindings();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! mpImpl->mpUpdateLockForMouse.expired())
|
|
{
|
|
std::shared_ptr<ViewShell::Implementation::ToolBarManagerLock> pLock(
|
|
mpImpl->mpUpdateLockForMouse);
|
|
if (pLock != nullptr)
|
|
pLock->Release();
|
|
}
|
|
}
|
|
|
|
void ViewShell::Command(const CommandEvent& rCEvt, ::sd::Window* pWin)
|
|
{
|
|
bool bDone = HandleScrollCommand (rCEvt, pWin);
|
|
|
|
if( bDone )
|
|
return;
|
|
|
|
if( rCEvt.GetCommand() == CommandEventId::InputLanguageChange )
|
|
{
|
|
//#i42732# update state of fontname if input language changes
|
|
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_CHAR_FONT );
|
|
GetViewFrame()->GetBindings().Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
|
|
}
|
|
else
|
|
{
|
|
bool bConsumed = false;
|
|
if( GetView() )
|
|
bConsumed = GetView()->getSmartTags().Command(rCEvt);
|
|
|
|
if( !bConsumed && HasCurrentFunction())
|
|
GetCurrentFunction()->Command(rCEvt);
|
|
}
|
|
}
|
|
|
|
bool ViewShell::Notify(NotifyEvent const & rNEvt, ::sd::Window* pWin)
|
|
{
|
|
// handle scroll commands when they arrived at child windows
|
|
bool bRet = false;
|
|
if( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
|
|
{
|
|
// note: dynamic_cast is not possible as GetData() returns a void*
|
|
CommandEvent* pCmdEvent = static_cast< CommandEvent* >(rNEvt.GetData());
|
|
bRet = HandleScrollCommand(*pCmdEvent, pWin);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
bool ViewShell::HandleScrollCommand(const CommandEvent& rCEvt, ::sd::Window* pWin)
|
|
{
|
|
bool bDone = false;
|
|
|
|
switch( rCEvt.GetCommand() )
|
|
{
|
|
case CommandEventId::Swipe:
|
|
{
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
if (xSlideShow.is())
|
|
{
|
|
const CommandSwipeData* pSwipeData = rCEvt.GetSwipeData();
|
|
bDone = xSlideShow->swipe(*pSwipeData);
|
|
}
|
|
}
|
|
break;
|
|
case CommandEventId::LongPress:
|
|
{
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
if (xSlideShow.is())
|
|
{
|
|
const CommandLongPressData* pLongPressData = rCEvt.GetLongPressData();
|
|
bDone = xSlideShow->longpress(*pLongPressData);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CommandEventId::Wheel:
|
|
{
|
|
Reference< XSlideShowController > xSlideShowController( SlideShow::GetSlideShowController(GetViewShellBase() ) );
|
|
if( xSlideShowController.is() )
|
|
{
|
|
// We ignore zooming with control+mouse wheel.
|
|
const CommandWheelData* pData = rCEvt.GetWheelData();
|
|
if( pData && !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) && !pData->IsHorz() )
|
|
{
|
|
long nDelta = pData->GetDelta();
|
|
if( nDelta > 0 )
|
|
xSlideShowController->gotoPreviousSlide();
|
|
else if( nDelta < 0 )
|
|
xSlideShowController->gotoNextEffect();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
[[fallthrough]];
|
|
case CommandEventId::StartAutoScroll:
|
|
case CommandEventId::AutoScroll:
|
|
{
|
|
const CommandWheelData* pData = rCEvt.GetWheelData();
|
|
|
|
if (pData != nullptr)
|
|
{
|
|
if (pData->IsMod1())
|
|
{
|
|
if( !GetDocSh()->IsUIActive() )
|
|
{
|
|
const long nOldZoom = GetActiveWindow()->GetZoom();
|
|
long nNewZoom;
|
|
Point aOldMousePos = GetActiveWindow()->PixelToLogic(rCEvt.GetMousePosPixel());
|
|
|
|
if( pData->GetDelta() < 0 )
|
|
nNewZoom = std::max<long>( pWin->GetMinZoom(), basegfx::zoomtools::zoomOut( nOldZoom ));
|
|
else
|
|
nNewZoom = std::min<long>( pWin->GetMaxZoom(), basegfx::zoomtools::zoomIn( nOldZoom ));
|
|
|
|
SetZoom( nNewZoom );
|
|
// Keep mouse at same doc point before zoom
|
|
Point aNewMousePos = GetActiveWindow()->PixelToLogic(rCEvt.GetMousePosPixel());
|
|
SetWinViewPos(GetWinViewPos() - (aNewMousePos - aOldMousePos));
|
|
|
|
Invalidate( SID_ATTR_ZOOM );
|
|
Invalidate( SID_ATTR_ZOOMSLIDER );
|
|
|
|
bDone = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( mpContentWindow.get() == pWin )
|
|
{
|
|
sal_uLong nScrollLines = pData->GetScrollLines();
|
|
if(IsPageFlipMode())
|
|
nScrollLines = COMMAND_WHEEL_PAGESCROLL;
|
|
CommandWheelData aWheelData( pData->GetDelta(),pData->GetNotchDelta(),
|
|
nScrollLines,pData->GetMode(),pData->GetModifier(),pData->IsHorz() );
|
|
CommandEvent aReWrite( rCEvt.GetMousePosPixel(),rCEvt.GetCommand(),
|
|
rCEvt.IsMouseEvent(),static_cast<const void *>(&aWheelData) );
|
|
bDone = pWin->HandleScrollCommand( aReWrite,
|
|
mpHorizontalScrollBar.get(),
|
|
mpVerticalScrollBar.get());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return bDone;
|
|
}
|
|
|
|
void ViewShell::SetupRulers()
|
|
{
|
|
if(!mbHasRulers || !mpContentWindow || SlideShow::IsRunning(GetViewShellBase()))
|
|
return;
|
|
|
|
long nHRulerOfs = 0;
|
|
|
|
if ( !mpVerticalRuler )
|
|
{
|
|
mpVerticalRuler.reset(CreateVRuler(GetActiveWindow()));
|
|
if ( mpVerticalRuler )
|
|
{
|
|
nHRulerOfs = mpVerticalRuler->GetSizePixel().Width();
|
|
mpVerticalRuler->SetActive();
|
|
mpVerticalRuler->Show();
|
|
}
|
|
}
|
|
if ( !mpHorizontalRuler )
|
|
{
|
|
mpHorizontalRuler.reset(CreateHRuler(GetActiveWindow()));
|
|
if ( mpHorizontalRuler )
|
|
{
|
|
mpHorizontalRuler->SetWinPos(nHRulerOfs);
|
|
mpHorizontalRuler->SetActive();
|
|
mpHorizontalRuler->Show();
|
|
}
|
|
}
|
|
}
|
|
|
|
const SfxPoolItem* ViewShell::GetNumBulletItem(SfxItemSet& aNewAttr, sal_uInt16& nNumItemId)
|
|
{
|
|
const SfxPoolItem* pTmpItem = nullptr;
|
|
|
|
if(aNewAttr.GetItemState(nNumItemId, false, &pTmpItem) == SfxItemState::SET)
|
|
{
|
|
return pTmpItem;
|
|
}
|
|
else
|
|
{
|
|
nNumItemId = aNewAttr.GetPool()->GetWhich(SID_ATTR_NUMBERING_RULE);
|
|
SfxItemState eState = aNewAttr.GetItemState(nNumItemId, false, &pTmpItem);
|
|
if (eState == SfxItemState::SET)
|
|
return pTmpItem;
|
|
else
|
|
{
|
|
bool bOutliner = false;
|
|
bool bTitle = false;
|
|
|
|
if( mpView )
|
|
{
|
|
const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
for(size_t nNum = 0; nNum < nCount; ++nNum)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(nNum)->GetMarkedSdrObj();
|
|
if( pObj->GetObjInventor() == SdrInventor::Default )
|
|
{
|
|
switch(pObj->GetObjIdentifier())
|
|
{
|
|
case OBJ_TITLETEXT:
|
|
bTitle = true;
|
|
break;
|
|
case OBJ_OUTLINETEXT:
|
|
bOutliner = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const SvxNumBulletItem *pItem = nullptr;
|
|
if(bOutliner)
|
|
{
|
|
SfxStyleSheetBasePool* pSSPool = mpView->GetDocSh()->GetStyleSheetPool();
|
|
SfxStyleSheetBase* pFirstStyleSheet = pSSPool->Find( STR_LAYOUT_OUTLINE " 1", SfxStyleFamily::Pseudo);
|
|
if( pFirstStyleSheet )
|
|
pFirstStyleSheet->GetItemSet().GetItemState(EE_PARA_NUMBULLET, false, reinterpret_cast<const SfxPoolItem**>(&pItem));
|
|
}
|
|
|
|
if( pItem == nullptr )
|
|
pItem = aNewAttr.GetPool()->GetSecondaryPool()->GetPoolDefaultItem(EE_PARA_NUMBULLET);
|
|
|
|
aNewAttr.Put(pItem->CloneSetWhich(EE_PARA_NUMBULLET));
|
|
|
|
if(bTitle && aNewAttr.GetItemState(EE_PARA_NUMBULLET) == SfxItemState::SET )
|
|
{
|
|
const SvxNumBulletItem* pBulletItem = aNewAttr.GetItem(EE_PARA_NUMBULLET);
|
|
SvxNumRule* pRule = pBulletItem->GetNumRule();
|
|
if(pRule)
|
|
{
|
|
SvxNumRule aNewRule( *pRule );
|
|
aNewRule.SetFeatureFlag( SvxNumRuleFlags::NO_NUMBERS );
|
|
|
|
SvxNumBulletItem aNewItem( aNewRule, EE_PARA_NUMBULLET );
|
|
aNewAttr.Put(aNewItem);
|
|
}
|
|
}
|
|
|
|
SfxItemState eNumState = aNewAttr.GetItemState(nNumItemId, false, &pTmpItem);
|
|
if (eNumState == SfxItemState::SET)
|
|
return pTmpItem;
|
|
|
|
}
|
|
}
|
|
return pTmpItem;
|
|
}
|
|
|
|
void ViewShell::Resize()
|
|
{
|
|
SetupRulers ();
|
|
|
|
if (mpParentWindow == nullptr)
|
|
return;
|
|
|
|
// Make sure that the new size is not degenerate.
|
|
const Size aSize (mpParentWindow->GetSizePixel());
|
|
if (aSize.IsEmpty())
|
|
return;
|
|
|
|
// Remember the new position and size.
|
|
maViewPos = Point(0,0);
|
|
maViewSize = aSize;
|
|
|
|
// Rearrange the UI elements to take care of the new position and size.
|
|
ArrangeGUIElements ();
|
|
// end of included AdjustPosSizePixel.
|
|
|
|
::sd::View* pView = GetView();
|
|
|
|
if (pView)
|
|
pView->VisAreaChanged(GetActiveWindow());
|
|
}
|
|
|
|
SvBorder ViewShell::GetBorder()
|
|
{
|
|
SvBorder aBorder;
|
|
|
|
// Horizontal scrollbar.
|
|
if (mpHorizontalScrollBar
|
|
&& mpHorizontalScrollBar->IsVisible())
|
|
{
|
|
aBorder.Bottom() = maScrBarWH.Height();
|
|
}
|
|
|
|
// Vertical scrollbar.
|
|
if (mpVerticalScrollBar
|
|
&& mpVerticalScrollBar->IsVisible())
|
|
{
|
|
aBorder.Right() = maScrBarWH.Width();
|
|
}
|
|
|
|
// Place horizontal ruler below tab bar.
|
|
if (mbHasRulers && mpContentWindow)
|
|
{
|
|
SetupRulers();
|
|
if (mpHorizontalRuler)
|
|
aBorder.Top() = mpHorizontalRuler->GetSizePixel().Height();
|
|
if (mpVerticalRuler)
|
|
aBorder.Left() = mpVerticalRuler->GetSizePixel().Width();
|
|
}
|
|
|
|
return aBorder;
|
|
}
|
|
|
|
void ViewShell::ArrangeGUIElements()
|
|
{
|
|
if (mpImpl->mbArrangeActive)
|
|
return;
|
|
if (maViewSize.IsEmpty())
|
|
return;
|
|
mpImpl->mbArrangeActive = true;
|
|
|
|
// Calculate border for in-place editing.
|
|
long nLeft = maViewPos.X();
|
|
long nTop = maViewPos.Y();
|
|
long nRight = maViewPos.X() + maViewSize.Width();
|
|
long nBottom = maViewPos.Y() + maViewSize.Height();
|
|
|
|
// Horizontal scrollbar.
|
|
if (mpHorizontalScrollBar
|
|
&& mpHorizontalScrollBar->IsVisible())
|
|
{
|
|
nBottom -= maScrBarWH.Height();
|
|
if (mpLayerTabBar && mpLayerTabBar->IsVisible())
|
|
nBottom -= mpLayerTabBar->GetSizePixel().Height();
|
|
mpHorizontalScrollBar->SetPosSizePixel (
|
|
Point(nLeft, nBottom),
|
|
Size(nRight - nLeft - maScrBarWH.Width(), maScrBarWH.Height()));
|
|
}
|
|
|
|
// Vertical scrollbar.
|
|
if (mpVerticalScrollBar
|
|
&& mpVerticalScrollBar->IsVisible())
|
|
{
|
|
nRight -= maScrBarWH.Width();
|
|
mpVerticalScrollBar->SetPosSizePixel (
|
|
Point(nRight,nTop),
|
|
Size (maScrBarWH.Width(), nBottom-nTop));
|
|
}
|
|
|
|
// Filler in the lower right corner.
|
|
if (mpScrollBarBox)
|
|
{
|
|
if (mpHorizontalScrollBar
|
|
&& mpHorizontalScrollBar->IsVisible()
|
|
&& mpVerticalScrollBar
|
|
&& mpVerticalScrollBar->IsVisible())
|
|
{
|
|
mpScrollBarBox->Show();
|
|
mpScrollBarBox->SetPosSizePixel(Point(nRight, nBottom), maScrBarWH);
|
|
}
|
|
else
|
|
mpScrollBarBox->Hide();
|
|
}
|
|
|
|
// Place horizontal ruler below tab bar.
|
|
if (mbHasRulers && mpContentWindow)
|
|
{
|
|
if (mpHorizontalRuler)
|
|
{
|
|
Size aRulerSize = mpHorizontalRuler->GetSizePixel();
|
|
aRulerSize.setWidth( nRight - nLeft );
|
|
mpHorizontalRuler->SetPosSizePixel (
|
|
Point(nLeft,nTop), aRulerSize);
|
|
if (mpVerticalRuler)
|
|
mpHorizontalRuler->SetBorderPos(
|
|
mpVerticalRuler->GetSizePixel().Width()-1);
|
|
nTop += aRulerSize.Height();
|
|
}
|
|
if (mpVerticalRuler)
|
|
{
|
|
Size aRulerSize = mpVerticalRuler->GetSizePixel();
|
|
aRulerSize.setHeight( nBottom - nTop );
|
|
mpVerticalRuler->SetPosSizePixel (
|
|
Point (nLeft,nTop), aRulerSize);
|
|
nLeft += aRulerSize.Width();
|
|
}
|
|
}
|
|
|
|
rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( GetViewShellBase() ) );
|
|
|
|
// The size of the window of the center pane is set differently from
|
|
// that of the windows in the docking windows.
|
|
bool bSlideShowActive = (xSlideShow.is() && xSlideShow->isRunning()) && !xSlideShow->isFullScreen() && xSlideShow->getAnimationMode() == ANIMATIONMODE_SHOW;
|
|
if ( !bSlideShowActive)
|
|
{
|
|
OSL_ASSERT (GetViewShell()!=nullptr);
|
|
|
|
if (mpContentWindow)
|
|
mpContentWindow->SetPosSizePixel(
|
|
Point(nLeft,nTop),
|
|
Size(nRight-nLeft,nBottom-nTop));
|
|
}
|
|
|
|
// Windows in the center and rulers at the left and top side.
|
|
maAllWindowRectangle = ::tools::Rectangle(
|
|
maViewPos,
|
|
Size(maViewSize.Width()-maScrBarWH.Width(),
|
|
maViewSize.Height()-maScrBarWH.Height()));
|
|
|
|
if (mpContentWindow)
|
|
mpContentWindow->UpdateMapOrigin();
|
|
|
|
UpdateScrollBars();
|
|
|
|
mpImpl->mbArrangeActive = false;
|
|
}
|
|
|
|
void ViewShell::SetUIUnit(FieldUnit eUnit)
|
|
{
|
|
// Set unit at horizontal and vertical rulers.
|
|
if (mpHorizontalRuler)
|
|
mpHorizontalRuler->SetUnit(eUnit);
|
|
|
|
if (mpVerticalRuler)
|
|
mpVerticalRuler->SetUnit(eUnit);
|
|
}
|
|
|
|
/**
|
|
* set DefTab at horizontal rulers
|
|
*/
|
|
void ViewShell::SetDefTabHRuler( sal_uInt16 nDefTab )
|
|
{
|
|
if (mpHorizontalRuler)
|
|
mpHorizontalRuler->SetDefTabDist( nDefTab );
|
|
}
|
|
|
|
/** Tell the FmFormShell that the view shell is closing. Give it the
|
|
opportunity to prevent that.
|
|
*/
|
|
bool ViewShell::PrepareClose (bool bUI)
|
|
{
|
|
bool bResult = true;
|
|
|
|
FmFormShell* pFormShell = GetViewShellBase().GetFormShellManager()->GetFormShell();
|
|
if (pFormShell != nullptr)
|
|
bResult = pFormShell->PrepareClose (bUI);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
void ViewShell::UpdatePreview (SdPage*)
|
|
{
|
|
// Do nothing. After the actual preview has been removed,
|
|
// OutlineViewShell::UpdatePreview() is the place where something
|
|
// useful is still done.
|
|
}
|
|
|
|
SfxUndoManager* ViewShell::ImpGetUndoManager() const
|
|
{
|
|
const ViewShell* pMainViewShell = GetViewShellBase().GetMainViewShell().get();
|
|
|
|
if( pMainViewShell == nullptr )
|
|
pMainViewShell = this;
|
|
|
|
::sd::View* pView = pMainViewShell->GetView();
|
|
|
|
// check for text edit our outline view
|
|
if( pView )
|
|
{
|
|
if( pMainViewShell->GetShellType() == ViewShell::ST_OUTLINE )
|
|
{
|
|
OutlineView* pOlView = dynamic_cast< OutlineView* >( pView );
|
|
if( pOlView )
|
|
{
|
|
::Outliner& rOutl = pOlView->GetOutliner();
|
|
return &rOutl.GetUndoManager();
|
|
}
|
|
}
|
|
else if( pView->IsTextEdit() )
|
|
{
|
|
SdrOutliner* pOL = pView->GetTextEditOutliner();
|
|
if( pOL )
|
|
return &pOL->GetUndoManager();
|
|
}
|
|
}
|
|
|
|
if( GetDocSh() )
|
|
return GetDocSh()->GetUndoManager();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void ViewShell::ImpGetUndoStrings(SfxItemSet &rSet) const
|
|
{
|
|
SfxUndoManager* pUndoManager = ImpGetUndoManager();
|
|
if(!pUndoManager)
|
|
return;
|
|
|
|
sal_uInt16 nCount(pUndoManager->GetUndoActionCount());
|
|
if(nCount)
|
|
{
|
|
// prepare list
|
|
std::vector<OUString> aStringList;
|
|
aStringList.reserve(nCount);
|
|
for (sal_uInt16 a = 0; a < nCount; ++a)
|
|
{
|
|
// generate one String in list per undo step
|
|
aStringList.push_back( pUndoManager->GetUndoActionComment(a) );
|
|
}
|
|
|
|
// set item
|
|
rSet.Put(SfxStringListItem(SID_GETUNDOSTRINGS, &aStringList));
|
|
}
|
|
else
|
|
{
|
|
rSet.DisableItem(SID_GETUNDOSTRINGS);
|
|
}
|
|
}
|
|
|
|
void ViewShell::ImpGetRedoStrings(SfxItemSet &rSet) const
|
|
{
|
|
SfxUndoManager* pUndoManager = ImpGetUndoManager();
|
|
if(!pUndoManager)
|
|
return;
|
|
|
|
sal_uInt16 nCount(pUndoManager->GetRedoActionCount());
|
|
if(nCount)
|
|
{
|
|
// prepare list
|
|
::std::vector< OUString > aStringList;
|
|
aStringList.reserve(nCount);
|
|
for(sal_uInt16 a = 0; a < nCount; a++)
|
|
// generate one String in list per undo step
|
|
aStringList.push_back( pUndoManager->GetRedoActionComment(a) );
|
|
|
|
// set item
|
|
rSet.Put(SfxStringListItem(SID_GETREDOSTRINGS, &aStringList));
|
|
}
|
|
else
|
|
{
|
|
rSet.DisableItem(SID_GETREDOSTRINGS);
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
class KeepSlideSorterInSyncWithPageChanges
|
|
{
|
|
sd::slidesorter::view::SlideSorterView::DrawLock m_aDrawLock;
|
|
sd::slidesorter::controller::SlideSorterController::ModelChangeLock m_aModelLock;
|
|
sd::slidesorter::controller::PageSelector::UpdateLock m_aUpdateLock;
|
|
sd::slidesorter::controller::SelectionObserver::Context m_aContext;
|
|
|
|
public:
|
|
explicit KeepSlideSorterInSyncWithPageChanges(sd::slidesorter::SlideSorter const & rSlideSorter)
|
|
: m_aDrawLock(rSlideSorter)
|
|
, m_aModelLock(rSlideSorter.GetController())
|
|
, m_aUpdateLock(rSlideSorter)
|
|
, m_aContext(rSlideSorter)
|
|
{
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
void ViewShell::ImpSidUndo(SfxRequest& rReq)
|
|
{
|
|
//The xWatcher keeps the SlideSorter selection in sync
|
|
//with the page insertions/deletions that Undo may introduce
|
|
std::unique_ptr<KeepSlideSorterInSyncWithPageChanges, o3tl::default_delete<KeepSlideSorterInSyncWithPageChanges>> xWatcher;
|
|
slidesorter::SlideSorterViewShell* pSlideSorterViewShell
|
|
= slidesorter::SlideSorterViewShell::GetSlideSorter(GetViewShellBase());
|
|
if (pSlideSorterViewShell)
|
|
xWatcher.reset(new KeepSlideSorterInSyncWithPageChanges(pSlideSorterViewShell->GetSlideSorter()));
|
|
|
|
SfxUndoManager* pUndoManager = ImpGetUndoManager();
|
|
sal_uInt16 nNumber(1);
|
|
const SfxItemSet* pReqArgs = rReq.GetArgs();
|
|
bool bRepair = false;
|
|
|
|
if(pReqArgs)
|
|
{
|
|
const SfxUInt16Item* pUIntItem = static_cast<const SfxUInt16Item*>(&pReqArgs->Get(SID_UNDO));
|
|
nNumber = pUIntItem->GetValue();
|
|
|
|
// Repair mode: allow undo/redo of all undo actions, even if access would
|
|
// be limited based on the view shell ID.
|
|
const SfxPoolItem* pRepairItem;
|
|
if (pReqArgs->GetItemState(SID_REPAIRPACKAGE, false, &pRepairItem) == SfxItemState::SET)
|
|
bRepair = static_cast<const SfxBoolItem*>(pRepairItem)->GetValue();
|
|
}
|
|
|
|
if(nNumber && pUndoManager)
|
|
{
|
|
sal_uInt16 nCount(pUndoManager->GetUndoActionCount());
|
|
if(nCount >= nNumber)
|
|
{
|
|
if (comphelper::LibreOfficeKit::isActive() && !bRepair)
|
|
{
|
|
// If another view created the first undo action, prevent redoing it from this view.
|
|
const SfxUndoAction* pAction = pUndoManager->GetUndoAction();
|
|
if (pAction->GetViewShellId() != GetViewShellBase().GetViewShellId())
|
|
{
|
|
rReq.SetReturnValue(SfxUInt32Item(SID_UNDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
|
|
return;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
// when UndoStack is cleared by ModifyPageUndoAction
|
|
// the nCount may have changed, so test GetUndoActionCount()
|
|
while(nNumber-- && pUndoManager->GetUndoActionCount())
|
|
pUndoManager->Undo();
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
// no need to handle. By definition, the UndoManager handled this by clearing the
|
|
// Undo/Redo stacks
|
|
}
|
|
}
|
|
|
|
// refresh rulers, maybe UNDO was move of TAB marker in ruler
|
|
if (mbHasRulers)
|
|
Invalidate(SID_ATTR_TABSTOP);
|
|
}
|
|
|
|
// This one is corresponding to the default handling
|
|
// of SID_UNDO in sfx2
|
|
GetViewFrame()->GetBindings().InvalidateAll(false);
|
|
|
|
rReq.Done();
|
|
}
|
|
|
|
void ViewShell::ImpSidRedo(SfxRequest& rReq)
|
|
{
|
|
//The xWatcher keeps the SlideSorter selection in sync
|
|
//with the page insertions/deletions that Undo may introduce
|
|
std::unique_ptr<KeepSlideSorterInSyncWithPageChanges, o3tl::default_delete<KeepSlideSorterInSyncWithPageChanges>> xWatcher;
|
|
slidesorter::SlideSorterViewShell* pSlideSorterViewShell
|
|
= slidesorter::SlideSorterViewShell::GetSlideSorter(GetViewShellBase());
|
|
if (pSlideSorterViewShell)
|
|
xWatcher.reset(new KeepSlideSorterInSyncWithPageChanges(pSlideSorterViewShell->GetSlideSorter()));
|
|
|
|
SfxUndoManager* pUndoManager = ImpGetUndoManager();
|
|
sal_uInt16 nNumber(1);
|
|
const SfxItemSet* pReqArgs = rReq.GetArgs();
|
|
bool bRepair = false;
|
|
|
|
if(pReqArgs)
|
|
{
|
|
const SfxUInt16Item* pUIntItem = static_cast<const SfxUInt16Item*>(&pReqArgs->Get(SID_REDO));
|
|
nNumber = pUIntItem->GetValue();
|
|
// Repair mode: allow undo/redo of all undo actions, even if access would
|
|
// be limited based on the view shell ID.
|
|
const SfxPoolItem* pRepairItem;
|
|
if (pReqArgs->GetItemState(SID_REPAIRPACKAGE, false, &pRepairItem) == SfxItemState::SET)
|
|
bRepair = static_cast<const SfxBoolItem*>(pRepairItem)->GetValue();
|
|
}
|
|
|
|
if(nNumber && pUndoManager)
|
|
{
|
|
sal_uInt16 nCount(pUndoManager->GetRedoActionCount());
|
|
if(nCount >= nNumber)
|
|
{
|
|
if (comphelper::LibreOfficeKit::isActive() && !bRepair)
|
|
{
|
|
// If another view created the first undo action, prevent redoing it from this view.
|
|
const SfxUndoAction* pAction = pUndoManager->GetRedoAction();
|
|
if (pAction->GetViewShellId() != GetViewShellBase().GetViewShellId())
|
|
{
|
|
rReq.SetReturnValue(SfxUInt32Item(SID_REDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
|
|
return;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
// when UndoStack is cleared by ModifyPageRedoAction
|
|
// the nCount may have changed, so test GetRedoActionCount()
|
|
while(nNumber-- && pUndoManager->GetRedoActionCount())
|
|
pUndoManager->Redo();
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
// no need to handle. By definition, the UndoManager handled this by clearing the
|
|
// Undo/Redo stacks
|
|
}
|
|
}
|
|
|
|
// refresh rulers, maybe REDO was move of TAB marker in ruler
|
|
if (mbHasRulers)
|
|
{
|
|
Invalidate(SID_ATTR_TABSTOP);
|
|
}
|
|
}
|
|
|
|
// This one is corresponding to the default handling
|
|
// of SID_UNDO in sfx2
|
|
GetViewFrame()->GetBindings().InvalidateAll(false);
|
|
|
|
rReq.Done();
|
|
}
|
|
|
|
void ViewShell::ExecReq( SfxRequest& rReq )
|
|
{
|
|
sal_uInt16 nSlot = rReq.GetSlot();
|
|
switch( nSlot )
|
|
{
|
|
case SID_MAIL_SCROLLBODY_PAGEDOWN:
|
|
{
|
|
rtl::Reference<FuPoor> xFunc( GetCurrentFunction() );
|
|
if( xFunc.is() )
|
|
ScrollLines( 0, -1 );
|
|
|
|
rReq.Done();
|
|
}
|
|
break;
|
|
|
|
case SID_OUTPUT_QUALITY_COLOR:
|
|
case SID_OUTPUT_QUALITY_GRAYSCALE:
|
|
case SID_OUTPUT_QUALITY_BLACKWHITE:
|
|
case SID_OUTPUT_QUALITY_CONTRAST:
|
|
{
|
|
DrawModeFlags nMode = OUTPUT_DRAWMODE_COLOR;
|
|
|
|
switch( nSlot )
|
|
{
|
|
case SID_OUTPUT_QUALITY_COLOR: nMode = OUTPUT_DRAWMODE_COLOR; break;
|
|
case SID_OUTPUT_QUALITY_GRAYSCALE: nMode = OUTPUT_DRAWMODE_GRAYSCALE; break;
|
|
case SID_OUTPUT_QUALITY_BLACKWHITE: nMode = OUTPUT_DRAWMODE_BLACKWHITE; break;
|
|
case SID_OUTPUT_QUALITY_CONTRAST: nMode = OUTPUT_DRAWMODE_CONTRAST; break;
|
|
}
|
|
|
|
GetActiveWindow()->SetDrawMode( nMode );
|
|
mpFrameView->SetDrawMode( nMode );
|
|
|
|
GetActiveWindow()->Invalidate();
|
|
|
|
Invalidate();
|
|
rReq.Done();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** This default implementation returns only an empty reference. See derived
|
|
classes for more interesting examples.
|
|
*/
|
|
css::uno::Reference<css::accessibility::XAccessible>
|
|
ViewShell::CreateAccessibleDocumentView (::sd::Window* )
|
|
{
|
|
OSL_FAIL("ViewShell::CreateAccessibleDocumentView should not be called!, perhaps Meyers, 3rd edition, Item 9:");
|
|
|
|
return css::uno::Reference<css::accessibility::XAccessible> ();
|
|
}
|
|
|
|
::sd::WindowUpdater* ViewShell::GetWindowUpdater() const
|
|
{
|
|
return mpWindowUpdater.get();
|
|
}
|
|
|
|
ViewShellBase& ViewShell::GetViewShellBase() const
|
|
{
|
|
return *static_cast<ViewShellBase*>(GetViewShell());
|
|
}
|
|
|
|
ViewShell::ShellType ViewShell::GetShellType() const
|
|
{
|
|
return meShellType;
|
|
}
|
|
|
|
DrawDocShell* ViewShell::GetDocSh() const
|
|
{
|
|
return GetViewShellBase().GetDocShell();
|
|
}
|
|
|
|
SdDrawDocument* ViewShell::GetDoc() const
|
|
{
|
|
return GetViewShellBase().GetDocument();
|
|
}
|
|
|
|
ErrCode ViewShell::DoVerb (long )
|
|
{
|
|
return ERRCODE_NONE;
|
|
}
|
|
|
|
void ViewShell::SetCurrentFunction( const rtl::Reference<FuPoor>& xFunction)
|
|
{
|
|
if( mxCurrentFunction.is() && (mxOldFunction != mxCurrentFunction) )
|
|
mxCurrentFunction->Dispose();
|
|
rtl::Reference<FuPoor> xDisposeAfterNewOne( mxCurrentFunction );
|
|
mxCurrentFunction = xFunction;
|
|
}
|
|
|
|
void ViewShell::SetOldFunction(const rtl::Reference<FuPoor>& xFunction)
|
|
{
|
|
if( mxOldFunction.is() && (xFunction != mxOldFunction) && (mxCurrentFunction != mxOldFunction) )
|
|
mxOldFunction->Dispose();
|
|
|
|
rtl::Reference<FuPoor> xDisposeAfterNewOne( mxOldFunction );
|
|
mxOldFunction = xFunction;
|
|
}
|
|
|
|
/** this method deactivates the current function. If an old function is
|
|
saved, this will become activated and current function.
|
|
*/
|
|
void ViewShell::Cancel()
|
|
{
|
|
if(mxCurrentFunction.is() && (mxCurrentFunction != mxOldFunction ))
|
|
{
|
|
rtl::Reference<FuPoor> xTemp( mxCurrentFunction );
|
|
mxCurrentFunction.clear();
|
|
xTemp->Deactivate();
|
|
xTemp->Dispose();
|
|
}
|
|
|
|
if(mxOldFunction.is())
|
|
{
|
|
mxCurrentFunction = mxOldFunction;
|
|
mxCurrentFunction->Activate();
|
|
}
|
|
}
|
|
|
|
void ViewShell::DeactivateCurrentFunction( bool bPermanent /* == false */ )
|
|
{
|
|
if( mxCurrentFunction.is() )
|
|
{
|
|
if(bPermanent && (mxOldFunction == mxCurrentFunction))
|
|
mxOldFunction.clear();
|
|
|
|
mxCurrentFunction->Deactivate();
|
|
if( mxCurrentFunction != mxOldFunction )
|
|
mxCurrentFunction->Dispose();
|
|
|
|
rtl::Reference<FuPoor> xDisposeAfterNewOne( mxCurrentFunction );
|
|
mxCurrentFunction.clear();
|
|
}
|
|
}
|
|
|
|
void ViewShell::DisposeFunctions()
|
|
{
|
|
if(mxCurrentFunction.is())
|
|
{
|
|
rtl::Reference<FuPoor> xTemp( mxCurrentFunction );
|
|
mxCurrentFunction.clear();
|
|
xTemp->Deactivate();
|
|
xTemp->Dispose();
|
|
}
|
|
|
|
if(mxOldFunction.is())
|
|
{
|
|
rtl::Reference<FuPoor> xDisposeAfterNewOne( mxOldFunction );
|
|
mxOldFunction->Dispose();
|
|
mxOldFunction.clear();
|
|
}
|
|
}
|
|
|
|
bool ViewShell::IsMainViewShell() const
|
|
{
|
|
return mpImpl->mbIsMainViewShell;
|
|
}
|
|
|
|
void ViewShell::SetIsMainViewShell (bool bIsMainViewShell)
|
|
{
|
|
if (bIsMainViewShell != mpImpl->mbIsMainViewShell)
|
|
{
|
|
mpImpl->mbIsMainViewShell = bIsMainViewShell;
|
|
if (bIsMainViewShell)
|
|
GetDocSh()->Connect (this);
|
|
else
|
|
GetDocSh()->Disconnect (this);
|
|
}
|
|
}
|
|
|
|
void ViewShell::PrePaint()
|
|
{
|
|
}
|
|
|
|
void ViewShell::Paint (const ::tools::Rectangle&, ::sd::Window* )
|
|
{
|
|
}
|
|
|
|
void ViewShell::ShowUIControls (bool bVisible)
|
|
{
|
|
if (mbHasRulers)
|
|
{
|
|
if (mpHorizontalRuler)
|
|
mpHorizontalRuler->Show( bVisible );
|
|
|
|
if (mpVerticalRuler)
|
|
mpVerticalRuler->Show( bVisible );
|
|
}
|
|
|
|
if (mpVerticalScrollBar)
|
|
mpVerticalScrollBar->Show( bVisible );
|
|
|
|
if (mpHorizontalScrollBar)
|
|
mpHorizontalScrollBar->Show( bVisible );
|
|
|
|
if (mpScrollBarBox)
|
|
mpScrollBarBox->Show(bVisible);
|
|
|
|
if (mpContentWindow)
|
|
mpContentWindow->Show( bVisible );
|
|
}
|
|
|
|
bool ViewShell::RelocateToParentWindow (vcl::Window* pParentWindow)
|
|
{
|
|
mpParentWindow = pParentWindow;
|
|
|
|
mpParentWindow->SetBackground (Wallpaper());
|
|
|
|
if (mpContentWindow)
|
|
mpContentWindow->SetParent(pParentWindow);
|
|
|
|
if (mpHorizontalScrollBar)
|
|
mpHorizontalScrollBar->SetParent(mpParentWindow);
|
|
if (mpVerticalScrollBar)
|
|
mpVerticalScrollBar->SetParent(mpParentWindow);
|
|
if (mpScrollBarBox)
|
|
mpScrollBarBox->SetParent(mpParentWindow);
|
|
|
|
return true;
|
|
}
|
|
|
|
void ViewShell::SwitchViewFireFocus(const css::uno::Reference< css::accessibility::XAccessible >& xAcc )
|
|
{
|
|
if (xAcc)
|
|
{
|
|
::accessibility::AccessibleDocumentViewBase* pBase = static_cast< ::accessibility::AccessibleDocumentViewBase* >(xAcc.get());
|
|
if (pBase)
|
|
pBase->SwitchViewActivated();
|
|
}
|
|
}
|
|
void ViewShell::SwitchActiveViewFireFocus()
|
|
{
|
|
if (mpContentWindow)
|
|
{
|
|
SwitchViewFireFocus(mpContentWindow->GetAccessible(false));
|
|
}
|
|
}
|
|
// move these two methods from DrawViewShell.
|
|
void ViewShell::fireSwitchCurrentPage(sal_Int32 pageIndex)
|
|
{
|
|
GetViewShellBase().GetDrawController().fireSwitchCurrentPage(pageIndex);
|
|
}
|
|
void ViewShell::NotifyAccUpdate( )
|
|
{
|
|
GetViewShellBase().GetDrawController().NotifyAccUpdate();
|
|
}
|
|
|
|
weld::Window* ViewShell::GetFrameWeld() const
|
|
{
|
|
return mpActiveWindow ? mpActiveWindow->GetFrameWeld() : nullptr;
|
|
}
|
|
|
|
sd::Window* ViewShell::GetContentWindow() const
|
|
{
|
|
return mpContentWindow.get();
|
|
}
|
|
|
|
} // end of namespace sd
|
|
|
|
//===== ViewShellObjectBarFactory =============================================
|
|
|
|
namespace {
|
|
|
|
ViewShellObjectBarFactory::ViewShellObjectBarFactory (
|
|
::sd::ViewShell& rViewShell)
|
|
: mrViewShell (rViewShell)
|
|
{
|
|
}
|
|
|
|
SfxShell* ViewShellObjectBarFactory::CreateShell( ::sd::ShellId nId )
|
|
{
|
|
SfxShell* pShell = nullptr;
|
|
|
|
::sd::View* pView = mrViewShell.GetView();
|
|
switch (nId)
|
|
{
|
|
case ToolbarId::Bezier_Toolbox_Sd:
|
|
pShell = new ::sd::BezierObjectBar(&mrViewShell, pView);
|
|
break;
|
|
|
|
case ToolbarId::Draw_Text_Toolbox_Sd:
|
|
pShell = new ::sd::TextObjectBar(
|
|
&mrViewShell, mrViewShell.GetDoc()->GetPool(), pView);
|
|
break;
|
|
|
|
case ToolbarId::Draw_Graf_Toolbox:
|
|
pShell = new ::sd::GraphicObjectBar(&mrViewShell, pView);
|
|
break;
|
|
|
|
case ToolbarId::Draw_Media_Toolbox:
|
|
pShell = new ::sd::MediaObjectBar(&mrViewShell, pView);
|
|
break;
|
|
|
|
case ToolbarId::Draw_Table_Toolbox:
|
|
pShell = ::sd::ui::table::CreateTableObjectBar( mrViewShell, pView );
|
|
break;
|
|
|
|
case ToolbarId::Svx_Extrusion_Bar:
|
|
pShell = new svx::ExtrusionBar(
|
|
&mrViewShell.GetViewShellBase());
|
|
break;
|
|
|
|
case ToolbarId::Svx_Fontwork_Bar:
|
|
pShell = new svx::FontworkBar(
|
|
&mrViewShell.GetViewShellBase());
|
|
break;
|
|
|
|
default:
|
|
pShell = nullptr;
|
|
break;
|
|
}
|
|
|
|
return pShell;
|
|
}
|
|
|
|
void ViewShellObjectBarFactory::ReleaseShell (SfxShell* pShell)
|
|
{
|
|
delete pShell;
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|