1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
48 #include <workwin.hxx>
49 #include <sfx2/ipclient.hxx>
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 );
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!
93 if ( !m_pImpl
->bClosing
)
95 m_pImpl
->bClosing
= true;
98 // now close frame; it will be deleted if this call is successful, so don't use any members after that!
102 Reference
< XCloseable
> xCloseable ( m_pImpl
->xFrame
, UNO_QUERY
);
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
>() );
114 catch( css::util::CloseVetoException
& )
116 m_pImpl
->bClosing
= false;
119 catch( css::lang::DisposedException
& )
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
)
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
)
159 // prevent recursive calls
160 if( !m_pImpl
->bPrepClosing
)
162 m_pImpl
->bPrepClosing
= true;
164 SfxObjectShell
* pCur
= GetCurrentDocument() ;
167 // SFX components have a known behaviour
168 // First check if this frame is the only view to its current document
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() ) );
179 // if there are other views only the current view of this frame must be asked
180 bRet
= GetCurrentViewFrame()->GetViewShell()->PrepareClose( bUI
);
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();
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
)
212 m_pImpl
->bInCancelTransfers
= true;
213 SfxObjectShell
* pObj
= GetCurrentDocument();
214 if( pObj
) //&& !( pObj->Get_Impl()->nLoadedFlags & SfxLoadedFlags::ALL ))
217 for( pFrm
= SfxViewFrame::GetFirst( pObj
);
218 pFrm
&& &pFrm
->GetFrame() == this;
219 pFrm
= SfxViewFrame::GetNext( *pFrm
, pObj
) ) ;
220 // No more Frame in Document -> Cancel
223 pObj
->CancelTransfers();
224 GetCurrentDocument()->Broadcast( SfxHint(SfxHintId::TitleChanged
) );
228 // Check if StarOne-Loader should be canceled
229 SfxFrameWeakRef
wFrame( this );
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() )
246 // otherwise allow AutoLoad
250 SfxObjectShell
* SfxFrame::GetCurrentDocument() const
252 return m_pImpl
->pCurrentViewFrame
?
253 m_pImpl
->pCurrentViewFrame
->GetObjectShell() :
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();
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
327 pSet
->Put( *pRefererItem
);
329 pSet
->Put( SfxStringItem( SID_REFERER
, OUString() ) );
332 pSet
->Put( *pOptionsItem
);
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() )
380 SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId
, SfxViewFrame
const *p
)
381 : SfxPoolItem( nWhichId
, SfxItemType::SfxFrameItemType
), pFrame( p
? &p
->GetFrame() : nullptr )
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
;
408 bool SfxFrameItem::QueryValue( css::uno::Any
& rVal
, sal_uInt8
) const
412 rVal
<<= wFrame
->GetFrameInterface();
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();
427 if ( pFr
->GetFrameInterface() == xFrame
)
429 wFrame
= pFrame
= pFr
;
433 pFr
= SfxFrame::GetNext( *pFr
);
442 SfxUnoAnyItem::SfxUnoAnyItem( sal_uInt16 nWhichId
, const css::uno::Any
& rAny
)
443 : SfxPoolItem( nWhichId
, SfxItemType::SfxUnoAnyItemType
)
448 bool SfxUnoAnyItem::operator==( const SfxPoolItem
& rItem
) const
450 assert(SfxPoolItem::operator==(rItem
)); (void)rItem
;
454 SfxUnoAnyItem
* SfxUnoAnyItem::Clone( SfxItemPool
*) const
456 return new SfxUnoAnyItem( *this );
459 bool SfxUnoAnyItem::QueryValue( css::uno::Any
& rVal
, sal_uInt8
/*nMemberId*/ ) const
465 bool SfxUnoAnyItem::PutValue( const css::uno::Any
& rVal
, sal_uInt8
/*nMemberId*/ )
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
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();
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();
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()
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();
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
);
570 tools::Long nDeltaY
= rBorder
.Top() + rBorder
.Bottom();
571 if ( aSize
.Height() > nDeltaY
)
572 aSize
.AdjustHeight( -nDeltaY
);
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;
596 // this makes sense only for inplace activated objects
599 Reference
< XChild
> xChild( GetCurrentDocument()->GetModel(), UNO_QUERY
);
602 Reference
< XModel
> xParent( xChild
->getParent(), UNO_QUERY
);
605 Reference
< XController
> xParentCtrler
= xParent
->getCurrentController();
606 if ( xParentCtrler
.is() )
608 Reference
< XFrame
> xFrame( xParentCtrler
->getFrame() );
609 SfxFrame
* pFr
= SfxFrame::GetFirst();
612 if ( pFr
->GetFrameInterface() == xFrame
)
618 pFr
= SfxFrame::GetNext( *pFr
);
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();
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() )
664 if ( OwnsBindings_Impl() )
668 SetToolSpaceBorderPixel_Impl( SvBorder() );
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;
678 = SfxObjectShell::GetShellFromComponent(pClient
->GetObject()->getComponent());
679 SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst(pDoc
);
680 pWork
= pFrame
? pFrame
->GetFrame().GetWorkWindow_Impl() : nullptr;
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() )
717 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */