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