Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / view / frame.cxx
blobefd6a4e67a9657d1320481b9c7b4d84e96142cb4
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/lang/XUnoTunnel.hpp>
27 #include <com/sun/star/container/XChild.hpp>
28 #include <com/sun/star/embed/XEmbeddedObject.hpp>
30 #include <vcl/menu.hxx>
31 #include <svl/intitem.hxx>
32 #include <svl/stritem.hxx>
33 #include <tools/svborder.hxx>
34 #include <osl/diagnose.h>
36 #include <appdata.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/event.hxx>
39 #include <sfx2/frame.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <sfx2/docfilt.hxx>
44 #include <sfx2/frmdescr.hxx>
45 #include <sfx2/sfxsids.hrc>
46 #include <sfx2/viewsh.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include "impframe.hxx"
49 #include <workwin.hxx>
50 #include <sfx2/ipclient.hxx>
51 #include <vector>
53 using namespace com::sun::star;
55 static std::vector<SfxFrame*>* pFramesArr_Impl=nullptr;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::util;
59 using namespace ::com::sun::star::frame;
60 using namespace ::com::sun::star::container;
62 SfxPoolItem* SfxUnoAnyItem::CreateDefault()
64 return new SfxUnoAnyItem();
67 SfxPoolItem* SfxUnoFrameItem::CreateDefault()
69 return new SfxUnoFrameItem();
72 void SfxFrame::Construct_Impl()
74 pImpl.reset(new SfxFrame_Impl);
75 if ( !pFramesArr_Impl )
76 pFramesArr_Impl = new std::vector<SfxFrame*>;
77 pFramesArr_Impl->push_back( this );
81 SfxFrame::~SfxFrame()
83 RemoveTopFrame_Impl( this );
84 pWindow.disposeAndClear();
86 auto it = std::find( pFramesArr_Impl->begin(), pFramesArr_Impl->end(), this );
87 if ( it != pFramesArr_Impl->end() )
88 pFramesArr_Impl->erase( it );
90 delete pImpl->pDescr;
93 bool SfxFrame::DoClose()
95 // Actually, one more PrepareClose is still needed!
96 bool bRet = false;
97 if ( !pImpl->bClosing )
99 pImpl->bClosing = true;
100 CancelTransfers();
102 // now close frame; it will be deleted if this call is successful, so don't use any members after that!
103 bRet = true;
106 Reference< XCloseable > xCloseable ( pImpl->xFrame, UNO_QUERY );
107 if (xCloseable.is())
108 xCloseable->close(true);
109 else if ( pImpl->xFrame.is() )
111 Reference < XFrame > xFrame = pImpl->xFrame;
112 xFrame->setComponent( Reference < css::awt::XWindow >(), Reference < XController >() );
113 xFrame->dispose();
115 else
116 DoClose_Impl();
118 catch( css::util::CloseVetoException& )
120 pImpl->bClosing = false;
121 bRet = false;
123 catch( css::lang::DisposedException& )
128 return bRet;
131 void SfxFrame::DoClose_Impl()
133 SfxBindings* pBindings = nullptr;
134 if ( pImpl->pCurrentViewFrame )
135 pBindings = &pImpl->pCurrentViewFrame->GetBindings();
137 // For internal tasks Controllers and Tools must be cleared
138 if ( pImpl->pWorkWin )
139 pImpl->pWorkWin->DeleteControllers_Impl();
141 if ( pImpl->pCurrentViewFrame )
142 pImpl->pCurrentViewFrame->Close();
144 if ( pImpl->bOwnsBindings )
146 delete pBindings;
147 pBindings = nullptr;
150 delete this;
153 bool SfxFrame::DocIsModified_Impl()
155 return pImpl->pCurrentViewFrame && pImpl->pCurrentViewFrame->GetObjectShell() &&
156 pImpl->pCurrentViewFrame->GetObjectShell()->IsModified();
159 bool SfxFrame::PrepareClose_Impl( bool bUI )
161 bool bRet = true;
163 // prevent recursive calls
164 if( !pImpl->bPrepClosing )
166 pImpl->bPrepClosing = true;
168 SfxObjectShell* pCur = GetCurrentDocument() ;
169 if( pCur )
171 // SFX components have a known behaviour
172 // First check if this frame is the only view to its current document
173 bool bOther = false;
174 for ( const SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pCur );
175 !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pCur ) )
177 bOther = ( &pFrame->GetFrame() != this );
180 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SfxEventHintId::PrepareCloseView, GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEVIEW ), pCur, GetController() ) );
182 if ( bOther )
183 // if there are other views only the current view of this frame must be asked
184 bRet = GetCurrentViewFrame()->GetViewShell()->PrepareClose( bUI );
185 else
186 // otherwise ask the document
187 bRet = pCur->PrepareClose( bUI );
190 pImpl->bPrepClosing = false;
193 if ( bRet && pImpl->pWorkWin )
194 // if closing was accepted by the component the UI subframes must be asked also
195 bRet = pImpl->pWorkWin->PrepareClose_Impl();
197 return bRet;
201 bool SfxFrame::IsClosing_Impl() const
203 return pImpl->bClosing;
206 void SfxFrame::SetIsClosing_Impl()
208 pImpl->bClosing = true;
211 void SfxFrame::CancelTransfers()
213 if( pImpl->bInCancelTransfers )
214 return;
216 pImpl->bInCancelTransfers = true;
217 SfxObjectShell* pObj = GetCurrentDocument();
218 if( pObj ) //&& !( pObj->Get_Impl()->nLoadedFlags & SfxLoadedFlags::ALL ))
220 SfxViewFrame* pFrm;
221 for( pFrm = SfxViewFrame::GetFirst( pObj );
222 pFrm && &pFrm->GetFrame() == this;
223 pFrm = SfxViewFrame::GetNext( *pFrm, pObj ) ) ;
224 // No more Frame in Document -> Cancel
225 if( !pFrm )
227 pObj->CancelTransfers();
228 GetCurrentDocument()->Broadcast( SfxHint(SfxHintId::TitleChanged) );
232 // Check if StarOne-Loader should be canceled
233 SfxFrameWeakRef wFrame( this );
234 if (wFrame.is())
235 pImpl->bInCancelTransfers = false;
238 SfxViewFrame* SfxFrame::GetCurrentViewFrame() const
240 return pImpl->pCurrentViewFrame;
243 bool SfxFrame::IsAutoLoadLocked_Impl() const
245 // Its own Document is locked?
246 const SfxObjectShell* pObjSh = GetCurrentDocument();
247 if ( !pObjSh || !pObjSh->IsAutoLoadLocked() )
248 return false;
250 // otherwise allow AutoLoad
251 return true;
254 SfxObjectShell* SfxFrame::GetCurrentDocument() const
256 return pImpl->pCurrentViewFrame ?
257 pImpl->pCurrentViewFrame->GetObjectShell() :
258 nullptr;
261 void SfxFrame::SetCurrentViewFrame_Impl( SfxViewFrame *pFrame )
263 pImpl->pCurrentViewFrame = pFrame;
266 bool SfxFrame::GetHasTitle() const
268 return pImpl->mbHasTitle;
271 void SfxFrame::SetHasTitle( bool n )
273 pImpl->mbHasTitle = n;
276 void SfxFrame::GetViewData_Impl()
278 // Update all modifiable data between load and unload, the
279 // fixed data is only processed once (after PrepareForDoc_Impl in
280 // updateDescriptor) to save time.
282 SfxViewFrame* pViewFrame = GetCurrentViewFrame();
283 if( pViewFrame && pViewFrame->GetViewShell() )
285 SfxItemSet *pSet = GetDescriptor()->GetArgs();
286 if ( GetController().is() && pSet->GetItemState( SID_VIEW_DATA ) != SfxItemState::SET )
288 css::uno::Any aData = GetController()->getViewData();
289 pSet->Put( SfxUnoAnyItem( SID_VIEW_DATA, aData ) );
292 if ( pViewFrame->GetCurViewId() )
293 pSet->Put( SfxUInt16Item( SID_VIEW_ID, static_cast<sal_uInt16>(pViewFrame->GetCurViewId()) ) );
297 void SfxFrame::UpdateDescriptor( SfxObjectShell const *pDoc )
299 // For PrepareForDoc_Impl frames, the descriptor of the updated
300 // and new itemset to be initialized. All data fir restoring the view
301 // are thus saved. If the document be replaced, GetViewData_Impl (so)
302 // the latest information hinzugef by "added. All together then the
303 // browser-history saved in. When you activate such frame pick entry
304 // is complete itemsets and the descriptor in the OpenDoc sent;.
305 // Here only the fixed properties identified "other adjustable, the
306 // retrieved by GetViewData (saves time).
308 assert(pDoc && "NULL-Document inserted ?!");
310 const SfxMedium *pMed = pDoc->GetMedium();
311 GetDescriptor()->SetActualURL();
313 // Mark FileOpen parameter
314 SfxItemSet* pItemSet = pMed->GetItemSet();
316 const std::shared_ptr<const SfxFilter>& pFilter = pMed->GetFilter();
317 OUString aFilter;
318 if ( pFilter )
319 aFilter = pFilter->GetFilterName();
321 const SfxStringItem* pRefererItem = SfxItemSet::GetItem<SfxStringItem>(pItemSet, SID_REFERER, false);
322 const SfxStringItem* pOptionsItem = SfxItemSet::GetItem<SfxStringItem>(pItemSet, SID_FILE_FILTEROPTIONS, false);
323 const SfxStringItem* pTitle1Item = SfxItemSet::GetItem<SfxStringItem>(pItemSet, SID_DOCINFO_TITLE, false);
325 SfxItemSet *pSet = GetDescriptor()->GetArgs();
327 // Delete all old Items
328 pSet->ClearItem();
330 if ( pRefererItem )
331 pSet->Put( *pRefererItem );
332 else
333 pSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
335 if ( pOptionsItem )
336 pSet->Put( *pOptionsItem );
338 if ( pTitle1Item )
339 pSet->Put( *pTitle1Item );
341 pSet->Put( SfxStringItem( SID_FILTER_NAME, aFilter ));
345 SfxFrameDescriptor* SfxFrame::GetDescriptor() const
347 // Create a FrameDescriptor On Demand; if there is no TopLevel-Frame
348 // will result in an error, as no valid link is created.
350 if ( !pImpl->pDescr )
352 DBG_ASSERT( true, "No TopLevel-Frame, but no Descriptor!" );
353 pImpl->pDescr = new SfxFrameDescriptor;
354 if ( GetCurrentDocument() )
355 pImpl->pDescr->SetURL( GetCurrentDocument()->GetMedium()->GetOrigURL() );
357 return pImpl->pDescr;
360 void SfxFrame::GetDefaultTargetList(TargetList& rList)
362 // An empty string for 'No Target'
363 rList.emplace_back( );
364 rList.emplace_back( "_top" );
365 rList.emplace_back( "_parent" );
366 rList.emplace_back( "_blank" );
367 rList.emplace_back( "_self" );
370 void SfxFrame::InsertTopFrame_Impl( SfxFrame* pFrame )
372 auto& rArr = SfxGetpApp()->Get_Impl()->vTopFrames;
373 rArr.push_back( pFrame );
376 void SfxFrame::RemoveTopFrame_Impl( SfxFrame* pFrame )
378 auto& rArr = SfxGetpApp()->Get_Impl()->vTopFrames;
379 auto it = std::find( rArr.begin(), rArr.end(), pFrame );
380 if ( it != rArr.end() )
381 rArr.erase( it );
384 SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxViewFrame const *p )
385 : SfxPoolItem( nWhichId ), pFrame( p ? &p->GetFrame() : nullptr )
387 wFrame = pFrame;
390 SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxFrame *p ):
391 SfxPoolItem( nWhichId ),
392 pFrame( p ), wFrame( p )
396 SfxFrameItem::SfxFrameItem( SfxFrame *p ):
397 SfxPoolItem( 0 ),
398 pFrame( p ), wFrame( p )
402 bool SfxFrameItem::operator==( const SfxPoolItem &rItem ) const
404 return SfxPoolItem::operator==(rItem) &&
405 static_cast<const SfxFrameItem&>(rItem).pFrame == pFrame &&
406 static_cast<const SfxFrameItem&>(rItem).wFrame == wFrame;
409 SfxFrameItem* SfxFrameItem::Clone( SfxItemPool *) const
411 SfxFrameItem* pNew = new SfxFrameItem( wFrame);
412 pNew->pFrame = pFrame;
413 return pNew;
416 bool SfxFrameItem::QueryValue( css::uno::Any& rVal, sal_uInt8 ) const
418 if ( wFrame )
420 rVal <<= wFrame->GetFrameInterface();
421 return true;
424 return false;
427 bool SfxFrameItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
429 Reference < XFrame > xFrame;
430 if ( (rVal >>= xFrame) && xFrame.is() )
432 SfxFrame* pFr = SfxFrame::GetFirst();
433 while ( pFr )
435 if ( pFr->GetFrameInterface() == xFrame )
437 wFrame = pFrame = pFr;
438 return true;
441 pFr = SfxFrame::GetNext( *pFr );
443 return true;
446 return false;
449 SfxUnoAnyItem::SfxUnoAnyItem()
450 : SfxPoolItem( 0 )
454 SfxUnoAnyItem::SfxUnoAnyItem( sal_uInt16 nWhichId, const css::uno::Any& rAny )
455 : SfxPoolItem( nWhichId )
457 aValue = rAny;
460 bool SfxUnoAnyItem::operator==( const SfxPoolItem& rItem ) const
462 assert(SfxPoolItem::operator==(rItem)); (void)rItem;
463 return false;
466 SfxUnoAnyItem* SfxUnoAnyItem::Clone( SfxItemPool *) const
468 return new SfxUnoAnyItem( *this );
471 bool SfxUnoAnyItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
473 rVal = aValue;
474 return true;
477 bool SfxUnoAnyItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
479 aValue = rVal;
480 return true;
483 SfxUnoFrameItem::SfxUnoFrameItem()
484 : SfxPoolItem()
485 , m_xFrame()
489 SfxUnoFrameItem::SfxUnoFrameItem( sal_uInt16 nWhichId, const css::uno::Reference< css::frame::XFrame >& i_rFrame )
490 : SfxPoolItem( nWhichId )
491 , m_xFrame( i_rFrame )
495 bool SfxUnoFrameItem::operator==( const SfxPoolItem& i_rItem ) const
497 return SfxPoolItem::operator==(i_rItem) &&
498 static_cast< const SfxUnoFrameItem& >( i_rItem ).m_xFrame == m_xFrame;
501 SfxUnoFrameItem* SfxUnoFrameItem::Clone( SfxItemPool* ) const
503 return new SfxUnoFrameItem( *this );
506 bool SfxUnoFrameItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
508 rVal <<= m_xFrame;
509 return true;
512 bool SfxUnoFrameItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
514 return ( rVal >>= m_xFrame );
517 css::uno::Reference< css::frame::XController > SfxFrame::GetController() const
519 if ( pImpl->pCurrentViewFrame && pImpl->pCurrentViewFrame->GetViewShell() )
520 return pImpl->pCurrentViewFrame->GetViewShell()->GetController();
521 else
522 return css::uno::Reference< css::frame::XController > ();
525 const css::uno::Reference< css::frame::XFrame >& SfxFrame::GetFrameInterface() const
527 return pImpl->xFrame;
530 void SfxFrame::SetFrameInterface_Impl( const css::uno::Reference< css::frame::XFrame >& rFrame )
532 pImpl->xFrame = rFrame;
533 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
534 if ( !rFrame.is() && GetCurrentViewFrame() )
535 GetCurrentViewFrame()->GetBindings().SetRecorder_Impl( xRecorder );
538 void SfxFrame::Appear()
540 if ( GetCurrentViewFrame() )
542 GetCurrentViewFrame()->Show();
543 GetWindow().Show();
544 pImpl->xFrame->getContainerWindow()->setVisible( true );
545 Reference < css::awt::XTopWindow > xTopWindow( pImpl->xFrame->getContainerWindow(), UNO_QUERY );
546 if ( xTopWindow.is() )
547 xTopWindow->toFront();
551 void SfxFrame::AppearWithUpdate()
553 Appear();
554 if ( GetCurrentViewFrame() )
555 GetCurrentViewFrame()->GetDispatcher()->Update_Impl( true );
558 void SfxFrame::SetOwnsBindings_Impl( bool bSet )
560 pImpl->bOwnsBindings = bSet;
563 bool SfxFrame::OwnsBindings_Impl() const
565 return pImpl->bOwnsBindings;
568 void SfxFrame::SetToolSpaceBorderPixel_Impl( const SvBorder& rBorder )
570 pImpl->aBorder = rBorder;
571 SfxViewFrame *pF = GetCurrentViewFrame();
572 if ( !pF )
573 return;
575 Point aPos ( rBorder.Left(), rBorder.Top() );
576 Size aSize( GetWindow().GetOutputSizePixel() );
577 tools::Long nDeltaX = rBorder.Left() + rBorder.Right();
578 if ( aSize.Width() > nDeltaX )
579 aSize.AdjustWidth( -nDeltaX );
580 else
581 aSize.setWidth( 0 );
583 tools::Long nDeltaY = rBorder.Top() + rBorder.Bottom();
584 if ( aSize.Height() > nDeltaY )
585 aSize.AdjustHeight( -nDeltaY );
586 else
587 aSize.setHeight( 0 );
589 pF->GetWindow().SetPosSizePixel( aPos, aSize );
592 tools::Rectangle SfxFrame::GetTopOuterRectPixel_Impl() const
594 Size aSize( GetWindow().GetOutputSizePixel() );
595 return tools::Rectangle( Point(), aSize );
598 SfxWorkWindow* SfxFrame::GetWorkWindow_Impl() const
600 if ( pImpl->pWorkWin )
601 return pImpl->pWorkWin;
602 else
603 return nullptr;
606 void SfxFrame::CreateWorkWindow_Impl()
608 SfxFrame* pFrame = this;
610 if ( IsInPlace() )
612 // this makes sense only for inplace activated objects
615 Reference < XChild > xChild( GetCurrentDocument()->GetModel(), UNO_QUERY );
616 if ( xChild.is() )
618 Reference < XModel > xParent( xChild->getParent(), UNO_QUERY );
619 if ( xParent.is() )
621 Reference< XController > xParentCtrler = xParent->getCurrentController();
622 if ( xParentCtrler.is() )
624 Reference < XFrame > xFrame( xParentCtrler->getFrame() );
625 SfxFrame* pFr = SfxFrame::GetFirst();
626 while ( pFr )
628 if ( pFr->GetFrameInterface() == xFrame )
630 pFrame = pFr;
631 break;
634 pFr = SfxFrame::GetNext( *pFr );
640 catch(Exception&)
642 OSL_FAIL("SfxFrame::CreateWorkWindow_Impl: Exception caught. Please try to submit a reproducible bug!");
646 pImpl->pWorkWin = new SfxWorkWindow( &pFrame->GetWindow(), this, pFrame );
649 void SfxFrame::GrabFocusOnComponent_Impl()
651 if ( pImpl->bReleasingComponent )
653 GetWindow().GrabFocus();
654 return;
657 vcl::Window* pFocusWindow = &GetWindow();
658 if ( GetCurrentViewFrame() && GetCurrentViewFrame()->GetViewShell() && GetCurrentViewFrame()->GetViewShell()->GetWindow() )
659 pFocusWindow = GetCurrentViewFrame()->GetViewShell()->GetWindow();
661 if( !pFocusWindow->HasChildPathFocus() )
662 pFocusWindow->GrabFocus();
665 void SfxFrame::ReleasingComponent_Impl()
667 pImpl->bReleasingComponent = true;
670 bool SfxFrame::IsInPlace() const
672 return pImpl->bInPlace;
675 void SfxFrame::Resize()
677 if ( IsClosing_Impl() )
678 return;
680 if ( OwnsBindings_Impl() )
682 if ( IsInPlace() )
684 SetToolSpaceBorderPixel_Impl( SvBorder() );
686 else
688 // check for IPClient that contains UIactive object or object that is currently UI activating
689 SfxWorkWindow *pWork = GetWorkWindow_Impl();
690 SfxInPlaceClient* pClient = GetCurrentViewFrame()->GetViewShell() ? GetCurrentViewFrame()->GetViewShell()->GetUIActiveIPClient_Impl() : nullptr;
691 if ( pClient )
693 SfxObjectShell* pDoc
694 = SfxObjectShell::GetShellFromComponent(pClient->GetObject()->getComponent());
695 SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc);
696 pWork = pFrame ? pFrame->GetFrame().GetWorkWindow_Impl() : nullptr;
699 if ( pWork )
701 pWork->ArrangeChildren_Impl();
702 pWork->ShowChildren_Impl();
705 // problem in presence of UIActive object: when the window is resized, but the toolspace border
706 // remains the same, setting the toolspace border at the ContainerEnvironment doesn't force a
707 // resize on the IPEnvironment; without that no resize is called for the SfxViewFrame. So always
708 // set the window size of the SfxViewFrame explicit.
709 SetToolSpaceBorderPixel_Impl( pImpl->aBorder );
712 else if ( pImpl->pCurrentViewFrame )
714 pImpl->pCurrentViewFrame->GetWindow().SetSizePixel( GetWindow().GetOutputSizePixel() );
719 SfxFrame* SfxFrame::GetFirst()
721 if ( !pFramesArr_Impl )
722 return nullptr;
723 return pFramesArr_Impl->empty() ? nullptr : pFramesArr_Impl->front();
726 SfxFrame* SfxFrame::GetNext( SfxFrame& rFrame )
728 auto it = std::find( pFramesArr_Impl->begin(), pFramesArr_Impl->end(), &rFrame );
729 if ( it != pFramesArr_Impl->end() && (++it) != pFramesArr_Impl->end() )
730 return *it;
731 else
732 return nullptr;
735 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */