Line data Source code
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 : #include "propcontroller.hxx"
21 : #include "pcrstrings.hxx"
22 : #include "standardcontrol.hxx"
23 : #include "linedescriptor.hxx"
24 : #include "propresid.hrc"
25 : #include "formresid.hrc"
26 : #include "propertyeditor.hxx"
27 : #include "modulepcr.hxx"
28 : #include "formstrings.hxx"
29 : #include "formmetadata.hxx"
30 : #include "formbrowsertools.hxx"
31 : #include "propertycomposer.hxx"
32 :
33 : #include <com/sun/star/awt/XWindow.hpp>
34 : #include <com/sun/star/util/XCloseable.hpp>
35 : #include <com/sun/star/inspection/PropertyControlType.hpp>
36 : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
37 : #include <tools/debug.hxx>
38 : #include <tools/diagnose_ex.h>
39 : #include <comphelper/types.hxx>
40 : #include <comphelper/extract.hxx>
41 : #include <toolkit/awt/vclxwindow.hxx>
42 : #include <toolkit/unohlp.hxx>
43 : #include <comphelper/property.hxx>
44 : #include <vcl/msgbox.hxx>
45 : #include <vcl/svapp.hxx>
46 : #include <osl/mutex.hxx>
47 : #include <cppuhelper/component_context.hxx>
48 : #include <cppuhelper/exc_hlp.hxx>
49 :
50 : #include <algorithm>
51 : #include <functional>
52 : #include <sal/macros.h>
53 :
54 : //------------------------------------------------------------------------
55 : // !!! outside the namespace !!!
56 0 : extern "C" void SAL_CALL createRegistryInfo_OPropertyBrowserController()
57 : {
58 0 : ::pcr::OAutoRegistration< ::pcr::OPropertyBrowserController > aAutoRegistration;
59 0 : }
60 :
61 : //............................................................................
62 : namespace pcr
63 : {
64 : //............................................................................
65 :
66 : using namespace ::com::sun::star;
67 : using namespace ::com::sun::star::uno;
68 : using namespace ::com::sun::star::awt;
69 : using namespace ::com::sun::star::form;
70 : using namespace ::com::sun::star::beans;
71 : using namespace ::com::sun::star::script;
72 : using namespace ::com::sun::star::lang;
73 : using namespace ::com::sun::star::container;
74 : using namespace ::com::sun::star::frame;
75 : using namespace ::com::sun::star::util;
76 : using namespace ::com::sun::star::inspection;
77 : using namespace ::com::sun::star::ucb;
78 : using namespace ::comphelper;
79 :
80 : #define THISREF() static_cast< XController* >(this)
81 :
82 : //========================================================================
83 : //= OPropertyBrowserController
84 : //========================================================================
85 : DBG_NAME(OPropertyBrowserController)
86 : //------------------------------------------------------------------------
87 0 : OPropertyBrowserController::OPropertyBrowserController( const Reference< XComponentContext >& _rxContext )
88 : :m_aContext(_rxContext)
89 : ,m_aDisposeListeners( m_aMutex )
90 : ,m_aControlObservers( m_aMutex )
91 : ,m_pView(NULL)
92 : ,m_bContainerFocusListening( false )
93 : ,m_bSuspendingPropertyHandlers( false )
94 : ,m_bConstructed( false )
95 0 : ,m_bBindingIntrospectee( false )
96 : {
97 : DBG_CTOR(OPropertyBrowserController,NULL);
98 0 : }
99 :
100 : //------------------------------------------------------------------------
101 0 : OPropertyBrowserController::~OPropertyBrowserController()
102 : {
103 : // stop listening for property changes
104 0 : acquire();
105 0 : stopInspection( true );
106 : DBG_DTOR(OPropertyBrowserController,NULL);
107 0 : }
108 :
109 : //------------------------------------------------------------------------
110 0 : IMPLEMENT_FORWARD_REFCOUNT( OPropertyBrowserController, OPropertyBrowserController_Base )
111 :
112 : //------------------------------------------------------------------------
113 0 : Any SAL_CALL OPropertyBrowserController::queryInterface( const Type& _rType ) throw (RuntimeException)
114 : {
115 0 : Any aReturn = OPropertyBrowserController_Base::queryInterface( _rType );
116 0 : if ( !aReturn.hasValue() )
117 : aReturn = ::cppu::queryInterface(
118 : _rType,
119 : static_cast< XObjectInspectorUI* >( this )
120 0 : );
121 0 : return aReturn;
122 : }
123 :
124 : //------------------------------------------------------------------------
125 0 : void OPropertyBrowserController::startContainerWindowListening()
126 : {
127 0 : if (m_bContainerFocusListening)
128 0 : return;
129 :
130 0 : if (m_xFrame.is())
131 : {
132 0 : Reference< XWindow > xContainerWindow = m_xFrame->getContainerWindow();
133 0 : if (xContainerWindow.is())
134 : {
135 0 : xContainerWindow->addFocusListener(this);
136 0 : m_bContainerFocusListening = sal_True;
137 0 : }
138 : }
139 :
140 : DBG_ASSERT(m_bContainerFocusListening, "OPropertyBrowserController::startContainerWindowListening: unable to start listening (inconsistence)!");
141 : }
142 :
143 : //------------------------------------------------------------------------
144 0 : void OPropertyBrowserController::stopContainerWindowListening()
145 : {
146 0 : if (!m_bContainerFocusListening)
147 0 : return;
148 :
149 0 : if (m_xFrame.is())
150 : {
151 0 : Reference< XWindow > xContainerWindow = m_xFrame->getContainerWindow();
152 0 : if (xContainerWindow.is())
153 : {
154 0 : xContainerWindow->removeFocusListener(this);
155 0 : m_bContainerFocusListening = sal_False;
156 0 : }
157 : }
158 :
159 : DBG_ASSERT(!m_bContainerFocusListening, "OPropertyBrowserController::stopContainerWindowListening: unable to stop listening (inconsistence)!");
160 : }
161 :
162 : //--------------------------------------------------------------------
163 0 : Reference< XObjectInspectorModel > SAL_CALL OPropertyBrowserController::getInspectorModel() throw (RuntimeException)
164 : {
165 0 : return m_xModel;
166 : }
167 :
168 : //--------------------------------------------------------------------
169 0 : void OPropertyBrowserController::impl_initializeView_nothrow()
170 : {
171 : OSL_PRECOND( haveView(), "OPropertyBrowserController::impl_initializeView_nothrow: not to be called when we have no view!" );
172 0 : if ( !haveView() )
173 0 : return;
174 :
175 0 : if ( !m_xModel.is() )
176 : // allowed
177 0 : return;
178 :
179 : try
180 : {
181 0 : getPropertyBox().EnableHelpSection( m_xModel->getHasHelpSection() );
182 0 : getPropertyBox().SetHelpLineLimites( m_xModel->getMinHelpTextLines(), m_xModel->getMaxHelpTextLines() );
183 : }
184 0 : catch( const Exception& )
185 : {
186 : DBG_UNHANDLED_EXCEPTION();
187 : }
188 : }
189 :
190 : //--------------------------------------------------------------------
191 0 : void OPropertyBrowserController::impl_updateReadOnlyView_nothrow()
192 : {
193 : // this is a huge cudgel, admitted.
194 : // The problem is that in case we were previously read-only, all our controls
195 : // were created read-only, too. We cannot simply switch them to not-read-only.
196 : // Even if they had an API for this, we do not know whether they were
197 : // originally created read-only, or if they are read-only just because
198 : // the model was.
199 0 : impl_rebindToInspectee_nothrow( m_aInspectedObjects );
200 0 : }
201 :
202 : //--------------------------------------------------------------------
203 0 : bool OPropertyBrowserController::impl_isReadOnlyModel_throw() const
204 : {
205 0 : if ( !m_xModel.is() )
206 0 : return false;
207 :
208 0 : return m_xModel->getIsReadOnly();
209 : }
210 :
211 : //--------------------------------------------------------------------
212 0 : void OPropertyBrowserController::impl_startOrStopModelListening_nothrow( bool _bDoListen ) const
213 : {
214 : try
215 : {
216 0 : Reference< XPropertySet > xModelProperties( m_xModel, UNO_QUERY );
217 0 : if ( !xModelProperties.is() )
218 : // okay, so the model doesn't want to change its properties
219 : // dynamically - fine with us
220 0 : return;
221 :
222 : void (SAL_CALL XPropertySet::*pListenerOperation)( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
223 0 : = _bDoListen ? &XPropertySet::addPropertyChangeListener : &XPropertySet::removePropertyChangeListener;
224 :
225 0 : (xModelProperties.get()->*pListenerOperation)(
226 : ::rtl::OUString( "IsReadOnly" ),
227 : const_cast< OPropertyBrowserController* >( this )
228 0 : );
229 : }
230 0 : catch( const Exception& )
231 : {
232 : DBG_UNHANDLED_EXCEPTION();
233 : }
234 : }
235 :
236 : //--------------------------------------------------------------------
237 0 : void OPropertyBrowserController::impl_bindToNewModel_nothrow( const Reference< XObjectInspectorModel >& _rxInspectorModel )
238 : {
239 0 : impl_startOrStopModelListening_nothrow( false );
240 0 : m_xModel = _rxInspectorModel;
241 0 : impl_startOrStopModelListening_nothrow( true );
242 :
243 : // initialize the view, if we already have one
244 0 : if ( haveView() )
245 0 : impl_initializeView_nothrow();
246 :
247 : // inspect again, if we already have inspectees
248 0 : if ( !m_aInspectedObjects.empty() )
249 0 : impl_rebindToInspectee_nothrow( m_aInspectedObjects );
250 0 : }
251 :
252 : //--------------------------------------------------------------------
253 0 : void SAL_CALL OPropertyBrowserController::setInspectorModel( const Reference< XObjectInspectorModel >& _inspectorModel ) throw (RuntimeException)
254 : {
255 0 : ::osl::MutexGuard aGuard( m_aMutex );
256 :
257 0 : if ( m_xModel == _inspectorModel )
258 0 : return;
259 :
260 0 : impl_bindToNewModel_nothrow( _inspectorModel );
261 : }
262 :
263 : //--------------------------------------------------------------------
264 0 : Reference< XObjectInspectorUI > SAL_CALL OPropertyBrowserController::getInspectorUI() throw (RuntimeException)
265 : {
266 : // we're derived from this interface, though we do not expose it in queryInterface and getTypes.
267 0 : return this;
268 : }
269 :
270 : //--------------------------------------------------------------------
271 0 : void SAL_CALL OPropertyBrowserController::inspect( const Sequence< Reference< XInterface > >& _rObjects ) throw (com::sun::star::util::VetoException, RuntimeException)
272 : {
273 0 : SolarMutexGuard aSolarGuard;
274 0 : ::osl::MutexGuard aGuard( m_aMutex );
275 :
276 0 : if ( m_bSuspendingPropertyHandlers || !suspendAll_nothrow() )
277 : { // we already are trying to suspend the component (this is somewhere up the stack)
278 : // OR one of our property handlers raised a veto against closing. Well, we *need* to close
279 : // it in order to inspect another object.
280 0 : throw VetoException();
281 : }
282 0 : if ( m_bBindingIntrospectee )
283 0 : throw VetoException();
284 :
285 0 : m_bBindingIntrospectee = true;
286 0 : impl_rebindToInspectee_nothrow( InterfaceArray( _rObjects.getConstArray(), _rObjects.getConstArray() + _rObjects.getLength() ) );
287 0 : m_bBindingIntrospectee = false;
288 :
289 0 : }
290 :
291 : //--------------------------------------------------------------------
292 0 : Reference< XDispatch > SAL_CALL OPropertyBrowserController::queryDispatch( const URL& /*URL*/, const ::rtl::OUString& /*TargetFrameName*/, ::sal_Int32 /*SearchFlags*/ ) throw (RuntimeException)
293 : {
294 : // we don't have any dispatches at all, right now
295 0 : return Reference< XDispatch >();
296 : }
297 :
298 : //--------------------------------------------------------------------
299 0 : Sequence< Reference< XDispatch > > SAL_CALL OPropertyBrowserController::queryDispatches( const Sequence< DispatchDescriptor >& Requests ) throw (RuntimeException)
300 : {
301 0 : Sequence< Reference< XDispatch > > aReturn;
302 0 : sal_Int32 nLen = Requests.getLength();
303 0 : aReturn.realloc( nLen );
304 :
305 0 : Reference< XDispatch >* pReturn = aReturn.getArray();
306 0 : const Reference< XDispatch >* pReturnEnd = aReturn.getArray() + nLen;
307 0 : const DispatchDescriptor* pDescripts = Requests.getConstArray();
308 :
309 0 : for ( ; pReturn != pReturnEnd; ++ pReturn, ++pDescripts )
310 0 : *pReturn = queryDispatch( pDescripts->FeatureURL, pDescripts->FrameName, pDescripts->SearchFlags );
311 :
312 0 : return aReturn;
313 : }
314 :
315 : //------------------------------------------------------------------------
316 0 : void SAL_CALL OPropertyBrowserController::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
317 : {
318 0 : if ( m_bConstructed )
319 0 : throw AlreadyInitializedException();
320 :
321 0 : StlSyntaxSequence< Any > arguments( _arguments );
322 0 : if ( arguments.empty() )
323 : { // constructor: "createDefault()"
324 0 : createDefault();
325 : return;
326 : }
327 :
328 0 : Reference< XObjectInspectorModel > xModel;
329 0 : if ( arguments.size() == 1 )
330 : { // constructor: "createWithModel( XObjectInspectorModel )"
331 0 : if ( !( arguments[0] >>= xModel ) )
332 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
333 0 : createWithModel( xModel );
334 : return;
335 : }
336 :
337 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
338 : }
339 :
340 : //------------------------------------------------------------------------
341 0 : void OPropertyBrowserController::createDefault()
342 : {
343 0 : m_bConstructed = true;
344 0 : }
345 :
346 : //------------------------------------------------------------------------
347 0 : void OPropertyBrowserController::createWithModel( const Reference< XObjectInspectorModel >& _rxModel )
348 : {
349 0 : osl_atomic_increment( &m_refCount );
350 : {
351 0 : setInspectorModel( _rxModel );
352 : }
353 0 : osl_atomic_decrement( &m_refCount );
354 :
355 0 : m_bConstructed = true;
356 0 : }
357 :
358 : //------------------------------------------------------------------------
359 0 : void SAL_CALL OPropertyBrowserController::attachFrame( const Reference< XFrame >& _rxFrame ) throw(RuntimeException)
360 : {
361 0 : SolarMutexGuard aSolarGuard;
362 0 : ::osl::MutexGuard aGuard( m_aMutex );
363 :
364 0 : if (_rxFrame.is() && haveView())
365 0 : throw RuntimeException(::rtl::OUString("Unable to attach to a second frame."),*this);
366 :
367 : // revoke as focus listener from the old container window
368 0 : stopContainerWindowListening();
369 :
370 0 : m_xFrame = _rxFrame;
371 0 : if (!m_xFrame.is())
372 0 : return;
373 :
374 : // TODO: this construction perhaps should be done outside. Don't know the exact meaning of attachFrame.
375 : // Maybe it is intended to only announce the frame to the controller, and the instance doing this
376 : // announcement is responsible for calling setComponent, too.
377 0 : Reference< XWindow > xContainerWindow = m_xFrame->getContainerWindow();
378 0 : VCLXWindow* pContainerWindow = VCLXWindow::GetImplementation(xContainerWindow);
379 0 : Window* pParentWin = pContainerWindow ? pContainerWindow->GetWindow() : NULL;
380 0 : if (!pParentWin)
381 0 : throw RuntimeException(::rtl::OUString("The frame is invalid. Unable to extract the container window."),*this);
382 :
383 0 : if ( Construct( pParentWin ) )
384 : {
385 : try
386 : {
387 0 : m_xFrame->setComponent( VCLUnoHelper::GetInterface( m_pView ), this );
388 : }
389 0 : catch( const Exception& )
390 : {
391 : OSL_FAIL( "OPropertyBrowserController::attachFrame: caught an exception!" );
392 : }
393 : }
394 :
395 0 : startContainerWindowListening();
396 :
397 0 : UpdateUI();
398 : }
399 :
400 : //------------------------------------------------------------------------
401 0 : sal_Bool SAL_CALL OPropertyBrowserController::attachModel( const Reference< XModel >& _rxModel ) throw(RuntimeException)
402 : {
403 0 : Reference< XObjectInspectorModel > xModel( _rxModel, UNO_QUERY );
404 0 : if ( !xModel.is() )
405 0 : return false;
406 :
407 0 : setInspectorModel( xModel );
408 0 : return getInspectorModel() == _rxModel;
409 : }
410 :
411 : //------------------------------------------------------------------------
412 0 : sal_Bool OPropertyBrowserController::suspendAll_nothrow()
413 : {
414 : // if there is a handle inside its "onInteractivePropertySelection" method,
415 : // then veto
416 : // Normally, we could expect every handler to do this itself, but being
417 : // realistic, it's safer to handle this here in general.
418 0 : if ( m_xInteractiveHandler.is() )
419 0 : return sal_False;
420 :
421 0 : m_bSuspendingPropertyHandlers = true;
422 0 : sal_Bool bHandlerVeto = !suspendPropertyHandlers_nothrow( sal_True );
423 0 : m_bSuspendingPropertyHandlers = false;
424 0 : if ( bHandlerVeto )
425 0 : return sal_False;
426 :
427 0 : return sal_True;
428 : }
429 :
430 : //------------------------------------------------------------------------
431 0 : sal_Bool OPropertyBrowserController::suspendPropertyHandlers_nothrow( sal_Bool _bSuspend )
432 : {
433 0 : PropertyHandlerArray aAllHandlers; // will contain every handler exactly once
434 0 : for ( PropertyHandlerRepository::const_iterator handler = m_aPropertyHandlers.begin();
435 0 : handler != m_aPropertyHandlers.end();
436 : ++handler
437 : )
438 : {
439 0 : if ( ::std::find( aAllHandlers.begin(), aAllHandlers.end(), handler->second ) != aAllHandlers.end() )
440 : // already visited this particular handler (m_aPropertyHandlers usually contains
441 : // the same handler more than once)
442 0 : continue;
443 0 : aAllHandlers.push_back( handler->second );
444 : }
445 :
446 0 : for ( PropertyHandlerArray::iterator loop = aAllHandlers.begin();
447 0 : loop != aAllHandlers.end();
448 : ++loop
449 : )
450 : {
451 : try
452 : {
453 0 : if ( !(*loop)->suspend( _bSuspend ) )
454 0 : if ( _bSuspend )
455 : // if we're not suspending, but reactivating, ignore the error
456 0 : return sal_False;
457 : }
458 0 : catch( const Exception& )
459 : {
460 : OSL_FAIL( "OPropertyBrowserController::suspendPropertyHandlers_nothrow: caught an exception!" );
461 : }
462 : }
463 0 : return sal_True;
464 : }
465 :
466 : //------------------------------------------------------------------------
467 0 : sal_Bool SAL_CALL OPropertyBrowserController::suspend( sal_Bool _bSuspend ) throw(RuntimeException)
468 : {
469 0 : ::osl::MutexGuard aGuard( m_aMutex );
470 : OSL_ENSURE( haveView(), "OPropertyBrowserController::suspend: don't have a view anymore!" );
471 :
472 0 : if ( !_bSuspend )
473 : { // this means a "suspend" is to be "revoked"
474 0 : suspendPropertyHandlers_nothrow( sal_False );
475 : // we ourself cannot revoke our suspend
476 0 : return sal_False;
477 : }
478 :
479 0 : if ( !suspendAll_nothrow() )
480 0 : return sal_False;
481 :
482 : // commit the editor's content
483 0 : if ( haveView() )
484 0 : getPropertyBox().CommitModified();
485 :
486 : // stop listening
487 0 : stopContainerWindowListening();
488 :
489 : // outtahere
490 0 : return sal_True;
491 : }
492 :
493 : //------------------------------------------------------------------------
494 0 : Any SAL_CALL OPropertyBrowserController::getViewData( ) throw(RuntimeException)
495 : {
496 0 : return makeAny( m_sPageSelection );
497 : }
498 :
499 : //------------------------------------------------------------------------
500 0 : void SAL_CALL OPropertyBrowserController::restoreViewData( const Any& Data ) throw(RuntimeException)
501 : {
502 0 : ::rtl::OUString sPageSelection;
503 0 : if ( ( Data >>= sPageSelection ) && !sPageSelection.isEmpty() )
504 : {
505 0 : m_sPageSelection = sPageSelection;
506 0 : selectPageFromViewData();
507 0 : }
508 0 : }
509 :
510 : //------------------------------------------------------------------------
511 0 : Reference< XModel > SAL_CALL OPropertyBrowserController::getModel( ) throw(RuntimeException)
512 : {
513 : // have no model
514 0 : return Reference< XModel >();
515 : }
516 :
517 : //------------------------------------------------------------------------
518 0 : Reference< XFrame > SAL_CALL OPropertyBrowserController::getFrame( ) throw(RuntimeException)
519 : {
520 0 : return m_xFrame;
521 : }
522 :
523 : //------------------------------------------------------------------------
524 0 : void SAL_CALL OPropertyBrowserController::dispose( ) throw(RuntimeException)
525 : {
526 0 : SolarMutexGuard aSolarGuard;
527 :
528 : // stop inspecting the current object
529 0 : stopInspection( false );
530 :
531 : // say our dispose listeners goodbye
532 0 : ::com::sun::star::lang::EventObject aEvt;
533 0 : aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
534 0 : m_aDisposeListeners.disposeAndClear(aEvt);
535 0 : m_aControlObservers.disposeAndClear(aEvt);
536 :
537 : // don't delete explicitly (this is done by the frame we reside in)
538 0 : m_pView = NULL;
539 :
540 0 : Reference< XComponent > xViewAsComp( m_xView, UNO_QUERY );
541 0 : if ( xViewAsComp.is() )
542 0 : xViewAsComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
543 0 : m_xView.clear( );
544 :
545 0 : m_aInspectedObjects.clear();
546 0 : impl_bindToNewModel_nothrow( NULL );
547 0 : }
548 :
549 : //------------------------------------------------------------------------
550 0 : void SAL_CALL OPropertyBrowserController::addEventListener( const Reference< XEventListener >& _rxListener ) throw(RuntimeException)
551 : {
552 0 : m_aDisposeListeners.addInterface(_rxListener);
553 0 : }
554 :
555 : //------------------------------------------------------------------------
556 0 : void SAL_CALL OPropertyBrowserController::removeEventListener( const Reference< XEventListener >& _rxListener ) throw(RuntimeException)
557 : {
558 0 : m_aDisposeListeners.removeInterface(_rxListener);
559 0 : }
560 :
561 : //------------------------------------------------------------------------
562 0 : ::rtl::OUString SAL_CALL OPropertyBrowserController::getImplementationName( ) throw(RuntimeException)
563 : {
564 0 : return getImplementationName_static();
565 : }
566 :
567 : //------------------------------------------------------------------------
568 0 : sal_Bool SAL_CALL OPropertyBrowserController::supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException)
569 : {
570 0 : Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
571 0 : const ::rtl::OUString* pArray = aSupported.getConstArray();
572 0 : for (sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray)
573 0 : if (pArray->equals(ServiceName))
574 0 : return sal_True;
575 0 : return sal_False;
576 : }
577 :
578 : //------------------------------------------------------------------------
579 0 : Sequence< ::rtl::OUString > SAL_CALL OPropertyBrowserController::getSupportedServiceNames( ) throw(RuntimeException)
580 : {
581 0 : return getSupportedServiceNames_static();
582 : }
583 :
584 : //------------------------------------------------------------------------
585 0 : ::rtl::OUString OPropertyBrowserController::getImplementationName_static( ) throw(RuntimeException)
586 : {
587 0 : return ::rtl::OUString("org.openoffice.comp.extensions.ObjectInspector");
588 : }
589 :
590 : //------------------------------------------------------------------------
591 0 : Sequence< ::rtl::OUString > OPropertyBrowserController::getSupportedServiceNames_static( ) throw(RuntimeException)
592 : {
593 0 : Sequence< ::rtl::OUString > aSupported(1);
594 0 : aSupported[0] = ::rtl::OUString("com.sun.star.inspection.ObjectInspector");
595 0 : return aSupported;
596 : }
597 :
598 : //------------------------------------------------------------------------
599 0 : Reference< XInterface > SAL_CALL OPropertyBrowserController::Create(const Reference< XComponentContext >& _rxContext)
600 : {
601 0 : return *(new OPropertyBrowserController( _rxContext ) );
602 : }
603 :
604 : //------------------------------------------------------------------------
605 0 : void SAL_CALL OPropertyBrowserController::focusGained( const FocusEvent& _rSource ) throw (RuntimeException)
606 : {
607 0 : Reference< XWindow > xSourceWindow(_rSource.Source, UNO_QUERY);
608 0 : Reference< XWindow > xContainerWindow;
609 0 : if (m_xFrame.is())
610 0 : xContainerWindow = m_xFrame->getContainerWindow();
611 :
612 0 : if ( xContainerWindow.get() == xSourceWindow.get() )
613 : { // our container window got the focus
614 0 : if ( haveView() )
615 0 : getPropertyBox().GrabFocus();
616 0 : }
617 0 : }
618 :
619 : //------------------------------------------------------------------------
620 0 : void SAL_CALL OPropertyBrowserController::focusLost( const FocusEvent& /*_rSource*/ ) throw (RuntimeException)
621 : {
622 : // not interested in
623 0 : }
624 :
625 : //------------------------------------------------------------------------
626 0 : void SAL_CALL OPropertyBrowserController::disposing( const EventObject& _rSource ) throw(RuntimeException)
627 : {
628 0 : if ( m_xView.is() && ( m_xView == _rSource.Source ) )
629 : {
630 0 : m_xView = NULL;
631 0 : m_pView = NULL;
632 : }
633 :
634 0 : for ( InterfaceArray::iterator loop = m_aInspectedObjects.begin();
635 0 : loop != m_aInspectedObjects.end();
636 : ++loop
637 : )
638 : {
639 0 : if ( *loop == _rSource.Source )
640 : {
641 0 : m_aInspectedObjects.erase( loop );
642 0 : break;
643 : }
644 : }
645 0 : }
646 :
647 : //------------------------------------------------------------------------
648 0 : IMPL_LINK_NOARG(OPropertyBrowserController, OnPageActivation)
649 : {
650 0 : updateViewDataFromActivePage();
651 0 : return 0L;
652 : }
653 :
654 : //------------------------------------------------------------------------
655 0 : void OPropertyBrowserController::updateViewDataFromActivePage()
656 : {
657 0 : if (!haveView())
658 0 : return;
659 :
660 0 : ::rtl::OUString sOldSelection = m_sPageSelection;
661 0 : m_sPageSelection = ::rtl::OUString();
662 :
663 0 : const sal_uInt16 nCurrentPage = m_pView->getActivaPage();
664 0 : if ( (sal_uInt16)-1 != nCurrentPage )
665 : {
666 0 : for ( HashString2Int16::const_iterator pageId = m_aPageIds.begin();
667 0 : pageId != m_aPageIds.end();
668 : ++pageId
669 : )
670 : {
671 0 : if ( nCurrentPage == pageId->second )
672 : {
673 0 : m_sPageSelection = pageId->first;
674 0 : break;
675 : }
676 : }
677 : }
678 :
679 0 : if ( !m_sPageSelection.isEmpty() )
680 0 : m_sLastValidPageSelection = m_sPageSelection;
681 0 : else if ( !sOldSelection.isEmpty() )
682 0 : m_sLastValidPageSelection = sOldSelection;
683 : }
684 :
685 : //------------------------------------------------------------------------
686 0 : sal_uInt16 OPropertyBrowserController::impl_getPageIdForCategory_nothrow( const ::rtl::OUString& _rCategoryName ) const
687 : {
688 0 : sal_uInt16 nPageId = (sal_uInt16)-1;
689 0 : HashString2Int16::const_iterator pagePos = m_aPageIds.find( _rCategoryName );
690 0 : if ( pagePos != m_aPageIds.end() )
691 0 : nPageId = pagePos->second;
692 0 : return nPageId;
693 : }
694 :
695 : //------------------------------------------------------------------------
696 0 : void OPropertyBrowserController::selectPageFromViewData()
697 : {
698 0 : sal_uInt16 nNewPage = impl_getPageIdForCategory_nothrow( m_sPageSelection );
699 :
700 0 : if ( haveView() && ( nNewPage != (sal_uInt16)-1 ) )
701 0 : m_pView->activatePage( nNewPage );
702 :
703 : // just in case ...
704 0 : updateViewDataFromActivePage();
705 0 : }
706 :
707 : //------------------------------------------------------------------------
708 0 : sal_Bool OPropertyBrowserController::Construct(Window* _pParentWin)
709 : {
710 : DBG_ASSERT(!haveView(), "OPropertyBrowserController::Construct: already have a view!");
711 : DBG_ASSERT(_pParentWin, "OPropertyBrowserController::Construct: invalid parent window!");
712 :
713 0 : m_pView = new OPropertyBrowserView(m_aContext.getLegacyServiceFactory(), _pParentWin);
714 0 : m_pView->setPageActivationHandler(LINK(this, OPropertyBrowserController, OnPageActivation));
715 :
716 : // add as dispose listener for our view. The view is disposed by the frame we're plugged into,
717 : // and this disposal _deletes_ the view, so it would be deadly if we use our m_pView member
718 : // after that
719 0 : m_xView = VCLUnoHelper::GetInterface(m_pView);
720 0 : Reference< XComponent > xViewAsComp(m_xView, UNO_QUERY);
721 0 : if (xViewAsComp.is())
722 0 : xViewAsComp->addEventListener( static_cast< XPropertyChangeListener* >( this ) );
723 :
724 0 : getPropertyBox().SetLineListener(this);
725 0 : getPropertyBox().SetControlObserver(this);
726 0 : impl_initializeView_nothrow();
727 :
728 0 : m_pView->Show();
729 :
730 0 : return sal_True;
731 : }
732 :
733 : //------------------------------------------------------------------------
734 0 : void SAL_CALL OPropertyBrowserController::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException)
735 : {
736 0 : if ( _rEvent.Source == m_xModel )
737 : {
738 0 : if ( _rEvent.PropertyName == "IsReadOnly" )
739 0 : impl_updateReadOnlyView_nothrow();
740 : return;
741 : }
742 :
743 0 : if ( m_sCommittingProperty == _rEvent.PropertyName )
744 : return;
745 :
746 0 : if ( !haveView() )
747 : return;
748 :
749 0 : Any aNewValue( _rEvent.NewValue );
750 0 : if ( impl_hasPropertyHandlerFor_nothrow( _rEvent.PropertyName ) )
751 : {
752 : // forward the new value to the property box, to reflect the change in the UI
753 0 : aNewValue = impl_getPropertyValue_throw( _rEvent.PropertyName );
754 :
755 : // check whether the state is ambiguous. This is interesting in case we display the properties
756 : // for multiple objects at once: In this case, we'll get a notification from one of the objects,
757 : // but need to care for the "composed" value, which can be "ambiguous".
758 0 : PropertyHandlerRef xHandler( impl_getHandlerForProperty_throw( _rEvent.PropertyName ), UNO_SET_THROW );
759 0 : PropertyState ePropertyState( xHandler->getPropertyState( _rEvent.PropertyName ) );
760 0 : bool bAmbiguousValue = ( PropertyState_AMBIGUOUS_VALUE == ePropertyState );
761 :
762 0 : getPropertyBox().SetPropertyValue( _rEvent.PropertyName, aNewValue, bAmbiguousValue );
763 : }
764 :
765 : // if it's a actuating property, then update the UI for any dependent
766 : // properties
767 0 : if ( impl_isActuatingProperty_nothrow( _rEvent.PropertyName ) )
768 0 : impl_broadcastPropertyChange_nothrow( _rEvent.PropertyName, aNewValue, _rEvent.OldValue, false );
769 : }
770 :
771 : //------------------------------------------------------------------------
772 0 : Reference< XPropertyControl > SAL_CALL OPropertyBrowserController::createPropertyControl( ::sal_Int16 ControlType, ::sal_Bool _CreateReadOnly ) throw (IllegalArgumentException, RuntimeException)
773 : {
774 0 : ::osl::MutexGuard aGuard( m_aMutex );
775 :
776 0 : Reference< XPropertyControl > xControl;
777 :
778 : // default winbits: a border only
779 0 : WinBits nWinBits = WB_BORDER;
780 :
781 : // read-only-ness
782 0 : _CreateReadOnly |= (sal_Bool)impl_isReadOnlyModel_throw();
783 0 : if ( _CreateReadOnly )
784 0 : nWinBits |= WB_READONLY;
785 :
786 0 : switch ( ControlType )
787 : {
788 : case PropertyControlType::StringListField:
789 0 : xControl = new OMultilineEditControl( &getPropertyBox(), eStringList, nWinBits | WB_DROPDOWN | WB_TABSTOP );
790 0 : break;
791 :
792 : case PropertyControlType::MultiLineTextField:
793 0 : xControl = new OMultilineEditControl( &getPropertyBox(), eMultiLineText, nWinBits | WB_DROPDOWN | WB_TABSTOP );
794 0 : break;
795 :
796 : case PropertyControlType::ListBox:
797 0 : xControl = new OListboxControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_DROPDOWN);
798 0 : break;
799 :
800 : case PropertyControlType::ComboBox:
801 0 : xControl = new OComboboxControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_DROPDOWN);
802 0 : break;
803 :
804 : case PropertyControlType::TextField:
805 0 : xControl = new OEditControl( &getPropertyBox(), sal_False, nWinBits | WB_TABSTOP );
806 0 : break;
807 :
808 : case PropertyControlType::CharacterField:
809 0 : xControl = new OEditControl( &getPropertyBox(), sal_True, nWinBits | WB_TABSTOP );
810 0 : break;
811 :
812 : case PropertyControlType::NumericField:
813 0 : xControl = new ONumericControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_SPIN | WB_REPEAT );
814 0 : break;
815 :
816 : case PropertyControlType::DateTimeField:
817 0 : xControl = new ODateTimeControl( &getPropertyBox(), nWinBits | WB_TABSTOP );
818 0 : break;
819 :
820 : case PropertyControlType::DateField:
821 0 : xControl = new ODateControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_SPIN | WB_REPEAT );
822 0 : break;
823 :
824 : case PropertyControlType::TimeField:
825 0 : xControl = new OTimeControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_SPIN | WB_REPEAT );
826 0 : break;
827 :
828 : case PropertyControlType::ColorListBox:
829 0 : xControl = new OColorControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_DROPDOWN );
830 0 : break;
831 :
832 : case PropertyControlType::HyperlinkField:
833 0 : xControl = new OHyperlinkControl( &getPropertyBox(), nWinBits | WB_TABSTOP | WB_DROPDOWN );
834 0 : break;
835 :
836 : default:
837 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
838 : }
839 :
840 0 : return xControl;
841 : }
842 :
843 : //------------------------------------------------------------------------
844 0 : void OPropertyBrowserController::impl_toggleInspecteeListening_nothrow( bool _bOn )
845 : {
846 0 : for ( InterfaceArray::const_iterator loop = m_aInspectedObjects.begin();
847 0 : loop != m_aInspectedObjects.end();
848 : ++loop
849 : )
850 : {
851 : try
852 : {
853 0 : Reference< XComponent > xComp( *loop, UNO_QUERY );
854 0 : if ( xComp.is() )
855 : {
856 0 : if ( _bOn )
857 0 : xComp->addEventListener( static_cast< XPropertyChangeListener* >( this ) );
858 : else
859 0 : xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
860 0 : }
861 : }
862 0 : catch( const Exception& )
863 : {
864 : DBG_UNHANDLED_EXCEPTION();
865 : }
866 : }
867 0 : }
868 :
869 : //------------------------------------------------------------------------
870 0 : void OPropertyBrowserController::stopInspection( bool _bCommitModified )
871 : {
872 0 : if ( haveView() )
873 : {
874 0 : if ( _bCommitModified )
875 : // commit the editor's content
876 0 : getPropertyBox().CommitModified();
877 :
878 : // hide the property box so that it does not flicker
879 0 : getPropertyBox().Hide();
880 :
881 : // clear the property box
882 0 : getPropertyBox().ClearAll();
883 : }
884 :
885 : // destroy the view first
886 0 : if ( haveView() )
887 : {
888 : // remove the pages
889 0 : for ( HashString2Int16::const_iterator erase = m_aPageIds.begin();
890 0 : erase != m_aPageIds.end();
891 : ++erase
892 : )
893 0 : getPropertyBox().RemovePage( erase->second );
894 0 : clearContainer( m_aPageIds );
895 : }
896 :
897 0 : clearContainer( m_aProperties );
898 :
899 : // de-register as dispose-listener from our inspected objects
900 0 : impl_toggleInspecteeListening_nothrow( false );
901 :
902 : // handlers are obsolete, so is our "composer" for their UI requests
903 0 : if ( m_pUIRequestComposer.get() )
904 0 : m_pUIRequestComposer->dispose();
905 0 : m_pUIRequestComposer.reset( NULL );
906 :
907 : // clean up the property handlers
908 0 : PropertyHandlerArray aAllHandlers; // will contain every handler exactly once
909 0 : for ( PropertyHandlerRepository::const_iterator aHandler = m_aPropertyHandlers.begin();
910 0 : aHandler != m_aPropertyHandlers.end();
911 : ++aHandler
912 : )
913 0 : if ( ::std::find( aAllHandlers.begin(), aAllHandlers.end(), aHandler->second ) == aAllHandlers.end() )
914 0 : aAllHandlers.push_back( aHandler->second );
915 :
916 0 : for ( PropertyHandlerArray::iterator loop = aAllHandlers.begin();
917 0 : loop != aAllHandlers.end();
918 : ++loop
919 : )
920 : {
921 : try
922 : {
923 0 : (*loop)->removePropertyChangeListener( this );
924 0 : (*loop)->dispose();
925 : }
926 0 : catch( const DisposedException& )
927 : {
928 : }
929 0 : catch( const Exception& )
930 : {
931 : DBG_UNHANDLED_EXCEPTION();
932 : }
933 : }
934 :
935 0 : clearContainer( m_aPropertyHandlers );
936 0 : clearContainer( m_aDependencyHandlers );
937 0 : }
938 :
939 : //------------------------------------------------------------------------
940 0 : bool OPropertyBrowserController::impl_hasPropertyHandlerFor_nothrow( const ::rtl::OUString& _rPropertyName ) const
941 : {
942 0 : PropertyHandlerRepository::const_iterator handlerPos = m_aPropertyHandlers.find( _rPropertyName );
943 0 : return ( handlerPos != m_aPropertyHandlers.end() );
944 : }
945 :
946 : //------------------------------------------------------------------------
947 0 : OPropertyBrowserController::PropertyHandlerRef OPropertyBrowserController::impl_getHandlerForProperty_throw( const ::rtl::OUString& _rPropertyName ) const
948 : {
949 0 : PropertyHandlerRepository::const_iterator handlerPos = m_aPropertyHandlers.find( _rPropertyName );
950 0 : if ( handlerPos == m_aPropertyHandlers.end() )
951 0 : throw RuntimeException();
952 0 : return handlerPos->second;
953 : }
954 :
955 : //------------------------------------------------------------------------
956 0 : Any OPropertyBrowserController::impl_getPropertyValue_throw( const ::rtl::OUString& _rPropertyName )
957 : {
958 0 : PropertyHandlerRef handler = impl_getHandlerForProperty_throw( _rPropertyName );
959 0 : return handler->getPropertyValue( _rPropertyName );
960 : }
961 :
962 : //------------------------------------------------------------------------
963 0 : void OPropertyBrowserController::impl_rebindToInspectee_nothrow( const InterfaceArray& _rObjects )
964 : {
965 : try
966 : {
967 : // stop inspecting the old object(s)
968 0 : stopInspection( true );
969 :
970 : // inspect the new object(s)
971 0 : m_aInspectedObjects = _rObjects;
972 0 : doInspection();
973 :
974 : // update the user interface
975 0 : UpdateUI();
976 : }
977 :
978 0 : catch(const Exception&)
979 : {
980 : OSL_FAIL("OPropertyBrowserController::impl_rebindToInspectee_nothrow: caught an exception !");
981 : }
982 0 : }
983 :
984 : //------------------------------------------------------------------------
985 0 : void OPropertyBrowserController::doInspection()
986 : {
987 : try
988 : {
989 : //////////////////////////////////////////////////////////////////////
990 : // obtain the properties of the object
991 0 : ::std::vector< Property > aProperties;
992 :
993 0 : PropertyHandlerArray aPropertyHandlers;
994 0 : getPropertyHandlers( m_aInspectedObjects, aPropertyHandlers );
995 :
996 0 : PropertyHandlerArray::iterator aHandler( aPropertyHandlers.begin() );
997 0 : while ( aHandler != aPropertyHandlers.end() )
998 : {
999 : DBG_ASSERT( aHandler->get(), "OPropertyBrowserController::doInspection: invalid handler!" );
1000 :
1001 0 : StlSyntaxSequence< Property > aThisHandlersProperties = (*aHandler)->getSupportedProperties();
1002 :
1003 0 : if ( aThisHandlersProperties.empty() )
1004 : {
1005 : // this handler doesn't know anything about the current inspectee -> ignore it
1006 0 : (*aHandler)->dispose();
1007 0 : aHandler = aPropertyHandlers.erase( aHandler );
1008 0 : continue;
1009 : }
1010 :
1011 : // append these properties to our "all properties" array
1012 0 : aProperties.reserve( aProperties.size() + aThisHandlersProperties.size() );
1013 0 : for ( StlSyntaxSequence< Property >::const_iterator copyProperty = aThisHandlersProperties.begin();
1014 0 : copyProperty != aThisHandlersProperties.end();
1015 : ++copyProperty
1016 : )
1017 : {
1018 : ::std::vector< Property >::const_iterator previous = ::std::find_if(
1019 : aProperties.begin(),
1020 : aProperties.end(),
1021 : FindPropertyByName( copyProperty->Name )
1022 0 : );
1023 0 : if ( previous == aProperties.end() )
1024 : {
1025 0 : aProperties.push_back( *copyProperty );
1026 0 : continue;
1027 : }
1028 :
1029 : // there already was another (previous) handler which supported this property.
1030 : // Don't add it to aProperties, again.
1031 :
1032 : // Also, ensure that handlers which previously expressed interest in *changes*
1033 : // of this property are not notified.
1034 : // This is 'cause we have a new handler which is responsible for this property,
1035 : // which means it can give it a completely different meaning than the previous
1036 : // handler for this property is prepared for.
1037 : ::std::pair< PropertyHandlerMultiRepository::iterator, PropertyHandlerMultiRepository::iterator >
1038 0 : aDepHandlers = m_aDependencyHandlers.equal_range( copyProperty->Name );
1039 0 : m_aDependencyHandlers.erase( aDepHandlers.first, aDepHandlers.second );
1040 : }
1041 :
1042 : // determine the superseded properties
1043 0 : StlSyntaxSequence< ::rtl::OUString > aSupersededByThisHandler = (*aHandler)->getSupersededProperties();
1044 0 : for ( StlSyntaxSequence< ::rtl::OUString >::const_iterator superseded = aSupersededByThisHandler.begin();
1045 0 : superseded != aSupersededByThisHandler.end();
1046 : ++superseded
1047 : )
1048 : {
1049 : ::std::vector< Property >::iterator existent = ::std::find_if(
1050 : aProperties.begin(),
1051 : aProperties.end(),
1052 : FindPropertyByName( *superseded )
1053 0 : );
1054 0 : if ( existent != aProperties.end() )
1055 : // one of the properties superseded by this handler was supported by a previous
1056 : // one -> erase
1057 0 : aProperties.erase( existent );
1058 : }
1059 :
1060 : // be notified of changes which this handler is responsible for
1061 0 : (*aHandler)->addPropertyChangeListener( this );
1062 :
1063 : // remember this handler for every of the properties which it is responsible
1064 : // for
1065 0 : for ( StlSyntaxSequence< Property >::const_iterator remember = aThisHandlersProperties.begin();
1066 0 : remember != aThisHandlersProperties.end();
1067 : ++remember
1068 : )
1069 : {
1070 0 : m_aPropertyHandlers[ remember->Name ] = *aHandler;
1071 : // note that this implies that if two handlers support the same property,
1072 : // the latter wins
1073 : }
1074 :
1075 : // see if the handler expresses interest in any actuating properties
1076 0 : StlSyntaxSequence< ::rtl::OUString > aInterestingActuations = (*aHandler)->getActuatingProperties();
1077 0 : for ( StlSyntaxSequence< ::rtl::OUString >::const_iterator aLoop = aInterestingActuations.begin();
1078 0 : aLoop != aInterestingActuations.end();
1079 : ++aLoop
1080 : )
1081 : {
1082 : m_aDependencyHandlers.insert( PropertyHandlerMultiRepository::value_type(
1083 0 : *aLoop, *aHandler ) );
1084 : }
1085 :
1086 0 : ++aHandler;
1087 0 : }
1088 :
1089 : // create a new composer for UI requests coming from the handlers
1090 0 : m_pUIRequestComposer.reset( new ComposedPropertyUIUpdate( getInspectorUI(), this ) );
1091 :
1092 : // sort the properties by relative position, as indicated by the model
1093 0 : for ( ::std::vector< Property >::const_iterator sourceProps = aProperties.begin();
1094 0 : sourceProps != aProperties.end();
1095 : ++sourceProps
1096 : )
1097 : {
1098 0 : sal_Int32 nRelativePropertyOrder = sourceProps - aProperties.begin();
1099 0 : if ( m_xModel.is() )
1100 0 : nRelativePropertyOrder = m_xModel->getPropertyOrderIndex( sourceProps->Name );
1101 0 : while ( m_aProperties.find( nRelativePropertyOrder ) != m_aProperties.end() )
1102 0 : ++nRelativePropertyOrder;
1103 0 : m_aProperties[ nRelativePropertyOrder ] = *sourceProps;
1104 : }
1105 :
1106 : // be notified when one of our inspectees dies
1107 0 : impl_toggleInspecteeListening_nothrow( true );
1108 : }
1109 0 : catch(const Exception&)
1110 : {
1111 : OSL_FAIL("OPropertyBrowserController::doInspection : caught an exception !");
1112 : }
1113 0 : }
1114 :
1115 : //------------------------------------------------------------------------
1116 0 : ::com::sun::star::awt::Size SAL_CALL OPropertyBrowserController::getMinimumSize() throw (::com::sun::star::uno::RuntimeException)
1117 : {
1118 0 : ::com::sun::star::awt::Size aSize;
1119 0 : if( m_pView )
1120 0 : return m_pView->getMinimumSize();
1121 : else
1122 0 : return aSize;
1123 : }
1124 :
1125 : //------------------------------------------------------------------------
1126 0 : ::com::sun::star::awt::Size SAL_CALL OPropertyBrowserController::getPreferredSize() throw (::com::sun::star::uno::RuntimeException)
1127 : {
1128 0 : return getMinimumSize();
1129 : }
1130 :
1131 : //------------------------------------------------------------------------
1132 0 : ::com::sun::star::awt::Size SAL_CALL OPropertyBrowserController::calcAdjustedSize( const ::com::sun::star::awt::Size& _rNewSize ) throw (::com::sun::star::uno::RuntimeException)
1133 : {
1134 0 : awt::Size aMinSize = getMinimumSize( );
1135 0 : awt::Size aAdjustedSize( _rNewSize );
1136 0 : if ( aAdjustedSize.Width < aMinSize.Width )
1137 0 : aAdjustedSize.Width = aMinSize.Width;
1138 0 : if ( aAdjustedSize.Height < aMinSize.Height )
1139 0 : aAdjustedSize.Height = aMinSize.Height;
1140 0 : return aAdjustedSize;
1141 : }
1142 :
1143 : //------------------------------------------------------------------------
1144 0 : void OPropertyBrowserController::describePropertyLine( const Property& _rProperty, OLineDescriptor& _rDescriptor ) SAL_THROW((Exception))
1145 : {
1146 : try
1147 : {
1148 0 : PropertyHandlerRepository::const_iterator handler = m_aPropertyHandlers.find( _rProperty.Name );
1149 0 : if ( handler == m_aPropertyHandlers.end() )
1150 0 : throw RuntimeException(); // caught below
1151 :
1152 0 : _rDescriptor.assignFrom( handler->second->describePropertyLine( _rProperty.Name, this ) );
1153 :
1154 : //////////////////////////////////////////////////////////////////////
1155 :
1156 0 : _rDescriptor.xPropertyHandler = handler->second;
1157 0 : _rDescriptor.sName = _rProperty.Name;
1158 0 : _rDescriptor.aValue = _rDescriptor.xPropertyHandler->getPropertyValue( _rProperty.Name );
1159 :
1160 0 : if ( _rDescriptor.DisplayName.isEmpty() )
1161 : {
1162 : #ifdef DBG_UTIL
1163 : ::rtl::OString sMessage( "OPropertyBrowserController::describePropertyLine: handler did not provide a display name for '" );
1164 : sMessage += ::rtl::OString( _rProperty.Name.getStr(), _rProperty.Name.getLength(), RTL_TEXTENCODING_ASCII_US );
1165 : sMessage += ::rtl::OString( "'!" );
1166 : DBG_ASSERT( !_rDescriptor.DisplayName.isEmpty(), sMessage.getStr() );
1167 : #endif
1168 0 : _rDescriptor.DisplayName = _rProperty.Name;
1169 : }
1170 :
1171 0 : PropertyState ePropertyState( _rDescriptor.xPropertyHandler->getPropertyState( _rProperty.Name ) );
1172 0 : if ( PropertyState_AMBIGUOUS_VALUE == ePropertyState )
1173 : {
1174 0 : _rDescriptor.bUnknownValue = true;
1175 0 : _rDescriptor.aValue.clear();
1176 : }
1177 :
1178 0 : _rDescriptor.bReadOnly = impl_isReadOnlyModel_throw();
1179 : }
1180 0 : catch( const Exception& )
1181 : {
1182 : OSL_FAIL( "OPropertyBrowserController::describePropertyLine: caught an exception!" );
1183 : }
1184 0 : }
1185 :
1186 : //------------------------------------------------------------------------
1187 0 : void OPropertyBrowserController::impl_buildCategories_throw()
1188 : {
1189 : OSL_PRECOND( m_aPageIds.empty(), "OPropertyBrowserController::impl_buildCategories_throw: duplicate call!" );
1190 :
1191 0 : StlSyntaxSequence< PropertyCategoryDescriptor > aCategories;
1192 0 : if ( m_xModel.is() )
1193 0 : aCategories = m_xModel->describeCategories();
1194 :
1195 0 : for ( StlSyntaxSequence< PropertyCategoryDescriptor >::const_iterator category = aCategories.begin();
1196 0 : category != aCategories.end();
1197 : ++category
1198 : )
1199 : {
1200 : OSL_ENSURE( m_aPageIds.find( category->ProgrammaticName ) == m_aPageIds.end(),
1201 : "OPropertyBrowserController::impl_buildCategories_throw: duplicate programmatic name!" );
1202 :
1203 0 : m_aPageIds[ category->ProgrammaticName ] =
1204 0 : getPropertyBox().AppendPage( category->UIName, HelpIdUrl::getHelpId( category->HelpURL ) );
1205 0 : }
1206 0 : }
1207 :
1208 : //------------------------------------------------------------------------
1209 0 : void OPropertyBrowserController::UpdateUI()
1210 : {
1211 : try
1212 : {
1213 0 : if ( !haveView() )
1214 : // too early, will return later
1215 0 : return;
1216 :
1217 0 : getPropertyBox().DisableUpdate();
1218 :
1219 0 : sal_Bool bHaveFocus = getPropertyBox().HasChildPathFocus();
1220 :
1221 : // create our tab pages
1222 0 : impl_buildCategories_throw();
1223 : // (and allow for pages to be actually unused)
1224 0 : ::std::set< sal_uInt16 > aUsedPages;
1225 :
1226 : // when building the UI below, remember which properties are actuating,
1227 : // to allow for a initial actuatinPropertyChanged call
1228 0 : ::std::vector< ::rtl::OUString > aActuatingProperties;
1229 0 : ::std::vector< Any > aActuatingPropertyValues;
1230 :
1231 : // ask the handlers to describe the property UI, and insert the resulting
1232 : // entries into our list boxes
1233 0 : OrderedPropertyMap::const_iterator property( m_aProperties.begin() );
1234 0 : for ( ; property != m_aProperties.end(); ++property )
1235 : {
1236 0 : OLineDescriptor aDescriptor;
1237 0 : describePropertyLine( property->second, aDescriptor );
1238 :
1239 0 : bool bIsActuatingProperty = impl_isActuatingProperty_nothrow( property->second.Name );
1240 :
1241 : #if OSL_DEBUG_LEVEL > 0
1242 : if ( aDescriptor.Category.isEmpty() )
1243 : {
1244 : ::rtl::OString sMessage( "OPropertyBrowserController::UpdateUI: empty category provided for property '" );
1245 : sMessage += ::rtl::OString( property->second.Name.getStr(), property->second.Name.getLength(), osl_getThreadTextEncoding() );
1246 : sMessage += "'!";
1247 : OSL_FAIL( sMessage.getStr() );
1248 : }
1249 : #endif
1250 : // finally insert this property control
1251 0 : sal_uInt16 nTargetPageId = impl_getPageIdForCategory_nothrow( aDescriptor.Category );
1252 0 : if ( nTargetPageId == (sal_uInt16)-1 )
1253 : {
1254 : // this category does not yet exist. This is allowed, as an inspector model might be lazy, and not provide
1255 : // any category information of its own. In this case, we have a fallback ...
1256 0 : m_aPageIds[ aDescriptor.Category ] =
1257 0 : getPropertyBox().AppendPage( aDescriptor.Category, rtl::OString() );
1258 0 : nTargetPageId = impl_getPageIdForCategory_nothrow( aDescriptor.Category );
1259 : }
1260 :
1261 0 : getPropertyBox().InsertEntry( aDescriptor, nTargetPageId );
1262 0 : aUsedPages.insert( nTargetPageId );
1263 :
1264 : // if it's an actuating property, remember it
1265 0 : if ( bIsActuatingProperty )
1266 : {
1267 0 : aActuatingProperties.push_back( property->second.Name );
1268 0 : aActuatingPropertyValues.push_back( impl_getPropertyValue_throw( property->second.Name ) );
1269 : }
1270 0 : }
1271 :
1272 : // update any dependencies for the actuating properties which we encountered
1273 : {
1274 0 : ::std::vector< ::rtl::OUString >::const_iterator aProperty = aActuatingProperties.begin();
1275 0 : ::std::vector< Any >::const_iterator aPropertyValue = aActuatingPropertyValues.begin();
1276 0 : for ( ; aProperty != aActuatingProperties.end(); ++aProperty, ++aPropertyValue )
1277 0 : impl_broadcastPropertyChange_nothrow( *aProperty, *aPropertyValue, *aPropertyValue, true );
1278 : }
1279 :
1280 : // remove any unused pages (which we did not encounter properties for)
1281 0 : HashString2Int16 aSurvivingPageIds;
1282 0 : for ( HashString2Int16::iterator pageId = m_aPageIds.begin();
1283 0 : pageId != m_aPageIds.end();
1284 : ++pageId
1285 : )
1286 : {
1287 0 : if ( aUsedPages.find( pageId->second ) == aUsedPages.end() )
1288 0 : getPropertyBox().RemovePage( pageId->second );
1289 : else
1290 0 : aSurvivingPageIds.insert( *pageId );
1291 : }
1292 0 : m_aPageIds.swap( aSurvivingPageIds );
1293 :
1294 :
1295 0 : getPropertyBox().Show();
1296 0 : getPropertyBox().EnableUpdate();
1297 0 : if ( bHaveFocus )
1298 0 : getPropertyBox().GrabFocus();
1299 :
1300 : // activate the first page
1301 0 : if ( !m_aPageIds.empty() )
1302 : {
1303 0 : Sequence< PropertyCategoryDescriptor > aCategories( m_xModel->describeCategories() );
1304 0 : if ( aCategories.getLength() )
1305 0 : m_pView->activatePage( m_aPageIds[ aCategories[0].ProgrammaticName ] );
1306 : else
1307 : // allowed: if we default-created the pages ...
1308 0 : m_pView->activatePage( m_aPageIds.begin()->second );
1309 : }
1310 :
1311 : // activate the previously active page (if possible)
1312 0 : if ( !m_sLastValidPageSelection.isEmpty() )
1313 0 : m_sPageSelection = m_sLastValidPageSelection;
1314 0 : selectPageFromViewData();
1315 : }
1316 0 : catch( const Exception& )
1317 : {
1318 : DBG_UNHANDLED_EXCEPTION();
1319 : }
1320 : }
1321 :
1322 : //------------------------------------------------------------------------
1323 0 : void OPropertyBrowserController::Clicked( const ::rtl::OUString& _rName, sal_Bool _bPrimary )
1324 : {
1325 : try
1326 : {
1327 : // since the browse buttons do not get the focus when clicked with the mouse,
1328 : // we need to commit the changes in the current property field
1329 0 : getPropertyBox().CommitModified();
1330 :
1331 0 : PropertyHandlerRepository::const_iterator handler = m_aPropertyHandlers.find( _rName );
1332 : DBG_ASSERT( handler != m_aPropertyHandlers.end(), "OPropertyBrowserController::Clicked: a property without handler? This will crash!" );
1333 :
1334 0 : ComposedUIAutoFireGuard aAutoFireGuard( *m_pUIRequestComposer );
1335 :
1336 0 : Any aData;
1337 0 : m_xInteractiveHandler = handler->second;
1338 : InteractiveSelectionResult eResult =
1339 0 : handler->second->onInteractivePropertySelection( _rName, _bPrimary, aData,
1340 0 : m_pUIRequestComposer->getUIForPropertyHandler( handler->second ) );
1341 :
1342 0 : switch ( eResult )
1343 : {
1344 : case InteractiveSelectionResult_Cancelled:
1345 : case InteractiveSelectionResult_Success:
1346 : // okay, nothing to do
1347 0 : break;
1348 : case InteractiveSelectionResult_ObtainedValue:
1349 0 : handler->second->setPropertyValue( _rName, aData );
1350 0 : break;
1351 : case InteractiveSelectionResult_Pending:
1352 : // also okay, we expect that the handler has disabled the UI as necessary
1353 0 : break;
1354 : default:
1355 : OSL_FAIL( "OPropertyBrowserController::Clicked: unknown result value!" );
1356 0 : break;
1357 0 : }
1358 : }
1359 0 : catch (const Exception&)
1360 : {
1361 : DBG_UNHANDLED_EXCEPTION();
1362 : }
1363 0 : m_xInteractiveHandler = NULL;
1364 0 : }
1365 :
1366 : //------------------------------------------------------------------------
1367 0 : sal_Bool SAL_CALL OPropertyBrowserController::hasPropertyByName( const ::rtl::OUString& _rName ) throw (RuntimeException)
1368 : {
1369 0 : for ( OrderedPropertyMap::const_iterator search = m_aProperties.begin();
1370 0 : search != m_aProperties.end();
1371 : ++search
1372 : )
1373 0 : if ( search->second.Name == _rName )
1374 0 : return true;
1375 0 : return false;
1376 : }
1377 :
1378 : //------------------------------------------------------------------------
1379 0 : void OPropertyBrowserController::Commit( const ::rtl::OUString& rName, const Any& _rValue )
1380 : {
1381 : try
1382 : {
1383 0 : rtl::OUString sPlcHolder = String( PcrRes( RID_EMBED_IMAGE_PLACEHOLDER ) );
1384 0 : bool bIsPlaceHolderValue = false;
1385 :
1386 0 : if ( rName.equals( PROPERTY_IMAGE_URL ) )
1387 : {
1388 : // if the prop value is the PlaceHolder
1389 : // can ignore it
1390 0 : rtl::OUString sVal;
1391 0 : _rValue >>= sVal;
1392 0 : if ( sVal.equals( sPlcHolder ) )
1393 0 : bIsPlaceHolderValue = true;
1394 : }
1395 0 : m_sCommittingProperty = rName;
1396 :
1397 0 : bool bIsActuatingProperty = impl_isActuatingProperty_nothrow( rName );
1398 :
1399 0 : Any aOldValue;
1400 0 : if ( bIsActuatingProperty )
1401 0 : aOldValue = impl_getPropertyValue_throw( rName );
1402 :
1403 : // do we have a dedicated handler for this property, which we can delegate some tasks to?
1404 0 : PropertyHandlerRef handler = impl_getHandlerForProperty_throw( rName );
1405 :
1406 : //////////////////////////////////////////////////////////////////////
1407 : // set the value ( only if it's not a placeholder )
1408 0 : if ( !bIsPlaceHolderValue )
1409 0 : handler->setPropertyValue( rName, _rValue );
1410 :
1411 : //////////////////////////////////////////////////////////////////////
1412 : // re-retrieve the value
1413 0 : Any aNormalizedValue = handler->getPropertyValue( rName );
1414 :
1415 : // care for any inter-property dependencies
1416 0 : if ( bIsActuatingProperty )
1417 0 : impl_broadcastPropertyChange_nothrow( rName, aNormalizedValue, aOldValue, false );
1418 :
1419 : // and display it again. This ensures proper formatting
1420 0 : getPropertyBox().SetPropertyValue( rName, aNormalizedValue, false );
1421 : }
1422 0 : catch(const PropertyVetoException& eVetoException)
1423 : {
1424 0 : InfoBox(m_pView, eVetoException.Message).Execute();
1425 0 : PropertyHandlerRef handler = impl_getHandlerForProperty_throw( rName );
1426 0 : Any aNormalizedValue = handler->getPropertyValue( rName );
1427 0 : getPropertyBox().SetPropertyValue( rName, aNormalizedValue, false );
1428 : }
1429 0 : catch(const Exception&)
1430 : {
1431 : OSL_FAIL("OPropertyBrowserController::Commit : caught an exception !");
1432 : }
1433 :
1434 0 : m_sCommittingProperty = ::rtl::OUString();
1435 0 : }
1436 :
1437 : //--------------------------------------------------------------------
1438 : namespace
1439 : {
1440 : }
1441 :
1442 : //--------------------------------------------------------------------
1443 0 : void OPropertyBrowserController::focusGained( const Reference< XPropertyControl >& _Control )
1444 : {
1445 0 : m_aControlObservers.notifyEach( &XPropertyControlObserver::focusGained, _Control );
1446 0 : }
1447 :
1448 : //--------------------------------------------------------------------
1449 0 : void OPropertyBrowserController::valueChanged( const Reference< XPropertyControl >& _Control )
1450 : {
1451 0 : m_aControlObservers.notifyEach( &XPropertyControlObserver::valueChanged, _Control );
1452 0 : }
1453 :
1454 : //------------------------------------------------------------------------
1455 : namespace
1456 : {
1457 0 : Reference< XPropertyHandler > lcl_createHandler( const ComponentContext& _rContext, const Any& _rFactoryDescriptor )
1458 : {
1459 0 : Reference< XPropertyHandler > xHandler;
1460 :
1461 0 : ::rtl::OUString sServiceName;
1462 0 : Reference< XSingleServiceFactory > xServiceFac;
1463 0 : Reference< XSingleComponentFactory > xComponentFac;
1464 :
1465 0 : if ( _rFactoryDescriptor >>= sServiceName )
1466 0 : _rContext.createComponent( sServiceName, xHandler );
1467 0 : else if ( _rFactoryDescriptor >>= xServiceFac )
1468 0 : xHandler = xHandler.query( xServiceFac->createInstance() );
1469 0 : else if ( _rFactoryDescriptor >>= xComponentFac )
1470 0 : xHandler = xHandler.query( xComponentFac->createInstanceWithContext( _rContext.getUNOContext() ) );
1471 : OSL_ENSURE(xHandler.is(),"lcl_createHandler: Can not create handler");
1472 0 : return xHandler;
1473 : }
1474 : }
1475 :
1476 : //------------------------------------------------------------------------
1477 0 : void OPropertyBrowserController::getPropertyHandlers( const InterfaceArray& _rObjects, PropertyHandlerArray& _rHandlers )
1478 : {
1479 0 : _rHandlers.resize( 0 );
1480 0 : if ( _rObjects.empty() )
1481 0 : return;
1482 :
1483 : // create a component context for the handlers, containing some information about where
1484 : // they live
1485 0 : Reference< XComponentContext > xHandlerContext( m_aContext.getUNOContext() );
1486 :
1487 : // if our own creator did not pass a dialog parent window, use our own view for this
1488 0 : Reference< XWindow > xParentWindow( m_aContext.getContextValueByAsciiName( "DialogParentWindow" ), UNO_QUERY );
1489 0 : if ( !xParentWindow.is() )
1490 : {
1491 : ::cppu::ContextEntry_Init aHandlerContextInfo[] =
1492 : {
1493 : ::cppu::ContextEntry_Init( ::rtl::OUString( "DialogParentWindow" ), makeAny( VCLUnoHelper::GetInterface( m_pView ) ) )
1494 0 : };
1495 : xHandlerContext = ::cppu::createComponentContext(
1496 : aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ),
1497 0 : m_aContext.getUNOContext() );
1498 : }
1499 :
1500 0 : Sequence< Any > aHandlerFactories;
1501 0 : if ( m_xModel.is() )
1502 0 : aHandlerFactories = m_xModel->getHandlerFactories();
1503 :
1504 0 : const Any* pHandlerFactory = aHandlerFactories.getConstArray();
1505 0 : const Any* pHandlerFactoryEnd = aHandlerFactories.getConstArray() + aHandlerFactories.getLength();
1506 :
1507 0 : while ( pHandlerFactory != pHandlerFactoryEnd )
1508 : {
1509 0 : if ( _rObjects.size() == 1 )
1510 : { // we're inspecting only one object -> one handler
1511 0 : Reference< XPropertyHandler > xHandler( lcl_createHandler( m_aContext, *pHandlerFactory ) );
1512 0 : if ( xHandler.is() )
1513 : {
1514 0 : xHandler->inspect( _rObjects[0] );
1515 0 : _rHandlers.push_back( xHandler );
1516 0 : }
1517 : }
1518 : else
1519 : {
1520 : // create a single handler for every single object
1521 0 : ::std::vector< Reference< XPropertyHandler > > aSingleHandlers( _rObjects.size() );
1522 0 : ::std::vector< Reference< XPropertyHandler > >::iterator pHandler = aSingleHandlers.begin();
1523 :
1524 0 : InterfaceArray::const_iterator pObject = _rObjects.begin();
1525 0 : InterfaceArray::const_iterator pObjectEnd = _rObjects.end();
1526 :
1527 0 : for ( ; pObject != pObjectEnd; ++pObject )
1528 : {
1529 0 : *pHandler = lcl_createHandler( m_aContext, *pHandlerFactory );
1530 0 : if ( pHandler->is() )
1531 : {
1532 0 : (*pHandler)->inspect( *pObject );
1533 0 : ++pHandler;
1534 : }
1535 : }
1536 0 : aSingleHandlers.resize( pHandler - aSingleHandlers.begin() );
1537 :
1538 : // then create a handler which composes information out of those single handlers
1539 0 : if ( !aSingleHandlers.empty() )
1540 0 : _rHandlers.push_back( new PropertyComposer( aSingleHandlers ) );
1541 : }
1542 :
1543 0 : ++pHandlerFactory;
1544 0 : }
1545 :
1546 : // note that the handlers will not be used by our caller, if they indicate that there are no
1547 : // properties they feel responsible for
1548 : }
1549 :
1550 : //------------------------------------------------------------------------
1551 0 : bool OPropertyBrowserController::impl_findObjectProperty_nothrow( const ::rtl::OUString& _rName, OrderedPropertyMap::const_iterator* _pProperty )
1552 : {
1553 0 : OrderedPropertyMap::const_iterator search = m_aProperties.begin();
1554 0 : for ( ; search != m_aProperties.end(); ++search )
1555 0 : if ( search->second.Name == _rName )
1556 0 : break;
1557 0 : if ( _pProperty )
1558 0 : *_pProperty = search;
1559 0 : return ( search != m_aProperties.end() );
1560 : }
1561 :
1562 : //------------------------------------------------------------------------
1563 0 : void OPropertyBrowserController::rebuildPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
1564 : {
1565 0 : ::osl::MutexGuard aGuard( m_aMutex );
1566 0 : if ( !haveView() )
1567 0 : throw RuntimeException();
1568 :
1569 0 : OrderedPropertyMap::const_iterator propertyPos;
1570 0 : if ( !impl_findObjectProperty_nothrow( _rPropertyName, &propertyPos ) )
1571 0 : return;
1572 :
1573 0 : OLineDescriptor aDescriptor;
1574 : try
1575 : {
1576 0 : describePropertyLine( propertyPos->second, aDescriptor );
1577 : }
1578 0 : catch( const Exception& )
1579 : {
1580 : OSL_FAIL( "OPropertyBrowserController::rebuildPropertyUI: caught an exception!" );
1581 : }
1582 :
1583 0 : getPropertyBox().ChangeEntry( aDescriptor );
1584 : }
1585 :
1586 : //------------------------------------------------------------------------
1587 0 : void OPropertyBrowserController::enablePropertyUI( const ::rtl::OUString& _rPropertyName, sal_Bool _bEnable ) throw (RuntimeException)
1588 : {
1589 0 : ::osl::MutexGuard aGuard( m_aMutex );
1590 0 : if ( !haveView() )
1591 0 : throw RuntimeException();
1592 :
1593 0 : if ( !impl_findObjectProperty_nothrow( _rPropertyName ) )
1594 0 : return;
1595 :
1596 0 : getPropertyBox().EnablePropertyLine( _rPropertyName, _bEnable );
1597 : }
1598 :
1599 : //------------------------------------------------------------------------
1600 0 : void OPropertyBrowserController::enablePropertyUIElements( const ::rtl::OUString& _rPropertyName, sal_Int16 _nElements, sal_Bool _bEnable ) throw (RuntimeException)
1601 : {
1602 0 : ::osl::MutexGuard aGuard( m_aMutex );
1603 0 : if ( !haveView() )
1604 0 : throw RuntimeException();
1605 :
1606 0 : if ( !impl_findObjectProperty_nothrow( _rPropertyName ) )
1607 0 : return;
1608 :
1609 0 : getPropertyBox().EnablePropertyControls( _rPropertyName, _nElements, _bEnable );
1610 : }
1611 :
1612 : //------------------------------------------------------------------------
1613 0 : void OPropertyBrowserController::showPropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
1614 : {
1615 0 : ::osl::MutexGuard aGuard( m_aMutex );
1616 0 : if ( !haveView() )
1617 0 : throw RuntimeException();
1618 :
1619 : // look up the property in our object properties
1620 0 : OrderedPropertyMap::const_iterator propertyPos;
1621 0 : if ( !impl_findObjectProperty_nothrow( _rPropertyName, &propertyPos ) )
1622 : return;
1623 :
1624 0 : if ( getPropertyBox().GetPropertyPos( _rPropertyName ) != LISTBOX_ENTRY_NOTFOUND )
1625 : {
1626 0 : rebuildPropertyUI( _rPropertyName );
1627 : return;
1628 : }
1629 :
1630 0 : OLineDescriptor aDescriptor;
1631 0 : describePropertyLine( propertyPos->second, aDescriptor );
1632 :
1633 : // look for the position to insert the property
1634 :
1635 : // side note: The methods GetPropertyPos and InsertEntry of the OPropertyEditor work
1636 : // only on the current page. This implies that it's impossible to use this method here
1637 : // to show property lines which are *not* on the current page.
1638 : // This is sufficient for now, but should be changed in the future.
1639 :
1640 : // by definition, the properties in m_aProperties are in the order in which they appear in the UI
1641 : // So all we need is a predecessor of pProperty in m_aProperties
1642 0 : sal_uInt16 nUIPos = LISTBOX_ENTRY_NOTFOUND;
1643 0 : do
1644 : {
1645 0 : if ( propertyPos != m_aProperties.begin() )
1646 0 : --propertyPos;
1647 0 : nUIPos = getPropertyBox().GetPropertyPos( propertyPos->second.Name );
1648 : }
1649 0 : while ( ( nUIPos == LISTBOX_ENTRY_NOTFOUND ) && ( propertyPos != m_aProperties.begin() ) );
1650 :
1651 0 : if ( nUIPos == LISTBOX_ENTRY_NOTFOUND )
1652 : // insert at the very top
1653 0 : nUIPos = 0;
1654 : else
1655 : // insert right after the predecessor we found
1656 0 : ++nUIPos;
1657 :
1658 0 : getPropertyBox().InsertEntry(
1659 0 : aDescriptor, impl_getPageIdForCategory_nothrow( aDescriptor.Category ), nUIPos );
1660 : }
1661 :
1662 : //------------------------------------------------------------------------
1663 0 : void OPropertyBrowserController::hidePropertyUI( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
1664 : {
1665 0 : ::osl::MutexGuard aGuard( m_aMutex );
1666 0 : if ( !haveView() )
1667 0 : throw RuntimeException();
1668 :
1669 0 : if ( !impl_findObjectProperty_nothrow( _rPropertyName ) )
1670 0 : return;
1671 :
1672 0 : getPropertyBox().RemoveEntry( _rPropertyName );
1673 : }
1674 :
1675 : //------------------------------------------------------------------------
1676 0 : void OPropertyBrowserController::showCategory( const ::rtl::OUString& _rCategory, sal_Bool _bShow ) throw (RuntimeException)
1677 : {
1678 0 : ::osl::MutexGuard aGuard( m_aMutex );
1679 0 : if ( !haveView() )
1680 0 : throw RuntimeException();
1681 :
1682 0 : sal_uInt16 nPageId = impl_getPageIdForCategory_nothrow( _rCategory );
1683 : OSL_ENSURE( nPageId != (sal_uInt16)-1, "OPropertyBrowserController::showCategory: invalid category!" );
1684 :
1685 0 : getPropertyBox().ShowPropertyPage( nPageId, _bShow );
1686 0 : }
1687 :
1688 : //------------------------------------------------------------------------
1689 0 : Reference< XPropertyControl > SAL_CALL OPropertyBrowserController::getPropertyControl( const ::rtl::OUString& _rPropertyName ) throw (RuntimeException)
1690 : {
1691 0 : ::osl::MutexGuard aGuard( m_aMutex );
1692 0 : if ( !haveView() )
1693 0 : throw RuntimeException();
1694 :
1695 0 : Reference< XPropertyControl > xControl( getPropertyBox().GetPropertyControl( _rPropertyName ) );
1696 0 : return xControl;
1697 : }
1698 :
1699 : //--------------------------------------------------------------------
1700 0 : void SAL_CALL OPropertyBrowserController::registerControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException)
1701 : {
1702 0 : m_aControlObservers.addInterface( _Observer );
1703 0 : }
1704 :
1705 : //--------------------------------------------------------------------
1706 0 : void SAL_CALL OPropertyBrowserController::revokeControlObserver( const Reference< XPropertyControlObserver >& _Observer ) throw (RuntimeException)
1707 : {
1708 0 : m_aControlObservers.removeInterface( _Observer );
1709 0 : }
1710 :
1711 : //------------------------------------------------------------------------
1712 0 : void SAL_CALL OPropertyBrowserController::setHelpSectionText( const ::rtl::OUString& _rHelpText ) throw (NoSupportException, RuntimeException)
1713 : {
1714 0 : SolarMutexGuard aSolarGuard;
1715 0 : ::osl::MutexGuard aGuard( m_aMutex );
1716 :
1717 0 : if ( !haveView() )
1718 0 : throw DisposedException();
1719 :
1720 0 : if ( !getPropertyBox().HasHelpSection() )
1721 0 : throw NoSupportException();
1722 :
1723 0 : getPropertyBox().SetHelpText( _rHelpText );
1724 0 : }
1725 :
1726 : //------------------------------------------------------------------------
1727 0 : void OPropertyBrowserController::impl_broadcastPropertyChange_nothrow( const ::rtl::OUString& _rPropertyName, const Any& _rNewValue, const Any& _rOldValue, bool _bFirstTimeInit ) const
1728 : {
1729 : // are there one or more handlers which are interested in the actuation?
1730 : ::std::pair< PropertyHandlerMultiRepository::const_iterator, PropertyHandlerMultiRepository::const_iterator > aInterestedHandlers =
1731 0 : m_aDependencyHandlers.equal_range( _rPropertyName );
1732 0 : if ( aInterestedHandlers.first == aInterestedHandlers.second )
1733 : // none of our handlers is interested in this
1734 0 : return;
1735 :
1736 0 : ComposedUIAutoFireGuard aAutoFireGuard( *m_pUIRequestComposer );
1737 : try
1738 : {
1739 : // collect the responses from all interested handlers
1740 0 : PropertyHandlerMultiRepository::const_iterator handler = aInterestedHandlers.first;
1741 0 : while ( handler != aInterestedHandlers.second )
1742 : {
1743 0 : handler->second->actuatingPropertyChanged( _rPropertyName, _rNewValue, _rOldValue,
1744 0 : m_pUIRequestComposer->getUIForPropertyHandler( handler->second ),
1745 0 : _bFirstTimeInit );
1746 0 : ++handler;
1747 : }
1748 : }
1749 0 : catch( const Exception& )
1750 : {
1751 : DBG_UNHANDLED_EXCEPTION();
1752 0 : }
1753 : }
1754 :
1755 : //............................................................................
1756 : } // namespace pcr
1757 : //............................................................................
1758 :
1759 :
1760 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|