tdf#150789 - FILEOPEN PPTX: fix text in SmartArt vertically off
[LibreOffice.git] / sfx2 / source / view / frame.cxx
blob1e565338fc59c5ed102deff797ce996f802705cf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/uno/Reference.h>
21 #include <com/sun/star/awt/XTopWindow.hpp>
22 #include <com/sun/star/awt/XWindow.hpp>
23 #include <com/sun/star/util/XCloseable.hpp>
24 #include <com/sun/star/util/CloseVetoException.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <com/sun/star/container/XChild.hpp>
27 #include <com/sun/star/embed/XEmbeddedObject.hpp>
29 #include <svl/intitem.hxx>
30 #include <svl/stritem.hxx>
31 #include <tools/svborder.hxx>
32 #include <comphelper/diagnose_ex.hxx>
34 #include <appdata.hxx>
35 #include <sfx2/app.hxx>
36 #include <sfx2/event.hxx>
37 #include <sfx2/frame.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <sfx2/docfilt.hxx>
42 #include <sfx2/frmdescr.hxx>
43 #include <sfx2/sfxsids.hrc>
44 #include <sfx2/viewsh.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include "impframe.hxx"
47 #include <utility>
48 #include <workwin.hxx>
49 #include <sfx2/ipclient.hxx>
50 #include <vector>
52 using namespace com::sun::star;
54 static std::vector<SfxFrame*> gaFramesArr_Impl;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::util;
58 using namespace ::com::sun::star::frame;
59 using namespace ::com::sun::star::container;
61 SfxPoolItem* SfxUnoAnyItem::CreateDefault()
63 return new SfxUnoAnyItem(0, uno::Any());
66 SfxPoolItem* SfxUnoFrameItem::CreateDefault()
68 return new SfxUnoFrameItem();
70 void SfxFrame::Construct_Impl()
72 m_pImpl.reset(new SfxFrame_Impl);
73 gaFramesArr_Impl.push_back( this );
77 SfxFrame::~SfxFrame()
79 RemoveTopFrame_Impl( this );
80 m_pWindow.disposeAndClear();
82 auto it = std::find( gaFramesArr_Impl.begin(), gaFramesArr_Impl.end(), this );
83 if ( it != gaFramesArr_Impl.end() )
84 gaFramesArr_Impl.erase( it );
86 delete m_pImpl->pDescr;
89 bool SfxFrame::DoClose()
91 // Actually, one more PrepareClose is still needed!
92 bool bRet = false;
93 if ( !m_pImpl->bClosing )
95 m_pImpl->bClosing = true;
96 CancelTransfers();
98 // now close frame; it will be deleted if this call is successful, so don't use any members after that!
99 bRet = true;
102 Reference< XCloseable > xCloseable ( m_pImpl->xFrame, UNO_QUERY );
103 if (xCloseable.is())
104 xCloseable->close(true);
105 else if ( m_pImpl->xFrame.is() )
107 Reference < XFrame > xFrame = m_pImpl->xFrame;
108 xFrame->setComponent( Reference < css::awt::XWindow >(), Reference < XController >() );
109 xFrame->dispose();
111 else
112 DoClose_Impl();
114 catch( css::util::CloseVetoException& )
116 m_pImpl->bClosing = false;
117 bRet = false;
119 catch( css::lang::DisposedException& )
124 return bRet;
127 void SfxFrame::DoClose_Impl()
129 SfxBindings* pBindings = nullptr;
130 if ( m_pImpl->pCurrentViewFrame )
131 pBindings = &m_pImpl->pCurrentViewFrame->GetBindings();
133 // For internal tasks Controllers and Tools must be cleared
134 if ( m_pImpl->pWorkWin )
135 m_pImpl->pWorkWin->DeleteControllers_Impl();
137 if ( m_pImpl->pCurrentViewFrame )
138 m_pImpl->pCurrentViewFrame->Close();
140 if ( m_pImpl->bOwnsBindings )
142 delete pBindings;
143 pBindings = nullptr;
146 delete this;
149 bool SfxFrame::DocIsModified_Impl()
151 return m_pImpl->pCurrentViewFrame && m_pImpl->pCurrentViewFrame->GetObjectShell() &&
152 m_pImpl->pCurrentViewFrame->GetObjectShell()->IsModified();
155 bool SfxFrame::PrepareClose_Impl( bool bUI )
157 bool bRet = true;
159 // prevent recursive calls
160 if( !m_pImpl->bPrepClosing )
162 m_pImpl->bPrepClosing = true;
164 SfxObjectShell* pCur = GetCurrentDocument() ;
165 if( pCur )
167 // SFX components have a known behaviour
168 // First check if this frame is the only view to its current document
169 bool bOther = false;
170 for ( const SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pCur );
171 !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pCur ) )
173 bOther = ( &pFrame->GetFrame() != this );
176 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SfxEventHintId::PrepareCloseView, GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEVIEW ), pCur, GetController() ) );
178 if ( bOther )
179 // if there are other views only the current view of this frame must be asked
180 bRet = GetCurrentViewFrame()->GetViewShell()->PrepareClose( bUI );
181 else
182 // otherwise ask the document
183 bRet = pCur->PrepareClose( bUI );
186 m_pImpl->bPrepClosing = false;
189 if ( bRet && m_pImpl->pWorkWin )
190 // if closing was accepted by the component the UI subframes must be asked also
191 bRet = m_pImpl->pWorkWin->PrepareClose_Impl();
193 return bRet;
197 bool SfxFrame::IsClosing_Impl() const
199 return m_pImpl->bClosing;
202 void SfxFrame::SetIsClosing_Impl()
204 m_pImpl->bClosing = true;
207 void SfxFrame::CancelTransfers()
209 if( m_pImpl->bInCancelTransfers )
210 return;
212 m_pImpl->bInCancelTransfers = true;
213 SfxObjectShell* pObj = GetCurrentDocument();
214 if( pObj ) //&& !( pObj->Get_Impl()->nLoadedFlags & SfxLoadedFlags::ALL ))
216 SfxViewFrame* pFrm;
217 for( pFrm = SfxViewFrame::GetFirst( pObj );
218 pFrm && &pFrm->GetFrame() == this;
219 pFrm = SfxViewFrame::GetNext( *pFrm, pObj ) ) ;
220 // No more Frame in Document -> Cancel
221 if( !pFrm )
223 pObj->CancelTransfers();
224 GetCurrentDocument()->Broadcast( SfxHint(SfxHintId::TitleChanged) );
228 // Check if StarOne-Loader should be canceled
229 SfxFrameWeakRef wFrame( this );
230 if (wFrame.is())
231 m_pImpl->bInCancelTransfers = false;
234 SfxViewFrame* SfxFrame::GetCurrentViewFrame() const
236 return m_pImpl->pCurrentViewFrame;
239 bool SfxFrame::IsAutoLoadLocked_Impl() const
241 // Its own Document is locked?
242 const SfxObjectShell* pObjSh = GetCurrentDocument();
243 if ( !pObjSh || !pObjSh->IsAutoLoadLocked() )
244 return false;
246 // otherwise allow AutoLoad
247 return true;
250 SfxObjectShell* SfxFrame::GetCurrentDocument() const
252 return m_pImpl->pCurrentViewFrame ?
253 m_pImpl->pCurrentViewFrame->GetObjectShell() :
254 nullptr;
257 void SfxFrame::SetCurrentViewFrame_Impl( SfxViewFrame *pFrame )
259 m_pImpl->pCurrentViewFrame = pFrame;
262 bool SfxFrame::GetHasTitle() const
264 return m_pImpl->mbHasTitle;
267 void SfxFrame::SetHasTitle( bool n )
269 m_pImpl->mbHasTitle = n;
272 void SfxFrame::GetViewData_Impl()
274 // Update all modifiable data between load and unload, the
275 // fixed data is only processed once (after PrepareForDoc_Impl in
276 // updateDescriptor) to save time.
278 SfxViewFrame* pViewFrame = GetCurrentViewFrame();
279 if( pViewFrame && pViewFrame->GetViewShell() )
281 SfxItemSet *pSet = GetDescriptor()->GetArgs();
282 if ( GetController().is() && pSet->GetItemState( SID_VIEW_DATA ) != SfxItemState::SET )
284 css::uno::Any aData = GetController()->getViewData();
285 pSet->Put( SfxUnoAnyItem( SID_VIEW_DATA, aData ) );
288 if ( pViewFrame->GetCurViewId() )
289 pSet->Put( SfxUInt16Item( SID_VIEW_ID, static_cast<sal_uInt16>(pViewFrame->GetCurViewId()) ) );
293 void SfxFrame::UpdateDescriptor( SfxObjectShell const *pDoc )
295 // For PrepareForDoc_Impl frames, the descriptor of the updated
296 // and new itemset to be initialized. All data fir restoring the view
297 // are thus saved. If the document be replaced, GetViewData_Impl (so)
298 // the latest information hinzugef by "added. All together then the
299 // browser-history saved in. When you activate such frame pick entry
300 // is complete itemsets and the descriptor in the OpenDoc sent;.
301 // Here only the fixed properties identified "other adjustable, the
302 // retrieved by GetViewData (saves time).
304 assert(pDoc && "NULL-Document inserted ?!");
306 const SfxMedium *pMed = pDoc->GetMedium();
307 GetDescriptor()->SetActualURL();
309 // Mark FileOpen parameter
310 SfxItemSet& rItemSet = pMed->GetItemSet();
312 const std::shared_ptr<const SfxFilter>& pFilter = pMed->GetFilter();
313 OUString aFilter;
314 if ( pFilter )
315 aFilter = pFilter->GetFilterName();
317 const SfxStringItem* pRefererItem = rItemSet.GetItem<SfxStringItem>(SID_REFERER, false);
318 const SfxStringItem* pOptionsItem = rItemSet.GetItem<SfxStringItem>(SID_FILE_FILTEROPTIONS, false);
319 const SfxStringItem* pTitle1Item = rItemSet.GetItem<SfxStringItem>(SID_DOCINFO_TITLE, false);
321 SfxItemSet *pSet = GetDescriptor()->GetArgs();
323 // Delete all old Items
324 pSet->ClearItem();
326 if ( pRefererItem )
327 pSet->Put( *pRefererItem );
328 else
329 pSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
331 if ( pOptionsItem )
332 pSet->Put( *pOptionsItem );
334 if ( pTitle1Item )
335 pSet->Put( *pTitle1Item );
337 pSet->Put( SfxStringItem( SID_FILTER_NAME, aFilter ));
341 SfxFrameDescriptor* SfxFrame::GetDescriptor() const
343 // Create a FrameDescriptor On Demand; if there is no TopLevel-Frame
344 // will result in an error, as no valid link is created.
346 if ( !m_pImpl->pDescr )
348 DBG_ASSERT( true, "No TopLevel-Frame, but no Descriptor!" );
349 m_pImpl->pDescr = new SfxFrameDescriptor;
350 if ( GetCurrentDocument() )
351 m_pImpl->pDescr->SetURL( GetCurrentDocument()->GetMedium()->GetOrigURL() );
353 return m_pImpl->pDescr;
356 void SfxFrame::GetDefaultTargetList(TargetList& rList)
358 // An empty string for 'No Target'
359 rList.emplace_back( );
360 rList.emplace_back( "_top" );
361 rList.emplace_back( "_parent" );
362 rList.emplace_back( "_blank" );
363 rList.emplace_back( "_self" );
366 void SfxFrame::InsertTopFrame_Impl( SfxFrame* pFrame )
368 auto& rArr = SfxGetpApp()->Get_Impl()->vTopFrames;
369 rArr.push_back( pFrame );
372 void SfxFrame::RemoveTopFrame_Impl( SfxFrame* pFrame )
374 auto& rArr = SfxGetpApp()->Get_Impl()->vTopFrames;
375 auto it = std::find( rArr.begin(), rArr.end(), pFrame );
376 if ( it != rArr.end() )
377 rArr.erase( it );
380 SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxViewFrame const *p )
381 : SfxPoolItem( nWhichId, SfxItemType::SfxFrameItemType ), pFrame( p ? &p->GetFrame() : nullptr )
383 wFrame = pFrame;
386 SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxFrame *p ):
387 SfxPoolItem( nWhichId, SfxItemType::SfxFrameItemType ),
388 pFrame( p ), wFrame( p )
392 bool SfxFrameItem::operator==( const SfxPoolItem &rItem ) const
394 return SfxPoolItem::operator==(rItem) &&
395 static_cast<const SfxFrameItem&>(rItem).pFrame == pFrame &&
396 static_cast<const SfxFrameItem&>(rItem).wFrame == wFrame;
399 SfxFrameItem* SfxFrameItem::Clone( SfxItemPool *) const
401 // Every ::Clone implementation *needs* to also ensure that
402 // the WhichID gets set/copied at the created Item (!)
403 SfxFrameItem* pNew = new SfxFrameItem(Which(), wFrame);
404 pNew->pFrame = pFrame;
405 return pNew;
408 bool SfxFrameItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
410 if ( wFrame )
412 rVal <<= wFrame->GetFrameInterface();
413 return true;
416 return false;
419 bool SfxFrameItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
421 Reference < XFrame > xFrame;
422 if ( (rVal >>= xFrame) && xFrame.is() )
424 SfxFrame* pFr = SfxFrame::GetFirst();
425 while ( pFr )
427 if ( pFr->GetFrameInterface() == xFrame )
429 wFrame = pFrame = pFr;
430 return true;
433 pFr = SfxFrame::GetNext( *pFr );
435 return true;
438 return false;
442 SfxUnoAnyItem::SfxUnoAnyItem( sal_uInt16 nWhichId, const css::uno::Any& rAny )
443 : SfxPoolItem( nWhichId, SfxItemType::SfxUnoAnyItemType )
445 aValue = rAny;
448 bool SfxUnoAnyItem::operator==( const SfxPoolItem& rItem ) const
450 assert(SfxPoolItem::operator==(rItem)); (void)rItem;
451 return false;
454 SfxUnoAnyItem* SfxUnoAnyItem::Clone( SfxItemPool *) const
456 return new SfxUnoAnyItem( *this );
459 bool SfxUnoAnyItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
461 rVal = aValue;
462 return true;
465 bool SfxUnoAnyItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
467 aValue = rVal;
468 return true;
471 SfxUnoFrameItem::SfxUnoFrameItem()
472 : SfxPoolItem( 0, SfxItemType::SfxUnoFrameItemType)
476 SfxUnoFrameItem::SfxUnoFrameItem( sal_uInt16 nWhichId, css::uno::Reference< css::frame::XFrame > i_xFrame )
477 : SfxPoolItem( nWhichId, SfxItemType::SfxUnoFrameItemType )
478 , m_xFrame(std::move( i_xFrame ))
482 bool SfxUnoFrameItem::operator==( const SfxPoolItem& i_rItem ) const
484 return SfxPoolItem::operator==(i_rItem) &&
485 static_cast< const SfxUnoFrameItem& >( i_rItem ).m_xFrame == m_xFrame;
488 SfxUnoFrameItem* SfxUnoFrameItem::Clone( SfxItemPool* ) const
490 return new SfxUnoFrameItem( *this );
493 bool SfxUnoFrameItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
495 rVal <<= m_xFrame;
496 return true;
499 bool SfxUnoFrameItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
501 return ( rVal >>= m_xFrame );
504 css::uno::Reference< css::frame::XController > SfxFrame::GetController() const
506 if ( m_pImpl->pCurrentViewFrame && m_pImpl->pCurrentViewFrame->GetViewShell() )
507 return m_pImpl->pCurrentViewFrame->GetViewShell()->GetController();
508 else
509 return css::uno::Reference< css::frame::XController > ();
512 const css::uno::Reference< css::frame::XFrame >& SfxFrame::GetFrameInterface() const
514 return m_pImpl->xFrame;
517 void SfxFrame::SetFrameInterface_Impl( const css::uno::Reference< css::frame::XFrame >& rFrame )
519 m_pImpl->xFrame = rFrame;
520 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
521 if ( !rFrame.is() && GetCurrentViewFrame() )
522 GetCurrentViewFrame()->GetBindings().SetRecorder_Impl( xRecorder );
525 void SfxFrame::Appear()
527 if ( GetCurrentViewFrame() )
529 GetCurrentViewFrame()->Show();
530 GetWindow().Show();
531 m_pImpl->xFrame->getContainerWindow()->setVisible( true );
532 Reference < css::awt::XTopWindow > xTopWindow( m_pImpl->xFrame->getContainerWindow(), UNO_QUERY );
533 if ( xTopWindow.is() )
534 xTopWindow->toFront();
538 void SfxFrame::AppearWithUpdate()
540 Appear();
541 if ( GetCurrentViewFrame() )
542 GetCurrentViewFrame()->GetDispatcher()->Update_Impl( true );
545 void SfxFrame::SetOwnsBindings_Impl( bool bSet )
547 m_pImpl->bOwnsBindings = bSet;
550 bool SfxFrame::OwnsBindings_Impl() const
552 return m_pImpl->bOwnsBindings;
555 void SfxFrame::SetToolSpaceBorderPixel_Impl( const SvBorder& rBorder )
557 m_pImpl->aBorder = rBorder;
558 SfxViewFrame *pF = GetCurrentViewFrame();
559 if ( !pF )
560 return;
562 Point aPos ( rBorder.Left(), rBorder.Top() );
563 Size aSize( GetWindow().GetOutputSizePixel() );
564 tools::Long nDeltaX = rBorder.Left() + rBorder.Right();
565 if ( aSize.Width() > nDeltaX )
566 aSize.AdjustWidth( -nDeltaX );
567 else
568 aSize.setWidth( 0 );
570 tools::Long nDeltaY = rBorder.Top() + rBorder.Bottom();
571 if ( aSize.Height() > nDeltaY )
572 aSize.AdjustHeight( -nDeltaY );
573 else
574 aSize.setHeight( 0 );
576 pF->GetWindow().SetPosSizePixel( aPos, aSize );
579 tools::Rectangle SfxFrame::GetTopOuterRectPixel_Impl() const
581 Size aSize( GetWindow().GetOutputSizePixel() );
582 return tools::Rectangle( Point(), aSize );
585 SfxWorkWindow* SfxFrame::GetWorkWindow_Impl() const
587 return m_pImpl->pWorkWin;
590 void SfxFrame::CreateWorkWindow_Impl()
592 SfxFrame* pFrame = this;
594 if ( IsInPlace() )
596 // this makes sense only for inplace activated objects
599 Reference < XChild > xChild( GetCurrentDocument()->GetModel(), UNO_QUERY );
600 if ( xChild.is() )
602 Reference < XModel > xParent( xChild->getParent(), UNO_QUERY );
603 if ( xParent.is() )
605 Reference< XController > xParentCtrler = xParent->getCurrentController();
606 if ( xParentCtrler.is() )
608 Reference < XFrame > xFrame( xParentCtrler->getFrame() );
609 SfxFrame* pFr = SfxFrame::GetFirst();
610 while ( pFr )
612 if ( pFr->GetFrameInterface() == xFrame )
614 pFrame = pFr;
615 break;
618 pFr = SfxFrame::GetNext( *pFr );
624 catch(Exception&)
626 TOOLS_WARN_EXCEPTION( "sfx.view", "SfxFrame::CreateWorkWindow_Impl: Exception caught. Please try to submit a reproducible bug!");
630 m_pImpl->pWorkWin = new SfxWorkWindow( &pFrame->GetWindow(), this, pFrame );
633 void SfxFrame::GrabFocusOnComponent_Impl()
635 if ( m_pImpl->bReleasingComponent )
637 GetWindow().GrabFocus();
638 return;
641 vcl::Window* pFocusWindow = &GetWindow();
642 if ( GetCurrentViewFrame() && GetCurrentViewFrame()->GetViewShell() && GetCurrentViewFrame()->GetViewShell()->GetWindow() )
643 pFocusWindow = GetCurrentViewFrame()->GetViewShell()->GetWindow();
645 if( !pFocusWindow->HasChildPathFocus() )
646 pFocusWindow->GrabFocus();
649 void SfxFrame::ReleasingComponent_Impl()
651 m_pImpl->bReleasingComponent = true;
654 bool SfxFrame::IsInPlace() const
656 return m_pImpl->bInPlace;
659 void SfxFrame::Resize()
661 if ( IsClosing_Impl() )
662 return;
664 if ( OwnsBindings_Impl() )
666 if ( IsInPlace() )
668 SetToolSpaceBorderPixel_Impl( SvBorder() );
670 else
672 // check for IPClient that contains UIactive object or object that is currently UI activating
673 SfxWorkWindow *pWork = GetWorkWindow_Impl();
674 SfxInPlaceClient* pClient = GetCurrentViewFrame()->GetViewShell() ? GetCurrentViewFrame()->GetViewShell()->GetUIActiveIPClient_Impl() : nullptr;
675 if ( pClient )
677 SfxObjectShell* pDoc
678 = SfxObjectShell::GetShellFromComponent(pClient->GetObject()->getComponent());
679 SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc);
680 pWork = pFrame ? pFrame->GetFrame().GetWorkWindow_Impl() : nullptr;
683 if ( pWork )
685 pWork->ArrangeChildren_Impl();
686 pWork->ShowChildren_Impl();
689 // problem in presence of UIActive object: when the window is resized, but the toolspace border
690 // remains the same, setting the toolspace border at the ContainerEnvironment doesn't force a
691 // resize on the IPEnvironment; without that no resize is called for the SfxViewFrame. So always
692 // set the window size of the SfxViewFrame explicit.
693 SetToolSpaceBorderPixel_Impl( m_pImpl->aBorder );
696 else if ( m_pImpl->pCurrentViewFrame )
698 m_pImpl->pCurrentViewFrame->GetWindow().SetSizePixel( GetWindow().GetOutputSizePixel() );
703 SfxFrame* SfxFrame::GetFirst()
705 return gaFramesArr_Impl.empty() ? nullptr : gaFramesArr_Impl.front();
708 SfxFrame* SfxFrame::GetNext( SfxFrame& rFrame )
710 auto it = std::find( gaFramesArr_Impl.begin(), gaFramesArr_Impl.end(), &rFrame );
711 if ( it != gaFramesArr_Impl.end() && (++it) != gaFramesArr_Impl.end() )
712 return *it;
713 else
714 return nullptr;
717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */