1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
21 #include <sal/macros.h>
22 
23 #include <fmprop.hxx>
24 #include <fmPropBrw.hxx>
25 #include <svx/strings.hrc>
26 #include <fmservs.hxx>
27 #include <fmshimp.hxx>
28 #include <fmpgeimp.hxx>
29 
30 #include <svx/dialmgr.hxx>
31 #include <svx/fmpage.hxx>
32 #include <svx/fmshell.hxx>
33 #include <svx/fmview.hxx>
34 #include <svx/sdrpagewindow.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <svx/svxids.hrc>
37 
38 #include <com/sun/star/awt/XLayoutConstrains.hpp>
39 #include <com/sun/star/awt/XControlContainer.hpp>
40 #include <com/sun/star/awt/PosSize.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #include <com/sun/star/form/XForm.hpp>
44 #include <com/sun/star/form/FormComponentType.hpp>
45 #include <com/sun/star/form/inspection/DefaultFormComponentInspectorModel.hpp>
46 #include <com/sun/star/frame/Frame.hpp>
47 #include <com/sun/star/inspection/ObjectInspector.hpp>
48 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
49 #include <com/sun/star/inspection/DefaultHelpProvider.hpp>
50 #include <com/sun/star/util/VetoException.hpp>
51 
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/property.hxx>
54 #include <comphelper/sequence.hxx>
55 #include <comphelper/types.hxx>
56 #include <cppuhelper/component_context.hxx>
57 #include <sfx2/bindings.hxx>
58 #include <sfx2/childwin.hxx>
59 #include <sfx2/dispatch.hxx>
60 #include <sfx2/objitem.hxx>
61 #include <sfx2/objsh.hxx>
62 #include <sfx2/viewfrm.hxx>
63 #include <toolkit/helper/vclunohelper.hxx>
64 #include <tools/debug.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <unotools/confignode.hxx>
67 #include <vcl/stdtext.hxx>
68 #include <vcl/weld.hxx>
69 
70 #include <algorithm>
71 
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::container;
75 using namespace ::com::sun::star::form;
76 using namespace ::com::sun::star::form::inspection;
77 using namespace ::com::sun::star::frame;
78 using namespace ::com::sun::star::inspection;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star::util;
82 using namespace ::svxform;
83 using ::com::sun::star::awt::XWindow;
84 
85 //= FmPropBrwMgr
86 
87 
SFX_IMPL_FLOATINGWINDOW(FmPropBrwMgr,SID_FM_SHOW_PROPERTIES)88 SFX_IMPL_FLOATINGWINDOW(FmPropBrwMgr, SID_FM_SHOW_PROPERTIES)
89 
90 
91 FmPropBrwMgr::FmPropBrwMgr( vcl::Window* _pParent, sal_uInt16 _nId,
92                             SfxBindings* _pBindings, SfxChildWinInfo* _pInfo)
93               :SfxChildWindow(_pParent, _nId)
94 {
95     SetWindow( VclPtr<FmPropBrw>::Create( ::comphelper::getProcessComponentContext(), _pBindings, this, _pParent, _pInfo ) );
96     static_cast<SfxFloatingWindow*>(GetWindow())->Initialize( _pInfo );
97 }
98 
99 
100 const long STD_WIN_SIZE_X = 300;
101 const long STD_WIN_SIZE_Y = 350;
102 
103 const long STD_MIN_SIZE_X = 250;
104 const long STD_MIN_SIZE_Y = 250;
105 
106 
GetUIHeadlineName(sal_Int16 nClassId,const Any & aUnoObj)107 static OUString GetUIHeadlineName(sal_Int16 nClassId, const Any& aUnoObj)
108 {
109     const char* pClassNameResourceId = nullptr;
110 
111     switch ( nClassId )
112     {
113         case FormComponentType::TEXTFIELD:
114         {
115             Reference< XInterface >  xIFace;
116             aUnoObj >>= xIFace;
117             pClassNameResourceId = RID_STR_PROPTITLE_EDIT;
118             if (xIFace.is())
119             {   // we have a chance to check if it's a formatted field model
120                 Reference< XServiceInfo >  xInfo(xIFace, UNO_QUERY);
121                 if (xInfo.is() && (xInfo->supportsService(FM_SUN_COMPONENT_FORMATTEDFIELD)))
122                     pClassNameResourceId = RID_STR_PROPTITLE_FORMATTED;
123                 else if (!xInfo.is())
124                 {
125                     // couldn't distinguish between formatted and edit with the service name, so try with the properties
126                     Reference< XPropertySet >  xProps(xIFace, UNO_QUERY);
127                     if (xProps.is())
128                     {
129                         Reference< XPropertySetInfo >  xPropsInfo = xProps->getPropertySetInfo();
130                         if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER))
131                             pClassNameResourceId = RID_STR_PROPTITLE_FORMATTED;
132                     }
133                 }
134             }
135         }
136         break;
137 
138         case FormComponentType::COMMANDBUTTON:
139             pClassNameResourceId = RID_STR_PROPTITLE_PUSHBUTTON; break;
140         case FormComponentType::RADIOBUTTON:
141             pClassNameResourceId = RID_STR_PROPTITLE_RADIOBUTTON; break;
142         case FormComponentType::CHECKBOX:
143             pClassNameResourceId = RID_STR_PROPTITLE_CHECKBOX; break;
144         case FormComponentType::LISTBOX:
145             pClassNameResourceId = RID_STR_PROPTITLE_LISTBOX; break;
146         case FormComponentType::COMBOBOX:
147             pClassNameResourceId = RID_STR_PROPTITLE_COMBOBOX; break;
148         case FormComponentType::GROUPBOX:
149             pClassNameResourceId = RID_STR_PROPTITLE_GROUPBOX; break;
150         case FormComponentType::IMAGEBUTTON:
151             pClassNameResourceId = RID_STR_PROPTITLE_IMAGEBUTTON; break;
152         case FormComponentType::FIXEDTEXT:
153             pClassNameResourceId = RID_STR_PROPTITLE_FIXEDTEXT; break;
154         case FormComponentType::GRIDCONTROL:
155             pClassNameResourceId = RID_STR_PROPTITLE_DBGRID; break;
156         case FormComponentType::FILECONTROL:
157             pClassNameResourceId = RID_STR_PROPTITLE_FILECONTROL; break;
158         case FormComponentType::DATEFIELD:
159             pClassNameResourceId = RID_STR_PROPTITLE_DATEFIELD; break;
160         case FormComponentType::TIMEFIELD:
161             pClassNameResourceId = RID_STR_PROPTITLE_TIMEFIELD; break;
162         case FormComponentType::NUMERICFIELD:
163             pClassNameResourceId = RID_STR_PROPTITLE_NUMERICFIELD; break;
164         case FormComponentType::CURRENCYFIELD:
165             pClassNameResourceId = RID_STR_PROPTITLE_CURRENCYFIELD; break;
166         case FormComponentType::PATTERNFIELD:
167             pClassNameResourceId = RID_STR_PROPTITLE_PATTERNFIELD; break;
168         case FormComponentType::IMAGECONTROL:
169             pClassNameResourceId = RID_STR_PROPTITLE_IMAGECONTROL; break;
170         case FormComponentType::HIDDENCONTROL:
171             pClassNameResourceId = RID_STR_PROPTITLE_HIDDEN; break;
172         case FormComponentType::SCROLLBAR:
173             pClassNameResourceId = RID_STR_PROPTITLE_SCROLLBAR; break;
174         case FormComponentType::SPINBUTTON:
175             pClassNameResourceId = RID_STR_PROPTITLE_SPINBUTTON; break;
176         case FormComponentType::NAVIGATIONBAR:
177             pClassNameResourceId = RID_STR_PROPTITLE_NAVBAR; break;
178         case FormComponentType::CONTROL:
179         default:
180             pClassNameResourceId = RID_STR_CONTROL; break;
181     }
182 
183     return SvxResId(pClassNameResourceId);
184 }
185 
FmPropBrw(const Reference<XComponentContext> & _xORB,SfxBindings * _pBindings,SfxChildWindow * _pMgr,vcl::Window * _pParent,const SfxChildWinInfo * _pInfo)186 FmPropBrw::FmPropBrw( const Reference< XComponentContext >& _xORB, SfxBindings* _pBindings,
187             SfxChildWindow* _pMgr, vcl::Window* _pParent, const SfxChildWinInfo* _pInfo )
188     :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_3DLOOK|WB_ROLLABLE) )
189     ,SfxControllerItem(SID_FM_PROPERTY_CONTROL, *_pBindings)
190     ,m_bInitialStateChange(true)
191     ,m_xORB(_xORB)
192 {
193 
194     ::Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y);
195     SetMinOutputSizePixel(::Size(STD_MIN_SIZE_X,STD_MIN_SIZE_Y));
196     SetOutputSizePixel(aPropWinSize);
197 
198     try
199     {
200         // create a frame wrapper for myself
201         m_xMeAsFrame = Frame::create(m_xORB);
202 
203         // create an intermediate window, which is to be the container window of the frame
204         // Do *not* use |this| as container window for the frame, this would result in undefined
205         // responsibility for this window (as soon as we initialize a frame with a window, the frame
206         // is responsible for its life time, but |this| is controlled by the belonging SfxChildWindow)
207         // #i34249#
208         VclPtr<vcl::Window> pContainerWindow = VclPtr<vcl::Window>::Create( this );
209         pContainerWindow->Show();
210         m_xFrameContainerWindow = VCLUnoHelper::GetInterface ( pContainerWindow );
211 
212         m_xMeAsFrame->initialize( m_xFrameContainerWindow );
213         m_xMeAsFrame->setName("form property browser");
214     }
215     catch (Exception&)
216     {
217         OSL_FAIL("FmPropBrw::FmPropBrw: could not create/initialize my frame!");
218         m_xMeAsFrame.clear();
219     }
220 
221     if (m_xMeAsFrame.is())
222         _pMgr->SetFrame( Reference<XFrame>(m_xMeAsFrame,UNO_QUERY_THROW) );
223 
224 
225     if ( m_xBrowserComponentWindow.is() )
226         m_xBrowserComponentWindow->setVisible( true );
227 
228     if ( _pInfo )
229         m_sLastActivePage = _pInfo->aExtraString;
230 }
231 
232 
Resize()233 void FmPropBrw::Resize()
234 {
235     SfxFloatingWindow::Resize();
236 
237     if ( m_xFrameContainerWindow.is() )
238     {
239         try
240         {
241             ::Size aOutputSize( GetOutputSizePixel() );
242             m_xFrameContainerWindow->setPosSize( 0, 0, aOutputSize.Width(), aOutputSize.Height(), awt::PosSize::POSSIZE );
243         }
244         catch( const Exception& )
245         {
246             OSL_FAIL( "FmPropBrw::Resize: caught an exception!" );
247         }
248     }
249 }
250 
251 
~FmPropBrw()252 FmPropBrw::~FmPropBrw()
253 {
254     disposeOnce();
255 }
256 
dispose()257 void FmPropBrw::dispose()
258 {
259     if (m_xBrowserController.is())
260         implDetachController();
261     try
262     {
263         // remove our own properties from the component context. We cannot ensure that the component context
264         // is freed (there might be refcount problems :-\), so at least ensure the context itself
265         // does hold the objects anymore
266         Reference<XNameContainer> xName(m_xInspectorContext,uno::UNO_QUERY);
267         if ( xName.is() )
268         {
269             const OUString pProps[] = { OUString( "ContextDocument" )
270                                              , OUString( "DialogParentWindow" )
271                                              , OUString( "ControlContext" )
272                                              , OUString( "ControlShapeAccess" ) };
273             for (const auto & i : pProps)
274                 xName->removeByName( i );
275         }
276     }
277     catch (const Exception& )
278     {
279         DBG_UNHANDLED_EXCEPTION("svx");
280     }
281     ::SfxControllerItem::dispose();
282     SfxFloatingWindow::dispose();
283 }
284 
285 
getCurrentPage() const286 OUString FmPropBrw::getCurrentPage() const
287 {
288     OUString sCurrentPage;
289     try
290     {
291         if ( m_xBrowserController.is() )
292         {
293             OSL_VERIFY( m_xBrowserController->getViewData() >>= sCurrentPage );
294         }
295 
296         if ( sCurrentPage.isEmpty() )
297             sCurrentPage = m_sLastActivePage;
298     }
299     catch( const Exception& )
300     {
301         OSL_FAIL( "FmPropBrw::getCurrentPage: caught an exception while retrieving the current page!" );
302     }
303     return sCurrentPage;
304 }
305 
306 
implDetachController()307 void FmPropBrw::implDetachController()
308 {
309     m_sLastActivePage = getCurrentPage();
310 
311     implSetNewSelection( InterfaceBag() );
312 
313     if ( m_xMeAsFrame.is() )
314     {
315         try
316         {
317             m_xMeAsFrame->setComponent(nullptr, nullptr);
318         }
319         catch( const Exception& )
320         {
321             OSL_FAIL( "FmPropBrw::implDetachController: caught an exception while resetting the component!" );
322         }
323     }
324 
325     // we attached a frame to the controller manually, so we need to manually tell it that it's detached, too
326     if ( m_xBrowserController.is() )
327         m_xBrowserController->attachFrame( nullptr );
328 
329     m_xBrowserController.clear();
330     m_xInspectorModel.clear();
331     m_xMeAsFrame.clear();
332 }
333 
334 
Close()335 bool FmPropBrw::Close()
336 {
337     // suspend the controller (it is allowed to veto)
338     if ( m_xMeAsFrame.is() )
339     {
340         try
341         {
342             Reference< XController > xController( m_xMeAsFrame->getController() );
343             if ( xController.is() && !xController->suspend( true ) )
344                 return false;
345         }
346         catch( const Exception& )
347         {
348             OSL_FAIL( "FmPropBrw::Close: caught an exception while asking the controller!" );
349         }
350     }
351 
352     implDetachController();
353 
354     if( IsRollUp() )
355         RollDown();
356 
357     // remember our bindings: while we're closed, we're deleted, too, so accessing the bindings after this
358     // would be deadly
359     // 10/19/00 - 79321 - FS
360     SfxBindings& rBindings = SfxControllerItem::GetBindings();
361 
362     bool bClose = SfxFloatingWindow::Close();
363 
364     if (bClose)
365     {
366         rBindings.Invalidate(SID_FM_CTL_PROPERTIES);
367         rBindings.Invalidate(SID_FM_PROPERTIES);
368     }
369 
370     return bClose;
371 }
372 
373 
implIsReadOnlyModel() const374 bool FmPropBrw::implIsReadOnlyModel() const
375 {
376     try
377     {
378         if ( m_xInspectorModel.is() )
379             return m_xInspectorModel->getIsReadOnly();
380         return false;
381     }
382     catch( const Exception& )
383     {
384         DBG_UNHANDLED_EXCEPTION("svx");
385     }
386     return true;
387 }
388 
389 
implSetNewSelection(const InterfaceBag & _rSelection)390 void FmPropBrw::implSetNewSelection( const InterfaceBag& _rSelection )
391 {
392     if ( m_xBrowserController.is() )
393     {
394         try
395         {
396             Reference< XObjectInspector > xInspector( m_xBrowserController, UNO_QUERY_THROW );
397 
398             // tell it the objects to inspect
399             xInspector->inspect( comphelper::containerToSequence(_rSelection) );
400         }
401         catch( const VetoException& )
402         {
403             return;
404         }
405         catch( const Exception& )
406         {
407             OSL_FAIL( "FmPropBrw::implSetNewSelection: caught an unexpected exception!" );
408             return;
409         }
410 
411         // set the new title according to the selected object
412         OUString sTitle;
413 
414         if ( _rSelection.empty() )
415         {
416             sTitle = SvxResId(RID_STR_NO_PROPERTIES);
417         }
418         else if ( _rSelection.size() > 1 )
419         {
420             // no form component and (no form or no name) -> Multiselection
421             sTitle = SvxResId(RID_STR_PROPERTIES_CONTROL) +
422                 SvxResId(RID_STR_PROPTITLE_MULTISELECT);
423         }
424         else
425         {
426             Reference< XPropertySet > xSingleSelection( *_rSelection.begin(), UNO_QUERY);
427             if  ( ::comphelper::hasProperty( FM_PROP_CLASSID, xSingleSelection ) )
428             {
429                 sal_Int16 nClassID = FormComponentType::CONTROL;
430                 xSingleSelection->getPropertyValue( FM_PROP_CLASSID ) >>= nClassID;
431 
432                 sTitle = SvxResId(RID_STR_PROPERTIES_CONTROL) +
433                     GetUIHeadlineName(nClassID, makeAny(xSingleSelection));
434             }
435             else if ( Reference< XForm >( xSingleSelection, UNO_QUERY ).is() )
436                 sTitle = SvxResId(RID_STR_PROPERTIES_FORM);
437         }
438 
439         if ( implIsReadOnlyModel() )
440             sTitle += SvxResId(RID_STR_READONLY_VIEW);
441 
442         SetText( sTitle );
443 
444         Reference< css::awt::XLayoutConstrains > xLayoutConstrains( m_xBrowserController, UNO_QUERY );
445         if( xLayoutConstrains.is() )
446         {
447             ::Size aConstrainedSize;
448             css::awt::Size aMinSize = xLayoutConstrains->getMinimumSize();
449 
450             sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
451             GetBorder( nLeft, nTop, nRight, nBottom );
452             aMinSize.Width += nLeft + nRight + 8;
453             aMinSize.Height += nTop + nBottom + 8;
454 
455             aConstrainedSize.setHeight( aMinSize.Height );
456             aConstrainedSize.setWidth( aMinSize.Width );
457             SetMinOutputSizePixel( aConstrainedSize );
458             aConstrainedSize = GetOutputSizePixel();
459             bool bResize = false;
460             if( aConstrainedSize.Width() < aMinSize.Width )
461             {
462                 aConstrainedSize.setWidth( aMinSize.Width );
463                 bResize = true;
464             }
465             if( aConstrainedSize.Height() < aMinSize.Height )
466             {
467                 aConstrainedSize.setHeight( aMinSize.Height );
468                 bResize = true;
469             }
470             if( bResize )
471                 SetOutputSizePixel( aConstrainedSize );
472         }
473     }
474 }
475 
476 
FillInfo(SfxChildWinInfo & rInfo) const477 void FmPropBrw::FillInfo( SfxChildWinInfo& rInfo ) const
478 {
479     rInfo.bVisible = false;
480     rInfo.aExtraString = getCurrentPage();
481 }
482 
483 
IMPL_LINK_NOARG(FmPropBrw,OnAsyncGetFocus,void *,void)484 IMPL_LINK_NOARG( FmPropBrw, OnAsyncGetFocus, void*, void )
485 {
486     if (m_xBrowserComponentWindow.is())
487         m_xBrowserComponentWindow->setFocus();
488 }
489 
490 
491 namespace
492 {
lcl_shouldEnableHelpSection(const Reference<XComponentContext> & _rxContext)493     bool lcl_shouldEnableHelpSection( const Reference< XComponentContext >& _rxContext )
494     {
495         ::utl::OConfigurationTreeRoot aConfiguration(
496             ::utl::OConfigurationTreeRoot::createWithComponentContext(
497                 _rxContext,
498                 "/org.openoffice.Office.Common/Forms/PropertyBrowser/" ) );
499 
500         bool bEnabled = false;
501         OSL_VERIFY( aConfiguration.getNodeValue( "DirectHelp" ) >>= bEnabled );
502         return bEnabled;
503     }
504 }
505 
impl_createPropertyBrowser_throw(FmFormShell * _pFormShell)506 void FmPropBrw::impl_createPropertyBrowser_throw( FmFormShell* _pFormShell )
507 {
508     // the document in which we live
509     Reference< XInterface > xDocument;
510     if ( _pFormShell && _pFormShell->GetObjectShell() )
511         xDocument = _pFormShell->GetObjectShell()->GetModel();
512 
513     // the context of the controls in our document
514     Reference< awt::XControlContainer > xControlContext;
515     if ( _pFormShell && _pFormShell->GetFormView() )
516     {
517         SdrPageView* pPageView = _pFormShell->GetFormView()->GetSdrPageView();
518 
519         if(pPageView)
520         {
521             SdrPageWindow* pPageWindow = pPageView->GetPageWindow(0);
522 
523             if(pPageWindow)
524             {
525                 xControlContext = pPageWindow->GetControlContainer();
526             }
527         }
528     }
529 
530     // the default parent window for message boxes
531     Reference< XWindow > xParentWindow( VCLUnoHelper::GetInterface ( this ) );
532 
533     // the mapping from control models to control shapes
534     Reference< XMap > xControlMap;
535     FmFormPage* pFormPage = _pFormShell ? _pFormShell->GetCurPage() : nullptr;
536     if ( pFormPage )
537         xControlMap = pFormPage->GetImpl().getControlToShapeMap();
538 
539     // our own component context
540 
541     // a ComponentContext for the
542     ::cppu::ContextEntry_Init aHandlerContextInfo[] =
543     {
544         ::cppu::ContextEntry_Init( "ContextDocument", makeAny( xDocument ) ),
545         ::cppu::ContextEntry_Init( "DialogParentWindow", makeAny( xParentWindow ) ),
546         ::cppu::ContextEntry_Init( "ControlContext", makeAny( xControlContext ) ),
547         ::cppu::ContextEntry_Init( "ControlShapeAccess", makeAny( xControlMap ) )
548     };
549     m_xInspectorContext.set(
550         ::cppu::createComponentContext( aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ),
551         m_xORB ) );
552 
553     bool bEnableHelpSection = lcl_shouldEnableHelpSection( m_xORB );
554 
555     // an object inspector model
556     m_xInspectorModel =
557             bEnableHelpSection
558         ?   DefaultFormComponentInspectorModel::createWithHelpSection( m_xInspectorContext, 3, 5 )
559         :   DefaultFormComponentInspectorModel::createDefault( m_xInspectorContext );
560 
561     // an object inspector
562     m_xBrowserController =
563         ObjectInspector::createWithModel(
564             m_xInspectorContext, m_xInspectorModel
565         );
566 
567     if ( !m_xBrowserController.is() )
568     {
569         vcl::Window *pWin = GetParent();
570         ShowServiceNotAvailableError(pWin ? pWin->GetFrameWeld() : nullptr, "com.sun.star.inspection.ObjectInspector", true);
571     }
572     else
573     {
574         m_xBrowserController->attachFrame( Reference<XFrame>(m_xMeAsFrame,UNO_QUERY_THROW) );
575         m_xBrowserComponentWindow = m_xMeAsFrame->getComponentWindow();
576         DBG_ASSERT( m_xBrowserComponentWindow.is(), "FmPropBrw::impl_createPropertyBrowser_throw: attached the controller, but have no component window!" );
577     }
578 
579     if ( bEnableHelpSection )
580     {
581         Reference< XObjectInspector > xInspector( m_xBrowserController, UNO_QUERY_THROW );
582         Reference< XObjectInspectorUI > xInspectorUI( xInspector->getInspectorUI() );
583         Reference< XInterface > xDefaultHelpProvider( DefaultHelpProvider::create( m_xInspectorContext, xInspectorUI ) );
584     }
585 }
586 
587 
impl_ensurePropertyBrowser_nothrow(FmFormShell * _pFormShell)588 void FmPropBrw::impl_ensurePropertyBrowser_nothrow( FmFormShell* _pFormShell )
589 {
590     // the document in which we live
591     Reference< XInterface > xDocument;
592     SfxObjectShell* pObjectShell = _pFormShell ? _pFormShell->GetObjectShell() : nullptr;
593     if ( pObjectShell )
594         xDocument = pObjectShell->GetModel();
595     if ( ( xDocument == m_xLastKnownDocument ) && m_xBrowserController.is() )
596         // nothing to do
597         return;
598 
599     try
600     {
601         // clean up any previous instances of the object inspector
602         if ( m_xMeAsFrame.is() )
603             m_xMeAsFrame->setComponent( nullptr, nullptr );
604         else
605             ::comphelper::disposeComponent( m_xBrowserController );
606         m_xBrowserController.clear();
607         m_xInspectorModel.clear();
608         m_xBrowserComponentWindow.clear();
609 
610         // and create a new one
611         impl_createPropertyBrowser_throw( _pFormShell );
612     }
613     catch( const Exception& )
614     {
615         DBG_UNHANDLED_EXCEPTION("svx");
616     }
617     m_xLastKnownDocument = xDocument;
618 }
619 
620 
StateChanged(sal_uInt16 nSID,SfxItemState eState,const SfxPoolItem * pState)621 void FmPropBrw::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
622 {
623     if (!pState  || SID_FM_PROPERTY_CONTROL != nSID)
624         return;
625 
626     try
627     {
628         if (eState >= SfxItemState::DEFAULT)
629         {
630             FmFormShell* pShell = dynamic_cast<FmFormShell*>( static_cast<const SfxObjectItem*>(pState)->GetShell() );
631             InterfaceBag aSelection;
632             if ( pShell )
633                 pShell->GetImpl()->getCurrentSelection_Lock(aSelection);
634 
635             impl_ensurePropertyBrowser_nothrow( pShell );
636 
637             // set the new object to inspect
638             implSetNewSelection( aSelection );
639 
640             // if this is the first time we're here, some additional things need to be done ...
641             if ( m_bInitialStateChange )
642             {
643                 // if we're just newly created, we want to have the focus
644                 PostUserEvent( LINK( this, FmPropBrw, OnAsyncGetFocus ), nullptr, true );
645 
646                 // and additionally, we want to show the page which was active during
647                 // our previous incarnation
648                 if ( !m_sLastActivePage.isEmpty() )
649                 {
650                     try
651                     {
652                         if ( m_xBrowserController.is() )
653                             m_xBrowserController->restoreViewData( makeAny( m_sLastActivePage ) );
654                     }
655                     catch( const Exception& )
656                     {
657                         OSL_FAIL( "FmPropBrw::StateChanged: caught an exception while setting the initial page!" );
658                     }
659                 }
660 
661                 m_bInitialStateChange = false;
662             }
663 
664         }
665         else
666         {
667             implSetNewSelection( InterfaceBag() );
668         }
669     }
670     catch (Exception&)
671     {
672         OSL_FAIL("FmPropBrw::StateChanged: Exception occurred!");
673     }
674 }
675 
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
677