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 <svx/dialmgr.hxx>
21 : #include <svx/fmshell.hxx>
22 : #include <svx/fmmodel.hxx>
23 : #include <svx/fmpage.hxx>
24 : #include <svx/fmglob.hxx>
25 : #include "svx/svditer.hxx"
26 : #include <svx/svdogrp.hxx>
27 : #include <svx/svdpagv.hxx>
28 :
29 : #include "fmprop.hrc"
30 :
31 : #include "fmundo.hxx"
32 : #include "fmhelp.hrc"
33 : #include "fmexpl.hrc"
34 : #include "fmexpl.hxx"
35 : #include "svx/fmresids.hrc"
36 : #include "fmshimp.hxx"
37 : #include "fmobj.hxx"
38 : #include <sfx2/objsh.hxx>
39 : #include <tools/diagnose_ex.h>
40 : #include <com/sun/star/container/XContainer.hpp>
41 :
42 :
43 : namespace svxform
44 : {
45 :
46 :
47 : using namespace ::com::sun::star::uno;
48 : using namespace ::com::sun::star::lang;
49 : using namespace ::com::sun::star::beans;
50 : using namespace ::com::sun::star::form;
51 : using namespace ::com::sun::star::awt;
52 : using namespace ::com::sun::star::container;
53 : using namespace ::com::sun::star::script;
54 : using namespace ::com::sun::star::sdb;
55 :
56 :
57 : // class OFormComponentObserver
58 :
59 :
60 0 : OFormComponentObserver::OFormComponentObserver(NavigatorTreeModel* _pModel)
61 : :m_pNavModel(_pModel)
62 : ,m_nLocks(0)
63 0 : ,m_bCanUndo(sal_True)
64 : {
65 0 : }
66 :
67 : // XPropertyChangeListener
68 :
69 0 : void SAL_CALL OFormComponentObserver::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
70 : {
71 0 : Remove( Source.Source );
72 0 : }
73 :
74 :
75 0 : void SAL_CALL OFormComponentObserver::propertyChange(const PropertyChangeEvent& evt) throw(RuntimeException, std::exception)
76 : {
77 0 : if( !m_pNavModel ) return;
78 0 : if( evt.PropertyName != FM_PROP_NAME ) return;
79 :
80 0 : Reference< XFormComponent > xFormComponent(evt.Source, UNO_QUERY);
81 0 : Reference< XForm > xForm(evt.Source, UNO_QUERY);
82 :
83 0 : FmEntryData* pEntryData( NULL );
84 0 : if( xForm.is() )
85 0 : pEntryData = m_pNavModel->FindData( xForm, m_pNavModel->GetRootList() );
86 0 : else if( xFormComponent.is() )
87 0 : pEntryData = m_pNavModel->FindData( xFormComponent, m_pNavModel->GetRootList() );
88 :
89 0 : if( pEntryData )
90 : {
91 0 : OUString aNewName = ::comphelper::getString(evt.NewValue);
92 0 : pEntryData->SetText( aNewName );
93 0 : FmNavNameChangedHint aNameChangedHint( pEntryData, aNewName );
94 0 : m_pNavModel->Broadcast( aNameChangedHint );
95 0 : }
96 : }
97 :
98 : // XContainerListener
99 :
100 0 : void SAL_CALL OFormComponentObserver::elementInserted(const ContainerEvent& evt) throw(RuntimeException, std::exception)
101 : {
102 0 : if (IsLocked() || !m_pNavModel)
103 0 : return;
104 :
105 : // keine Undoaction einfuegen
106 0 : m_bCanUndo = sal_False;
107 :
108 0 : Reference< XInterface > xTemp;
109 0 : evt.Element >>= xTemp;
110 0 : Insert(xTemp, ::comphelper::getINT32(evt.Accessor));
111 :
112 0 : m_bCanUndo = sal_True;
113 : }
114 :
115 :
116 0 : void OFormComponentObserver::Insert(const Reference< XInterface > & xIface, sal_Int32 nIndex)
117 : {
118 0 : Reference< XForm > xForm(xIface, UNO_QUERY);
119 0 : if (xForm.is())
120 : {
121 0 : m_pNavModel->InsertForm(xForm, sal_uInt32(nIndex));
122 0 : Reference< XIndexContainer > xContainer(xForm, UNO_QUERY);
123 0 : Reference< XInterface > xTemp;
124 0 : for (sal_Int32 i = 0; i < xContainer->getCount(); i++)
125 : {
126 0 : xContainer->getByIndex(i) >>= xTemp;
127 0 : Insert(xTemp, i);
128 0 : }
129 : }
130 : else
131 : {
132 0 : Reference< XFormComponent > xFormComp(xIface, UNO_QUERY);
133 0 : if (xFormComp.is())
134 0 : m_pNavModel->InsertFormComponent(xFormComp, sal_uInt32(nIndex));
135 0 : }
136 0 : }
137 :
138 :
139 0 : void SAL_CALL OFormComponentObserver::elementReplaced(const ContainerEvent& evt) throw(RuntimeException, std::exception)
140 : {
141 0 : if (IsLocked() || !m_pNavModel)
142 0 : return;
143 :
144 0 : m_bCanUndo = sal_False;
145 :
146 : // EntryData loeschen
147 0 : Reference< XFormComponent > xReplaced;
148 0 : evt.ReplacedElement >>= xReplaced;
149 0 : FmEntryData* pEntryData = m_pNavModel->FindData(xReplaced, m_pNavModel->GetRootList(), sal_True);
150 0 : if (pEntryData)
151 : {
152 0 : if (pEntryData->ISA(FmControlData))
153 : {
154 0 : Reference< XFormComponent > xComp;
155 0 : evt.Element >>= xComp;
156 : DBG_ASSERT(xComp.is(), "OFormComponentObserver::elementReplaced : invalid argument !");
157 : // an einer FmControlData sollte eine XFormComponent haengen
158 0 : m_pNavModel->ReplaceFormComponent(xReplaced, xComp);
159 : }
160 0 : else if (pEntryData->ISA(FmFormData))
161 : {
162 : OSL_FAIL("replacing forms not implemented yet !");
163 : }
164 : }
165 :
166 0 : m_bCanUndo = sal_True;
167 : }
168 :
169 :
170 0 : void OFormComponentObserver::Remove( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement )
171 : {
172 0 : if (IsLocked() || !m_pNavModel)
173 0 : return;
174 :
175 0 : m_bCanUndo = sal_False;
176 :
177 :
178 : // EntryData loeschen
179 0 : FmEntryData* pEntryData = m_pNavModel->FindData( _rxElement, m_pNavModel->GetRootList(), sal_True );
180 0 : if (pEntryData)
181 0 : m_pNavModel->Remove(pEntryData);
182 :
183 0 : m_bCanUndo = sal_True;
184 : }
185 :
186 :
187 0 : void SAL_CALL OFormComponentObserver::elementRemoved(const ContainerEvent& evt) throw(RuntimeException, std::exception)
188 : {
189 0 : Reference< XInterface > xElement;
190 0 : evt.Element >>= xElement;
191 0 : Remove( xElement );
192 0 : }
193 :
194 :
195 : // class NavigatorTreeModel
196 :
197 :
198 :
199 0 : NavigatorTreeModel::NavigatorTreeModel( const ImageList& _rNormalImages )
200 : :m_pFormShell(NULL)
201 : ,m_pFormPage(NULL)
202 : ,m_pFormModel(NULL)
203 0 : ,m_aNormalImages( _rNormalImages )
204 : {
205 0 : m_pPropChangeList = new OFormComponentObserver(this);
206 0 : m_pPropChangeList->acquire();
207 0 : m_pRootList = new FmEntryDataList();
208 0 : }
209 :
210 :
211 0 : NavigatorTreeModel::~NavigatorTreeModel()
212 : {
213 :
214 : // Als Listener abmelden
215 0 : if( m_pFormShell)
216 : {
217 0 : FmFormModel* pFormModel = m_pFormShell->GetFormModel();
218 0 : if( pFormModel && IsListening(*pFormModel))
219 0 : EndListening( *pFormModel );
220 :
221 0 : if (IsListening(*m_pFormShell))
222 0 : EndListening(*m_pFormShell);
223 : }
224 :
225 0 : Clear();
226 0 : delete m_pRootList;
227 0 : m_pPropChangeList->ReleaseModel();
228 0 : m_pPropChangeList->release();
229 0 : }
230 :
231 :
232 :
233 0 : void NavigatorTreeModel::SetModified( sal_Bool bMod )
234 : {
235 0 : if( !m_pFormShell ) return;
236 0 : SfxObjectShell* pObjShell = m_pFormShell->GetFormModel()->GetObjectShell();
237 0 : if( !pObjShell ) return;
238 0 : pObjShell->SetModified( bMod );
239 : }
240 :
241 :
242 0 : void NavigatorTreeModel::Clear()
243 : {
244 0 : Reference< css::form::XForms > xForms( GetForms());
245 0 : if(xForms.is())
246 0 : xForms->removeContainerListener((XContainerListener*)m_pPropChangeList);
247 :
248 :
249 : // RootList loeschen
250 0 : GetRootList()->clear();
251 :
252 :
253 : // UI benachrichtigen
254 0 : FmNavClearedHint aClearedHint;
255 0 : Broadcast( aClearedHint );
256 0 : }
257 :
258 :
259 0 : Reference< css::form::XForms > NavigatorTreeModel::GetForms() const
260 : {
261 0 : if( !m_pFormShell || !m_pFormShell->GetCurPage())
262 0 : return NULL;
263 : else
264 0 : return m_pFormShell->GetCurPage()->GetForms();
265 : }
266 :
267 :
268 0 : void NavigatorTreeModel::Insert(FmEntryData* pEntry, sal_uLong nRelPos, sal_Bool bAlterModel)
269 : {
270 0 : if (IsListening(*m_pFormModel))
271 0 : EndListening(*m_pFormModel);
272 :
273 0 : m_pPropChangeList->Lock();
274 0 : FmFormData* pFolder = (FmFormData*) pEntry->GetParent();
275 0 : Reference< XChild > xElement( pEntry->GetChildIFace() );
276 0 : if (bAlterModel)
277 : {
278 0 : OUString aStr;
279 0 : if (pEntry->ISA(FmFormData))
280 0 : aStr = SVX_RESSTR(RID_STR_FORM);
281 : else
282 0 : aStr = SVX_RESSTR(RID_STR_CONTROL);
283 :
284 0 : Reference< XIndexContainer > xContainer;
285 0 : if (pFolder)
286 0 : xContainer = Reference< XIndexContainer > (pFolder->GetFormIface(), UNO_QUERY);
287 : else
288 0 : xContainer = Reference< XIndexContainer > (GetForms(), UNO_QUERY);
289 :
290 0 : bool bUndo = m_pFormModel->IsUndoEnabled();
291 :
292 0 : if( bUndo )
293 : {
294 0 : OUString aUndoStr(SVX_RESSTR(RID_STR_UNDO_CONTAINER_INSERT));
295 0 : aUndoStr = aUndoStr.replaceFirst("#", aStr);
296 0 : m_pFormModel->BegUndo(aUndoStr);
297 : }
298 :
299 0 : if (nRelPos >= (sal_uInt32)xContainer->getCount())
300 0 : nRelPos = (sal_uInt32)xContainer->getCount();
301 :
302 : // UndoAction
303 0 : if ( bUndo && m_pPropChangeList->CanUndo())
304 : {
305 : m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
306 : FmUndoContainerAction::Inserted,
307 : xContainer,
308 : xElement,
309 0 : nRelPos));
310 : }
311 :
312 : // das Element muss den Typ haben, den der Container erwartet
313 0 : if (xContainer->getElementType() ==
314 0 : ::getCppuType((const Reference< XForm>*)0))
315 :
316 : {
317 0 : Reference< XForm > xElementAsForm(xElement, UNO_QUERY);
318 0 : xContainer->insertByIndex(nRelPos, makeAny(xElementAsForm));
319 : }
320 0 : else if (xContainer->getElementType() ==
321 0 : ::getCppuType((const Reference< XFormComponent>*)0))
322 :
323 : {
324 0 : Reference< XFormComponent > xElementAsComponent(xElement, UNO_QUERY);
325 0 : xContainer->insertByIndex(nRelPos, makeAny(xElementAsComponent));
326 : }
327 : else
328 : {
329 : OSL_FAIL("NavigatorTreeModel::Insert : the parent container needs an elementtype I don't know !");
330 : }
331 :
332 0 : if( bUndo )
333 0 : m_pFormModel->EndUndo();
334 : }
335 :
336 :
337 : // Als PropertyChangeListener anmelden
338 0 : Reference< XPropertySet > xSet(xElement, UNO_QUERY);
339 0 : if( xSet.is() )
340 0 : xSet->addPropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
341 :
342 :
343 : // Daten aus Model entfernen
344 0 : if (pEntry->ISA(FmFormData))
345 : {
346 0 : Reference< XContainer > xContainer(xElement, UNO_QUERY);
347 0 : if (xContainer.is())
348 0 : xContainer->addContainerListener((XContainerListener*)m_pPropChangeList);
349 : }
350 :
351 0 : if (pFolder)
352 0 : pFolder->GetChildList()->insert( pEntry, nRelPos );
353 : else
354 0 : GetRootList()->insert( pEntry, nRelPos );
355 :
356 :
357 : // UI benachrichtigen
358 0 : FmNavInsertedHint aInsertedHint( pEntry, nRelPos );
359 0 : Broadcast( aInsertedHint );
360 :
361 0 : m_pPropChangeList->UnLock();
362 0 : if (IsListening(*m_pFormModel))
363 0 : StartListening(*m_pFormModel);
364 0 : }
365 :
366 :
367 0 : void NavigatorTreeModel::Remove(FmEntryData* pEntry, sal_Bool bAlterModel)
368 : {
369 :
370 : // Form und Parent holen
371 0 : if (!pEntry || !m_pFormModel)
372 0 : return;
373 :
374 0 : if (IsListening(*m_pFormModel))
375 0 : EndListening(*m_pFormModel);
376 :
377 0 : const bool bUndo = m_pFormModel->IsUndoEnabled();
378 :
379 0 : m_pPropChangeList->Lock();
380 0 : FmFormData* pFolder = (FmFormData*) pEntry->GetParent();
381 0 : Reference< XChild > xElement ( pEntry->GetChildIFace() );
382 0 : if (bAlterModel)
383 : {
384 0 : OUString aStr;
385 0 : if (pEntry->ISA(FmFormData))
386 0 : aStr = SVX_RESSTR(RID_STR_FORM);
387 : else
388 0 : aStr = SVX_RESSTR(RID_STR_CONTROL);
389 :
390 0 : if( bUndo )
391 : {
392 0 : OUString aUndoStr(SVX_RESSTR(RID_STR_UNDO_CONTAINER_REMOVE));
393 0 : aUndoStr = aUndoStr.replaceFirst("#", aStr);
394 0 : m_pFormModel->BegUndo(aUndoStr);
395 0 : }
396 : }
397 :
398 : // jetzt die eigentliche Entfernung der Daten aus dem Model
399 0 : if (pEntry->ISA(FmFormData))
400 0 : RemoveForm((FmFormData*)pEntry);
401 : else
402 0 : RemoveFormComponent((FmControlData*)pEntry);
403 :
404 :
405 0 : if (bAlterModel)
406 : {
407 0 : Reference< XIndexContainer > xContainer(xElement->getParent(), UNO_QUERY);
408 : // aus dem Container entfernen
409 0 : sal_Int32 nContainerIndex = getElementPos(xContainer.get(), xElement);
410 : // UndoAction
411 0 : if (nContainerIndex >= 0)
412 : {
413 0 : if ( bUndo && m_pPropChangeList->CanUndo())
414 : {
415 : m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel,
416 : FmUndoContainerAction::Removed,
417 : xContainer,
418 0 : xElement, nContainerIndex ));
419 : }
420 0 : else if( !m_pPropChangeList->CanUndo() )
421 : {
422 0 : FmUndoContainerAction::DisposeElement( xElement );
423 : }
424 :
425 0 : xContainer->removeByIndex(nContainerIndex );
426 : }
427 :
428 0 : if( bUndo )
429 0 : m_pFormModel->EndUndo();
430 : }
431 :
432 : // beim Vater austragen
433 0 : if (pFolder)
434 0 : pFolder->GetChildList()->remove( pEntry );
435 : else
436 : {
437 0 : GetRootList()->remove( pEntry );
438 :
439 : // Wenn keine Form mehr in der Root, an der Shell CurForm zuruecksetzen
440 0 : if ( !GetRootList()->size() )
441 0 : m_pFormShell->GetImpl()->forgetCurrentForm();
442 : }
443 :
444 :
445 : // UI benachrichtigen
446 0 : FmNavRemovedHint aRemovedHint( pEntry );
447 0 : Broadcast( aRemovedHint );
448 :
449 : // Eintrag loeschen
450 0 : delete pEntry;
451 :
452 0 : m_pPropChangeList->UnLock();
453 0 : StartListening(*m_pFormModel);
454 : }
455 :
456 :
457 0 : void NavigatorTreeModel::RemoveForm(FmFormData* pFormData)
458 : {
459 :
460 : // Form und Parent holen
461 0 : if (!pFormData || !m_pFormModel)
462 0 : return;
463 :
464 0 : FmEntryDataList* pChildList = pFormData->GetChildList();
465 0 : for ( size_t i = pChildList->size(); i > 0; )
466 : {
467 0 : FmEntryData* pEntryData = pChildList->at( --i );
468 :
469 :
470 : // Child ist Form -> rekursiver Aufruf
471 0 : if( pEntryData->ISA(FmFormData) )
472 0 : RemoveForm( (FmFormData*)pEntryData);
473 0 : else if( pEntryData->ISA(FmControlData) )
474 0 : RemoveFormComponent((FmControlData*) pEntryData);
475 : }
476 :
477 :
478 : // Als PropertyChangeListener abmelden
479 0 : Reference< XPropertySet > xSet( pFormData->GetPropertySet() );
480 0 : if ( xSet.is() )
481 0 : xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList );
482 :
483 0 : Reference< XContainer > xContainer( pFormData->GetContainer() );
484 0 : if (xContainer.is())
485 0 : xContainer->removeContainerListener((XContainerListener*)m_pPropChangeList);
486 : }
487 :
488 :
489 0 : void NavigatorTreeModel::RemoveFormComponent(FmControlData* pControlData)
490 : {
491 :
492 : // Control und Parent holen
493 0 : if (!pControlData)
494 0 : return;
495 :
496 :
497 : // Als PropertyChangeListener abmelden
498 0 : Reference< XPropertySet > xSet( pControlData->GetPropertySet() );
499 0 : if (xSet.is())
500 0 : xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList);
501 : }
502 :
503 :
504 0 : void NavigatorTreeModel::ClearBranch( FmFormData* pParentData )
505 : {
506 :
507 : // Alle Eintraege dieses Zweiges loeschen
508 0 : FmEntryDataList* pChildList = pParentData->GetChildList();
509 :
510 0 : for( size_t i = pChildList->size(); i > 0; )
511 : {
512 0 : FmEntryData* pChildData = pChildList->at( --i );
513 0 : if( pChildData->ISA(FmFormData) )
514 0 : ClearBranch( (FmFormData*)pChildData );
515 :
516 0 : pChildList->remove( pChildData );
517 : }
518 0 : }
519 :
520 :
521 0 : void NavigatorTreeModel::FillBranch( FmFormData* pFormData )
522 : {
523 :
524 : // Forms aus der Root einfuegen
525 0 : if( pFormData == NULL )
526 : {
527 0 : Reference< XIndexContainer > xForms(GetForms(), UNO_QUERY);
528 0 : if (!xForms.is())
529 0 : return;
530 :
531 0 : Reference< XForm > xSubForm;
532 : FmFormData* pSubFormData;
533 0 : for (sal_Int32 i=0; i<xForms->getCount(); ++i)
534 : {
535 : DBG_ASSERT( xForms->getByIndex(i).getValueType() == ::getCppuType((const Reference< XForm>*)NULL),
536 : "NavigatorTreeModel::FillBranch : the root container should supply only elements of type XForm");
537 :
538 0 : xForms->getByIndex(i) >>= xSubForm;
539 0 : pSubFormData = new FmFormData( xSubForm, m_aNormalImages, pFormData );
540 0 : Insert( pSubFormData, CONTAINER_APPEND );
541 :
542 :
543 : // Neuer Branch, wenn SubForm wiederum Subforms enthaelt
544 0 : FillBranch( pSubFormData );
545 0 : }
546 : }
547 :
548 :
549 : // Componenten einfuegen
550 : else
551 : {
552 0 : Reference< XIndexContainer > xComponents( GetFormComponents(pFormData));
553 0 : if( !xComponents.is() ) return;
554 :
555 0 : Reference< XInterface > xInterface;
556 0 : Reference< XPropertySet > xSet;
557 : FmControlData* pNewControlData;
558 : FmFormData* pSubFormData;
559 :
560 0 : Reference< XFormComponent > xCurrentComponent;
561 0 : for (sal_Int32 j=0; j<xComponents->getCount(); ++j)
562 : {
563 0 : xComponents->getByIndex(j) >>= xCurrentComponent;
564 0 : Reference< XForm > xSubForm(xCurrentComponent, UNO_QUERY);
565 :
566 0 : if (xSubForm.is())
567 : { // die aktuelle Component ist eine Form
568 0 : pSubFormData = new FmFormData(xSubForm, m_aNormalImages, pFormData);
569 0 : Insert(pSubFormData, CONTAINER_APPEND);
570 :
571 :
572 : // Neuer Branch, wenn SubForm wiederum Subforms enthaelt
573 0 : FillBranch(pSubFormData);
574 : }
575 : else
576 : {
577 0 : pNewControlData = new FmControlData(xCurrentComponent, m_aNormalImages, pFormData);
578 0 : Insert(pNewControlData, CONTAINER_APPEND);
579 : }
580 0 : }
581 : }
582 : }
583 :
584 :
585 0 : void NavigatorTreeModel::InsertForm(const Reference< XForm > & xForm, sal_uInt32 nRelPos)
586 : {
587 0 : FmFormData* pFormData = (FmFormData*)FindData( xForm, GetRootList() );
588 0 : if (pFormData)
589 0 : return;
590 :
591 :
592 : // ParentData setzen
593 0 : Reference< XInterface > xIFace( xForm->getParent());
594 0 : Reference< XForm > xParentForm(xIFace, UNO_QUERY);
595 0 : FmFormData* pParentData = NULL;
596 0 : if (xParentForm.is())
597 0 : pParentData = (FmFormData*)FindData( xParentForm, GetRootList() );
598 :
599 0 : pFormData = new FmFormData( xForm, m_aNormalImages, pParentData );
600 0 : Insert( pFormData, nRelPos );
601 : }
602 :
603 :
604 0 : void NavigatorTreeModel::InsertFormComponent(const Reference< XFormComponent > & xComp, sal_uInt32 nRelPos)
605 : {
606 :
607 : // ParentData setzen
608 0 : Reference< XInterface > xIFace( xComp->getParent());
609 0 : Reference< XForm > xForm(xIFace, UNO_QUERY);
610 0 : if (!xForm.is())
611 0 : return;
612 :
613 0 : FmFormData* pParentData = (FmFormData*)FindData( xForm, GetRootList() );
614 0 : if( !pParentData )
615 : {
616 0 : pParentData = new FmFormData( xForm, m_aNormalImages, NULL );
617 0 : Insert( pParentData, CONTAINER_APPEND );
618 : }
619 :
620 0 : if (!FindData(xComp, pParentData->GetChildList(),sal_False))
621 : {
622 :
623 : // Neue EntryData setzen
624 0 : FmEntryData* pNewEntryData = new FmControlData( xComp, m_aNormalImages, pParentData );
625 :
626 :
627 : // Neue EntryData einfuegen
628 0 : Insert( pNewEntryData, nRelPos );
629 0 : }
630 : }
631 :
632 :
633 0 : void NavigatorTreeModel::ReplaceFormComponent(
634 : const Reference< XFormComponent > & xOld,
635 : const Reference< XFormComponent > & xNew
636 : )
637 : {
638 0 : FmEntryData* pData = FindData(xOld, GetRootList(), sal_True);
639 : DBG_ASSERT(pData && pData->ISA(FmControlData), "NavigatorTreeModel::ReplaceFormComponent : invalid argument !");
640 0 : ((FmControlData*)pData)->ModelReplaced( xNew, m_aNormalImages );
641 :
642 0 : FmNavModelReplacedHint aReplacedHint( pData );
643 0 : Broadcast( aReplacedHint );
644 0 : }
645 :
646 :
647 0 : FmEntryData* NavigatorTreeModel::FindData(const Reference< XInterface > & xElement, FmEntryDataList* pDataList, sal_Bool bRecurs)
648 : {
649 : // normalize
650 0 : Reference< XInterface > xIFace( xElement, UNO_QUERY );
651 :
652 0 : for ( size_t i = 0; i < pDataList->size(); i++ )
653 : {
654 0 : FmEntryData* pEntryData = pDataList->at( i );
655 0 : if ( pEntryData->GetElement().get() == xIFace.get() )
656 0 : return pEntryData;
657 0 : else if (bRecurs)
658 : {
659 0 : pEntryData = FindData( xElement, pEntryData->GetChildList() );
660 0 : if (pEntryData)
661 0 : return pEntryData;
662 : }
663 : }
664 0 : return NULL;
665 : }
666 :
667 :
668 0 : FmEntryData* NavigatorTreeModel::FindData( const OUString& rText, FmFormData* pParentData, sal_Bool bRecurs )
669 : {
670 : FmEntryDataList* pDataList;
671 0 : if( !pParentData )
672 0 : pDataList = GetRootList();
673 : else
674 0 : pDataList = pParentData->GetChildList();
675 :
676 0 : OUString aEntryText;
677 : FmEntryData* pEntryData;
678 : FmEntryData* pChildData;
679 :
680 0 : for( size_t i = 0; i < pDataList->size(); i++ )
681 : {
682 0 : pEntryData = pDataList->at( i );
683 0 : aEntryText = pEntryData->GetText();
684 :
685 0 : if (rText == aEntryText)
686 0 : return pEntryData;
687 :
688 0 : if( bRecurs && pEntryData->ISA(FmFormData) )
689 : {
690 0 : pChildData = FindData( rText, (FmFormData*)pEntryData );
691 0 : if( pChildData )
692 0 : return pChildData;
693 : }
694 : }
695 :
696 0 : return NULL;
697 : }
698 :
699 :
700 0 : void NavigatorTreeModel::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
701 : {
702 0 : if( rHint.ISA(SdrHint) )
703 : {
704 0 : SdrHint* pSdrHint = (SdrHint*)&rHint;
705 0 : switch( pSdrHint->GetKind() )
706 : {
707 : case HINT_OBJINSERTED:
708 0 : InsertSdrObj(pSdrHint->GetObject());
709 0 : break;
710 : case HINT_OBJREMOVED:
711 0 : RemoveSdrObj(pSdrHint->GetObject());
712 0 : break;
713 : default:
714 0 : break;
715 : }
716 : }
717 : // hat sich die shell verabschiedet?
718 0 : else if ( rHint.ISA(SfxSimpleHint) && ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING)
719 0 : UpdateContent((FmFormShell*)NULL);
720 :
721 : // hat sich die Markierung der Controls veraendert ?
722 0 : else if (rHint.ISA(FmNavViewMarksChanged))
723 : {
724 0 : FmNavViewMarksChanged* pvmcHint = (FmNavViewMarksChanged*)&rHint;
725 0 : BroadcastMarkedObjects( pvmcHint->GetAffectedView()->GetMarkedObjectList() );
726 : }
727 0 : }
728 :
729 :
730 0 : void NavigatorTreeModel::InsertSdrObj( const SdrObject* pObj )
731 : {
732 0 : const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
733 0 : if ( pFormObject )
734 : {
735 : try
736 : {
737 0 : Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
738 0 : Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
739 :
740 0 : sal_Int32 nPos = getElementPos( xContainer, xFormComponent );
741 0 : InsertFormComponent( xFormComponent, nPos );
742 : }
743 0 : catch( const Exception& )
744 : {
745 : DBG_UNHANDLED_EXCEPTION();
746 : }
747 : }
748 0 : else if ( pObj->IsGroupObject() )
749 : {
750 0 : SdrObjListIter aIter( *pObj->GetSubList() );
751 0 : while ( aIter.IsMore() )
752 0 : InsertSdrObj( aIter.Next() );
753 : }
754 0 : }
755 :
756 :
757 0 : void NavigatorTreeModel::RemoveSdrObj( const SdrObject* pObj )
758 : {
759 0 : const FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
760 0 : if ( pFormObject )
761 : {
762 : try
763 : {
764 0 : Reference< XFormComponent > xFormComponent( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
765 0 : FmEntryData* pEntryData = FindData( xFormComponent, GetRootList(), sal_True );
766 0 : if ( pEntryData )
767 0 : Remove( pEntryData );
768 : }
769 0 : catch( const Exception& )
770 : {
771 : DBG_UNHANDLED_EXCEPTION();
772 : }
773 : }
774 0 : else if ( pObj->IsGroupObject() )
775 : {
776 0 : SdrObjListIter aIter( *pObj->GetSubList() );
777 0 : while ( aIter.IsMore() )
778 0 : RemoveSdrObj( aIter.Next() );
779 : }
780 0 : }
781 :
782 0 : sal_Bool NavigatorTreeModel::InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject)
783 : {
784 0 : if ( pObject->ISA(SdrObjGroup) )
785 : { // rekursiv absteigen
786 0 : const SdrObjList *pChildren = ((SdrObjGroup*)pObject)->GetSubList();
787 0 : for ( sal_uInt16 i=0; i<pChildren->GetObjCount(); ++i )
788 : {
789 0 : SdrObject* pCurrent = pChildren->GetObj(i);
790 0 : if (!InsertFormComponent(rHint, pCurrent))
791 0 : return sal_False;
792 : }
793 : }
794 : else
795 : {
796 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject );
797 0 : if ( !pFormObject )
798 0 : return sal_False;
799 :
800 : try
801 : {
802 0 : Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
803 0 : FmEntryData* pControlData = FindData( xFormViewControl, GetRootList() );
804 0 : if ( !pControlData )
805 0 : return sal_False;
806 :
807 0 : rHint.AddItem( pControlData );
808 0 : return sal_True;
809 : }
810 0 : catch( const Exception& )
811 : {
812 : DBG_UNHANDLED_EXCEPTION();
813 0 : return sal_False;
814 : }
815 : }
816 :
817 0 : return sal_True;
818 : }
819 :
820 0 : void NavigatorTreeModel::BroadcastMarkedObjects(const SdrMarkList& mlMarked)
821 : {
822 : // gehen wir durch alle markierten Objekte und suchen wir die raus, mit denen ich was anfangen kann
823 0 : FmNavRequestSelectHint rshRequestSelection;
824 0 : bool bIsMixedSelection = false;
825 :
826 0 : for (sal_uLong i=0; (i<mlMarked.GetMarkCount()) && !bIsMixedSelection; i++)
827 : {
828 0 : SdrObject* pobjCurrent = mlMarked.GetMark(i)->GetMarkedSdrObj();
829 0 : bIsMixedSelection |= !InsertFormComponent(rshRequestSelection, pobjCurrent);
830 : // bei einem Nicht-Form-Control liefert InsertFormComponent sal_False !
831 : }
832 :
833 0 : rshRequestSelection.SetMixedSelection(bIsMixedSelection);
834 0 : if (bIsMixedSelection)
835 0 : rshRequestSelection.ClearItems();
836 :
837 0 : Broadcast(rshRequestSelection);
838 : // eine leere Liste interpretiert der NavigatorTree so, dass er seine Selektion komplett rausnimmt
839 0 : }
840 :
841 :
842 0 : void NavigatorTreeModel::UpdateContent( const Reference< css::form::XForms > & xForms )
843 : {
844 :
845 : // Model von der Root aufwaerts neu fuellen
846 0 : Clear();
847 0 : if (xForms.is())
848 : {
849 0 : xForms->addContainerListener((XContainerListener*)m_pPropChangeList);
850 :
851 0 : FillBranch(NULL);
852 :
853 : // jetzt in meinem Tree genau die das in meiner View markierte Control selektieren
854 : // (bzw alle solchen), falls es eines gibt ...
855 0 : if(!m_pFormShell) return; // keine Shell -> wech
856 :
857 0 : FmFormView* pFormView = m_pFormShell->GetFormView();
858 : DBG_ASSERT(pFormView != NULL, "NavigatorTreeModel::UpdateContent : keine FormView");
859 0 : BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
860 : }
861 : }
862 :
863 :
864 0 : void NavigatorTreeModel::UpdateContent( FmFormShell* pShell )
865 : {
866 :
867 : // Wenn Shell sich nicht veraendert hat, nichts machen
868 0 : FmFormPage* pNewPage = pShell ? pShell->GetCurPage() : NULL;
869 0 : if ((pShell == m_pFormShell) && (m_pFormPage == pNewPage))
870 0 : return;
871 :
872 :
873 : // Als Listener abmelden
874 0 : if( m_pFormShell )
875 : {
876 0 : if (m_pFormModel)
877 0 : EndListening( *m_pFormModel );
878 0 : m_pFormModel = NULL;
879 0 : EndListening( *m_pFormShell );
880 0 : Clear();
881 : }
882 :
883 :
884 : // Vollupdate
885 0 : m_pFormShell = pShell;
886 0 : if (m_pFormShell)
887 : {
888 0 : m_pFormPage = pNewPage;
889 0 : UpdateContent(m_pFormPage->GetForms());
890 : } else
891 0 : m_pFormPage = NULL;
892 :
893 :
894 : // Als Listener neu anmelden
895 0 : if( m_pFormShell )
896 : {
897 0 : StartListening( *m_pFormShell );
898 0 : m_pFormModel = m_pFormShell->GetFormModel();
899 0 : if( m_pFormModel )
900 0 : StartListening( *m_pFormModel );
901 : }
902 : }
903 :
904 :
905 0 : Reference< XIndexContainer > NavigatorTreeModel::GetFormComponents( FmFormData* pFormData )
906 : {
907 :
908 : // Von der Form Components holen
909 0 : if (pFormData)
910 0 : return Reference< XIndexContainer > (pFormData->GetFormIface(), UNO_QUERY);
911 :
912 0 : return Reference< XIndexContainer > ();
913 : }
914 :
915 :
916 0 : sal_Bool NavigatorTreeModel::Rename( FmEntryData* pEntryData, const OUString& rNewText )
917 : {
918 :
919 : // Wenn Name schon vorhanden, Fehlermeldung
920 0 : pEntryData->SetText( rNewText );
921 :
922 :
923 : // PropertySet besorgen
924 0 : Reference< XFormComponent > xFormComponent;
925 :
926 0 : if( pEntryData->ISA(FmFormData) )
927 : {
928 0 : FmFormData* pFormData = (FmFormData*)pEntryData;
929 0 : Reference< XForm > xForm( pFormData->GetFormIface());
930 0 : xFormComponent = xForm;
931 : }
932 :
933 0 : if( pEntryData->ISA(FmControlData) )
934 : {
935 0 : FmControlData* pControlData = (FmControlData*)pEntryData;
936 0 : xFormComponent = pControlData->GetFormComponent();
937 : }
938 :
939 0 : if( !xFormComponent.is() ) return sal_False;
940 0 : Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
941 0 : if( !xSet.is() ) return sal_False;
942 :
943 :
944 : // Namen setzen
945 0 : xSet->setPropertyValue( FM_PROP_NAME, makeAny(rNewText) );
946 :
947 0 : return sal_True;
948 : }
949 :
950 :
951 0 : SdrObject* NavigatorTreeModel::Search(SdrObjListIter& rIter, const Reference< XFormComponent > & xComp)
952 : {
953 0 : while (rIter.IsMore())
954 : {
955 0 : SdrObject* pObj = rIter.Next();
956 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pObj );
957 0 : if ( pFormObject )
958 : {
959 0 : Reference< XFormComponent > xFormViewControl( pFormObject->GetUnoControlModel(), UNO_QUERY );
960 0 : if ( xFormViewControl == xComp )
961 0 : return pObj;
962 : }
963 0 : else if ( pObj->IsGroupObject() )
964 : {
965 0 : SdrObjListIter aIter( *pObj->GetSubList() );
966 0 : pObj = Search( aIter, xComp );
967 0 : if ( pObj )
968 0 : return pObj;
969 : }
970 : }
971 0 : return NULL;
972 : }
973 :
974 :
975 : } // namespace svxform
976 :
977 :
978 :
979 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|