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/svdpagv.hxx>
25 : #include "svx/svditer.hxx"
26 :
27 : #include "fmhelp.hrc"
28 : #include "fmexpl.hxx"
29 : #include "svx/fmresids.hrc"
30 : #include "fmshimp.hxx"
31 : #include "fmservs.hxx"
32 : #include "fmundo.hxx"
33 : #include "fmpgeimp.hxx"
34 : #include "fmitems.hxx"
35 : #include "fmobj.hxx"
36 : #include "fmprop.hrc"
37 : #include <vcl/wrkwin.hxx>
38 : #include <sfx2/viewsh.hxx>
39 : #include <sfx2/dispatch.hxx>
40 : #include <sfx2/viewfrm.hxx>
41 : #include <comphelper/processfactory.hxx>
42 : #include <comphelper/property.hxx>
43 : #include <com/sun/star/form/FormComponentType.hpp>
44 : #include <com/sun/star/sdb/CommandType.hpp>
45 : #include <com/sun/star/beans/PropertyAttribute.hpp>
46 : #include <com/sun/star/script/XEventAttacherManager.hpp>
47 : #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
48 : #include <com/sun/star/datatransfer/XTransferable.hpp>
49 : #include <svx/sdrpaintwindow.hxx>
50 :
51 : #include <svx/svxdlg.hxx>
52 : #include <svx/dialogs.hrc>
53 : #include "svtools/treelistentry.hxx"
54 :
55 : namespace svxform
56 : {
57 :
58 :
59 : #define DROP_ACTION_TIMER_INITIAL_TICKS 10
60 : // Time until scroll starts
61 : #define DROP_ACTION_TIMER_SCROLL_TICKS 3
62 : // Time to scroll one line
63 : #define DROP_ACTION_TIMER_TICK_BASE 10
64 : // factor for both declarations (in ms)
65 :
66 : #define EXPLORER_SYNC_DELAY 200
67 : // Time (in ms) until explorer synchronizes the view after select or deselect
68 :
69 : using namespace ::com::sun::star::uno;
70 : using namespace ::com::sun::star::lang;
71 : using namespace ::com::sun::star::beans;
72 : using namespace ::com::sun::star::form;
73 : using namespace ::com::sun::star::awt;
74 : using namespace ::com::sun::star::container;
75 : using namespace ::com::sun::star::script;
76 : using namespace ::com::sun::star::datatransfer;
77 : using namespace ::com::sun::star::datatransfer::clipboard;
78 : using namespace ::com::sun::star::sdb;
79 :
80 :
81 : // helper
82 :
83 :
84 : typedef ::std::map< Reference< XInterface >, SdrObject*, ::comphelper::OInterfaceCompare< XInterface > >
85 : MapModelToShape;
86 : typedef MapModelToShape::value_type ModelShapePair;
87 :
88 :
89 0 : void collectShapeModelMapping( SdrPage* _pPage, MapModelToShape& _rMapping )
90 : {
91 : OSL_ENSURE( _pPage, "collectShapeModelMapping: invalid arg!" );
92 :
93 0 : _rMapping.clear();
94 :
95 0 : SdrObjListIter aIter( *_pPage );
96 0 : while ( aIter.IsMore() )
97 : {
98 0 : SdrObject* pSdrObject = aIter.Next();
99 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
100 0 : if ( !pFormObject )
101 0 : continue;
102 :
103 0 : Reference< XInterface > xNormalizedModel( pFormObject->GetUnoControlModel(), UNO_QUERY );
104 : // note that this is normalized (i.e. queried for XInterface explicitly)
105 :
106 : #ifdef DBG_UTIL
107 : ::std::pair< MapModelToShape::iterator, bool > aPos =
108 : #endif
109 0 : _rMapping.insert( ModelShapePair( xNormalizedModel, pSdrObject ) );
110 : DBG_ASSERT( aPos.second, "collectShapeModelMapping: model was already existent!" );
111 : // if this asserts, this would mean we have 2 shapes pointing to the same model
112 0 : }
113 0 : }
114 :
115 0 : NavigatorTree::NavigatorTree( vcl::Window* pParent )
116 : :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL ) // #100258# OJ WB_HSCROLL added
117 : ,m_aControlExchange(this)
118 : ,m_pNavModel( NULL )
119 : ,m_pRootEntry(NULL)
120 : ,m_pEditEntry(NULL)
121 : ,nEditEvent(0)
122 : ,m_sdiState(SDI_DIRTY)
123 : ,m_aTimerTriggered(-1,-1)
124 : ,m_aDropActionType( DA_SCROLLUP )
125 : ,m_nSelectLock(0)
126 : ,m_nFormsSelected(0)
127 : ,m_nControlsSelected(0)
128 : ,m_nHiddenControls(0)
129 : ,m_aTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS )
130 : ,m_bDragDataDirty(false)
131 : ,m_bPrevSelectionMixed(false)
132 : ,m_bMarkingObjects(false)
133 : ,m_bRootSelected(false)
134 : ,m_bInitialUpdate(true)
135 0 : ,m_bKeyboardCut( false )
136 : {
137 0 : SetHelpId( HID_FORM_NAVIGATOR );
138 :
139 0 : m_aNavigatorImages = ImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
140 :
141 : SetNodeBitmaps(
142 : m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
143 : m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE )
144 0 : );
145 :
146 0 : SetDragDropMode(DragDropMode::ALL);
147 0 : EnableInplaceEditing( true );
148 0 : SetSelectionMode(MULTIPLE_SELECTION);
149 :
150 0 : m_pNavModel = new NavigatorTreeModel( m_aNavigatorImages );
151 0 : Clear();
152 :
153 0 : StartListening( *m_pNavModel );
154 :
155 0 : m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer));
156 :
157 0 : m_aSynchronizeTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnSynchronizeTimer));
158 0 : SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
159 0 : SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel));
160 0 : }
161 :
162 :
163 0 : NavigatorTree::~NavigatorTree()
164 : {
165 0 : disposeOnce();
166 0 : }
167 :
168 0 : void NavigatorTree::dispose()
169 : {
170 0 : if( nEditEvent )
171 0 : Application::RemoveUserEvent( nEditEvent );
172 :
173 0 : if (m_aSynchronizeTimer.IsActive())
174 0 : m_aSynchronizeTimer.Stop();
175 :
176 : DBG_ASSERT(GetNavModel() != NULL, "NavigatorTree::~NavigatorTree : unexpected : no ExplorerModel");
177 0 : EndListening( *m_pNavModel );
178 0 : Clear();
179 0 : delete m_pNavModel;
180 0 : SvTreeListBox::dispose();
181 0 : }
182 :
183 :
184 0 : void NavigatorTree::Clear()
185 : {
186 0 : m_pNavModel->Clear();
187 0 : }
188 :
189 :
190 0 : void NavigatorTree::UpdateContent( FmFormShell* pFormShell )
191 : {
192 0 : if (m_bInitialUpdate)
193 : {
194 0 : GrabFocus();
195 0 : m_bInitialUpdate = false;
196 : }
197 :
198 0 : FmFormShell* pOldShell = GetNavModel()->GetFormShell();
199 0 : FmFormPage* pOldPage = GetNavModel()->GetFormPage();
200 0 : FmFormPage* pNewPage = pFormShell ? pFormShell->GetCurPage() : NULL;
201 :
202 0 : if ((pOldShell != pFormShell) || (pOldPage != pNewPage))
203 : {
204 : // new shell during editing
205 0 : if (IsEditingActive())
206 0 : CancelTextEditing();
207 :
208 0 : m_bDragDataDirty = true; // as a precaution, although i dont drag
209 : }
210 0 : GetNavModel()->UpdateContent( pFormShell );
211 :
212 : // if there is a form, expand root
213 0 : if (m_pRootEntry && !IsExpanded(m_pRootEntry))
214 0 : Expand(m_pRootEntry);
215 : // if there is EXACTLY ONE form, expand it too
216 0 : if (m_pRootEntry)
217 : {
218 0 : SvTreeListEntry* pFirst = FirstChild(m_pRootEntry);
219 0 : if (pFirst && !NextSibling(pFirst))
220 0 : Expand(pFirst);
221 : }
222 0 : }
223 :
224 :
225 0 : bool NavigatorTree::implAllowExchange( sal_Int8 _nAction, bool* _pHasNonHidden )
226 : {
227 0 : SvTreeListEntry* pCurEntry = GetCurEntry();
228 0 : if (!pCurEntry)
229 0 : return false;
230 :
231 : // Information for AcceptDrop and Execute Drop
232 0 : CollectSelectionData(SDI_ALL);
233 0 : if (m_arrCurrentSelection.empty())
234 : // nothing to do
235 0 : return false;
236 :
237 : // check whether there are only hidden controls
238 : // I may add a format to pCtrlExch
239 0 : bool bHasNonHidden = false;
240 0 : for ( SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
241 0 : it != m_arrCurrentSelection.end(); ++it )
242 : {
243 0 : FmEntryData* pCurrent = static_cast< FmEntryData* >( (*it)->GetUserData() );
244 0 : if ( IsHiddenControl( pCurrent ) )
245 0 : continue;
246 0 : bHasNonHidden = true;
247 0 : break;
248 : }
249 :
250 0 : if ( bHasNonHidden && ( 0 == ( _nAction & DND_ACTION_MOVE ) ) )
251 : // non-hidden controls need to be moved
252 0 : return false;
253 :
254 0 : if ( _pHasNonHidden )
255 0 : *_pHasNonHidden = bHasNonHidden;
256 :
257 0 : return true;
258 : }
259 :
260 :
261 0 : bool NavigatorTree::implPrepareExchange( sal_Int8 _nAction )
262 : {
263 0 : EndSelection();
264 :
265 0 : bool bHasNonHidden = false;
266 0 : if ( !implAllowExchange( _nAction, &bHasNonHidden ) )
267 0 : return false;
268 :
269 0 : m_aControlExchange.prepareDrag();
270 0 : m_aControlExchange->setFocusEntry( GetCurEntry() );
271 :
272 0 : for ( SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
273 0 : it != m_arrCurrentSelection.end(); ++it )
274 0 : m_aControlExchange->addSelectedEntry(*it);
275 :
276 0 : m_aControlExchange->setFormsRoot( GetNavModel()->GetFormPage()->GetForms() );
277 0 : m_aControlExchange->buildPathFormat( this, m_pRootEntry );
278 :
279 0 : if (!bHasNonHidden)
280 : {
281 : // create a sequence
282 0 : Sequence< Reference< XInterface > > seqIFaces(m_arrCurrentSelection.size());
283 0 : Reference< XInterface >* pArray = seqIFaces.getArray();
284 0 : for ( SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
285 0 : it != m_arrCurrentSelection.end(); ++it, ++pArray )
286 0 : *pArray = static_cast< FmEntryData* >( (*it)->GetUserData() )->GetElement();
287 :
288 : // and the new format
289 0 : m_aControlExchange->addHiddenControlsFormat(seqIFaces);
290 : }
291 :
292 0 : m_bDragDataDirty = false;
293 0 : return true;
294 : }
295 :
296 :
297 0 : void NavigatorTree::StartDrag( sal_Int8 /*nAction*/, const ::Point& /*rPosPixel*/ )
298 : {
299 0 : EndSelection();
300 :
301 0 : if ( !implPrepareExchange( DND_ACTION_COPYMOVE ) )
302 : // nothing to do or something went wrong
303 0 : return;
304 :
305 : // collected all possible formats for current situation, we can start now
306 0 : m_aControlExchange.startDrag( DND_ACTION_COPYMOVE );
307 : }
308 :
309 :
310 0 : void NavigatorTree::Command( const CommandEvent& rEvt )
311 : {
312 0 : bool bHandled = false;
313 0 : switch( rEvt.GetCommand() )
314 : {
315 : case CommandEventId::ContextMenu:
316 : {
317 : // Position of click
318 0 : ::Point ptWhere;
319 0 : if (rEvt.IsMouseEvent())
320 : {
321 0 : ptWhere = rEvt.GetMousePosPixel();
322 0 : SvTreeListEntry* ptClickedOn = GetEntry(ptWhere);
323 0 : if (ptClickedOn == NULL)
324 0 : break;
325 0 : if ( !IsSelected(ptClickedOn) )
326 : {
327 0 : SelectAll(false);
328 0 : Select(ptClickedOn, true);
329 0 : SetCurEntry(ptClickedOn);
330 : }
331 : }
332 : else
333 : {
334 0 : if (m_arrCurrentSelection.empty()) // only happens with context menu via keyboard
335 0 : break;
336 :
337 0 : SvTreeListEntry* pCurrent = GetCurEntry();
338 0 : if (!pCurrent)
339 0 : break;
340 0 : ptWhere = GetEntryPosition(pCurrent);
341 : }
342 :
343 : // update my selection data
344 0 : CollectSelectionData(SDI_ALL);
345 :
346 : // if there is at least one no-root-entry and the root selected, i deselect root
347 0 : if ( (m_arrCurrentSelection.size() > 1) && m_bRootSelected )
348 : {
349 0 : Select( m_pRootEntry, false );
350 0 : SetCursor( *m_arrCurrentSelection.begin(), true);
351 : }
352 0 : bool bSingleSelection = (m_arrCurrentSelection.size() == 1);
353 :
354 :
355 : DBG_ASSERT( (m_arrCurrentSelection.size() > 0) || m_bRootSelected, "no entries selected" );
356 : // shouldn't happen, because i would have selected one during call to IsSelected,
357 : // if there was none before
358 :
359 :
360 : // create menu
361 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
362 0 : FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
363 0 : if( pFormShell && pFormModel )
364 : {
365 0 : PopupMenu aContextMenu(SVX_RES(RID_FMEXPLORER_POPUPMENU));
366 0 : PopupMenu* pSubMenuNew = aContextMenu.GetPopupMenu( SID_FM_NEW );
367 :
368 : // menu 'New' only exists, if only the root or only one form is selected
369 0 : aContextMenu.EnableItem( SID_FM_NEW, bSingleSelection && (m_nFormsSelected || m_bRootSelected) );
370 :
371 : // 'New'\'Form' under the same terms
372 0 : pSubMenuNew->EnableItem( SID_FM_NEW_FORM, bSingleSelection && (m_nFormsSelected || m_bRootSelected) );
373 0 : pSubMenuNew->SetItemImage(SID_FM_NEW_FORM, m_aNavigatorImages.GetImage(RID_SVXIMG_FORM));
374 0 : pSubMenuNew->SetItemImage(SID_FM_NEW_HIDDEN, m_aNavigatorImages.GetImage(RID_SVXIMG_HIDDEN));
375 :
376 : // 'New'\'hidden...', if exactly one form is selected
377 0 : pSubMenuNew->EnableItem( SID_FM_NEW_HIDDEN, bSingleSelection && m_nFormsSelected );
378 :
379 : // 'Delete': everything which is not root can be removed
380 0 : aContextMenu.EnableItem( SID_FM_DELETE, !m_bRootSelected );
381 :
382 : // 'Cut', 'Copy' and 'Paste'
383 0 : aContextMenu.EnableItem( SID_CUT, !m_bRootSelected && implAllowExchange( DND_ACTION_MOVE ) );
384 0 : aContextMenu.EnableItem( SID_COPY, !m_bRootSelected && implAllowExchange( DND_ACTION_COPY ) );
385 0 : aContextMenu.EnableItem( SID_PASTE, implAcceptPaste( ) );
386 :
387 : // TabDialog, if exaclty one form
388 0 : aContextMenu.EnableItem( SID_FM_TAB_DIALOG, bSingleSelection && m_nFormsSelected );
389 :
390 : // in XML forms, we don't allow for the properties of a form
391 : // #i36484#
392 0 : if ( pFormShell->GetImpl()->isEnhancedForm() && !m_nControlsSelected )
393 0 : aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) );
394 :
395 : // if the property browser is already open, we don't allow for the properties, too
396 0 : if( pFormShell->GetImpl()->IsPropBrwOpen() )
397 0 : aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) );
398 : // and finally, if there's a mixed selection of forms and controls, disable the entry, too
399 : else
400 : aContextMenu.EnableItem( SID_FM_SHOW_PROPERTY_BROWSER,
401 0 : (m_nControlsSelected && !m_nFormsSelected) || (!m_nControlsSelected && m_nFormsSelected) );
402 :
403 : // rename, if one element and no root
404 0 : aContextMenu.EnableItem( SID_FM_RENAME_OBJECT, bSingleSelection && !m_bRootSelected );
405 :
406 : // Readonly-entry is only for root
407 0 : aContextMenu.EnableItem( SID_FM_OPEN_READONLY, m_bRootSelected );
408 : // the same for automatic control focus
409 0 : aContextMenu.EnableItem( SID_FM_AUTOCONTROLFOCUS, m_bRootSelected );
410 :
411 : // ConvertTo-Slots are enabled, if one control is selected
412 : // the corresponding slot is disabled
413 0 : if (!m_bRootSelected && !m_nFormsSelected && (m_nControlsSelected == 1))
414 : {
415 0 : aContextMenu.SetPopupMenu( SID_FM_CHANGECONTROLTYPE, FmXFormShell::GetConversionMenu() );
416 : #if OSL_DEBUG_LEVEL > 0
417 : FmControlData* pCurrent = static_cast<FmControlData*>((*m_arrCurrentSelection.begin())->GetUserData());
418 : OSL_ENSURE( pFormShell->GetImpl()->isSolelySelected( pCurrent->GetFormComponent() ),
419 : "NavigatorTree::Command: inconsistency between the navigator selection, and the selection as the shell knows it!" );
420 : #endif
421 :
422 0 : pFormShell->GetImpl()->checkControlConversionSlotsForCurrentSelection( *aContextMenu.GetPopupMenu( SID_FM_CHANGECONTROLTYPE ) );
423 : }
424 : else
425 0 : aContextMenu.EnableItem( SID_FM_CHANGECONTROLTYPE, false );
426 :
427 : // remove all disabled entries
428 0 : aContextMenu.RemoveDisabledEntries(true, true);
429 :
430 : // set OpenReadOnly
431 :
432 0 : aContextMenu.CheckItem( SID_FM_OPEN_READONLY, pFormModel->GetOpenInDesignMode() );
433 0 : aContextMenu.CheckItem( SID_FM_AUTOCONTROLFOCUS, pFormModel->GetAutoControlFocus() );
434 :
435 0 : sal_uInt16 nSlotId = aContextMenu.Execute( this, ptWhere );
436 0 : switch( nSlotId )
437 : {
438 : case SID_FM_NEW_FORM:
439 : {
440 0 : OUString aStr(SVX_RESSTR(RID_STR_FORM));
441 0 : OUString aUndoStr = SVX_RESSTR(RID_STR_UNDO_CONTAINER_INSERT).replaceAll(OUString('#'), aStr);
442 :
443 0 : pFormModel->BegUndo(aUndoStr);
444 : // slot was only available, if there is only one selected entry,
445 : // which is a root or a form
446 0 : NewForm( *m_arrCurrentSelection.begin() );
447 0 : pFormModel->EndUndo();
448 :
449 0 : } break;
450 : case SID_FM_NEW_HIDDEN:
451 : {
452 0 : OUString aStr(SVX_RESSTR(RID_STR_CONTROL));
453 0 : OUString aUndoStr = SVX_RESSTR(RID_STR_UNDO_CONTAINER_INSERT).replaceAll(OUString('#'), aStr);
454 :
455 0 : pFormModel->BegUndo(aUndoStr);
456 : // slot was valid for (exactly) one selected form
457 0 : OUString fControlName = FM_COMPONENT_HIDDEN;
458 0 : NewControl( fControlName, *m_arrCurrentSelection.begin() );
459 0 : pFormModel->EndUndo();
460 :
461 0 : } break;
462 :
463 : case SID_CUT:
464 0 : doCut();
465 0 : break;
466 :
467 : case SID_COPY:
468 0 : doCopy();
469 0 : break;
470 :
471 : case SID_PASTE:
472 0 : doPaste();
473 0 : break;
474 :
475 : case SID_FM_DELETE:
476 : {
477 0 : DeleteSelection();
478 : }
479 0 : break;
480 : case SID_FM_TAB_DIALOG:
481 : {
482 : // this slot was effective for exactly one selected form
483 0 : SvTreeListEntry* pSelectedForm = *m_arrCurrentSelection.begin();
484 : DBG_ASSERT( IsFormEntry(pSelectedForm), "NavigatorTree::Command: This entry must be a FormEntry." );
485 :
486 0 : FmFormData* pFormData = static_cast<FmFormData*>(pSelectedForm->GetUserData());
487 0 : Reference< XForm > xForm( pFormData->GetFormIface());
488 :
489 0 : Reference< XTabControllerModel > xTabController(xForm, UNO_QUERY);
490 0 : if( !xTabController.is() )
491 0 : break;
492 0 : GetNavModel()->GetFormShell()->GetImpl()->ExecuteTabOrderDialog( xTabController );
493 : }
494 0 : break;
495 :
496 : case SID_FM_SHOW_PROPERTY_BROWSER:
497 : {
498 0 : ShowSelectionProperties(true);
499 : }
500 0 : break;
501 : case SID_FM_RENAME_OBJECT:
502 : {
503 : // only allowed for one no-root-entry
504 0 : EditEntry( *m_arrCurrentSelection.begin() );
505 : }
506 0 : break;
507 : case SID_FM_OPEN_READONLY:
508 : {
509 0 : pFormModel->SetOpenInDesignMode( !pFormModel->GetOpenInDesignMode() );
510 0 : pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY);
511 : }
512 0 : break;
513 : case SID_FM_AUTOCONTROLFOCUS:
514 : {
515 0 : pFormModel->SetAutoControlFocus( !pFormModel->GetAutoControlFocus() );
516 0 : pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS);
517 : }
518 0 : break;
519 : default:
520 0 : if (FmXFormShell::isControlConversionSlot(nSlotId))
521 : {
522 0 : FmControlData* pCurrent = static_cast<FmControlData*>((*m_arrCurrentSelection.begin())->GetUserData());
523 0 : if ( pFormShell->GetImpl()->executeControlConversionSlot( pCurrent->GetFormComponent(), nSlotId ) )
524 0 : ShowSelectionProperties();
525 : }
526 0 : }
527 : }
528 0 : bHandled = true;
529 : }
530 0 : break;
531 0 : default: break;
532 : }
533 :
534 0 : if (!bHandled)
535 0 : SvTreeListBox::Command( rEvt );
536 0 : }
537 :
538 :
539 0 : SvTreeListEntry* NavigatorTree::FindEntry( FmEntryData* pEntryData )
540 : {
541 0 : if( !pEntryData ) return NULL;
542 0 : SvTreeListEntry* pCurEntry = First();
543 0 : while( pCurEntry )
544 : {
545 0 : FmEntryData* pCurEntryData = static_cast<FmEntryData*>(pCurEntry->GetUserData());
546 0 : if( pCurEntryData && pCurEntryData->IsEqualWithoutChildren(pEntryData) )
547 0 : return pCurEntry;
548 :
549 0 : pCurEntry = Next( pCurEntry );
550 : }
551 :
552 0 : return NULL;
553 : }
554 :
555 :
556 0 : void NavigatorTree::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
557 : {
558 0 : if( dynamic_cast<const FmNavRemovedHint*>(&rHint) )
559 : {
560 0 : const FmNavRemovedHint* pRemovedHint = static_cast<const FmNavRemovedHint*>(&rHint);
561 0 : FmEntryData* pEntryData = pRemovedHint->GetEntryData();
562 0 : Remove( pEntryData );
563 : }
564 :
565 0 : else if( dynamic_cast<const FmNavInsertedHint*>(&rHint) )
566 : {
567 0 : const FmNavInsertedHint* pInsertedHint = static_cast<const FmNavInsertedHint*>(&rHint);
568 0 : FmEntryData* pEntryData = pInsertedHint->GetEntryData();
569 0 : sal_uInt32 nRelPos = pInsertedHint->GetRelPos();
570 0 : Insert( pEntryData, nRelPos );
571 : }
572 :
573 0 : else if( dynamic_cast<const FmNavModelReplacedHint*>(&rHint) )
574 : {
575 0 : FmEntryData* pData = static_cast<const FmNavModelReplacedHint*>(&rHint)->GetEntryData();
576 0 : SvTreeListEntry* pEntry = FindEntry( pData );
577 0 : if (pEntry)
578 : { // reset image
579 0 : SetCollapsedEntryBmp( pEntry, pData->GetNormalImage() );
580 0 : SetExpandedEntryBmp( pEntry, pData->GetNormalImage() );
581 0 : }
582 : }
583 :
584 0 : else if( dynamic_cast<const FmNavNameChangedHint*>(&rHint) )
585 : {
586 0 : const FmNavNameChangedHint* pNameChangedHint = static_cast<const FmNavNameChangedHint*>(&rHint);
587 0 : SvTreeListEntry* pEntry = FindEntry( pNameChangedHint->GetEntryData() );
588 0 : SetEntryText( pEntry, pNameChangedHint->GetNewName() );
589 : }
590 :
591 0 : else if( dynamic_cast<const FmNavClearedHint*>(&rHint) )
592 : {
593 0 : SvTreeListBox::Clear();
594 :
595 :
596 : // default-entry "Forms"
597 0 : Image aRootImage( m_aNavigatorImages.GetImage( RID_SVXIMG_FORMS ) );
598 0 : m_pRootEntry = InsertEntry( SVX_RESSTR(RID_STR_FORMS), aRootImage, aRootImage,
599 0 : NULL, false, 0, NULL );
600 : }
601 0 : else if (!m_bMarkingObjects && dynamic_cast<const FmNavRequestSelectHint*>(&rHint))
602 : { // if m_bMarkingObjects is sal_True, i mark objects myself
603 : // and because of the synchronous mechanism, its exactly the hint,
604 : // which was triggered by myself, and thus can be ignored
605 0 : FmNavRequestSelectHint* pershHint = const_cast<FmNavRequestSelectHint*>(static_cast<const FmNavRequestSelectHint*>(&rHint));
606 0 : FmEntryDataArray& arredToSelect = pershHint->GetItems();
607 0 : SynchronizeSelection(arredToSelect);
608 :
609 0 : if (pershHint->IsMixedSelection())
610 : // in this case i deselect all, although the view had a mixed selection
611 : // during next selection, i must adapt the navigator to the view
612 0 : m_bPrevSelectionMixed = true;
613 : }
614 0 : }
615 :
616 :
617 0 : SvTreeListEntry* NavigatorTree::Insert( FmEntryData* pEntryData, sal_uIntPtr nRelPos )
618 : {
619 :
620 : // insert current entry
621 0 : SvTreeListEntry* pParentEntry = FindEntry( pEntryData->GetParent() );
622 : SvTreeListEntry* pNewEntry;
623 :
624 0 : if( !pParentEntry )
625 : pNewEntry = InsertEntry( pEntryData->GetText(),
626 0 : pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
627 0 : m_pRootEntry, false, nRelPos, pEntryData );
628 :
629 : else
630 : pNewEntry = InsertEntry( pEntryData->GetText(),
631 0 : pEntryData->GetNormalImage(), pEntryData->GetNormalImage(),
632 0 : pParentEntry, false, nRelPos, pEntryData );
633 :
634 :
635 : // If root-entry, expand root
636 0 : if( !pParentEntry )
637 0 : Expand( m_pRootEntry );
638 :
639 :
640 : // insert children
641 0 : FmEntryDataList* pChildList = pEntryData->GetChildList();
642 0 : size_t nChildCount = pChildList->size();
643 0 : for( size_t i = 0; i < nChildCount; i++ )
644 : {
645 0 : FmEntryData* pChildData = pChildList->at( i );
646 0 : Insert( pChildData, TREELIST_APPEND );
647 : }
648 :
649 0 : return pNewEntry;
650 : }
651 :
652 :
653 0 : void NavigatorTree::Remove( FmEntryData* pEntryData )
654 : {
655 0 : if( !pEntryData )
656 0 : return;
657 :
658 : // entry for the data
659 0 : SvTreeListEntry* pEntry = FindEntry( pEntryData );
660 0 : if (!pEntry)
661 0 : return;
662 :
663 : // delete entry from TreeListBox
664 : // i'm not allowed, to treat the selection, which i trigger:
665 : // select changes the MarkList of the view, if somebody else does this at the same time
666 : // and removes a selection, we get a problem
667 : // e.g. Group controls with open navigator
668 0 : LockSelectionHandling();
669 :
670 : // little problem : i remember the selected data, but if somebody deletes one of these entries,
671 : // i get inconsistent ... this would be bad
672 0 : Select(pEntry, false);
673 :
674 : // selection can be modified during deletion,
675 : // but because i disabled SelectionHandling, i have to do it later
676 0 : sal_uIntPtr nExpectedSelectionCount = GetSelectionCount();
677 :
678 0 : if( pEntry )
679 0 : GetModel()->Remove( pEntry );
680 :
681 0 : if (nExpectedSelectionCount != GetSelectionCount())
682 0 : SynchronizeSelection();
683 :
684 : // by default i treat the selection of course
685 0 : UnlockSelectionHandling();
686 : }
687 :
688 :
689 0 : bool NavigatorTree::IsFormEntry( SvTreeListEntry* pEntry )
690 : {
691 0 : FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
692 0 : return !pEntryData || pEntryData->ISA(FmFormData);
693 : }
694 :
695 :
696 0 : bool NavigatorTree::IsFormComponentEntry( SvTreeListEntry* pEntry )
697 : {
698 0 : FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
699 0 : return pEntryData && pEntryData->ISA(FmControlData);
700 : }
701 :
702 :
703 0 : bool NavigatorTree::implAcceptPaste( )
704 : {
705 0 : SvTreeListEntry* pFirstSelected = FirstSelected();
706 0 : if ( !pFirstSelected || NextSelected( pFirstSelected ) )
707 : // no selected entry, or at least two selected entries
708 0 : return false;
709 :
710 : // get the clipboard
711 0 : TransferableDataHelper aClipboardContent( TransferableDataHelper::CreateFromSystemClipboard( this ) );
712 :
713 0 : sal_Int8 nAction = m_aControlExchange.isClipboardOwner() && doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY;
714 0 : return ( nAction == implAcceptDataTransfer( aClipboardContent.GetDataFlavorExVector(), nAction, pFirstSelected, false ) );
715 : }
716 :
717 :
718 0 : sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const ::Point& _rDropPos, bool _bDnD )
719 : {
720 0 : return implAcceptDataTransfer( _rFlavors, _nAction, GetEntry( _rDropPos ), _bDnD );
721 : }
722 :
723 :
724 0 : sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, SvTreeListEntry* _pTargetEntry, bool _bDnD )
725 : {
726 : // no target -> no drop
727 0 : if (!_pTargetEntry)
728 0 : return DND_ACTION_NONE;
729 :
730 : // format check
731 0 : bool bHasDefControlFormat = OControlExchange::hasFieldExchangeFormat( _rFlavors );
732 0 : bool bHasControlPathFormat = OControlExchange::hasControlPathFormat( _rFlavors );
733 0 : bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( _rFlavors );
734 0 : if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat)
735 0 : return DND_ACTION_NONE;
736 :
737 0 : bool bSelfSource = _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner();
738 :
739 0 : if ( bHasHiddenControlsFormat )
740 : { // bHasHiddenControlsFormat means that only hidden controls are part of the data
741 :
742 : // hidden controls can be copied to a form only
743 0 : if ( !_pTargetEntry || ( _pTargetEntry == m_pRootEntry ) || !IsFormEntry( _pTargetEntry ) )
744 0 : return DND_ACTION_NONE;
745 :
746 0 : return bSelfSource ? ( DND_ACTION_COPYMOVE & _nAction ) : DND_ACTION_COPY;
747 : }
748 :
749 0 : if ( !bSelfSource )
750 : {
751 : // DnD or CnP crossing navigator boundaries
752 : // The main problem here is that the current API does not allow us to sneak into the content which
753 : // is to be inserted. So we have to allow it for the moment, but maybe reject later on (in the real drop).
754 :
755 : // TODO: this smart behaviour later on ... at the moment, we disallow data transfer crossing navigator
756 : // boundaries.
757 :
758 0 : return DND_ACTION_NONE;
759 : }
760 :
761 : DBG_ASSERT( _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner(),
762 : "NavigatorTree::implAcceptDataTransfer: here only with source=dest!" );
763 : // somebody changed the logic of this method ...
764 :
765 : // from here on, I can work with m_aControlExchange instead of _rData!
766 :
767 0 : bool bForeignCollection = m_aControlExchange->getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
768 0 : if ( bForeignCollection )
769 : {
770 : // crossing shell/page boundaries, we can exchange hidden controls only
771 : // But if we survived the checks above, we do not have hidden controls.
772 : // -> no data transfer
773 : DBG_ASSERT( !bHasHiddenControlsFormat, "NavigatorTree::implAcceptDataTransfer: still hidden controls format!" );
774 : // somebody changed the logic of this method ...
775 :
776 0 : return DND_ACTION_COPY;
777 : }
778 :
779 0 : if (DND_ACTION_MOVE != _nAction) // 'normal' controls within a shell are moved only (never copied)
780 0 : return DND_ACTION_NONE;
781 :
782 0 : if ( m_bDragDataDirty || !bHasDefControlFormat )
783 : {
784 0 : if (!bHasControlPathFormat)
785 : // i am in the shell/page, which has the contorls, but i have no format,
786 : // which survived the shell change (SVX_FM_CONTROLS_AS_PATH)
787 0 : return DND_ACTION_NONE;
788 :
789 : // i must recreate the list of the ExchangeObjects, because the shell was changed during dragging
790 : // (there are SvLBoxEntries in it, and we lost them during change)
791 0 : m_aControlExchange->buildListFromPath(this, m_pRootEntry);
792 0 : m_bDragDataDirty = false;
793 : }
794 :
795 : // List of dropped entries from DragServer
796 0 : const ListBoxEntrySet& aDropped = m_aControlExchange->selected();
797 : DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implAcceptDataTransfer: no entries !");
798 :
799 0 : bool bDropTargetIsComponent = IsFormComponentEntry( _pTargetEntry );
800 : //SvTreeListEntry* pDropTargetParent = GetParent( _pTargetEntry );
801 :
802 : // conditions to disallow the drop
803 : // 0) the root entry is part of the list (can't DnD the root!)
804 : // 1) one of the draged entries is to be dropped onto it's own parent
805 : // 2) - " - is to be dropped onto itself
806 : // 3) - " - is a Form and to be dropped onto one of it's descendants
807 : // 4) one of the entries is a control and to be dropped onto the root
808 : // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling
809 : // means moving the control)
810 :
811 : // collect the ancestors of the drop targte (speeds up 3)
812 0 : SvLBoxEntrySortedArray arrDropAnchestors;
813 0 : SvTreeListEntry* pLoop = _pTargetEntry;
814 0 : while (pLoop)
815 : {
816 0 : arrDropAnchestors.insert(pLoop);
817 0 : pLoop = GetParent(pLoop);
818 : }
819 :
820 0 : for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
821 0 : dropped != aDropped.end();
822 : ++dropped
823 : )
824 : {
825 0 : SvTreeListEntry* pCurrent = *dropped;
826 0 : SvTreeListEntry* pCurrentParent = GetParent(pCurrent);
827 :
828 : // test for 0)
829 0 : if (pCurrent == m_pRootEntry)
830 0 : return DND_ACTION_NONE;
831 :
832 : // test for 1)
833 0 : if ( _pTargetEntry == pCurrentParent )
834 0 : return DND_ACTION_NONE;
835 :
836 : // test for 2)
837 0 : if (pCurrent == _pTargetEntry)
838 0 : return DND_ACTION_NONE;
839 :
840 : // test for 5)
841 : // if ( bDropTargetIsComponent && (pDropTargetParent != pCurrentParent) )
842 0 : if ( bDropTargetIsComponent ) // TODO : the line above can be inserted, if ExecuteDrop can handle inversion
843 0 : return DND_ACTION_NONE;
844 :
845 : // test for 3)
846 0 : if ( IsFormEntry(pCurrent) )
847 : {
848 0 : if ( arrDropAnchestors.find(pCurrent) != arrDropAnchestors.end() )
849 0 : return DND_ACTION_NONE;
850 0 : } else if ( IsFormComponentEntry(pCurrent) )
851 : {
852 : // test for 4)
853 0 : if (_pTargetEntry == m_pRootEntry)
854 0 : return DND_ACTION_NONE;
855 : }
856 : }
857 :
858 0 : return DND_ACTION_MOVE;
859 : }
860 :
861 :
862 0 : sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& rEvt )
863 : {
864 0 : ::Point aDropPos = rEvt.maPosPixel;
865 :
866 : // first handle possible DropActions (Scroll and swing open)
867 0 : if (rEvt.mbLeaving)
868 : {
869 0 : if (m_aDropActionTimer.IsActive())
870 0 : m_aDropActionTimer.Stop();
871 : } else
872 : {
873 0 : bool bNeedTrigger = false;
874 : // on the first entry ?
875 0 : if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight()))
876 : {
877 0 : m_aDropActionType = DA_SCROLLUP;
878 0 : bNeedTrigger = true;
879 : } else
880 : // on the last one (respectively the area, an entry would tale, if it flush with the bottom ?
881 0 : if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight()))
882 : {
883 0 : m_aDropActionType = DA_SCROLLDOWN;
884 0 : bNeedTrigger = true;
885 : } else
886 : { // on an entry with children, not swang open
887 0 : SvTreeListEntry* pDropppedOn = GetEntry(aDropPos);
888 0 : if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn))
889 : {
890 : // -> swing open
891 0 : m_aDropActionType = DA_EXPANDNODE;
892 0 : bNeedTrigger = true;
893 : }
894 : }
895 :
896 0 : if (bNeedTrigger && (m_aTimerTriggered != aDropPos))
897 : {
898 : // restart counting
899 0 : m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS;
900 : // remember pos, because i get AcceptDrops, although mouse hasn't moved
901 0 : m_aTimerTriggered = aDropPos;
902 : // start Timer
903 0 : if (!m_aDropActionTimer.IsActive()) // exist Timer?
904 : {
905 0 : m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE);
906 0 : m_aDropActionTimer.Start();
907 : }
908 0 : } else if (!bNeedTrigger)
909 0 : m_aDropActionTimer.Stop();
910 : }
911 :
912 0 : return implAcceptDataTransfer( GetDataFlavorExVector(), rEvt.mnAction, aDropPos, true );
913 : }
914 :
915 :
916 0 : sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const ::Point& _rDropPos, bool _bDnD )
917 : {
918 0 : return implExecuteDataTransfer( _rData, _nAction, GetEntry( _rDropPos ), _bDnD );
919 : }
920 :
921 :
922 0 : sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, SvTreeListEntry* _pTargetEntry, bool _bDnD )
923 : {
924 0 : const DataFlavorExVector& rDataFlavors = _rData.GetDataFlavorExVector();
925 :
926 0 : if ( DND_ACTION_NONE == implAcceptDataTransfer( rDataFlavors, _nAction, _pTargetEntry, _bDnD ) )
927 : // under some platforms, it may happen that ExecuteDrop is called though AcceptDrop returned DND_ACTION_NONE
928 0 : return DND_ACTION_NONE;
929 :
930 : // would be bad, if we scroll after drop
931 0 : if (m_aDropActionTimer.IsActive())
932 0 : m_aDropActionTimer.Stop();
933 :
934 0 : if (!_pTargetEntry)
935 : // no target -> no drop
936 0 : return DND_ACTION_NONE;
937 :
938 : // format checks
939 : #ifdef DBG_UTIL
940 : bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( rDataFlavors );
941 : bool bForeignCollection = _rData.getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get();
942 : DBG_ASSERT(!bForeignCollection || bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: invalid format (AcceptDrop shouldn't have let this pass) !");
943 : DBG_ASSERT(bForeignCollection || !m_bDragDataDirty, "NavigatorTree::implExecuteDataTransfer: invalid state (shell changed since last exchange resync) !");
944 : // this should be done in AcceptDrop : the list of conrtols is created in _rData
945 : // and m_bDragDataDirty is reseted
946 : #endif
947 :
948 0 : if ( DND_ACTION_COPY == _nAction )
949 : { // bHasHiddenControlsFormat means that only hidden controls are part of the data
950 : DBG_ASSERT( bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: copy allowed for hidden controls only!" );
951 : DBG_ASSERT( _pTargetEntry && ( _pTargetEntry != m_pRootEntry ) && IsFormEntry( _pTargetEntry ),
952 : "NavigatorTree::implExecuteDataTransfer: should not be here!" );
953 : // implAcceptDataTransfer should have caught both cases
954 :
955 : DBG_ASSERT(bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: only copying of hidden controls is supported !");
956 : // should be catched by AcceptDrop
957 :
958 : // because i want to select all targets (and only them)
959 0 : SelectAll(false);
960 :
961 0 : Sequence< Reference< XInterface > > aControls = _rData.hiddenControls();
962 0 : sal_Int32 nCount = aControls.getLength();
963 0 : const Reference< XInterface >* pControls = aControls.getConstArray();
964 :
965 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
966 0 : FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
967 :
968 : // within undo
969 0 : if (pFormModel)
970 : {
971 0 : OUString aStr(SVX_RESSTR(RID_STR_CONTROL));
972 0 : OUString aUndoStr = SVX_RESSTR(RID_STR_UNDO_CONTAINER_INSERT).replaceAll(OUString('#'), aStr);
973 0 : pFormModel->BegUndo(aUndoStr);
974 : }
975 :
976 : // copy controls
977 0 : for (sal_Int32 i=0; i<nCount; ++i)
978 : {
979 : // create new control
980 0 : OUString fControlName = FM_COMPONENT_HIDDEN;
981 0 : FmControlData* pNewControlData = NewControl( fControlName, _pTargetEntry, false);
982 0 : Reference< XPropertySet > xNewPropSet( pNewControlData->GetPropertySet() );
983 :
984 : // copy properties form old control to new one
985 0 : Reference< XPropertySet > xCurrent(pControls[i], UNO_QUERY);
986 : #if (OSL_DEBUG_LEVEL > 1)
987 : // check whether it is a hidden control
988 : sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID));
989 : OSL_ENSURE(nClassId == FormComponentType::HIDDENCONTROL, "NavigatorTree::implExecuteDataTransfer: invalid control in drop list !");
990 : // if SVX_FM_HIDDEN_CONTROLS-format exists, the sequence
991 : // should only contain hidden controls
992 : #endif // (OSL_DEBUG_LEVEL > 1)
993 0 : Reference< XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo());
994 0 : Sequence< Property> seqAllCurrentProps = xPropInfo->getProperties();
995 0 : Property* pAllCurrentProps = seqAllCurrentProps.getArray();
996 0 : for (sal_Int32 j=0; j<seqAllCurrentProps.getLength(); ++j)
997 : {
998 0 : OUString sCurrentProp = pAllCurrentProps[j].Name;
999 0 : if (((pAllCurrentProps[j].Attributes & PropertyAttribute::READONLY) == 0) && (sCurrentProp != FM_PROP_NAME))
1000 : { // (read-only attribs aren't set, ditto name,
1001 : // NewControl defined it uniquely
1002 0 : xNewPropSet->setPropertyValue(sCurrentProp, xCurrent->getPropertyValue(sCurrentProp));
1003 : }
1004 0 : }
1005 :
1006 0 : SvTreeListEntry* pToSelect = FindEntry(pNewControlData);
1007 0 : Select(pToSelect, true);
1008 0 : if (i == 0)
1009 0 : SetCurEntry(pToSelect);
1010 0 : }
1011 :
1012 0 : if (pFormModel)
1013 0 : pFormModel->EndUndo();
1014 :
1015 0 : return _nAction;
1016 : }
1017 :
1018 0 : if ( !OControlExchange::hasFieldExchangeFormat( _rData.GetDataFlavorExVector() ) )
1019 : {
1020 : // can't do anything without the internal format here ... usually happens when doing DnD or CnP
1021 : // over navigator boundaries
1022 0 : return DND_ACTION_NONE;
1023 : }
1024 :
1025 : // some data for the target
1026 0 : bool bDropTargetIsForm = IsFormEntry(_pTargetEntry);
1027 0 : FmFormData* pTargetData = bDropTargetIsForm ? static_cast<FmFormData*>(_pTargetEntry->GetUserData()) : NULL;
1028 :
1029 : DBG_ASSERT( DND_ACTION_COPY != _nAction, "NavigatorTree::implExecuteDataTransfer: somebody changed the logics!" );
1030 :
1031 : // list of dragged entries
1032 0 : ListBoxEntrySet aDropped = _rData.selected();
1033 : DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implExecuteDataTransfer: no entries!");
1034 :
1035 : // shell and model
1036 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1037 0 : FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL;
1038 0 : if (!pFormModel)
1039 0 : return DND_ACTION_NONE;
1040 :
1041 : // for Undo
1042 0 : const bool bUndo = pFormModel->IsUndoEnabled();
1043 :
1044 0 : if( bUndo )
1045 : {
1046 0 : OUString strUndoDescription(SVX_RESSTR(RID_STR_UNDO_CONTAINER_REPLACE));
1047 0 : pFormModel->BegUndo(strUndoDescription);
1048 : }
1049 :
1050 : // remove selection before adding an entry, so the mark doesn't flicker
1051 : // -> lock action of selection
1052 0 : LockSelectionHandling();
1053 :
1054 : // go through all dropped entries
1055 0 : for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin();
1056 0 : dropped != aDropped.end();
1057 : ++dropped
1058 : )
1059 : {
1060 : // some data of the current element
1061 0 : SvTreeListEntry* pCurrent = *dropped;
1062 : DBG_ASSERT(pCurrent != NULL, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1063 : DBG_ASSERT(GetParent(pCurrent) != NULL, "NavigatorTree::implExecuteDataTransfer: invalid entry");
1064 : // don't drag root
1065 :
1066 0 : FmEntryData* pCurrentUserData = static_cast<FmEntryData*>(pCurrent->GetUserData());
1067 :
1068 0 : Reference< XChild > xCurrentChild(pCurrentUserData->GetChildIFace(), UNO_QUERY);
1069 0 : Reference< XIndexContainer > xContainer(xCurrentChild->getParent(), UNO_QUERY);
1070 :
1071 0 : FmFormData* pCurrentParentUserData = static_cast<FmFormData*>(pCurrentUserData->GetParent());
1072 : DBG_ASSERT(pCurrentParentUserData == NULL || pCurrentParentUserData->ISA(FmFormData), "NavigatorTree::implExecuteDataTransfer: invalid parent");
1073 :
1074 : // remove from parent
1075 0 : if (pCurrentParentUserData)
1076 0 : pCurrentParentUserData->GetChildList()->remove( pCurrentUserData );
1077 : else
1078 0 : GetNavModel()->GetRootList()->remove( pCurrentUserData );
1079 :
1080 : // remove from container
1081 0 : sal_Int32 nIndex = getElementPos(xContainer, xCurrentChild);
1082 0 : GetNavModel()->m_pPropChangeList->Lock();
1083 : // UndoAction for removal
1084 0 : if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1085 : {
1086 : pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Removed,
1087 0 : xContainer, xCurrentChild, nIndex));
1088 : }
1089 0 : else if( !GetNavModel()->m_pPropChangeList->CanUndo() )
1090 : {
1091 0 : FmUndoContainerAction::DisposeElement( xCurrentChild );
1092 : }
1093 :
1094 : // copy events
1095 0 : Reference< XEventAttacherManager > xManager(xContainer, UNO_QUERY);
1096 0 : Sequence< ScriptEventDescriptor > aEvts;
1097 :
1098 0 : if (xManager.is() && nIndex >= 0)
1099 0 : aEvts = xManager->getScriptEvents(nIndex);
1100 0 : xContainer->removeByIndex(nIndex);
1101 :
1102 : // remove selection
1103 0 : Select(pCurrent, false);
1104 : // and delete it
1105 0 : Remove(pCurrentUserData);
1106 :
1107 : // position in DropParents, where to insert dropped entries
1108 0 : if (pTargetData)
1109 0 : xContainer = Reference< XIndexContainer > (pTargetData->GetElement(), UNO_QUERY);
1110 : else
1111 0 : xContainer = Reference< XIndexContainer > (GetNavModel()->GetForms(), UNO_QUERY);
1112 :
1113 : // allways insert at the end
1114 0 : nIndex = xContainer->getCount();
1115 :
1116 : // UndoAction for insertion
1117 0 : if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo())
1118 : pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Inserted,
1119 0 : xContainer, xCurrentChild, nIndex));
1120 :
1121 : // insert in new container
1122 0 : if (pTargetData)
1123 : {
1124 : // insert in a form needs a FormComponent
1125 0 : xContainer->insertByIndex( nIndex,
1126 0 : makeAny( Reference< XFormComponent >( xCurrentChild, UNO_QUERY ) ) );
1127 : }
1128 : else
1129 : {
1130 0 : xContainer->insertByIndex( nIndex,
1131 0 : makeAny( Reference< XForm >( xCurrentChild, UNO_QUERY ) ) );
1132 : }
1133 :
1134 0 : if (aEvts.getLength())
1135 : {
1136 0 : xManager = Reference< XEventAttacherManager > (xContainer, UNO_QUERY);
1137 0 : if (xManager.is())
1138 0 : xManager->registerScriptEvents(nIndex, aEvts);
1139 : }
1140 :
1141 0 : GetNavModel()->m_pPropChangeList->UnLock();
1142 :
1143 : // give an entry the new parent
1144 0 : pCurrentUserData->SetParent(pTargetData);
1145 :
1146 : // give parent the new child
1147 0 : if (pTargetData)
1148 0 : pTargetData->GetChildList()->insert( pCurrentUserData, nIndex );
1149 : else
1150 0 : GetNavModel()->GetRootList()->insert( pCurrentUserData, nIndex );
1151 :
1152 : // announce to myself and reselect
1153 0 : SvTreeListEntry* pNew = Insert( pCurrentUserData, nIndex );
1154 0 : if ( ( aDropped.begin() == dropped ) && pNew )
1155 : {
1156 0 : SvTreeListEntry* pParent = GetParent( pNew );
1157 0 : if ( pParent )
1158 0 : Expand( pParent );
1159 : }
1160 0 : }
1161 :
1162 0 : UnlockSelectionHandling();
1163 :
1164 0 : if( bUndo )
1165 0 : pFormModel->EndUndo();
1166 :
1167 : // During the move, the markings of the underlying view did not change (because the view is not affected by the logical
1168 : // hierarchy of the form/control models. But my selection changed - which means I have to adjust it according to the
1169 : // view marks, again.
1170 0 : SynchronizeSelection();
1171 :
1172 : // in addition, with the move of controls such things as "the current form" may have changed - force the shell
1173 : // to update itself accordingly
1174 0 : if( pFormShell && pFormShell->GetImpl() && pFormShell->GetFormView() )
1175 0 : pFormShell->GetImpl()->DetermineSelection( pFormShell->GetFormView()->GetMarkedObjectList() );
1176 :
1177 0 : if ( m_aControlExchange.isClipboardOwner() && ( DND_ACTION_MOVE == _nAction ) )
1178 0 : m_aControlExchange->clear();
1179 :
1180 0 : return _nAction;
1181 : }
1182 :
1183 :
1184 0 : sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& rEvt )
1185 : {
1186 0 : sal_Int8 nResult( DND_ACTION_NONE );
1187 :
1188 0 : if ( m_aControlExchange.isDragSource() )
1189 0 : nResult = implExecuteDataTransfer( *m_aControlExchange, rEvt.mnAction, rEvt.maPosPixel, true );
1190 : else
1191 : {
1192 0 : OControlTransferData aDroppedData( rEvt.maDropEvent.Transferable );
1193 0 : nResult = implExecuteDataTransfer( aDroppedData, rEvt.mnAction, rEvt.maPosPixel, true );
1194 : }
1195 :
1196 0 : return nResult;
1197 : }
1198 :
1199 :
1200 0 : void NavigatorTree::doPaste()
1201 : {
1202 : try
1203 : {
1204 0 : if ( m_aControlExchange.isClipboardOwner() )
1205 : {
1206 0 : implExecuteDataTransfer( *m_aControlExchange, doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY, FirstSelected(), false );
1207 : }
1208 : else
1209 : {
1210 : // the clipboard content
1211 0 : Reference< XClipboard > xClipboard( GetClipboard() );
1212 0 : Reference< XTransferable > xTransferable;
1213 0 : if ( xClipboard.is() )
1214 0 : xTransferable = xClipboard->getContents();
1215 :
1216 0 : OControlTransferData aClipboardContent( xTransferable );
1217 0 : implExecuteDataTransfer( aClipboardContent, DND_ACTION_COPY, FirstSelected(), false );
1218 : }
1219 : }
1220 0 : catch( const Exception& )
1221 : {
1222 : OSL_FAIL( "NavigatorTree::doPaste: caught an exception!" );
1223 : }
1224 0 : }
1225 :
1226 :
1227 0 : void NavigatorTree::doCopy()
1228 : {
1229 0 : if ( implPrepareExchange( DND_ACTION_COPY ) )
1230 : {
1231 0 : m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1232 0 : m_aControlExchange.copyToClipboard( );
1233 : }
1234 0 : }
1235 :
1236 :
1237 0 : void NavigatorTree::ModelHasRemoved( SvTreeListEntry* _pEntry )
1238 : {
1239 0 : SvTreeListEntry* pTypedEntry = static_cast< SvTreeListEntry* >( _pEntry );
1240 0 : if ( doingKeyboardCut() )
1241 0 : m_aCutEntries.erase( pTypedEntry );
1242 :
1243 0 : if ( m_aControlExchange.isDataExchangeActive() )
1244 : {
1245 0 : if ( 0 == m_aControlExchange->onEntryRemoved( pTypedEntry ) )
1246 : {
1247 : // last of the entries which we put into the clipboard has been deleted from the tree.
1248 : // Give up the clipboard ownership.
1249 0 : m_aControlExchange.clear();
1250 : }
1251 : }
1252 0 : }
1253 :
1254 :
1255 0 : void NavigatorTree::doCut()
1256 : {
1257 0 : if ( implPrepareExchange( DND_ACTION_MOVE ) )
1258 : {
1259 0 : m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) );
1260 0 : m_aControlExchange.copyToClipboard( );
1261 0 : m_bKeyboardCut = true;
1262 :
1263 : // mark all the entries we just "cut" into the clipboard as "nearly moved"
1264 0 : for ( SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1265 0 : it != m_arrCurrentSelection.end(); ++it )
1266 : {
1267 0 : SvTreeListEntry* pEntry = *it;
1268 0 : if ( pEntry )
1269 : {
1270 0 : m_aCutEntries.insert( pEntry );
1271 0 : pEntry->SetFlags( pEntry->GetFlags() | SvTLEntryFlags::SEMITRANSPARENT );
1272 0 : InvalidateEntry( pEntry );
1273 : }
1274 : }
1275 : }
1276 0 : }
1277 :
1278 :
1279 0 : void NavigatorTree::KeyInput(const ::KeyEvent& rKEvt)
1280 : {
1281 0 : const vcl::KeyCode& rCode = rKEvt.GetKeyCode();
1282 :
1283 : // delete?
1284 0 : if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE && !rKEvt.GetKeyCode().GetModifier())
1285 : {
1286 0 : DeleteSelection();
1287 0 : return;
1288 : }
1289 :
1290 : // copy'n'paste?
1291 0 : switch ( rCode.GetFunction() )
1292 : {
1293 : case KeyFuncType::CUT:
1294 0 : doCut();
1295 0 : break;
1296 :
1297 : case KeyFuncType::PASTE:
1298 0 : if ( implAcceptPaste() )
1299 0 : doPaste();
1300 0 : break;
1301 :
1302 : case KeyFuncType::COPY:
1303 0 : doCopy();
1304 0 : break;
1305 :
1306 : default:
1307 0 : break;
1308 : }
1309 :
1310 0 : SvTreeListBox::KeyInput(rKEvt);
1311 : }
1312 :
1313 :
1314 0 : bool NavigatorTree::EditingEntry( SvTreeListEntry* pEntry, ::Selection& rSelection )
1315 : {
1316 0 : if (!SvTreeListBox::EditingEntry( pEntry, rSelection ))
1317 0 : return false;
1318 :
1319 0 : return (pEntry && (pEntry->GetUserData() != NULL));
1320 : // root, which isn't allowed to be renamed, has UserData=NULL
1321 : }
1322 :
1323 :
1324 0 : void NavigatorTree::NewForm( SvTreeListEntry* pParentEntry )
1325 : {
1326 :
1327 : // get ParentFormData
1328 0 : if( !IsFormEntry(pParentEntry) )
1329 0 : return;
1330 :
1331 0 : FmFormData* pParentFormData = static_cast<FmFormData*>(pParentEntry->GetUserData());
1332 :
1333 :
1334 : // create new form
1335 0 : Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
1336 0 : Reference< XForm > xNewForm(xContext->getServiceManager()->createInstanceWithContext(FM_SUN_COMPONENT_FORM, xContext), UNO_QUERY);
1337 0 : if (!xNewForm.is())
1338 0 : return;
1339 :
1340 0 : FmFormData* pNewFormData = new FmFormData( xNewForm, m_aNavigatorImages, pParentFormData );
1341 :
1342 :
1343 : // set name
1344 0 : OUString aName = GenerateName(pNewFormData);
1345 0 : pNewFormData->SetText(aName);
1346 :
1347 0 : Reference< XPropertySet > xPropertySet(xNewForm, UNO_QUERY);
1348 0 : if (!xPropertySet.is())
1349 0 : return;
1350 : try
1351 : {
1352 0 : xPropertySet->setPropertyValue( FM_PROP_NAME, makeAny(aName) );
1353 : // a form should always have the command type table as default
1354 0 : xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE)));
1355 : }
1356 0 : catch ( const Exception& )
1357 : {
1358 : OSL_FAIL("NavigatorTree::NewForm : could not set esssential properties !");
1359 : }
1360 :
1361 :
1362 :
1363 : // insert form
1364 0 : GetNavModel()->Insert( pNewFormData, TREELIST_APPEND, true );
1365 :
1366 :
1367 : // set new form as active
1368 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1369 0 : if( pFormShell )
1370 : {
1371 0 : InterfaceBag aSelection;
1372 0 : aSelection.insert( Reference<XInterface>( xNewForm, UNO_QUERY ) );
1373 0 : pFormShell->GetImpl()->setCurrentSelection( aSelection );
1374 :
1375 0 : pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES, true, true);
1376 : }
1377 0 : GetNavModel()->SetModified();
1378 :
1379 :
1380 : // switch to EditMode
1381 0 : SvTreeListEntry* pNewEntry = FindEntry( pNewFormData );
1382 0 : EditEntry( pNewEntry );
1383 : }
1384 :
1385 :
1386 0 : FmControlData* NavigatorTree::NewControl( const OUString& rServiceName, SvTreeListEntry* pParentEntry, bool bEditName )
1387 : {
1388 :
1389 : // get ParentForm
1390 0 : if (!GetNavModel()->GetFormShell())
1391 0 : return NULL;
1392 0 : if (!IsFormEntry(pParentEntry))
1393 0 : return NULL;
1394 :
1395 0 : FmFormData* pParentFormData = static_cast<FmFormData*>(pParentEntry->GetUserData());
1396 0 : Reference< XForm > xParentForm( pParentFormData->GetFormIface());
1397 :
1398 :
1399 : // create new component
1400 0 : Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
1401 0 : Reference<XFormComponent> xNewComponent( xContext->getServiceManager()->createInstanceWithContext(rServiceName, xContext), UNO_QUERY);
1402 0 : if (!xNewComponent.is())
1403 0 : return NULL;
1404 :
1405 0 : FmControlData* pNewFormControlData = new FmControlData( xNewComponent, m_aNavigatorImages, pParentFormData );
1406 :
1407 :
1408 : // set name
1409 0 : OUString sName = FmFormPageImpl::setUniqueName( xNewComponent, xParentForm );
1410 :
1411 0 : pNewFormControlData->SetText( sName );
1412 :
1413 :
1414 : // insert FormComponent
1415 0 : GetNavModel()->Insert( pNewFormControlData, TREELIST_APPEND, true );
1416 0 : GetNavModel()->SetModified();
1417 :
1418 0 : if (bEditName)
1419 : {
1420 :
1421 : // switch to EditMode
1422 0 : SvTreeListEntry* pNewEntry = FindEntry( pNewFormControlData );
1423 0 : Select( pNewEntry, true );
1424 0 : EditEntry( pNewEntry );
1425 : }
1426 :
1427 0 : return pNewFormControlData;
1428 : }
1429 :
1430 :
1431 0 : OUString NavigatorTree::GenerateName( FmEntryData* pEntryData )
1432 : {
1433 0 : const sal_uInt16 nMaxCount = 99;
1434 0 : OUString aNewName;
1435 :
1436 :
1437 : // create base name
1438 0 : OUString aBaseName;
1439 0 : if( pEntryData->ISA(FmFormData) )
1440 0 : aBaseName = SVX_RESSTR( RID_STR_STDFORMNAME );
1441 0 : else if( pEntryData->ISA(FmControlData) )
1442 0 : aBaseName = SVX_RESSTR( RID_STR_CONTROL );
1443 :
1444 :
1445 : // create new name
1446 0 : FmFormData* pFormParentData = static_cast<FmFormData*>(pEntryData->GetParent());
1447 :
1448 0 : for( sal_Int32 i=0; i<nMaxCount; i++ )
1449 : {
1450 0 : aNewName = aBaseName;
1451 0 : if( i>0 )
1452 : {
1453 0 : aNewName += " ";
1454 0 : aNewName += OUString::number(i).getStr();
1455 : }
1456 :
1457 0 : if( GetNavModel()->FindData(aNewName, pFormParentData,false) == NULL )
1458 0 : break;
1459 : }
1460 :
1461 0 : return aNewName;
1462 : }
1463 :
1464 :
1465 0 : bool NavigatorTree::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
1466 : {
1467 0 : if (EditingCanceled())
1468 0 : return true;
1469 :
1470 0 : GrabFocus();
1471 0 : FmEntryData* pEntryData = static_cast<FmEntryData*>(pEntry->GetUserData());
1472 0 : bool bRes = NavigatorTreeModel::Rename( pEntryData, rNewText);
1473 0 : if( !bRes )
1474 : {
1475 0 : m_pEditEntry = pEntry;
1476 0 : nEditEvent = Application::PostUserEvent( LINK(this, NavigatorTree, OnEdit), NULL, true );
1477 : } else
1478 0 : SetCursor(pEntry, true);
1479 :
1480 0 : return bRes;
1481 : }
1482 :
1483 :
1484 0 : IMPL_LINK_NOARG(NavigatorTree, OnEdit)
1485 : {
1486 0 : nEditEvent = 0;
1487 0 : EditEntry( m_pEditEntry );
1488 0 : m_pEditEntry = NULL;
1489 :
1490 0 : return 0L;
1491 : }
1492 :
1493 :
1494 0 : IMPL_LINK_NOARG_TYPED(NavigatorTree, OnDropActionTimer, Timer *, void)
1495 : {
1496 0 : if (--m_aTimerCounter > 0)
1497 0 : return;
1498 :
1499 0 : switch ( m_aDropActionType )
1500 : {
1501 : case DA_EXPANDNODE:
1502 : {
1503 0 : SvTreeListEntry* pToExpand = GetEntry(m_aTimerTriggered);
1504 0 : if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand))
1505 : // normaly, we have to test, if the node is expanded,
1506 : // but there is no method for this either in base class nor the model
1507 : // the base class should tolerate it anyway
1508 0 : Expand(pToExpand);
1509 :
1510 : // After expansion there is nothing to do like after scrolling
1511 0 : m_aDropActionTimer.Stop();
1512 : }
1513 0 : break;
1514 :
1515 : case DA_SCROLLUP :
1516 0 : ScrollOutputArea( 1 );
1517 0 : m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1518 0 : break;
1519 :
1520 : case DA_SCROLLDOWN :
1521 0 : ScrollOutputArea( -1 );
1522 0 : m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS;
1523 0 : break;
1524 :
1525 : }
1526 : }
1527 :
1528 :
1529 0 : IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/)
1530 : {
1531 0 : m_sdiState = SDI_DIRTY;
1532 :
1533 0 : if (IsSelectionHandlingLocked())
1534 0 : return 0L;
1535 :
1536 0 : if (m_aSynchronizeTimer.IsActive())
1537 0 : m_aSynchronizeTimer.Stop();
1538 :
1539 0 : m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY);
1540 0 : m_aSynchronizeTimer.Start();
1541 :
1542 0 : return 0L;
1543 : }
1544 :
1545 :
1546 0 : IMPL_LINK_NOARG_TYPED(NavigatorTree, OnSynchronizeTimer, Timer *, void)
1547 : {
1548 0 : SynchronizeMarkList();
1549 0 : }
1550 :
1551 :
1552 :
1553 0 : IMPL_LINK_NOARG(NavigatorTree, OnClipboardAction)
1554 : {
1555 0 : if ( !m_aControlExchange.isClipboardOwner() )
1556 : {
1557 0 : if ( doingKeyboardCut() )
1558 : {
1559 0 : for ( ListBoxEntrySet::const_iterator i = m_aCutEntries.begin();
1560 0 : i != m_aCutEntries.end();
1561 : ++i
1562 : )
1563 : {
1564 0 : SvTreeListEntry* pEntry = *i;
1565 0 : if ( !pEntry )
1566 0 : continue;
1567 :
1568 0 : pEntry->SetFlags( pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT );
1569 0 : InvalidateEntry( pEntry );
1570 : }
1571 0 : ListBoxEntrySet aEmpty;
1572 0 : m_aCutEntries.swap( aEmpty );
1573 :
1574 0 : m_bKeyboardCut = false;
1575 : }
1576 : }
1577 0 : return 0L;
1578 : }
1579 :
1580 :
1581 0 : void NavigatorTree::ShowSelectionProperties(bool bForce)
1582 : {
1583 : // at first i need the FormShell
1584 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1585 0 : if (!pFormShell)
1586 : // no shell -> impossible to set curObject -> leave
1587 0 : return;
1588 :
1589 0 : CollectSelectionData(SDI_ALL);
1590 : SAL_WARN_IF(static_cast<size_t>(m_nFormsSelected + m_nControlsSelected
1591 : + (m_bRootSelected ? 1 : 0)) != m_arrCurrentSelection.size(),
1592 : "svx.form",
1593 : "NavigatorTree::ShowSelectionProperties : selection meta data invalid !");
1594 :
1595 :
1596 0 : InterfaceBag aSelection;
1597 0 : bool bSetSelectionAsMarkList = false;
1598 :
1599 0 : if (m_bRootSelected)
1600 : ; // no properties for the root, neither for single nor for multi selection
1601 0 : else if ( m_nFormsSelected + m_nControlsSelected == 0 ) // none of the two should be less 0
1602 : ; // no selection -> no properties
1603 0 : else if ( m_nFormsSelected * m_nControlsSelected != 0 )
1604 : ; // mixed selection -> no properties
1605 : else
1606 : { // either only forms, or only controls are selected
1607 0 : if (m_arrCurrentSelection.size() == 1)
1608 : {
1609 0 : if (m_nFormsSelected > 0)
1610 : { // exactly one form is selected
1611 0 : FmFormData* pFormData = static_cast<FmFormData*>((*m_arrCurrentSelection.begin())->GetUserData());
1612 0 : aSelection.insert( Reference< XInterface >( pFormData->GetFormIface(), UNO_QUERY ) );
1613 : }
1614 : else
1615 : { // exactly one control is selected (whatever hidden or normal)
1616 0 : FmEntryData* pEntryData = static_cast<FmEntryData*>((*m_arrCurrentSelection.begin())->GetUserData());
1617 :
1618 0 : aSelection.insert( Reference< XInterface >( pEntryData->GetElement(), UNO_QUERY ) );
1619 : }
1620 : }
1621 : else
1622 : { // it's a MultiSelection, so we must build a MultiSet
1623 0 : if (m_nFormsSelected > 0)
1624 : { // ... only forms
1625 : // first of all collect PropertySet-Interfaces of the forms
1626 0 : SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1627 0 : for ( sal_Int32 i = 0; i < m_nFormsSelected; ++i )
1628 : {
1629 0 : FmFormData* pFormData = static_cast<FmFormData*>((*it)->GetUserData());
1630 0 : aSelection.insert( pFormData->GetPropertySet().get() );
1631 0 : ++it;
1632 : }
1633 : }
1634 : else
1635 : { // ... only controls
1636 0 : if (m_nHiddenControls == m_nControlsSelected)
1637 : { // a MultiSet for properties of hidden controls
1638 0 : SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1639 0 : for ( sal_Int32 i = 0; i < m_nHiddenControls; ++i )
1640 : {
1641 0 : FmEntryData* pEntryData = static_cast<FmEntryData*>((*it)->GetUserData());
1642 0 : aSelection.insert( pEntryData->GetPropertySet().get() );
1643 0 : ++it;
1644 : }
1645 : }
1646 0 : else if (m_nHiddenControls == 0)
1647 : { // only normal controls
1648 0 : bSetSelectionAsMarkList = true;
1649 : }
1650 : }
1651 : }
1652 :
1653 : }
1654 :
1655 : // and now my form and my SelObject
1656 0 : if ( bSetSelectionAsMarkList )
1657 0 : pFormShell->GetImpl()->setCurrentSelectionFromMark( pFormShell->GetFormView()->GetMarkedObjectList() );
1658 : else
1659 0 : pFormShell->GetImpl()->setCurrentSelection( aSelection );
1660 :
1661 0 : if ( pFormShell->GetImpl()->IsPropBrwOpen() || bForce )
1662 : {
1663 : // and now deliver all to the PropertyBrowser
1664 0 : pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SfxCallMode::ASYNCHRON );
1665 0 : }
1666 : }
1667 :
1668 :
1669 0 : void NavigatorTree::DeleteSelection()
1670 : {
1671 : // of course, i can't delete root
1672 0 : bool bRootSelected = IsSelected(m_pRootEntry);
1673 0 : sal_uIntPtr nSelectedEntries = GetSelectionCount();
1674 0 : if (bRootSelected && (nSelectedEntries > 1)) // root and other elements ?
1675 0 : Select(m_pRootEntry, false); // yes -> remove root from selection
1676 :
1677 0 : if ((nSelectedEntries == 0) || bRootSelected) // still root ?
1678 0 : return; // -> only selected element -> leave
1679 :
1680 : DBG_ASSERT(!m_bPrevSelectionMixed, "NavigatorTree::DeleteSelection() : delete permitted if mark and selection are inconsistent");
1681 :
1682 : // i need the FormModel later
1683 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1684 0 : if (!pFormShell)
1685 0 : return;
1686 0 : FmFormModel* pFormModel = pFormShell->GetFormModel();
1687 0 : if (!pFormModel)
1688 0 : return;
1689 :
1690 : // now I have to safeguard the DeleteList: if you delete a form and a dependent element
1691 : // - in this order - than the SvLBoxEntryPtr of the dependent element is already invalid,
1692 : // when it should be deleted... you have to prohibit this GPF, that of course would happen,
1693 : // so I take the 'normalized' list
1694 0 : CollectSelectionData( SDI_NORMALIZED );
1695 :
1696 : // see below for why we need this mapping from models to shapes
1697 0 : FmFormView* pFormView = pFormShell->GetFormView();
1698 0 : SdrPageView* pPageView = pFormView ? pFormView->GetSdrPageView() : NULL;
1699 0 : SdrPage* pPage = pPageView ? pPageView->GetPage() : NULL;
1700 : DBG_ASSERT( pPage, "NavigatorTree::DeleteSelection: invalid form page!" );
1701 :
1702 0 : MapModelToShape aModelShapes;
1703 0 : if ( pPage )
1704 0 : collectShapeModelMapping( pPage, aModelShapes );
1705 :
1706 : // problem: we have to use ExplorerModel::Remove, since only this one properly deletes Form objects.
1707 : // But, the controls themself must be deleted via DeleteMarked (else, the Writer has some problems
1708 : // somewhere). In case I'd first delete the structure, then the controls, the UNDO would not work
1709 : // (since UNDO then would mean to first restore the controls, then the structure, means their parent
1710 : // form). The other way round, the EntryDatas would be invalid, if I'd first delete the controls and
1711 : // then go on to the strucure. This means I have to delete the forms *after* the normal controls, so
1712 : // that during UNDO, they're restored in the proper order.
1713 0 : pFormShell->GetImpl()->EnableTrackProperties(false);
1714 0 : for (SvLBoxEntrySortedArray::reverse_iterator it = m_arrCurrentSelection.rbegin();
1715 0 : it != m_arrCurrentSelection.rend(); )
1716 : {
1717 0 : FmEntryData* pCurrent = static_cast<FmEntryData*>((*it)->GetUserData());
1718 :
1719 : // a form ?
1720 0 : bool bIsForm = pCurrent->ISA(FmFormData);
1721 :
1722 : // because deletion is done by the view, and i build on its MarkList,
1723 : // but normally only direct controls, no indirect ones, are marked in a marked form,
1724 : // i have to do it later
1725 0 : if (bIsForm)
1726 0 : MarkViewObj(static_cast<FmFormData*>(pCurrent), true, true); // second sal_True means "deep"
1727 :
1728 : // a hidden control ?
1729 0 : bool bIsHidden = IsHiddenControl(pCurrent);
1730 :
1731 : // keep forms and hidden controls, the rest not
1732 0 : if (!bIsForm && !bIsHidden)
1733 : {
1734 : // well, no form and no hidden control -> we can remove it from m_arrCurrentSelection, as it will
1735 : // be deleted automatically. This is because for every model (except forms and hidden control models)
1736 : // there exist a shape, which is marked _if_and_only_if_ the model is selected in our tree.
1737 0 : if ( aModelShapes.find( pCurrent->GetElement() ) != aModelShapes.end() )
1738 : {
1739 : // if there's a shape for the current entry, then either it is marked or it is in a
1740 : // hidden layer (#i28502#), or something like this.
1741 : // In the first case, it will be deleted below, in the second case, we currently don't
1742 : // delete it, as there's no real (working!) API for this, neither in UNO nor in non-UNO.
1743 0 : m_arrCurrentSelection.erase( --(it.base()) );
1744 : }
1745 : else
1746 0 : ++it;
1747 : // In case there is no shape for the current entry, we keep the entry in m_arrCurrentSelection,
1748 : // since then we can definitely remove it.
1749 : // #103597#
1750 : }
1751 : else
1752 0 : ++it;
1753 : }
1754 0 : pFormShell->GetImpl()->EnableTrackProperties(true);
1755 :
1756 : // let the view delete the marked controls
1757 0 : pFormShell->GetFormView()->DeleteMarked();
1758 :
1759 : // start UNDO at this point. Unfortunately, this results in 2 UNDO actions, since DeleteMarked is
1760 : // creating an own one. However, if we'd move it before DeleteMarked, Writer doesi not really like
1761 : // this ... :(
1762 : // #i31038#
1763 : {
1764 :
1765 : // initialize UNDO
1766 0 : OUString aUndoStr;
1767 0 : if ( m_arrCurrentSelection.size() == 1 )
1768 : {
1769 0 : aUndoStr = SVX_RESSTR(RID_STR_UNDO_CONTAINER_REMOVE);
1770 0 : if (m_nFormsSelected)
1771 0 : aUndoStr = aUndoStr.replaceFirst( "#", SVX_RESSTR( RID_STR_FORM ) );
1772 : else
1773 : // it must be a control (else the root would be selected, but it cannot be deleted)
1774 0 : aUndoStr = aUndoStr.replaceFirst( "#", SVX_RESSTR( RID_STR_CONTROL ) );
1775 : }
1776 : else
1777 : {
1778 0 : aUndoStr = SVX_RESSTR(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE);
1779 0 : aUndoStr = aUndoStr.replaceFirst( "#", OUString::number( m_arrCurrentSelection.size() ) );
1780 : }
1781 0 : pFormModel->BegUndo(aUndoStr);
1782 : }
1783 :
1784 : // remove remaining structure
1785 0 : for (SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1786 0 : it != m_arrCurrentSelection.end(); ++it)
1787 : {
1788 0 : FmEntryData* pCurrent = static_cast<FmEntryData*>((*it)->GetUserData());
1789 :
1790 : // if the entry still has children, we skipped deletion of one of those children.
1791 : // This may for instance be because the shape is in a hidden layer, where we're unable
1792 : // to remove it
1793 0 : if ( pCurrent->GetChildList()->size() )
1794 0 : continue;
1795 :
1796 : // one remaining subtile problem, before deleting it : if it's a form and the shell
1797 : // knows it as CurrentObject, i have to tell it something else
1798 0 : if (pCurrent->ISA(FmFormData))
1799 : {
1800 0 : Reference< XForm > xCurrentForm( static_cast< FmFormData* >( pCurrent )->GetFormIface() );
1801 0 : if ( pFormShell->GetImpl()->getCurrentForm() == xCurrentForm ) // shell knows form to be deleted ?
1802 0 : pFormShell->GetImpl()->forgetCurrentForm(); // -> take away ...
1803 : }
1804 0 : GetNavModel()->Remove(pCurrent, true);
1805 : }
1806 0 : pFormModel->EndUndo();
1807 : }
1808 :
1809 :
1810 0 : void NavigatorTree::CollectSelectionData(SELDATA_ITEMS sdiHow)
1811 : {
1812 : DBG_ASSERT(sdiHow != SDI_DIRTY, "NavigatorTree::CollectSelectionData : ever thought about your parameter ? DIRTY ?");
1813 0 : if (sdiHow == m_sdiState)
1814 0 : return;
1815 :
1816 0 : m_arrCurrentSelection.clear();
1817 0 : m_nFormsSelected = m_nControlsSelected = m_nHiddenControls = 0;
1818 0 : m_bRootSelected = false;
1819 :
1820 0 : SvTreeListEntry* pSelectionLoop = FirstSelected();
1821 0 : while (pSelectionLoop)
1822 : {
1823 : // count different elements
1824 0 : if (pSelectionLoop == m_pRootEntry)
1825 0 : m_bRootSelected = true;
1826 : else
1827 : {
1828 0 : if (IsFormEntry(pSelectionLoop))
1829 0 : ++m_nFormsSelected;
1830 : else
1831 : {
1832 0 : ++m_nControlsSelected;
1833 0 : if (IsHiddenControl(static_cast<FmEntryData*>(pSelectionLoop->GetUserData())))
1834 0 : ++m_nHiddenControls;
1835 : }
1836 : }
1837 :
1838 0 : if (sdiHow == SDI_NORMALIZED)
1839 : {
1840 : // don't take something with a selected ancestor
1841 0 : if (pSelectionLoop == m_pRootEntry)
1842 0 : m_arrCurrentSelection.insert(pSelectionLoop);
1843 : else
1844 : {
1845 0 : SvTreeListEntry* pParentLoop = GetParent(pSelectionLoop);
1846 0 : while (pParentLoop)
1847 : {
1848 : // actually i would have to test, if parent is part of m_arr_CurrentSelection ...
1849 : // but if it's selected, than it's in m_arrCurrentSelection
1850 : // or one of it's ancestors, which was selected earlier.
1851 : // In both cases IsSelected is enough
1852 0 : if (IsSelected(pParentLoop))
1853 0 : break;
1854 : else
1855 : {
1856 0 : if (m_pRootEntry == pParentLoop)
1857 : {
1858 : // until root (exclusive), there was no selected parent -> entry belongs to normalized list
1859 0 : m_arrCurrentSelection.insert(pSelectionLoop);
1860 0 : break;
1861 : }
1862 : else
1863 0 : pParentLoop = GetParent(pParentLoop);
1864 : }
1865 : }
1866 : }
1867 : }
1868 0 : else if (sdiHow == SDI_NORMALIZED_FORMARK)
1869 : {
1870 0 : SvTreeListEntry* pParent = GetParent(pSelectionLoop);
1871 0 : if (!pParent || !IsSelected(pParent) || IsFormEntry(pSelectionLoop))
1872 0 : m_arrCurrentSelection.insert(pSelectionLoop);
1873 : }
1874 : else
1875 0 : m_arrCurrentSelection.insert(pSelectionLoop);
1876 :
1877 :
1878 0 : pSelectionLoop = NextSelected(pSelectionLoop);
1879 : }
1880 :
1881 0 : m_sdiState = sdiHow;
1882 : }
1883 :
1884 :
1885 0 : void NavigatorTree::SynchronizeSelection(FmEntryDataArray& arredToSelect)
1886 : {
1887 0 : LockSelectionHandling();
1888 0 : if (arredToSelect.empty())
1889 : {
1890 0 : SelectAll(false);
1891 : }
1892 : else
1893 : {
1894 : // compare current selection with requested SelectList
1895 0 : SvTreeListEntry* pSelection = FirstSelected();
1896 0 : while (pSelection)
1897 : {
1898 0 : FmEntryData* pCurrent = static_cast<FmEntryData*>(pSelection->GetUserData());
1899 0 : if (pCurrent != NULL)
1900 : {
1901 0 : FmEntryDataArray::iterator it = arredToSelect.find(pCurrent);
1902 0 : if ( it != arredToSelect.end() )
1903 : { // entry already selected, but also in SelectList
1904 : // remove it from there
1905 0 : arredToSelect.erase(it);
1906 : } else
1907 : { // entry selected, but not in SelectList -> remove selection
1908 0 : Select(pSelection, false);
1909 : // make it visible (maybe it's the only modification i do in this handler
1910 : // so you should see it
1911 0 : MakeVisible(pSelection);
1912 : }
1913 : }
1914 : else
1915 0 : Select(pSelection, false);
1916 :
1917 0 : pSelection = NextSelected(pSelection);
1918 : }
1919 :
1920 : // now SelectList contains only entries, which have to be selected
1921 : // two possabilities : 1) run through SelectList, get SvTreeListEntry for every entry and select it (is more intuitive)
1922 : // 2) run through my SvLBoxEntries and select those, i can find in the SelectList
1923 : // 1) needs =(k*n) (k=length of SelectList, n=number of entries),
1924 : // plus the fact, that FindEntry uses extensive IsEqualWithoutChilden instead of comparing pointer to UserData
1925 : // 2) needs =(n*log k), dublicates some code from FindEntry
1926 : // This may be a frequently used code ( at every change in mark of the view!),
1927 : // so i use latter one
1928 0 : SvTreeListEntry* pLoop = First();
1929 0 : while( pLoop )
1930 : {
1931 0 : FmEntryData* pCurEntryData = static_cast<FmEntryData*>(pLoop->GetUserData());
1932 0 : FmEntryDataArray::iterator it = arredToSelect.find(pCurEntryData);
1933 0 : if ( it != arredToSelect.end() )
1934 : {
1935 0 : Select(pLoop, true);
1936 0 : MakeVisible(pLoop);
1937 0 : SetCursor(pLoop, true);
1938 : }
1939 :
1940 0 : pLoop = Next( pLoop );
1941 : }
1942 : }
1943 0 : UnlockSelectionHandling();
1944 0 : }
1945 :
1946 :
1947 0 : void NavigatorTree::SynchronizeSelection()
1948 : {
1949 : // shell and view
1950 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1951 0 : if(!pFormShell) return;
1952 :
1953 0 : FmFormView* pFormView = pFormShell->GetFormView();
1954 0 : if (!pFormView) return;
1955 :
1956 0 : GetNavModel()->BroadcastMarkedObjects(pFormView->GetMarkedObjectList());
1957 : }
1958 :
1959 :
1960 0 : void NavigatorTree::SynchronizeMarkList()
1961 : {
1962 : // i'll need this shell
1963 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
1964 0 : if (!pFormShell) return;
1965 :
1966 0 : CollectSelectionData(SDI_NORMALIZED_FORMARK);
1967 :
1968 : // the view shouldn't notify now if MarkList changed
1969 0 : pFormShell->GetImpl()->EnableTrackProperties(false);
1970 :
1971 0 : UnmarkAllViewObj();
1972 :
1973 0 : for (SvLBoxEntrySortedArray::const_iterator it = m_arrCurrentSelection.begin();
1974 0 : it != m_arrCurrentSelection.end(); ++it)
1975 : {
1976 0 : SvTreeListEntry* pSelectionLoop = *it;
1977 : // When form selection, mark all controls of form
1978 0 : if (IsFormEntry(pSelectionLoop) && (pSelectionLoop != m_pRootEntry))
1979 0 : MarkViewObj(static_cast<FmFormData*>(pSelectionLoop->GetUserData()), true, false);
1980 :
1981 : // When control selection, mark Control-SdrObjects
1982 0 : else if (IsFormComponentEntry(pSelectionLoop))
1983 : {
1984 0 : FmControlData* pControlData = static_cast<FmControlData*>(pSelectionLoop->GetUserData());
1985 0 : if (pControlData)
1986 : {
1987 :
1988 : // When HiddenControl no object can be selected
1989 0 : Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
1990 0 : if (!xFormComponent.is())
1991 0 : continue;
1992 0 : Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY);
1993 0 : if (!xSet.is())
1994 0 : continue;
1995 :
1996 0 : sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID));
1997 0 : if (nClassId != FormComponentType::HIDDENCONTROL)
1998 0 : MarkViewObj(pControlData, true, true);
1999 : }
2000 : }
2001 : }
2002 :
2003 : // if PropertyBrowser is open, i have to adopt it according to my selection
2004 : // (Not as MarkList of view : if a form is selected, all belonging controls are selected in the view
2005 : // but of course i want to see the form-properties
2006 0 : ShowSelectionProperties(false);
2007 :
2008 : // reset flag at view
2009 0 : pFormShell->GetImpl()->EnableTrackProperties(true);
2010 :
2011 : // if exactly one form is selected now, shell should notice it as CurrentForm
2012 : // (if selection handling isn't locked, view cares about it in MarkListHasChanged
2013 : // but mechanism doesn't work, if form is empty for example
2014 0 : if ((m_arrCurrentSelection.size() == 1) && (m_nFormsSelected == 1))
2015 : {
2016 0 : FmFormData* pSingleSelectionData = PTR_CAST( FmFormData, static_cast< FmEntryData* >( FirstSelected()->GetUserData() ) );
2017 : DBG_ASSERT( pSingleSelectionData, "NavigatorTree::SynchronizeMarkList: invalid selected form!" );
2018 0 : if ( pSingleSelectionData )
2019 : {
2020 0 : InterfaceBag aSelection;
2021 0 : aSelection.insert( Reference< XInterface >( pSingleSelectionData->GetFormIface(), UNO_QUERY ) );
2022 0 : pFormShell->GetImpl()->setCurrentSelection( aSelection );
2023 : }
2024 : }
2025 : }
2026 :
2027 :
2028 0 : bool NavigatorTree::IsHiddenControl(FmEntryData* pEntryData)
2029 : {
2030 0 : if (pEntryData == NULL) return false;
2031 :
2032 0 : Reference< XPropertySet > xProperties( pEntryData->GetPropertySet() );
2033 0 : if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties))
2034 : {
2035 0 : Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID );
2036 0 : return (::comphelper::getINT16(aClassID) == FormComponentType::HIDDENCONTROL);
2037 : }
2038 0 : return false;
2039 : }
2040 :
2041 :
2042 0 : bool NavigatorTree::Select( SvTreeListEntry* pEntry, bool bSelect )
2043 : {
2044 0 : if (bSelect == IsSelected(pEntry)) // this happens sometimes, maybe base class is to exact ;)
2045 0 : return true;
2046 :
2047 0 : return SvTreeListBox::Select(pEntry, bSelect );
2048 : }
2049 :
2050 :
2051 0 : void NavigatorTree::UnmarkAllViewObj()
2052 : {
2053 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2054 0 : if( !pFormShell )
2055 0 : return;
2056 0 : FmFormView* pFormView = pFormShell->GetFormView();
2057 0 : pFormView->UnMarkAll();
2058 : }
2059 :
2060 0 : void NavigatorTree::MarkViewObj(FmFormData* pFormData, bool bMark, bool bDeep )
2061 : {
2062 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2063 0 : if( !pFormShell )
2064 0 : return;
2065 :
2066 : // first collect all sdrobjects
2067 0 : ::std::set< Reference< XFormComponent > > aObjects;
2068 0 : CollectObjects(pFormData,bDeep,aObjects);
2069 :
2070 :
2071 : // find and select appropriate SdrObj in page
2072 0 : FmFormView* pFormView = pFormShell->GetFormView();
2073 0 : SdrPageView* pPageView = pFormView->GetSdrPageView();
2074 0 : SdrPage* pPage = pPageView->GetPage();
2075 : //FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage );
2076 :
2077 0 : SdrObjListIter aIter( *pPage );
2078 0 : while ( aIter.IsMore() )
2079 : {
2080 0 : SdrObject* pSdrObject = aIter.Next();
2081 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
2082 0 : if ( !pFormObject )
2083 0 : continue;
2084 :
2085 0 : Reference< XFormComponent > xControlModel( pFormObject->GetUnoControlModel(),UNO_QUERY );
2086 0 : if ( xControlModel.is() && aObjects.find(xControlModel) != aObjects.end() && bMark != pFormView->IsObjMarked( pSdrObject ) )
2087 : {
2088 : // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
2089 0 : pFormView->MarkObj( pSdrObject, pPageView, !bMark, false );
2090 : }
2091 0 : } // while ( aIter.IsMore() )
2092 0 : if ( bMark )
2093 : {
2094 : // make the mark visible
2095 0 : ::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
2096 0 : for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2097 : {
2098 0 : SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
2099 0 : OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
2100 0 : if ( ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) && !aMarkRect.IsEmpty() )
2101 : {
2102 0 : pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
2103 : }
2104 : } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2105 0 : }
2106 : }
2107 :
2108 0 : void NavigatorTree::CollectObjects(FmFormData* pFormData, bool bDeep, ::std::set< Reference< XFormComponent > >& _rObjects)
2109 : {
2110 0 : FmEntryDataList* pChildList = pFormData->GetChildList();
2111 : FmControlData* pControlData;
2112 0 : for( size_t i = 0; i < pChildList->size(); ++i )
2113 : {
2114 0 : FmEntryData* pEntryData = pChildList->at( i );
2115 0 : if( pEntryData->ISA(FmControlData) )
2116 : {
2117 0 : pControlData = static_cast<FmControlData*>(pEntryData);
2118 0 : _rObjects.insert(pControlData->GetFormComponent());
2119 : } // if( pEntryData->ISA(FmControlData) )
2120 0 : else if (bDeep && (pEntryData->ISA(FmFormData)))
2121 0 : CollectObjects(static_cast<FmFormData*>(pEntryData), bDeep, _rObjects);
2122 : } // for( sal_uInt32 i=0; i<pChildList->Count(); i++ )
2123 0 : }
2124 :
2125 0 : void NavigatorTree::MarkViewObj( FmControlData* pControlData, bool bMarkHandles, bool bMark)
2126 : {
2127 0 : if( !pControlData )
2128 0 : return;
2129 0 : FmFormShell* pFormShell = GetNavModel()->GetFormShell();
2130 0 : if( !pFormShell )
2131 0 : return;
2132 :
2133 :
2134 : // find and select appropriate SdrObj
2135 0 : FmFormView* pFormView = pFormShell->GetFormView();
2136 0 : Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent());
2137 0 : SdrPageView* pPageView = pFormView->GetSdrPageView();
2138 0 : SdrPage* pPage = pPageView->GetPage();
2139 :
2140 0 : bool bPaint = false;
2141 0 : SdrObjListIter aIter( *pPage );
2142 0 : while ( aIter.IsMore() )
2143 : {
2144 0 : SdrObject* pSdrObject = aIter.Next();
2145 0 : FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject );
2146 0 : if ( !pFormObject )
2147 0 : continue;
2148 :
2149 0 : Reference< XInterface > xControlModel( pFormObject->GetUnoControlModel() );
2150 0 : if ( xControlModel != xFormComponent )
2151 0 : continue;
2152 :
2153 : // mark the object
2154 0 : if ( bMark != pFormView->IsObjMarked( pSdrObject ) )
2155 : // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first
2156 0 : pFormView->MarkObj( pSdrObject, pPageView, !bMark, false );
2157 :
2158 0 : if ( !bMarkHandles || !bMark )
2159 0 : continue;
2160 :
2161 0 : bPaint = true;
2162 :
2163 0 : } // while ( aIter.IsMore() )
2164 0 : if ( bPaint )
2165 : {
2166 : // make the mark visible
2167 0 : ::Rectangle aMarkRect( pFormView->GetAllMarkedRect());
2168 0 : for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2169 : {
2170 0 : SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i );
2171 0 : OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
2172 0 : if ( OUTDEV_WINDOW == rOutDev.GetOutDevType() )
2173 : {
2174 0 : pFormView->MakeVisible( aMarkRect, static_cast<vcl::Window&>(rOutDev) );
2175 : }
2176 : } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i )
2177 0 : }
2178 : }
2179 :
2180 :
2181 435 : }
2182 :
2183 :
2184 :
2185 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|