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 : /*
21 : TODO:
22 : - delete anchor in SelectionEngine when selecting manually
23 : - SelectAll( sal_False ) => only repaint the delselected entries
24 : */
25 :
26 : #include <svtools/treelistbox.hxx>
27 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 : #include <vcl/svapp.hxx>
29 : #include <vcl/accel.hxx>
30 : #include <vcl/i18nhelp.hxx>
31 : #include <vcl/builder.hxx>
32 : #include <sot/formats.hxx>
33 : #include <unotools/accessiblestatesethelper.hxx>
34 : #include <rtl/instance.hxx>
35 : #include <comphelper/string.hxx>
36 :
37 : #include <svtools/svmedit.hxx>
38 : #include <svtools/svlbitm.hxx>
39 : #include "svtools/treelistentry.hxx"
40 : #include "svtools/viewdataentry.hxx"
41 : #include "svimpbox.hxx"
42 :
43 : #include <set>
44 : #include <string.h>
45 : #include <vector>
46 :
47 : using namespace ::com::sun::star::accessibility;
48 :
49 : // Drag&Drop
50 : static SvTreeListBox* pDDSource = NULL;
51 : static SvTreeListBox* pDDTarget = NULL;
52 :
53 : DBG_NAME(SvInplaceEdit2)
54 :
55 : #define SVLBOX_ACC_RETURN 1
56 : #define SVLBOX_ACC_ESCAPE 2
57 :
58 : // ***************************************************************
59 :
60 0 : class MyEdit_Impl : public Edit
61 : {
62 : SvInplaceEdit2* pOwner;
63 : public:
64 : MyEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
65 : virtual void KeyInput( const KeyEvent& rKEvt );
66 : virtual void LoseFocus();
67 : };
68 :
69 0 : class MyMultiEdit_Impl : public MultiLineEdit
70 : {
71 : SvInplaceEdit2* pOwner;
72 : public:
73 : MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* pOwner );
74 : virtual void KeyInput( const KeyEvent& rKEvt );
75 : virtual void LoseFocus();
76 : };
77 :
78 0 : MyEdit_Impl::MyEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner ) :
79 :
80 : Edit( pParent, WB_LEFT ),
81 :
82 0 : pOwner( _pOwner )
83 :
84 : {
85 0 : }
86 :
87 0 : void MyEdit_Impl::KeyInput( const KeyEvent& rKEvt )
88 : {
89 0 : if( !pOwner->KeyInput( rKEvt ))
90 0 : Edit::KeyInput( rKEvt );
91 0 : }
92 :
93 0 : void MyEdit_Impl::LoseFocus()
94 : {
95 0 : pOwner->LoseFocus();
96 0 : }
97 :
98 0 : MyMultiEdit_Impl::MyMultiEdit_Impl( Window* pParent, SvInplaceEdit2* _pOwner )
99 : : MultiLineEdit( pParent,
100 : WB_CENTER
101 0 : ), pOwner(_pOwner)
102 : {
103 0 : }
104 :
105 0 : void MyMultiEdit_Impl::KeyInput( const KeyEvent& rKEvt )
106 : {
107 0 : if( !pOwner->KeyInput( rKEvt ))
108 0 : MultiLineEdit::KeyInput( rKEvt );
109 0 : }
110 :
111 0 : void MyMultiEdit_Impl::LoseFocus()
112 : {
113 0 : pOwner->LoseFocus();
114 0 : }
115 :
116 :
117 0 : SvInplaceEdit2::SvInplaceEdit2
118 : (
119 : Window* pParent, const Point& rPos,
120 : const Size& rSize,
121 : const String& rData,
122 : const Link& rNotifyEditEnd,
123 : const Selection& rSelection,
124 : sal_Bool bMulti
125 : ) :
126 :
127 : aCallBackHdl ( rNotifyEditEnd ),
128 : bCanceled ( sal_False ),
129 0 : bAlreadyInCallBack ( sal_False )
130 :
131 : {
132 : DBG_CTOR(SvInplaceEdit2,0);
133 :
134 0 : if( bMulti )
135 0 : pEdit = new MyMultiEdit_Impl( pParent, this );
136 : else
137 0 : pEdit = new MyEdit_Impl( pParent, this );
138 :
139 0 : Font aFont( pParent->GetFont() );
140 0 : aFont.SetTransparent( sal_False );
141 0 : Color aColor( pParent->GetBackground().GetColor() );
142 0 : aFont.SetFillColor(aColor );
143 0 : pEdit->SetFont( aFont );
144 0 : pEdit->SetBackground( pParent->GetBackground() );
145 0 : pEdit->SetPosPixel( rPos );
146 0 : pEdit->SetSizePixel( rSize );
147 0 : pEdit->SetText( rData );
148 0 : pEdit->SetSelection( rSelection );
149 0 : pEdit->SaveValue();
150 :
151 0 : aAccReturn.InsertItem( SVLBOX_ACC_RETURN, KeyCode(KEY_RETURN) );
152 0 : aAccEscape.InsertItem( SVLBOX_ACC_ESCAPE, KeyCode(KEY_ESCAPE) );
153 :
154 0 : aAccReturn.SetActivateHdl( LINK( this, SvInplaceEdit2, ReturnHdl_Impl) );
155 0 : aAccEscape.SetActivateHdl( LINK( this, SvInplaceEdit2, EscapeHdl_Impl) );
156 0 : GetpApp()->InsertAccel( &aAccReturn );
157 0 : GetpApp()->InsertAccel( &aAccEscape );
158 :
159 0 : pEdit->Show();
160 0 : pEdit->GrabFocus();
161 0 : }
162 :
163 0 : SvInplaceEdit2::~SvInplaceEdit2()
164 : {
165 : DBG_DTOR(SvInplaceEdit2,0);
166 0 : if( !bAlreadyInCallBack )
167 : {
168 0 : GetpApp()->RemoveAccel( &aAccReturn );
169 0 : GetpApp()->RemoveAccel( &aAccEscape );
170 : }
171 0 : delete pEdit;
172 0 : }
173 :
174 0 : String SvInplaceEdit2::GetSavedValue() const
175 : {
176 0 : return pEdit->GetSavedValue();
177 : }
178 :
179 0 : void SvInplaceEdit2::Hide()
180 : {
181 0 : pEdit->Hide();
182 0 : }
183 :
184 :
185 0 : IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2, ReturnHdl_Impl)
186 : {
187 : DBG_CHKTHIS(SvInplaceEdit2,0);
188 0 : bCanceled = sal_False;
189 0 : CallCallBackHdl_Impl();
190 0 : return 1;
191 : }
192 0 : IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2, ReturnHdl_Impl)
193 :
194 0 : IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2, EscapeHdl_Impl)
195 : {
196 : DBG_CHKTHIS(SvInplaceEdit2,0);
197 0 : bCanceled = sal_True;
198 0 : CallCallBackHdl_Impl();
199 0 : return 1;
200 : }
201 0 : IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2, EscapeHdl_Impl)
202 :
203 :
204 0 : sal_Bool SvInplaceEdit2::KeyInput( const KeyEvent& rKEvt )
205 : {
206 : DBG_CHKTHIS(SvInplaceEdit2,0);
207 0 : KeyCode aCode = rKEvt.GetKeyCode();
208 0 : sal_uInt16 nCode = aCode.GetCode();
209 :
210 0 : switch ( nCode )
211 : {
212 : case KEY_ESCAPE:
213 0 : bCanceled = sal_True;
214 0 : CallCallBackHdl_Impl();
215 0 : return sal_True;
216 :
217 : case KEY_RETURN:
218 0 : bCanceled = sal_False;
219 0 : CallCallBackHdl_Impl();
220 0 : return sal_True;
221 : }
222 0 : return sal_False;
223 : }
224 :
225 0 : void SvInplaceEdit2::StopEditing( sal_Bool bCancel )
226 : {
227 : DBG_CHKTHIS(SvInplaceEdit2,0);
228 0 : if ( !bAlreadyInCallBack )
229 : {
230 0 : bCanceled = bCancel;
231 0 : CallCallBackHdl_Impl();
232 : }
233 0 : }
234 :
235 0 : void SvInplaceEdit2::LoseFocus()
236 : {
237 : DBG_CHKTHIS(SvInplaceEdit2,0);
238 0 : if ( !bAlreadyInCallBack
239 0 : && ((!Application::GetFocusWindow()) || !pEdit->IsChild( Application::GetFocusWindow()) )
240 : )
241 : {
242 0 : bCanceled = sal_False;
243 0 : aTimer.SetTimeout(10);
244 0 : aTimer.SetTimeoutHdl(LINK(this,SvInplaceEdit2,Timeout_Impl));
245 0 : aTimer.Start();
246 : }
247 0 : }
248 :
249 0 : IMPL_LINK_NOARG_INLINE_START(SvInplaceEdit2, Timeout_Impl)
250 : {
251 : DBG_CHKTHIS(SvInplaceEdit2,0);
252 0 : CallCallBackHdl_Impl();
253 0 : return 0;
254 : }
255 0 : IMPL_LINK_NOARG_INLINE_END(SvInplaceEdit2, Timeout_Impl)
256 :
257 0 : void SvInplaceEdit2::CallCallBackHdl_Impl()
258 : {
259 : DBG_CHKTHIS(SvInplaceEdit2,0);
260 0 : aTimer.Stop();
261 0 : if ( !bAlreadyInCallBack )
262 : {
263 0 : bAlreadyInCallBack = sal_True;
264 0 : GetpApp()->RemoveAccel( &aAccReturn );
265 0 : GetpApp()->RemoveAccel( &aAccEscape );
266 0 : pEdit->Hide();
267 0 : aCallBackHdl.Call( this );
268 : }
269 0 : }
270 :
271 0 : String SvInplaceEdit2::GetText() const
272 : {
273 0 : return pEdit->GetText();
274 : }
275 :
276 : // ***************************************************************
277 : // class SvLBoxTab
278 : // ***************************************************************
279 :
280 : DBG_NAME(SvLBoxTab);
281 :
282 0 : SvLBoxTab::SvLBoxTab()
283 : {
284 : DBG_CTOR(SvLBoxTab,0);
285 0 : nPos = 0;
286 0 : pUserData = 0;
287 0 : nFlags = 0;
288 0 : }
289 :
290 0 : SvLBoxTab::SvLBoxTab( long nPosition, sal_uInt16 nTabFlags )
291 : {
292 : DBG_CTOR(SvLBoxTab,0);
293 0 : nPos = nPosition;
294 0 : pUserData = 0;
295 0 : nFlags = nTabFlags;
296 0 : }
297 :
298 0 : SvLBoxTab::SvLBoxTab( const SvLBoxTab& rTab )
299 : {
300 : DBG_CTOR(SvLBoxTab,0);
301 0 : nPos = rTab.nPos;
302 0 : pUserData = rTab.pUserData;
303 0 : nFlags = rTab.nFlags;
304 0 : }
305 :
306 0 : SvLBoxTab::~SvLBoxTab()
307 : {
308 : DBG_DTOR(SvLBoxTab,0);
309 0 : }
310 :
311 :
312 0 : long SvLBoxTab::CalcOffset( long nItemWidth, long nTabWidth )
313 : {
314 : DBG_CHKTHIS(SvLBoxTab,0);
315 0 : long nOffset = 0;
316 0 : if ( nFlags & SV_LBOXTAB_ADJUST_RIGHT )
317 : {
318 0 : nOffset = nTabWidth - nItemWidth;
319 0 : if( nOffset < 0 )
320 0 : nOffset = 0;
321 : }
322 0 : else if ( nFlags & SV_LBOXTAB_ADJUST_CENTER )
323 : {
324 0 : if( nFlags & SV_LBOXTAB_FORCE )
325 : {
326 : // correct implementation of centering
327 0 : nOffset = ( nTabWidth - nItemWidth ) / 2;
328 0 : if( nOffset < 0 )
329 0 : nOffset = 0;
330 : }
331 : else
332 : {
333 : // historically grown, wrong calculation of tabs which is needed by
334 : // Abo-Tabbox, Tools/Options/Customize etc.
335 0 : nItemWidth++;
336 0 : nOffset = -( nItemWidth / 2 );
337 : }
338 : }
339 0 : return nOffset;
340 : }
341 :
342 : // ***************************************************************
343 : // class SvLBoxItem
344 : // ***************************************************************
345 :
346 : DBG_NAME(SvLBoxItem);
347 :
348 0 : SvLBoxItem::SvLBoxItem( SvTreeListEntry*, sal_uInt16 )
349 : {
350 : DBG_CTOR(SvLBoxItem,0);
351 0 : }
352 :
353 0 : SvLBoxItem::SvLBoxItem()
354 : {
355 : DBG_CTOR(SvLBoxItem,0);
356 0 : }
357 :
358 0 : SvLBoxItem::~SvLBoxItem()
359 : {
360 : DBG_DTOR(SvLBoxItem,0);
361 0 : }
362 :
363 0 : const Size& SvLBoxItem::GetSize(const SvTreeListBox* pView, const SvTreeListEntry* pEntry) const
364 : {
365 : DBG_CHKTHIS(SvLBoxItem,0);
366 0 : const SvViewDataItem* pViewData = pView->GetViewDataItem( pEntry, this );
367 0 : return pViewData->maSize;
368 : }
369 :
370 0 : const Size& SvLBoxItem::GetSize(const SvViewDataEntry* pData, sal_uInt16 nItemPos) const
371 : {
372 0 : const SvViewDataItem* pIData = pData->GetItem(nItemPos);
373 0 : return pIData->maSize;
374 : }
375 :
376 0 : struct SvTreeListBoxImpl
377 : {
378 : bool m_bIsEmptyTextAllowed:1;
379 : bool m_bEntryMnemonicsEnabled:1;
380 : bool m_bDoingQuickSelection:1;
381 :
382 : Link* m_pLink;
383 :
384 : vcl::MnemonicEngine m_aMnemonicEngine;
385 : vcl::QuickSelectionEngine m_aQuickSelectionEngine;
386 :
387 0 : SvTreeListBoxImpl(SvTreeListBox& _rBox) :
388 : m_bIsEmptyTextAllowed(true),
389 : m_bEntryMnemonicsEnabled(false),
390 : m_bDoingQuickSelection(false),
391 : m_pLink(NULL),
392 : m_aMnemonicEngine(_rBox),
393 0 : m_aQuickSelectionEngine(_rBox) {}
394 : };
395 :
396 : DBG_NAME(SvTreeListBox);
397 :
398 0 : SvTreeListBox::SvTreeListBox(Window* pParent, WinBits nWinStyle) :
399 : Control(pParent, nWinStyle | WB_CLIPCHILDREN),
400 : DropTargetHelper(this),
401 : DragSourceHelper(this),
402 0 : mpImpl(new SvTreeListBoxImpl(*this)),
403 : mbContextBmpExpanded(false),
404 0 : eSelMode(NO_SELECTION)
405 : {
406 : DBG_CTOR(SvTreeListBox,0);
407 0 : nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
408 0 : nImpFlags = 0;
409 0 : pTargetEntry = 0;
410 0 : nDragDropMode = 0;
411 0 : SvTreeList* pTempModel = new SvTreeList;
412 0 : pTempModel->SetRefCount( 0 );
413 0 : SetBaseModel(pTempModel);
414 0 : pModel->SetCloneLink( LINK(this, SvTreeListBox, CloneHdl_Impl ));
415 0 : pModel->InsertView( this );
416 0 : pHdlEntry = 0;
417 0 : pEdCtrl = 0;
418 0 : eSelMode = SINGLE_SELECTION;
419 0 : nDragDropMode = SV_DRAGDROP_NONE;
420 0 : SetType(WINDOW_TREELISTBOX);
421 :
422 0 : InitTreeView();
423 :
424 0 : SetSublistOpenWithLeftRight();
425 0 : }
426 :
427 0 : SvTreeListBox::SvTreeListBox(Window* pParent, const ResId& rResId) :
428 : Control(pParent, rResId),
429 : DropTargetHelper(this),
430 : DragSourceHelper(this),
431 0 : mpImpl(new SvTreeListBoxImpl(*this)),
432 : mbContextBmpExpanded(false),
433 0 : eSelMode(NO_SELECTION)
434 : {
435 : DBG_CTOR(SvTreeListBox,0);
436 0 : pTargetEntry = 0;
437 0 : nImpFlags = 0;
438 0 : nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
439 0 : nDragDropMode = 0;
440 0 : SvTreeList* pTempModel = new SvTreeList;
441 0 : pTempModel->SetRefCount( 0 );
442 0 : SetBaseModel(pTempModel);
443 0 : pModel->InsertView( this );
444 0 : pHdlEntry = 0;
445 0 : pEdCtrl = 0;
446 0 : pModel->SetCloneLink( LINK(this, SvTreeListBox, CloneHdl_Impl ));
447 0 : SetType(WINDOW_TREELISTBOX);
448 :
449 0 : InitTreeView();
450 0 : Resize();
451 :
452 0 : SetSublistOpenWithLeftRight();
453 0 : }
454 :
455 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvTreeListBox(Window *pParent, VclBuilder::stringmap &)
456 : {
457 0 : return new SvTreeListBox(pParent, WB_TABSTOP);
458 : }
459 :
460 0 : void SvTreeListBox::Clear()
461 : {
462 : DBG_CHKTHIS(SvTreeListBox,0);
463 0 : pModel->Clear(); // Model calls SvTreeListBox::ModelHasCleared()
464 0 : }
465 :
466 0 : void SvTreeListBox::EnableEntryMnemonics( bool _bEnable )
467 : {
468 0 : if ( _bEnable == IsEntryMnemonicsEnabled() )
469 0 : return;
470 :
471 0 : mpImpl->m_bEntryMnemonicsEnabled = _bEnable;
472 0 : Invalidate();
473 : }
474 :
475 0 : bool SvTreeListBox::IsEntryMnemonicsEnabled() const
476 : {
477 0 : return mpImpl->m_bEntryMnemonicsEnabled;
478 : }
479 :
480 0 : IMPL_LINK_INLINE_START( SvTreeListBox, CloneHdl_Impl, SvTreeListEntry*, pEntry )
481 : {
482 : DBG_CHKTHIS(SvTreeListBox,0);
483 0 : return (long)(CloneEntry((SvTreeListEntry*)pEntry));
484 : }
485 0 : IMPL_LINK_INLINE_END( SvTreeListBox, CloneHdl_Impl, SvTreeListEntry*, pEntry )
486 :
487 0 : sal_uLong SvTreeListBox::Insert( SvTreeListEntry* pEntry, SvTreeListEntry* pParent, sal_uLong nPos )
488 : {
489 : DBG_CHKTHIS(SvTreeListBox,0);
490 0 : sal_uLong nInsPos = pModel->Insert( pEntry, pParent, nPos );
491 0 : return nInsPos;
492 : }
493 :
494 0 : sal_uLong SvTreeListBox::Insert( SvTreeListEntry* pEntry,sal_uLong nRootPos )
495 : {
496 : DBG_CHKTHIS(SvTreeListBox,0);
497 0 : sal_uLong nInsPos = pModel->Insert( pEntry, nRootPos );
498 0 : return nInsPos;
499 : }
500 :
501 0 : long SvTreeListBox::ExpandingHdl()
502 : {
503 : DBG_CHKTHIS(SvTreeListBox,0);
504 0 : return aExpandingHdl.IsSet() ? aExpandingHdl.Call( this ) : 1;
505 : }
506 :
507 0 : void SvTreeListBox::ExpandedHdl()
508 : {
509 : DBG_CHKTHIS(SvTreeListBox,0);
510 0 : aExpandedHdl.Call( this );
511 0 : }
512 :
513 0 : void SvTreeListBox::SelectHdl()
514 : {
515 : DBG_CHKTHIS(SvTreeListBox,0);
516 0 : aSelectHdl.Call( this );
517 0 : }
518 :
519 0 : void SvTreeListBox::DeselectHdl()
520 : {
521 : DBG_CHKTHIS(SvTreeListBox,0);
522 0 : aDeselectHdl.Call( this );
523 0 : }
524 :
525 0 : sal_Bool SvTreeListBox::DoubleClickHdl()
526 : {
527 : DBG_CHKTHIS(SvTreeListBox,0);
528 0 : aDoubleClickHdl.Call( this );
529 0 : return sal_True;
530 : }
531 :
532 :
533 0 : sal_Bool SvTreeListBox::CheckDragAndDropMode( SvTreeListBox* pSource, sal_Int8 nAction )
534 : {
535 : DBG_CHKTHIS(SvTreeListBox,0);
536 0 : if ( pSource == this )
537 : {
538 0 : if ( !(nDragDropMode & (SV_DRAGDROP_CTRL_MOVE | SV_DRAGDROP_CTRL_COPY) ) )
539 0 : return sal_False; // D&D locked within list
540 0 : if( DND_ACTION_MOVE == nAction )
541 : {
542 0 : if ( !(nDragDropMode & SV_DRAGDROP_CTRL_MOVE) )
543 0 : return sal_False; // no local move
544 : }
545 : else
546 : {
547 0 : if ( !(nDragDropMode & SV_DRAGDROP_CTRL_COPY))
548 0 : return sal_False; // no local copy
549 : }
550 : }
551 : else
552 : {
553 0 : if ( !(nDragDropMode & SV_DRAGDROP_APP_DROP ) )
554 0 : return sal_False; // no drop
555 0 : if ( DND_ACTION_MOVE == nAction )
556 : {
557 0 : if ( !(nDragDropMode & SV_DRAGDROP_APP_MOVE) )
558 0 : return sal_False; // no global move
559 : }
560 : else
561 : {
562 0 : if ( !(nDragDropMode & SV_DRAGDROP_APP_COPY))
563 0 : return sal_False; // no global copy
564 : }
565 : }
566 0 : return sal_True;
567 : }
568 :
569 :
570 :
571 :
572 0 : void SvTreeListBox::NotifyRemoving( SvTreeListEntry* )
573 : {
574 : DBG_CHKTHIS(SvTreeListBox,0);
575 0 : }
576 :
577 : /*
578 : NotifyMoving/Copying
579 : ====================
580 :
581 : default behavior:
582 :
583 : 1. target doesn't have children
584 : - entry becomes sibling of target. entry comes after target
585 : (->Window: below the target)
586 : 2. target is an expanded parent
587 : - entry inserted at the beginning of the target childlist
588 : 3. target is a collapsed parent
589 : - entry is inserted at the end of the target childlist
590 : */
591 : #ifdef DBG_UTIL
592 : sal_Bool SvTreeListBox::NotifyMoving(
593 : SvTreeListEntry* pTarget, // D&D dropping position in this->GetModel()
594 : SvTreeListEntry* pEntry, // entry that we want to move, from
595 : // GetSourceListBox()->GetModel()
596 : SvTreeListEntry*& rpNewParent, // new target parent
597 : sal_uLong& rNewChildPos) // position in childlist of target parent
598 : #else
599 0 : sal_Bool SvTreeListBox::NotifyMoving(
600 : SvTreeListEntry* pTarget, // D&D dropping position in this->GetModel()
601 : SvTreeListEntry*, // entry that we want to move, from
602 : // GetSourceListBox()->GetModel()
603 : SvTreeListEntry*& rpNewParent, // new target parent
604 : sal_uLong& rNewChildPos) // position in childlist of target parent
605 : #endif
606 : {
607 : DBG_CHKTHIS(SvTreeListBox,0);
608 : DBG_ASSERT(pEntry,"NotifyMoving:SoureEntry?");
609 0 : if( !pTarget )
610 : {
611 0 : rpNewParent = 0;
612 0 : rNewChildPos = 0;
613 0 : return sal_True;
614 : }
615 0 : if ( !pTarget->HasChildren() && !pTarget->HasChildrenOnDemand() )
616 : {
617 : // case 1
618 0 : rpNewParent = GetParent( pTarget );
619 0 : rNewChildPos = pModel->GetRelPos( pTarget ) + 1;
620 0 : rNewChildPos += nCurEntrySelPos;
621 0 : nCurEntrySelPos++;
622 : }
623 : else
624 : {
625 : // cases 2 & 3
626 0 : rpNewParent = pTarget;
627 0 : if( IsExpanded(pTarget))
628 0 : rNewChildPos = 0;
629 : else
630 0 : rNewChildPos = LIST_APPEND;
631 : }
632 0 : return sal_True;
633 : }
634 :
635 0 : sal_Bool SvTreeListBox::NotifyCopying(
636 : SvTreeListEntry* pTarget, // D&D dropping position in this->GetModel()
637 : SvTreeListEntry* pEntry, // entry that we want to move, from
638 : // GetSourceListBox()->GetModel()
639 : SvTreeListEntry*& rpNewParent, // new target parent
640 : sal_uLong& rNewChildPos) // position in childlist of target parent
641 : {
642 : DBG_CHKTHIS(SvTreeListBox,0);
643 0 : return NotifyMoving(pTarget,pEntry,rpNewParent,rNewChildPos);
644 : }
645 :
646 0 : SvTreeListEntry* SvTreeListBox::FirstChild( SvTreeListEntry* pParent ) const
647 : {
648 0 : return pModel->FirstChild(pParent);
649 : }
650 :
651 0 : SvTreeListEntry* SvTreeListBox::NextSibling( SvTreeListEntry* pEntry ) const
652 : {
653 0 : return pModel->NextSibling(pEntry);
654 : }
655 :
656 0 : SvTreeListEntry* SvTreeListBox::PrevSibling( SvTreeListEntry* pEntry ) const
657 : {
658 0 : return pModel->PrevSibling(pEntry);
659 : }
660 :
661 : // return: all entries copied
662 0 : sal_Bool SvTreeListBox::CopySelection( SvTreeListBox* pSource, SvTreeListEntry* pTarget )
663 : {
664 : DBG_CHKTHIS(SvTreeListBox,0);
665 0 : nCurEntrySelPos = 0; // selection counter for NotifyMoving/Copying
666 0 : sal_Bool bSuccess = sal_True;
667 0 : std::vector<SvTreeListEntry*> aList;
668 0 : sal_Bool bClone = (sal_Bool)( (sal_uLong)(pSource->GetModel()) != (sal_uLong)GetModel() );
669 0 : Link aCloneLink( pModel->GetCloneLink() );
670 0 : pModel->SetCloneLink( LINK(this, SvTreeListBox, CloneHdl_Impl ));
671 :
672 : // cache selection to simplify iterating over the selection when doing a D&D
673 : // exchange within the same listbox
674 0 : SvTreeListEntry* pSourceEntry = pSource->FirstSelected();
675 0 : while ( pSourceEntry )
676 : {
677 : // children are copied automatically
678 0 : pSource->SelectChildren( pSourceEntry, sal_False );
679 0 : aList.push_back( pSourceEntry );
680 0 : pSourceEntry = pSource->NextSelected( pSourceEntry );
681 : }
682 :
683 0 : std::vector<SvTreeListEntry*>::const_iterator it = aList.begin(), itEnd = aList.end();
684 0 : for (; it != itEnd; ++it)
685 : {
686 0 : pSourceEntry = *it;
687 0 : SvTreeListEntry* pNewParent = 0;
688 0 : sal_uLong nInsertionPos = ULONG_MAX;
689 0 : sal_Bool bOk=NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
690 0 : if ( bOk )
691 : {
692 0 : if ( bClone )
693 : {
694 0 : sal_uLong nCloneCount = 0;
695 0 : pSourceEntry = pModel->Clone(pSourceEntry, nCloneCount);
696 0 : pModel->InsertTree(pSourceEntry, pNewParent, nInsertionPos);
697 : }
698 : else
699 : {
700 0 : sal_uLong nListPos = pModel->Copy(pSourceEntry, pNewParent, nInsertionPos);
701 0 : pSourceEntry = GetEntry( pNewParent, nListPos );
702 : }
703 : }
704 : else
705 0 : bSuccess = sal_False;
706 :
707 0 : if( bOk == (sal_Bool)2 ) // HACK: make visible moved entry?
708 0 : MakeVisible( pSourceEntry );
709 : }
710 0 : pModel->SetCloneLink( aCloneLink );
711 0 : return bSuccess;
712 : }
713 :
714 : // return: all entries were moved
715 0 : sal_Bool SvTreeListBox::MoveSelection( SvTreeListBox* pSource, SvTreeListEntry* pTarget )
716 : {
717 0 : return MoveSelectionCopyFallbackPossible( pSource, pTarget, sal_False );
718 : }
719 :
720 0 : sal_Bool SvTreeListBox::MoveSelectionCopyFallbackPossible( SvTreeListBox* pSource, SvTreeListEntry* pTarget, sal_Bool bAllowCopyFallback )
721 : {
722 : DBG_CHKTHIS(SvTreeListBox,0);
723 0 : nCurEntrySelPos = 0; // selection counter for NotifyMoving/Copying
724 0 : sal_Bool bSuccess = sal_True;
725 0 : std::vector<SvTreeListEntry*> aList;
726 0 : sal_Bool bClone = (sal_Bool)( (sal_uLong)(pSource->GetModel()) != (sal_uLong)GetModel() );
727 0 : Link aCloneLink( pModel->GetCloneLink() );
728 0 : if ( bClone )
729 0 : pModel->SetCloneLink( LINK(this, SvTreeListBox, CloneHdl_Impl ));
730 :
731 0 : SvTreeListEntry* pSourceEntry = pSource->FirstSelected();
732 0 : while ( pSourceEntry )
733 : {
734 : // children are automatically moved
735 0 : pSource->SelectChildren( pSourceEntry, sal_False );
736 0 : aList.push_back( pSourceEntry );
737 0 : pSourceEntry = pSource->NextSelected( pSourceEntry );
738 : }
739 :
740 0 : std::vector<SvTreeListEntry*>::const_iterator it = aList.begin(), itEnd = aList.end();
741 0 : for (; it != itEnd; ++it)
742 : {
743 0 : pSourceEntry = *it;
744 :
745 0 : SvTreeListEntry* pNewParent = 0;
746 0 : sal_uLong nInsertionPos = ULONG_MAX;
747 0 : sal_Bool bOk = NotifyMoving(pTarget,pSourceEntry,pNewParent,nInsertionPos);
748 0 : sal_Bool bCopyOk = bOk;
749 0 : if ( !bOk && bAllowCopyFallback )
750 : {
751 0 : nInsertionPos = LIST_APPEND;
752 0 : bCopyOk = NotifyCopying(pTarget,pSourceEntry,pNewParent,nInsertionPos);
753 : }
754 :
755 0 : if ( bOk || bCopyOk )
756 : {
757 0 : if ( bClone )
758 : {
759 0 : sal_uLong nCloneCount = 0;
760 0 : pSourceEntry = pModel->Clone(pSourceEntry, nCloneCount);
761 0 : pModel->InsertTree(pSourceEntry, pNewParent, nInsertionPos);
762 : }
763 : else
764 : {
765 0 : if ( bOk )
766 0 : pModel->Move(pSourceEntry, pNewParent, nInsertionPos);
767 : else
768 0 : pModel->Copy(pSourceEntry, pNewParent, nInsertionPos);
769 0 : }
770 : }
771 : else
772 0 : bSuccess = sal_False;
773 :
774 0 : if( bOk == (sal_Bool)2 ) // HACK: make moved entry visible?
775 0 : MakeVisible( pSourceEntry );
776 : }
777 0 : pModel->SetCloneLink( aCloneLink );
778 0 : return bSuccess;
779 : }
780 :
781 0 : void SvTreeListBox::RemoveSelection()
782 : {
783 : DBG_CHKTHIS(SvTreeListBox,0);
784 0 : std::vector<const SvTreeListEntry*> aList;
785 : // cache selection, as the implementation deselects everything on the first
786 : // remove
787 0 : SvTreeListEntry* pEntry = FirstSelected();
788 0 : while ( pEntry )
789 : {
790 0 : aList.push_back( pEntry );
791 0 : if ( pEntry->HasChildren() )
792 : // remove deletes all children automatically
793 0 : SelectChildren(pEntry, false);
794 0 : pEntry = NextSelected( pEntry );
795 : }
796 :
797 0 : std::vector<const SvTreeListEntry*>::const_iterator it = aList.begin(), itEnd = aList.end();
798 0 : for (; it != itEnd; ++it)
799 0 : pModel->Remove(*it);
800 0 : }
801 :
802 0 : SvTreeListBox* SvTreeListBox::GetSourceView() const
803 : {
804 0 : return pDDSource;
805 : }
806 :
807 0 : void SvTreeListBox::RecalcViewData()
808 : {
809 : DBG_CHKTHIS(SvTreeListBox,0);
810 0 : SvTreeListEntry* pEntry = First();
811 0 : while( pEntry )
812 : {
813 0 : sal_uInt16 nCount = pEntry->ItemCount();
814 0 : sal_uInt16 nCurPos = 0;
815 0 : while ( nCurPos < nCount )
816 : {
817 0 : SvLBoxItem* pItem = pEntry->GetItem( nCurPos );
818 0 : pItem->InitViewData( this, pEntry );
819 0 : nCurPos++;
820 : }
821 0 : ViewDataInitialized( pEntry );
822 0 : pEntry = Next( pEntry );
823 : }
824 0 : }
825 :
826 0 : void SvTreeListBox::ViewDataInitialized( SvTreeListEntry* )
827 : {
828 : DBG_CHKTHIS(SvTreeListBox,0);
829 0 : }
830 :
831 0 : void SvTreeListBox::ImplShowTargetEmphasis( SvTreeListEntry* pEntry, sal_Bool bShow)
832 : {
833 : DBG_CHKTHIS(SvTreeListBox,0);
834 0 : if ( bShow && (nImpFlags & SVLBOX_TARGEMPH_VIS) )
835 0 : return;
836 0 : if ( !bShow && !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
837 0 : return;
838 0 : ShowTargetEmphasis( pEntry, bShow );
839 0 : if( bShow )
840 0 : nImpFlags |= SVLBOX_TARGEMPH_VIS;
841 : else
842 0 : nImpFlags &= ~SVLBOX_TARGEMPH_VIS;
843 : }
844 :
845 0 : void SvTreeListBox::OnCurrentEntryChanged()
846 : {
847 0 : if ( !mpImpl->m_bDoingQuickSelection )
848 0 : mpImpl->m_aQuickSelectionEngine.Reset();
849 0 : }
850 :
851 0 : SvTreeListEntry* SvTreeListBox::GetEntry( SvTreeListEntry* pParent, sal_uLong nPos ) const
852 : {
853 0 : return pModel->GetEntry(pParent, nPos);
854 : }
855 :
856 0 : SvTreeListEntry* SvTreeListBox::GetEntry( sal_uLong nRootPos ) const
857 : {
858 0 : return pModel->GetEntry(nRootPos);
859 : }
860 :
861 0 : SvTreeListEntry* SvTreeListBox::GetEntryFromPath( const ::std::deque< sal_Int32 >& _rPath ) const
862 : {
863 : DBG_CHKTHIS(SvTreeListBox,0);
864 :
865 0 : SvTreeListEntry* pEntry = NULL;
866 0 : SvTreeListEntry* pParent = NULL;
867 0 : for( ::std::deque< sal_Int32 >::const_iterator pItem = _rPath.begin(); pItem != _rPath.end(); ++pItem )
868 : {
869 0 : pEntry = GetEntry( pParent, *pItem );
870 0 : if ( !pEntry )
871 0 : break;
872 0 : pParent = pEntry;
873 : }
874 :
875 0 : return pEntry;
876 : }
877 :
878 0 : void SvTreeListBox::FillEntryPath( SvTreeListEntry* pEntry, ::std::deque< sal_Int32 >& _rPath ) const
879 : {
880 : DBG_CHKTHIS(SvTreeListBox,0);
881 :
882 0 : if ( pEntry )
883 : {
884 0 : SvTreeListEntry* pParentEntry = GetParent( pEntry );
885 0 : while ( sal_True )
886 : {
887 0 : sal_uLong i, nCount = GetLevelChildCount( pParentEntry );
888 0 : for ( i = 0; i < nCount; ++i )
889 : {
890 0 : SvTreeListEntry* pTemp = GetEntry( pParentEntry, i );
891 : DBG_ASSERT( pEntry, "invalid entry" );
892 0 : if ( pEntry == pTemp )
893 : {
894 0 : _rPath.push_front( (sal_Int32)i );
895 0 : break;
896 : }
897 : }
898 :
899 0 : if ( pParentEntry )
900 : {
901 0 : pEntry = pParentEntry;
902 0 : pParentEntry = GetParent( pParentEntry );
903 : }
904 : else
905 0 : break;
906 : }
907 : }
908 0 : }
909 :
910 0 : const SvTreeListEntry* SvTreeListBox::GetParent( const SvTreeListEntry* pEntry ) const
911 : {
912 0 : return pModel->GetParent(pEntry);
913 : }
914 :
915 0 : SvTreeListEntry* SvTreeListBox::GetParent( SvTreeListEntry* pEntry ) const
916 : {
917 0 : return pModel->GetParent(pEntry);
918 : }
919 :
920 0 : SvTreeListEntry* SvTreeListBox::GetRootLevelParent( SvTreeListEntry* pEntry ) const
921 : {
922 0 : return pModel->GetRootLevelParent(pEntry);
923 : }
924 :
925 0 : sal_uLong SvTreeListBox::GetChildCount( SvTreeListEntry* pParent ) const
926 : {
927 0 : return pModel->GetChildCount(pParent);
928 : }
929 :
930 0 : sal_uLong SvTreeListBox::GetLevelChildCount( SvTreeListEntry* _pParent ) const
931 : {
932 : DBG_CHKTHIS(SvTreeListBox,0);
933 :
934 0 : sal_uLong nCount = 0;
935 0 : SvTreeListEntry* pEntry = FirstChild( _pParent );
936 0 : while ( pEntry )
937 : {
938 0 : ++nCount;
939 0 : pEntry = NextSibling( pEntry );
940 : }
941 :
942 0 : return nCount;
943 : }
944 :
945 0 : SvViewDataEntry* SvTreeListBox::GetViewDataEntry( SvTreeListEntry* pEntry ) const
946 : {
947 0 : return (SvViewDataEntry*)SvListView::GetViewData(pEntry);
948 : }
949 :
950 0 : SvViewDataItem* SvTreeListBox::GetViewDataItem(SvTreeListEntry* pEntry, SvLBoxItem* pItem)
951 : {
952 0 : return const_cast<SvViewDataItem*>(static_cast<const SvTreeListBox*>(this)->GetViewDataItem(pEntry, pItem));
953 : }
954 :
955 0 : const SvViewDataItem* SvTreeListBox::GetViewDataItem(const SvTreeListEntry* pEntry, const SvLBoxItem* pItem) const
956 : {
957 0 : const SvViewDataEntry* pEntryData = (const SvViewDataEntry*)SvListView::GetViewData(pEntry);
958 : DBG_ASSERT(pEntryData,"Entry not in View");
959 0 : sal_uInt16 nItemPos = pEntry->GetPos(pItem);
960 0 : return pEntryData->GetItem(nItemPos);
961 : }
962 :
963 0 : SvViewDataEntry* SvTreeListBox::CreateViewData( SvTreeListEntry* )
964 : {
965 : DBG_CHKTHIS(SvTreeListBox,0);
966 0 : SvViewDataEntry* pEntryData = new SvViewDataEntry;
967 0 : return (SvViewDataEntry*)pEntryData;
968 : }
969 :
970 0 : void SvTreeListBox::InitViewData( SvViewDataEntry* pData, SvTreeListEntry* pEntry )
971 : {
972 : DBG_CHKTHIS(SvTreeListBox,0);
973 0 : SvTreeListEntry* pInhEntry = (SvTreeListEntry*)pEntry;
974 0 : SvViewDataEntry* pEntryData = (SvViewDataEntry*)pData;
975 :
976 0 : pEntryData->Init(pInhEntry->ItemCount());
977 0 : sal_uInt16 nCount = pInhEntry->ItemCount();
978 0 : sal_uInt16 nCurPos = 0;
979 0 : while( nCurPos < nCount )
980 : {
981 0 : SvLBoxItem* pItem = pInhEntry->GetItem( nCurPos );
982 0 : SvViewDataItem* pItemData = pEntryData->GetItem(nCurPos);
983 0 : pItem->InitViewData( this, pInhEntry, pItemData );
984 0 : pItemData++;
985 0 : nCurPos++;
986 : }
987 0 : }
988 :
989 :
990 :
991 0 : void SvTreeListBox::EnableSelectionAsDropTarget( sal_Bool bEnable, sal_Bool bWithChildren )
992 : {
993 : DBG_CHKTHIS(SvTreeListBox,0);
994 : sal_uInt16 nRefDepth;
995 : SvTreeListEntry* pTemp;
996 :
997 0 : SvTreeListEntry* pSelEntry = FirstSelected();
998 0 : while( pSelEntry )
999 : {
1000 0 : if ( !bEnable )
1001 : {
1002 0 : pSelEntry->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1003 0 : if ( bWithChildren )
1004 : {
1005 0 : nRefDepth = pModel->GetDepth( pSelEntry );
1006 0 : pTemp = Next( pSelEntry );
1007 0 : while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1008 : {
1009 0 : pTemp->nEntryFlags |= SV_ENTRYFLAG_DISABLE_DROP;
1010 0 : pTemp = Next( pTemp );
1011 : }
1012 : }
1013 : }
1014 : else
1015 : {
1016 0 : pSelEntry->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1017 0 : if ( bWithChildren )
1018 : {
1019 0 : nRefDepth = pModel->GetDepth( pSelEntry );
1020 0 : pTemp = Next( pSelEntry );
1021 0 : while( pTemp && pModel->GetDepth( pTemp ) > nRefDepth )
1022 : {
1023 0 : pTemp->nEntryFlags &= (~SV_ENTRYFLAG_DISABLE_DROP);
1024 0 : pTemp = Next( pTemp );
1025 : }
1026 : }
1027 : }
1028 0 : pSelEntry = NextSelected( pSelEntry );
1029 : }
1030 0 : }
1031 :
1032 : // ******************************************************************
1033 : // InplaceEditing
1034 : // ******************************************************************
1035 :
1036 0 : void SvTreeListBox::EditText( const String& rStr, const Rectangle& rRect,
1037 : const Selection& rSel )
1038 : {
1039 0 : EditText( rStr, rRect, rSel, sal_False );
1040 0 : }
1041 :
1042 0 : void SvTreeListBox::EditText( const String& rStr, const Rectangle& rRect,
1043 : const Selection& rSel, sal_Bool bMulti )
1044 : {
1045 : DBG_CHKTHIS(SvTreeListBox,0);
1046 0 : if( pEdCtrl )
1047 0 : delete pEdCtrl;
1048 0 : nImpFlags |= SVLBOX_IN_EDT;
1049 0 : nImpFlags &= ~SVLBOX_EDTEND_CALLED;
1050 0 : HideFocus();
1051 : pEdCtrl = new SvInplaceEdit2(
1052 : this, rRect.TopLeft(), rRect.GetSize(), rStr,
1053 : LINK( this, SvTreeListBox, TextEditEndedHdl_Impl ),
1054 0 : rSel, bMulti );
1055 0 : }
1056 :
1057 0 : IMPL_LINK_NOARG(SvTreeListBox, TextEditEndedHdl_Impl)
1058 : {
1059 : DBG_CHKTHIS(SvTreeListBox,0);
1060 0 : if ( nImpFlags & SVLBOX_EDTEND_CALLED ) // avoid nesting
1061 0 : return 0;
1062 0 : nImpFlags |= SVLBOX_EDTEND_CALLED;
1063 0 : String aStr;
1064 0 : if ( !pEdCtrl->EditingCanceled() )
1065 0 : aStr = pEdCtrl->GetText();
1066 : else
1067 0 : aStr = pEdCtrl->GetSavedValue();
1068 0 : if ( IsEmptyTextAllowed() || aStr.Len() > 0 )
1069 0 : EditedText( aStr );
1070 : // Hide may only be called after the new text was put into the entry, so
1071 : // that we don't call the selection handler in the GetFocus of the listbox
1072 : // with the old entry text.
1073 0 : pEdCtrl->Hide();
1074 : // delete pEdCtrl;
1075 : // pEdCtrl = 0;
1076 0 : nImpFlags &= (~SVLBOX_IN_EDT);
1077 0 : GrabFocus();
1078 0 : return 0;
1079 : }
1080 :
1081 0 : void SvTreeListBox::CancelTextEditing()
1082 : {
1083 : DBG_CHKTHIS(SvTreeListBox,0);
1084 0 : if ( pEdCtrl )
1085 0 : pEdCtrl->StopEditing( sal_True );
1086 0 : nImpFlags &= (~SVLBOX_IN_EDT);
1087 0 : }
1088 :
1089 0 : void SvTreeListBox::EndEditing( bool bCancel )
1090 : {
1091 : DBG_CHKTHIS(SvTreeListBox,0);
1092 0 : if( pEdCtrl )
1093 0 : pEdCtrl->StopEditing( bCancel );
1094 0 : nImpFlags &= (~SVLBOX_IN_EDT);
1095 0 : }
1096 :
1097 :
1098 0 : bool SvTreeListBox::IsEmptyTextAllowed() const
1099 : {
1100 : DBG_CHKTHIS(SvTreeListBox,0);
1101 0 : return mpImpl->m_bIsEmptyTextAllowed;
1102 : }
1103 :
1104 0 : void SvTreeListBox::ForbidEmptyText()
1105 : {
1106 : DBG_CHKTHIS(SvTreeListBox,0);
1107 0 : mpImpl->m_bIsEmptyTextAllowed = false;
1108 0 : }
1109 :
1110 0 : SvTreeListEntry* SvTreeListBox::CreateEntry() const
1111 : {
1112 : DBG_CHKTHIS(SvTreeListBox,0);
1113 0 : return new SvTreeListEntry;
1114 : }
1115 :
1116 0 : const void* SvTreeListBox::FirstSearchEntry( String& _rEntryText ) const
1117 : {
1118 0 : SvTreeListEntry* pEntry = GetCurEntry();
1119 0 : if ( pEntry )
1120 0 : pEntry = const_cast< SvTreeListEntry* >( static_cast< const SvTreeListEntry* >( NextSearchEntry( pEntry, _rEntryText ) ) );
1121 : else
1122 : {
1123 0 : pEntry = FirstSelected();
1124 0 : if ( !pEntry )
1125 0 : pEntry = First();
1126 : }
1127 :
1128 0 : if ( pEntry )
1129 0 : _rEntryText = GetEntryText( pEntry );
1130 :
1131 0 : return pEntry;
1132 : }
1133 :
1134 0 : const void* SvTreeListBox::NextSearchEntry( const void* _pCurrentSearchEntry, String& _rEntryText ) const
1135 : {
1136 0 : SvTreeListEntry* pEntry = const_cast< SvTreeListEntry* >( static_cast< const SvTreeListEntry* >( _pCurrentSearchEntry ) );
1137 :
1138 0 : if ( ( ( GetChildCount( pEntry ) > 0 )
1139 0 : || ( pEntry->HasChildrenOnDemand() )
1140 : )
1141 0 : && !IsExpanded( pEntry )
1142 : )
1143 : {
1144 0 : pEntry = NextSibling( pEntry );
1145 : }
1146 : else
1147 : {
1148 0 : pEntry = Next( pEntry );
1149 : }
1150 :
1151 0 : if ( !pEntry )
1152 0 : pEntry = First();
1153 :
1154 0 : if ( pEntry )
1155 0 : _rEntryText = GetEntryText( pEntry );
1156 :
1157 0 : return pEntry;
1158 : }
1159 :
1160 0 : void SvTreeListBox::SelectSearchEntry( const void* _pEntry )
1161 : {
1162 0 : SvTreeListEntry* pEntry = const_cast< SvTreeListEntry* >( static_cast< const SvTreeListEntry* >( _pEntry ) );
1163 : DBG_ASSERT( pEntry, "SvTreeListBox::SelectSearchEntry: invalid entry!" );
1164 0 : if ( !pEntry )
1165 0 : return;
1166 :
1167 0 : SelectAll( sal_False );
1168 0 : SetCurEntry( pEntry );
1169 0 : Select( pEntry );
1170 : }
1171 :
1172 0 : void SvTreeListBox::ExecuteSearchEntry( const void* /*_pEntry*/ ) const
1173 : {
1174 : // nothing to do here, we have no "execution"
1175 0 : }
1176 :
1177 0 : ::vcl::StringEntryIdentifier SvTreeListBox::CurrentEntry( String& _out_entryText ) const
1178 : {
1179 : // always accept the current entry if there is one
1180 0 : SvTreeListEntry* pCurrentEntry( GetCurEntry() );
1181 0 : if ( pCurrentEntry )
1182 : {
1183 0 : _out_entryText = GetEntryText( pCurrentEntry );
1184 0 : return pCurrentEntry;
1185 : }
1186 0 : return FirstSearchEntry( _out_entryText );
1187 : }
1188 :
1189 0 : ::vcl::StringEntryIdentifier SvTreeListBox::NextEntry( ::vcl::StringEntryIdentifier _currentEntry, String& _out_entryText ) const
1190 : {
1191 0 : return NextSearchEntry( _currentEntry, _out_entryText );
1192 : }
1193 :
1194 0 : void SvTreeListBox::SelectEntry( ::vcl::StringEntryIdentifier _entry )
1195 : {
1196 0 : SelectSearchEntry( _entry );
1197 0 : }
1198 :
1199 0 : bool SvTreeListBox::HandleKeyInput( const KeyEvent& _rKEvt )
1200 : {
1201 0 : if ( IsEntryMnemonicsEnabled()
1202 0 : && mpImpl->m_aMnemonicEngine.HandleKeyEvent( _rKEvt )
1203 : )
1204 0 : return true;
1205 :
1206 0 : if ( ( GetStyle() & WB_QUICK_SEARCH ) != 0 )
1207 : {
1208 0 : mpImpl->m_bDoingQuickSelection = true;
1209 0 : const bool bHandled = mpImpl->m_aQuickSelectionEngine.HandleKeyEvent( _rKEvt );
1210 0 : mpImpl->m_bDoingQuickSelection = false;
1211 0 : if ( bHandled )
1212 0 : return true;
1213 : }
1214 :
1215 0 : return false;
1216 : }
1217 :
1218 0 : void SvTreeListBox::WriteDragServerInfo( const Point&, SvLBoxDDInfo* )
1219 : {
1220 : DBG_CHKTHIS(SvTreeListBox,0);
1221 0 : }
1222 :
1223 0 : void SvTreeListBox::ReadDragServerInfo(const Point&, SvLBoxDDInfo* )
1224 : {
1225 : DBG_CHKTHIS(SvTreeListBox,0);
1226 0 : }
1227 :
1228 0 : sal_Bool SvTreeListBox::EditingCanceled() const
1229 : {
1230 0 : if( pEdCtrl && pEdCtrl->EditingCanceled() )
1231 0 : return sal_True;
1232 0 : return sal_False;
1233 : }
1234 :
1235 :
1236 : //JP 28.3.2001: new Drag & Drop API
1237 0 : sal_Int8 SvTreeListBox::AcceptDrop( const AcceptDropEvent& rEvt )
1238 : {
1239 : DBG_CHKTHIS(SvTreeListBox,0);
1240 0 : sal_Int8 nRet = DND_ACTION_NONE;
1241 :
1242 0 : if( rEvt.mbLeaving || !CheckDragAndDropMode( pDDSource, rEvt.mnAction ) )
1243 : {
1244 0 : ImplShowTargetEmphasis( pTargetEntry, sal_False );
1245 : }
1246 0 : else if( !nDragDropMode )
1247 : {
1248 : SAL_WARN( "svtools.contnr", "SvTreeListBox::QueryDrop(): no target" );
1249 : }
1250 : else
1251 : {
1252 0 : SvTreeListEntry* pEntry = GetDropTarget( rEvt.maPosPixel );
1253 0 : if( !IsDropFormatSupported( SOT_FORMATSTR_ID_TREELISTBOX ) )
1254 : {
1255 : SAL_WARN( "svtools.contnr", "SvTreeListBox::QueryDrop(): no format" );
1256 : }
1257 : else
1258 : {
1259 : DBG_ASSERT( pDDSource, "SvTreeListBox::QueryDrop(): SourceBox == 0" );
1260 0 : if( !( pEntry && pDDSource->GetModel() == this->GetModel()
1261 : && DND_ACTION_MOVE == rEvt.mnAction
1262 0 : && ( pEntry->nEntryFlags & SV_ENTRYFLAG_DISABLE_DROP ) ))
1263 : {
1264 0 : if( NotifyAcceptDrop( pEntry ))
1265 0 : nRet = rEvt.mnAction;
1266 : }
1267 : }
1268 :
1269 : // **** draw emphasis ****
1270 0 : if( DND_ACTION_NONE == nRet )
1271 0 : ImplShowTargetEmphasis( pTargetEntry, sal_False );
1272 0 : else if( pEntry != pTargetEntry || !(nImpFlags & SVLBOX_TARGEMPH_VIS) )
1273 : {
1274 0 : ImplShowTargetEmphasis( pTargetEntry, sal_False );
1275 0 : pTargetEntry = pEntry;
1276 0 : ImplShowTargetEmphasis( pTargetEntry, sal_True );
1277 : }
1278 : }
1279 0 : return nRet;
1280 : }
1281 :
1282 0 : sal_Int8 SvTreeListBox::ExecuteDrop( const ExecuteDropEvent& rEvt, SvTreeListBox* pSourceView )
1283 : {
1284 : DBG_CHKTHIS(SvTreeListBox,0);
1285 0 : sal_Int8 nRet = DND_ACTION_NONE;
1286 :
1287 : DBG_ASSERT( pSourceView, "SvTreeListBox::ExecuteDrop(): no source view" );
1288 0 : pSourceView->EnableSelectionAsDropTarget( sal_True, sal_True );
1289 :
1290 0 : ImplShowTargetEmphasis( pTargetEntry, sal_False );
1291 0 : pDDTarget = this;
1292 :
1293 : SvLBoxDDInfo aDDInfo;
1294 :
1295 0 : TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
1296 0 : if( aData.HasFormat( SOT_FORMATSTR_ID_TREELISTBOX ))
1297 : {
1298 0 : ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
1299 0 : if( aData.GetSequence( SOT_FORMATSTR_ID_TREELISTBOX, aSeq ) &&
1300 0 : sizeof(SvLBoxDDInfo) == aSeq.getLength() )
1301 : {
1302 0 : memcpy( &aDDInfo, aSeq.getConstArray(), sizeof(SvLBoxDDInfo) );
1303 0 : nRet = rEvt.mnAction;
1304 0 : }
1305 : }
1306 :
1307 0 : if( DND_ACTION_NONE != nRet )
1308 : {
1309 0 : nRet = DND_ACTION_NONE;
1310 :
1311 0 : ReadDragServerInfo( rEvt.maPosPixel, &aDDInfo );
1312 :
1313 0 : SvTreeListEntry* pTarget = pTargetEntry; // may be 0!
1314 :
1315 0 : if( DND_ACTION_COPY == rEvt.mnAction )
1316 : {
1317 0 : if ( CopySelection( aDDInfo.pSource, pTarget ) )
1318 0 : nRet = rEvt.mnAction;
1319 : }
1320 0 : else if( DND_ACTION_MOVE == rEvt.mnAction )
1321 : {
1322 0 : if ( MoveSelection( aDDInfo.pSource, pTarget ) )
1323 0 : nRet = rEvt.mnAction;
1324 : }
1325 0 : else if( DND_ACTION_COPYMOVE == rEvt.mnAction )
1326 : {
1327 0 : if ( MoveSelectionCopyFallbackPossible( aDDInfo.pSource, pTarget, sal_True ) )
1328 0 : nRet = rEvt.mnAction;
1329 : }
1330 : }
1331 0 : return nRet;
1332 : }
1333 :
1334 0 : sal_Int8 SvTreeListBox::ExecuteDrop( const ExecuteDropEvent& rEvt )
1335 : {
1336 : DBG_CHKTHIS(SvTreeListBox,0);
1337 0 : return ExecuteDrop( rEvt, GetSourceView() );
1338 : }
1339 :
1340 0 : void SvTreeListBox::StartDrag( sal_Int8, const Point& rPosPixel )
1341 : {
1342 : DBG_CHKTHIS(SvTreeListBox,0);
1343 :
1344 0 : Point aEventPos( rPosPixel );
1345 0 : MouseEvent aMouseEvt( aEventPos, 1, MOUSE_SELECT, MOUSE_LEFT );
1346 0 : MouseButtonUp( aMouseEvt );
1347 :
1348 0 : nOldDragMode = GetDragDropMode();
1349 0 : if ( !nOldDragMode )
1350 : return;
1351 :
1352 0 : ReleaseMouse();
1353 :
1354 0 : SvTreeListEntry* pEntry = GetEntry( rPosPixel ); // GetDropTarget( rPos );
1355 0 : if( !pEntry )
1356 : {
1357 0 : DragFinished( DND_ACTION_NONE );
1358 : return;
1359 : }
1360 :
1361 0 : TransferDataContainer* pContainer = new TransferDataContainer;
1362 : ::com::sun::star::uno::Reference<
1363 0 : ::com::sun::star::datatransfer::XTransferable > xRef( pContainer );
1364 :
1365 0 : nDragDropMode = NotifyStartDrag( *pContainer, pEntry );
1366 0 : if( !nDragDropMode || 0 == GetSelectionCount() )
1367 : {
1368 0 : nDragDropMode = nOldDragMode;
1369 0 : DragFinished( DND_ACTION_NONE );
1370 : return;
1371 : }
1372 :
1373 : SvLBoxDDInfo aDDInfo;
1374 0 : memset(&aDDInfo,0,sizeof(SvLBoxDDInfo));
1375 0 : aDDInfo.pApp = GetpApp();
1376 0 : aDDInfo.pSource = this;
1377 0 : aDDInfo.pDDStartEntry = pEntry;
1378 : // let derived views do their thing
1379 0 : WriteDragServerInfo( rPosPixel, &aDDInfo );
1380 :
1381 : pContainer->CopyAnyData( SOT_FORMATSTR_ID_TREELISTBOX,
1382 0 : (sal_Char*)&aDDInfo, sizeof(SvLBoxDDInfo) );
1383 0 : pDDSource = this;
1384 0 : pDDTarget = 0;
1385 :
1386 0 : sal_Bool bOldUpdateMode = Control::IsUpdateMode();
1387 0 : Control::SetUpdateMode( sal_True );
1388 0 : Update();
1389 0 : Control::SetUpdateMode( bOldUpdateMode );
1390 :
1391 : // Disallow using the selection and its children as drop targets.
1392 : // Important: If the selection of the SourceListBox is changed in the
1393 : // DropHandler, the entries have to be allowed as drop targets again:
1394 : // (GetSourceListBox()->EnableSelectionAsDropTarget( sal_True, sal_True );)
1395 0 : EnableSelectionAsDropTarget( sal_False, sal_True /* with children */ );
1396 :
1397 0 : pContainer->StartDrag( this, nDragOptions, GetDragFinishedHdl() );
1398 : }
1399 :
1400 0 : void SvTreeListBox::DragFinished( sal_Int8
1401 : #ifndef UNX
1402 : nAction
1403 : #endif
1404 : )
1405 : {
1406 0 : EnableSelectionAsDropTarget( sal_True, sal_True );
1407 :
1408 : #ifndef UNX
1409 : if( (nAction == DND_ACTION_MOVE) && ( (pDDTarget &&
1410 : ((sal_uLong)(pDDTarget->GetModel())!=(sal_uLong)(this->GetModel()))) ||
1411 : !pDDTarget ))
1412 : {
1413 : RemoveSelection();
1414 : }
1415 : #endif
1416 :
1417 0 : ImplShowTargetEmphasis( pTargetEntry, sal_False );
1418 0 : pDDSource = 0;
1419 0 : pDDTarget = 0;
1420 0 : pTargetEntry = 0;
1421 0 : nDragDropMode = nOldDragMode;
1422 0 : }
1423 :
1424 0 : DragDropMode SvTreeListBox::NotifyStartDrag( TransferDataContainer&, SvTreeListEntry* )
1425 : {
1426 : DBG_CHKTHIS(SvTreeListBox,0);
1427 0 : return (DragDropMode)0xffff;
1428 : }
1429 :
1430 0 : sal_Bool SvTreeListBox::NotifyAcceptDrop( SvTreeListEntry* )
1431 : {
1432 : DBG_CHKTHIS(SvTreeListBox,0);
1433 0 : return sal_True;
1434 : }
1435 :
1436 : // Handler and methods for Drag - finished handler.
1437 : // The with get GetDragFinishedHdl() get link can set on the
1438 : // TransferDataContainer. This link is a callback for the DragFinished
1439 : // call. AddBox method is called from the GetDragFinishedHdl() and the
1440 : // remove is called in link callback and in the destructor. So it can't
1441 : // called to a deleted object.
1442 :
1443 : namespace
1444 : {
1445 : struct SortLBoxes : public rtl::Static<std::set<sal_uLong>, SortLBoxes> {};
1446 : }
1447 :
1448 0 : void SvTreeListBox::AddBoxToDDList_Impl( const SvTreeListBox& rB )
1449 : {
1450 0 : sal_uLong nVal = (sal_uLong)&rB;
1451 0 : SortLBoxes::get().insert( nVal );
1452 0 : }
1453 :
1454 0 : void SvTreeListBox::RemoveBoxFromDDList_Impl( const SvTreeListBox& rB )
1455 : {
1456 0 : sal_uLong nVal = (sal_uLong)&rB;
1457 0 : SortLBoxes::get().erase( nVal );
1458 0 : }
1459 :
1460 0 : IMPL_STATIC_LINK( SvTreeListBox, DragFinishHdl_Impl, sal_Int8*, pAction )
1461 : {
1462 0 : sal_uLong nVal = (sal_uLong)pThis;
1463 0 : std::set<sal_uLong> &rSortLBoxes = SortLBoxes::get();
1464 0 : std::set<sal_uLong>::const_iterator it = rSortLBoxes.find(nVal);
1465 0 : if( it != rSortLBoxes.end() )
1466 : {
1467 0 : pThis->DragFinished( *pAction );
1468 0 : rSortLBoxes.erase( it );
1469 : }
1470 0 : return 0;
1471 : }
1472 :
1473 0 : Link SvTreeListBox::GetDragFinishedHdl() const
1474 : {
1475 0 : AddBoxToDDList_Impl( *this );
1476 0 : return STATIC_LINK( this, SvTreeListBox, DragFinishHdl_Impl );
1477 : }
1478 :
1479 : /*
1480 : Bugs/TODO
1481 :
1482 : - calculate rectangle when editing in-place (bug with some fonts)
1483 : - SetSpaceBetweenEntries: offset is not taken into account in SetEntryHeight
1484 : */
1485 :
1486 : #define TREEFLAG_FIXEDHEIGHT 0x0010
1487 :
1488 : #define SV_LBOX_DEFAULT_INDENT_PIXEL 20
1489 :
1490 0 : void SvTreeListBox::InitTreeView()
1491 : {
1492 : DBG_CHKTHIS(SvTreeListBox,0);
1493 0 : pCheckButtonData = NULL;
1494 0 : pEdEntry = NULL;
1495 0 : pEdItem = NULL;
1496 0 : nEntryHeight = 0;
1497 0 : pEdCtrl = NULL;
1498 0 : nFirstSelTab = 0;
1499 0 : nLastSelTab = 0;
1500 0 : nFocusWidth = -1;
1501 0 : mnCheckboxItemWidth = 0;
1502 :
1503 0 : Link* pLink = new Link( LINK(this,SvTreeListBox, DefaultCompare) );
1504 0 : mpImpl->m_pLink = pLink;
1505 :
1506 0 : nTreeFlags = TREEFLAG_RECALCTABS;
1507 0 : nIndent = SV_LBOX_DEFAULT_INDENT_PIXEL;
1508 0 : nEntryHeightOffs = SV_ENTRYHEIGHTOFFS_PIXEL;
1509 0 : pImp = new SvImpLBox( this, GetModel(), GetStyle() );
1510 :
1511 0 : mbContextBmpExpanded = true;
1512 0 : nContextBmpWidthMax = 0;
1513 0 : SetFont( GetFont() );
1514 0 : SetSpaceBetweenEntries( 0 );
1515 0 : SetLineColor();
1516 0 : InitSettings( sal_True, sal_True, sal_True );
1517 0 : ImplInitStyle();
1518 0 : SetTabs();
1519 0 : }
1520 :
1521 :
1522 0 : SvTreeListBox::~SvTreeListBox()
1523 : {
1524 : DBG_DTOR(SvTreeListBox,0);
1525 :
1526 0 : pImp->CallEventListeners( VCLEVENT_OBJECT_DYING );
1527 0 : delete pImp;
1528 0 : delete mpImpl->m_pLink;
1529 0 : ClearTabList();
1530 :
1531 0 : delete pEdCtrl;
1532 0 : pEdCtrl = 0;
1533 0 : pModel->RemoveView( this );
1534 0 : if ( pModel->GetRefCount() == 0 )
1535 : {
1536 0 : pModel->Clear();
1537 0 : delete pModel;
1538 0 : pModel = NULL;
1539 : }
1540 :
1541 0 : SvTreeListBox::RemoveBoxFromDDList_Impl( *this );
1542 :
1543 0 : if( this == pDDSource )
1544 0 : pDDSource = 0;
1545 0 : if( this == pDDTarget )
1546 0 : pDDTarget = 0;
1547 0 : delete mpImpl;
1548 0 : }
1549 :
1550 0 : void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits )
1551 : {
1552 0 : pImp->SetExtendedWindowBits( _nBits );
1553 0 : }
1554 :
1555 0 : void SvTreeListBox::SetModel( SvTreeList* pNewModel )
1556 : {
1557 : DBG_CHKTHIS(SvTreeListBox,0);
1558 0 : pImp->SetModel( pNewModel );
1559 0 : SetBaseModel(pNewModel);
1560 0 : }
1561 :
1562 0 : void SvTreeListBox::SetBaseModel( SvTreeList* pNewModel )
1563 : {
1564 : // does the CleanUp
1565 0 : SvListView::SetModel( pNewModel );
1566 0 : pModel->SetCloneLink( LINK(this, SvTreeListBox, CloneHdl_Impl ));
1567 0 : SvTreeListEntry* pEntry = First();
1568 0 : while( pEntry )
1569 : {
1570 0 : ModelHasInserted( pEntry );
1571 0 : pEntry = Next( pEntry );
1572 : }
1573 0 : }
1574 :
1575 0 : void SvTreeListBox::DisconnectFromModel()
1576 : {
1577 : DBG_CHKTHIS(SvTreeListBox,0);
1578 0 : SvTreeList* pNewModel = new SvTreeList;
1579 0 : pNewModel->SetRefCount( 0 ); // else this will never be deleted
1580 0 : SvListView::SetModel( pNewModel );
1581 :
1582 0 : pImp->SetModel( GetModel() );
1583 0 : }
1584 :
1585 0 : void SvTreeListBox::SetSublistOpenWithReturn( sal_Bool b )
1586 : {
1587 0 : pImp->bSubLstOpRet = b;
1588 0 : }
1589 :
1590 0 : void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b )
1591 : {
1592 0 : pImp->bSubLstOpLR = b;
1593 0 : }
1594 :
1595 0 : void SvTreeListBox::Resize()
1596 : {
1597 : DBG_CHKTHIS(SvTreeListBox,0);
1598 0 : if( IsEditingActive() )
1599 0 : EndEditing( sal_True );
1600 :
1601 0 : Control::Resize();
1602 :
1603 0 : pImp->Resize();
1604 0 : nFocusWidth = -1;
1605 0 : pImp->ShowCursor( sal_False );
1606 0 : pImp->ShowCursor( sal_True );
1607 0 : }
1608 :
1609 : /* Cases:
1610 :
1611 : A) entries have bitmaps
1612 : 0. no buttons
1613 : 1. node buttons (can optionally also be on root items)
1614 : 2. node buttons (can optionally also be on root items) + CheckButton
1615 : 3. CheckButton
1616 : B) entries don't have bitmaps (=>via WindowBits because of D&D!)
1617 : 0. no buttons
1618 : 1. node buttons (can optionally also be on root items)
1619 : 2. node buttons (can optionally also be on root items) + CheckButton
1620 : 3. CheckButton
1621 : */
1622 :
1623 : #define NO_BUTTONS 0
1624 : #define NODE_BUTTONS 1
1625 : #define NODE_AND_CHECK_BUTTONS 2
1626 : #define CHECK_BUTTONS 3
1627 :
1628 : #define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC | \
1629 : SV_LBOXTAB_ADJUST_LEFT | \
1630 : SV_LBOXTAB_EDITABLE | \
1631 : SV_LBOXTAB_SHOW_SELECTION)
1632 :
1633 : #define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER)
1634 :
1635 : #define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC | \
1636 : SV_LBOXTAB_ADJUST_CENTER | \
1637 : SV_LBOXTAB_PUSHABLE)
1638 :
1639 : #define TAB_STARTPOS 2
1640 :
1641 : // take care of GetTextOffset when doing changes
1642 0 : void SvTreeListBox::SetTabs()
1643 : {
1644 : DBG_CHKTHIS(SvTreeListBox,0);
1645 0 : if( IsEditingActive() )
1646 0 : EndEditing( sal_True );
1647 0 : nTreeFlags &= (~TREEFLAG_RECALCTABS);
1648 0 : nFocusWidth = -1;
1649 0 : const WinBits nStyle( GetStyle() );
1650 0 : sal_Bool bHasButtons = (nStyle & WB_HASBUTTONS)!=0;
1651 : sal_Bool bHasButtonsAtRoot = (nStyle & (WB_HASLINESATROOT |
1652 0 : WB_HASBUTTONSATROOT))!=0;
1653 0 : long nStartPos = TAB_STARTPOS;
1654 0 : long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width();
1655 :
1656 : // pCheckButtonData->Width() knows nothing about the native checkbox width,
1657 : // so we have mnCheckboxItemWidth which becomes valid when something is added.
1658 0 : long nCheckWidth = 0;
1659 0 : if( nTreeFlags & TREEFLAG_CHKBTN )
1660 0 : nCheckWidth = mnCheckboxItemWidth;
1661 0 : long nCheckWidthDIV2 = nCheckWidth / 2;
1662 :
1663 0 : long nContextWidth = nContextBmpWidthMax;
1664 0 : long nContextWidthDIV2 = nContextWidth / 2;
1665 :
1666 0 : ClearTabList();
1667 :
1668 0 : int nCase = NO_BUTTONS;
1669 0 : if( !(nTreeFlags & TREEFLAG_CHKBTN) )
1670 : {
1671 0 : if( bHasButtons )
1672 0 : nCase = NODE_BUTTONS;
1673 : }
1674 : else
1675 : {
1676 0 : if( bHasButtons )
1677 0 : nCase = NODE_AND_CHECK_BUTTONS;
1678 : else
1679 0 : nCase = CHECK_BUTTONS;
1680 : }
1681 :
1682 0 : switch( nCase )
1683 : {
1684 : case NO_BUTTONS :
1685 0 : nStartPos += nContextWidthDIV2; // because of centering
1686 0 : AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
1687 0 : nStartPos += nContextWidthDIV2; // right edge of context bitmap
1688 : // only set a distance if there are bitmaps
1689 0 : if( nContextBmpWidthMax )
1690 0 : nStartPos += 5; // distance context bitmap to text
1691 0 : AddTab( nStartPos, TABFLAGS_TEXT );
1692 0 : break;
1693 :
1694 : case NODE_BUTTONS :
1695 0 : if( bHasButtonsAtRoot )
1696 0 : nStartPos += ( nIndent + (nNodeWidthPixel/2) );
1697 : else
1698 0 : nStartPos += nContextWidthDIV2;
1699 0 : AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
1700 0 : nStartPos += nContextWidthDIV2; // right edge of context bitmap
1701 : // only set a distance if there are bitmaps
1702 0 : if( nContextBmpWidthMax )
1703 0 : nStartPos += 5; // distance context bitmap to text
1704 0 : AddTab( nStartPos, TABFLAGS_TEXT );
1705 0 : break;
1706 :
1707 : case NODE_AND_CHECK_BUTTONS :
1708 0 : if( bHasButtonsAtRoot )
1709 0 : nStartPos += ( nIndent + nNodeWidthPixel );
1710 : else
1711 0 : nStartPos += nCheckWidthDIV2;
1712 0 : AddTab( nStartPos, TABFLAGS_CHECKBTN );
1713 0 : nStartPos += nCheckWidthDIV2; // right edge of CheckButton
1714 0 : nStartPos += 3; // distance CheckButton to context bitmap
1715 0 : nStartPos += nContextWidthDIV2; // center of context bitmap
1716 0 : AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
1717 0 : nStartPos += nContextWidthDIV2; // right edge of context bitmap
1718 : // only set a distance if there are bitmaps
1719 0 : if( nContextBmpWidthMax )
1720 0 : nStartPos += 5; // distance context bitmap to text
1721 0 : AddTab( nStartPos, TABFLAGS_TEXT );
1722 0 : break;
1723 :
1724 : case CHECK_BUTTONS :
1725 0 : nStartPos += nCheckWidthDIV2;
1726 0 : AddTab( nStartPos, TABFLAGS_CHECKBTN );
1727 0 : nStartPos += nCheckWidthDIV2; // right edge of CheckButton
1728 0 : nStartPos += 3; // distance CheckButton to context bitmap
1729 0 : nStartPos += nContextWidthDIV2; // center of context bitmap
1730 0 : AddTab( nStartPos, TABFLAGS_CONTEXTBMP );
1731 0 : nStartPos += nContextWidthDIV2; // right edge of context bitmap
1732 : // only set a distance if there are bitmaps
1733 0 : if( nContextBmpWidthMax )
1734 0 : nStartPos += 5; // distance context bitmap to text
1735 0 : AddTab( nStartPos, TABFLAGS_TEXT );
1736 0 : break;
1737 : }
1738 0 : pImp->NotifyTabsChanged();
1739 0 : }
1740 :
1741 0 : void SvTreeListBox::InitEntry(SvTreeListEntry* pEntry,
1742 : const OUString& aStr, const Image& aCollEntryBmp, const Image& aExpEntryBmp,
1743 : SvLBoxButtonKind eButtonKind)
1744 : {
1745 : DBG_CHKTHIS(SvTreeListBox,0);
1746 : SvLBoxButton* pButton;
1747 : SvLBoxString* pString;
1748 : SvLBoxContextBmp* pContextBmp;
1749 :
1750 0 : if( nTreeFlags & TREEFLAG_CHKBTN )
1751 : {
1752 0 : pButton= new SvLBoxButton( pEntry,eButtonKind,0,pCheckButtonData );
1753 0 : pEntry->AddItem( pButton );
1754 : }
1755 :
1756 : pContextBmp= new SvLBoxContextBmp(
1757 0 : pEntry,0, aCollEntryBmp,aExpEntryBmp, mbContextBmpExpanded);
1758 0 : pEntry->AddItem( pContextBmp );
1759 :
1760 0 : pString = new SvLBoxString( pEntry, 0, aStr );
1761 0 : pEntry->AddItem( pString );
1762 0 : }
1763 :
1764 0 : String SvTreeListBox::GetEntryText(SvTreeListEntry* pEntry) const
1765 : {
1766 : DBG_CHKTHIS(SvTreeListBox,0);
1767 : DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): no entry" );
1768 0 : SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
1769 : DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): item not found" );
1770 0 : return pItem->GetText();
1771 : }
1772 :
1773 0 : String SvTreeListBox::SearchEntryText( SvTreeListEntry* pEntry ) const
1774 : {
1775 : DBG_CHKTHIS(SvTreeListBox,0);
1776 : DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" );
1777 0 : String sRet;
1778 0 : sal_uInt16 nCount = pEntry->ItemCount();
1779 0 : sal_uInt16 nCur = 0;
1780 : SvLBoxItem* pItem;
1781 0 : while( nCur < nCount )
1782 : {
1783 0 : pItem = pEntry->GetItem( nCur );
1784 0 : if (pItem->GetType() == SV_ITEM_ID_LBOXSTRING && !static_cast<const SvLBoxString*>(pItem)->GetText().isEmpty())
1785 : {
1786 0 : sRet = static_cast<const SvLBoxString*>(pItem)->GetText();
1787 0 : break;
1788 : }
1789 0 : nCur++;
1790 : }
1791 0 : return sRet;
1792 : }
1793 :
1794 0 : const Image& SvTreeListBox::GetExpandedEntryBmp(const SvTreeListEntry* pEntry) const
1795 : {
1796 : DBG_CHKTHIS(SvTreeListBox,0);
1797 : DBG_ASSERT(pEntry,"Entry?");
1798 0 : const SvLBoxContextBmp* pItem = static_cast<const SvLBoxContextBmp*>(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1799 : DBG_ASSERT(pItem,"GetContextBmp:Item not found");
1800 0 : return pItem->GetBitmap2( );
1801 : }
1802 :
1803 0 : const Image& SvTreeListBox::GetCollapsedEntryBmp( const SvTreeListEntry* pEntry ) const
1804 : {
1805 : DBG_CHKTHIS(SvTreeListBox,0);
1806 : DBG_ASSERT(pEntry,"Entry?");
1807 0 : const SvLBoxContextBmp* pItem = static_cast<const SvLBoxContextBmp*>(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1808 : DBG_ASSERT(pItem,"GetContextBmp:Item not found");
1809 0 : return pItem->GetBitmap1( );
1810 : }
1811 :
1812 0 : IMPL_LINK_INLINE_START( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
1813 : {
1814 : DBG_CHKTHIS(SvTreeListBox,0);
1815 0 : pHdlEntry = pData->GetActEntry();
1816 0 : CheckButtonHdl();
1817 0 : return 0;
1818 : }
1819 0 : IMPL_LINK_INLINE_END( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData )
1820 :
1821 0 : SvTreeListEntry* SvTreeListBox::InsertEntry(
1822 : const XubString& aText,
1823 : SvTreeListEntry* pParent,
1824 : sal_Bool bChildrenOnDemand, sal_uLong nPos,
1825 : void* pUser,
1826 : SvLBoxButtonKind eButtonKind
1827 : )
1828 : {
1829 : DBG_CHKTHIS(SvTreeListBox,0);
1830 0 : nTreeFlags |= TREEFLAG_MANINS;
1831 :
1832 0 : const Image& rDefExpBmp = pImp->GetDefaultEntryExpBmp( );
1833 0 : const Image& rDefColBmp = pImp->GetDefaultEntryColBmp( );
1834 :
1835 0 : aCurInsertedExpBmp = rDefExpBmp;
1836 0 : aCurInsertedColBmp = rDefColBmp;
1837 :
1838 0 : SvTreeListEntry* pEntry = CreateEntry();
1839 0 : pEntry->SetUserData( pUser );
1840 0 : InitEntry( pEntry, aText, rDefColBmp, rDefExpBmp, eButtonKind );
1841 0 : pEntry->EnableChildrenOnDemand( bChildrenOnDemand );
1842 :
1843 0 : if( !pParent )
1844 0 : Insert( pEntry, nPos );
1845 : else
1846 0 : Insert( pEntry, pParent, nPos );
1847 :
1848 0 : aPrevInsertedExpBmp = rDefExpBmp;
1849 0 : aPrevInsertedColBmp = rDefColBmp;
1850 :
1851 0 : nTreeFlags &= (~TREEFLAG_MANINS);
1852 :
1853 0 : return pEntry;
1854 : }
1855 :
1856 0 : SvTreeListEntry* SvTreeListBox::InsertEntry( const XubString& aText,
1857 : const Image& aExpEntryBmp, const Image& aCollEntryBmp,
1858 : SvTreeListEntry* pParent, sal_Bool bChildrenOnDemand, sal_uLong nPos, void* pUser,
1859 : SvLBoxButtonKind eButtonKind )
1860 : {
1861 : DBG_CHKTHIS(SvTreeListBox,0);
1862 0 : nTreeFlags |= TREEFLAG_MANINS;
1863 :
1864 0 : aCurInsertedExpBmp = aExpEntryBmp;
1865 0 : aCurInsertedColBmp = aCollEntryBmp;
1866 :
1867 0 : SvTreeListEntry* pEntry = CreateEntry();
1868 0 : pEntry->SetUserData( pUser );
1869 0 : InitEntry( pEntry, aText, aCollEntryBmp, aExpEntryBmp, eButtonKind );
1870 :
1871 0 : pEntry->EnableChildrenOnDemand( bChildrenOnDemand );
1872 :
1873 0 : if( !pParent )
1874 0 : Insert( pEntry, nPos );
1875 : else
1876 0 : Insert( pEntry, pParent, nPos );
1877 :
1878 0 : aPrevInsertedExpBmp = aExpEntryBmp;
1879 0 : aPrevInsertedColBmp = aCollEntryBmp;
1880 :
1881 0 : nTreeFlags &= (~TREEFLAG_MANINS);
1882 :
1883 0 : return pEntry;
1884 : }
1885 :
1886 0 : void SvTreeListBox::SetEntryText( SvTreeListEntry* pEntry, const XubString& aStr)
1887 : {
1888 : DBG_CHKTHIS(SvTreeListBox,0);
1889 0 : SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
1890 : DBG_ASSERT(pItem,"SetText:Item not found");
1891 0 : pItem->SetText( aStr );
1892 0 : pItem->InitViewData( this, pEntry, 0 );
1893 0 : GetModel()->InvalidateEntry( pEntry );
1894 0 : }
1895 :
1896 0 : void SvTreeListBox::SetExpandedEntryBmp( SvTreeListEntry* pEntry, const Image& aBmp )
1897 : {
1898 : DBG_CHKTHIS(SvTreeListBox,0);
1899 0 : SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1900 :
1901 : DBG_ASSERT(pItem,"SetExpBmp:Item not found");
1902 0 : pItem->SetBitmap2( aBmp );
1903 :
1904 0 : GetModel()->InvalidateEntry( pEntry );
1905 0 : SetEntryHeight( pEntry );
1906 0 : Size aSize = aBmp.GetSizePixel();
1907 0 : short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
1908 0 : if( nWidth > nContextBmpWidthMax )
1909 : {
1910 0 : nContextBmpWidthMax = nWidth;
1911 0 : SetTabs();
1912 : }
1913 0 : }
1914 :
1915 0 : void SvTreeListBox::SetCollapsedEntryBmp(SvTreeListEntry* pEntry,const Image& aBmp )
1916 : {
1917 : DBG_CHKTHIS(SvTreeListBox,0);
1918 0 : SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
1919 :
1920 : DBG_ASSERT(pItem,"SetExpBmp:Item not found");
1921 0 : pItem->SetBitmap1( aBmp );
1922 :
1923 0 : GetModel()->InvalidateEntry( pEntry );
1924 0 : SetEntryHeight( pEntry );
1925 0 : Size aSize = aBmp.GetSizePixel();
1926 0 : short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
1927 0 : if( nWidth > nContextBmpWidthMax )
1928 : {
1929 0 : nContextBmpWidthMax = nWidth;
1930 0 : SetTabs();
1931 : }
1932 0 : }
1933 :
1934 0 : void SvTreeListBox::ImpEntryInserted( SvTreeListEntry* pEntry )
1935 : {
1936 : DBG_CHKTHIS(SvTreeListBox,0);
1937 :
1938 0 : SvTreeListEntry* pParent = (SvTreeListEntry*)pModel->GetParent( pEntry );
1939 0 : if( pParent )
1940 : {
1941 0 : sal_uInt16 nFlags = pParent->GetFlags();
1942 0 : nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
1943 0 : pParent->SetFlags( nFlags );
1944 : }
1945 :
1946 0 : if(!((nTreeFlags & TREEFLAG_MANINS) &&
1947 0 : (aPrevInsertedExpBmp == aCurInsertedExpBmp) &&
1948 0 : (aPrevInsertedColBmp == aCurInsertedColBmp) ))
1949 : {
1950 0 : Size aSize = GetCollapsedEntryBmp( pEntry ).GetSizePixel();
1951 0 : if( aSize.Width() > nContextBmpWidthMax )
1952 : {
1953 0 : nContextBmpWidthMax = (short)aSize.Width();
1954 0 : nTreeFlags |= TREEFLAG_RECALCTABS;
1955 : }
1956 0 : aSize = GetExpandedEntryBmp( pEntry ).GetSizePixel();
1957 0 : if( aSize.Width() > nContextBmpWidthMax )
1958 : {
1959 0 : nContextBmpWidthMax = (short)aSize.Width();
1960 0 : nTreeFlags |= TREEFLAG_RECALCTABS;
1961 : }
1962 : }
1963 0 : SetEntryHeight( (SvTreeListEntry*)pEntry );
1964 :
1965 0 : if( nTreeFlags & TREEFLAG_CHKBTN )
1966 : {
1967 0 : SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
1968 0 : if( pItem )
1969 : {
1970 0 : long nWidth = pItem->GetSize(this, pEntry).Width();
1971 0 : if( mnCheckboxItemWidth < nWidth )
1972 : {
1973 0 : mnCheckboxItemWidth = nWidth;
1974 0 : nTreeFlags |= TREEFLAG_RECALCTABS;
1975 : }
1976 : }
1977 : }
1978 0 : }
1979 :
1980 :
1981 :
1982 0 : void SvTreeListBox::SetCheckButtonState( SvTreeListEntry* pEntry, SvButtonState eState)
1983 : {
1984 : DBG_CHKTHIS(SvTreeListBox,0);
1985 0 : if( nTreeFlags & TREEFLAG_CHKBTN )
1986 : {
1987 0 : SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
1988 0 : if(!(pItem && pItem->CheckModification()))
1989 0 : return ;
1990 0 : switch( eState )
1991 : {
1992 : case SV_BUTTON_CHECKED:
1993 0 : pItem->SetStateChecked();
1994 0 : break;
1995 :
1996 : case SV_BUTTON_UNCHECKED:
1997 0 : pItem->SetStateUnchecked();
1998 0 : break;
1999 :
2000 : case SV_BUTTON_TRISTATE:
2001 0 : pItem->SetStateTristate();
2002 0 : break;
2003 : }
2004 0 : InvalidateEntry( pEntry );
2005 : }
2006 : }
2007 :
2008 0 : SvButtonState SvTreeListBox::GetCheckButtonState( SvTreeListEntry* pEntry ) const
2009 : {
2010 : DBG_CHKTHIS(SvTreeListBox,0);
2011 0 : SvButtonState eState = SV_BUTTON_UNCHECKED;
2012 0 : if( nTreeFlags & TREEFLAG_CHKBTN )
2013 : {
2014 0 : SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
2015 0 : if(!pItem)
2016 0 : return SV_BUTTON_TRISTATE;
2017 0 : sal_uInt16 nButtonFlags = pItem->GetButtonFlags();
2018 0 : eState = pCheckButtonData->ConvertToButtonState( nButtonFlags );
2019 : }
2020 0 : return eState;
2021 : }
2022 :
2023 0 : void SvTreeListBox::CheckButtonHdl()
2024 : {
2025 : DBG_CHKTHIS(SvTreeListBox,0);
2026 0 : aCheckButtonHdl.Call( this );
2027 0 : if ( pCheckButtonData )
2028 0 : pImp->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE, (void*)pCheckButtonData->GetActEntry() );
2029 0 : }
2030 :
2031 : //
2032 : // TODO: Currently all data is cloned so that they conform to the default tree
2033 : // view format. Actually, the model should be used as a reference here. This
2034 : // leads to us _not_ calling SvTreeListEntry::Clone, but only its base class
2035 : // SvTreeListEntry.
2036 : //
2037 :
2038 0 : SvTreeListEntry* SvTreeListBox::CloneEntry( SvTreeListEntry* pSource )
2039 : {
2040 : DBG_CHKTHIS(SvTreeListBox,0);
2041 0 : XubString aStr;
2042 0 : Image aCollEntryBmp;
2043 0 : Image aExpEntryBmp;
2044 0 : SvLBoxButtonKind eButtonKind = SvLBoxButtonKind_enabledCheckbox;
2045 :
2046 0 : SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING));
2047 0 : if( pStringItem )
2048 0 : aStr = pStringItem->GetText();
2049 0 : SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
2050 0 : if( pBmpItem )
2051 : {
2052 0 : aCollEntryBmp = pBmpItem->GetBitmap1( );
2053 0 : aExpEntryBmp = pBmpItem->GetBitmap2( );
2054 : }
2055 0 : SvLBoxButton* pButtonItem = (SvLBoxButton*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXBUTTON));
2056 0 : if( pButtonItem )
2057 0 : eButtonKind = pButtonItem->GetKind();
2058 0 : SvTreeListEntry* pClone = CreateEntry();
2059 0 : InitEntry( pClone, aStr, aCollEntryBmp, aExpEntryBmp, eButtonKind );
2060 0 : pClone->SvTreeListEntry::Clone( pSource );
2061 0 : pClone->EnableChildrenOnDemand( pSource->HasChildrenOnDemand() );
2062 0 : pClone->SetUserData( pSource->GetUserData() );
2063 :
2064 0 : return pClone;
2065 : }
2066 :
2067 0 : void SvTreeListBox::SetIndent( short nNewIndent )
2068 : {
2069 : DBG_CHKTHIS(SvTreeListBox,0);
2070 0 : nIndent = nNewIndent;
2071 0 : SetTabs();
2072 0 : if( IsUpdateMode() )
2073 0 : Invalidate();
2074 0 : }
2075 :
2076 0 : const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( ) const
2077 : {
2078 0 : return pImp->GetDefaultEntryExpBmp( );
2079 : }
2080 :
2081 0 : const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( ) const
2082 : {
2083 0 : return pImp->GetDefaultEntryColBmp( );
2084 : }
2085 :
2086 0 : void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp )
2087 : {
2088 : DBG_CHKTHIS(SvTreeListBox,0);
2089 0 : Size aSize = aBmp.GetSizePixel();
2090 0 : if( aSize.Width() > nContextBmpWidthMax )
2091 0 : nContextBmpWidthMax = (short)aSize.Width();
2092 0 : SetTabs();
2093 :
2094 0 : pImp->SetDefaultEntryExpBmp( aBmp );
2095 0 : }
2096 :
2097 0 : void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp )
2098 : {
2099 : DBG_CHKTHIS(SvTreeListBox,0);
2100 0 : Size aSize = aBmp.GetSizePixel();
2101 0 : if( aSize.Width() > nContextBmpWidthMax )
2102 0 : nContextBmpWidthMax = (short)aSize.Width();
2103 0 : SetTabs();
2104 :
2105 0 : pImp->SetDefaultEntryColBmp( aBmp );
2106 0 : }
2107 :
2108 0 : void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData )
2109 : {
2110 : DBG_CHKTHIS(SvTreeListBox,0);
2111 : DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0");
2112 0 : if( !pData )
2113 0 : nTreeFlags &= (~TREEFLAG_CHKBTN);
2114 : else
2115 : {
2116 0 : SetCheckButtonData( pData );
2117 0 : nTreeFlags |= TREEFLAG_CHKBTN;
2118 0 : pData->SetLink( LINK(this, SvTreeListBox, CheckButtonClick));
2119 : }
2120 :
2121 0 : SetTabs();
2122 0 : if( IsUpdateMode() )
2123 0 : Invalidate();
2124 0 : }
2125 :
2126 0 : void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData* pData )
2127 : {
2128 : DBG_CHKTHIS(SvTreeListBox,0);
2129 0 : if ( pData )
2130 0 : pCheckButtonData = pData;
2131 0 : }
2132 :
2133 0 : const Image& SvTreeListBox::GetDefaultExpandedNodeImage( )
2134 : {
2135 0 : return SvImpLBox::GetDefaultExpandedNodeImage( );
2136 : }
2137 :
2138 0 : const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( )
2139 : {
2140 0 : return SvImpLBox::GetDefaultCollapsedNodeImage( );
2141 : }
2142 :
2143 0 : void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp )
2144 : {
2145 : DBG_CHKTHIS(SvTreeListBox,0);
2146 0 : SetExpandedNodeBmp( rExpandedNodeBmp );
2147 0 : SetCollapsedNodeBmp( rCollapsedNodeBmp );
2148 0 : SetTabs();
2149 0 : }
2150 :
2151 0 : sal_Bool SvTreeListBox::EditingEntry( SvTreeListEntry*, Selection& )
2152 : {
2153 : DBG_CHKTHIS(SvTreeListBox,0);
2154 0 : return sal_True;
2155 : }
2156 :
2157 0 : sal_Bool SvTreeListBox::EditedEntry( SvTreeListEntry* /*pEntry*/,const rtl::OUString& /*rNewText*/)
2158 : {
2159 : DBG_CHKTHIS(SvTreeListBox,0);
2160 0 : return sal_True;
2161 : }
2162 :
2163 0 : void SvTreeListBox::EnableInplaceEditing( bool bOn )
2164 : {
2165 : DBG_CHKTHIS(SvTreeListBox,0);
2166 0 : if (bOn)
2167 0 : nImpFlags |= SVLBOX_EDT_ENABLED;
2168 : else
2169 0 : nImpFlags &= ~SVLBOX_EDT_ENABLED;
2170 0 : }
2171 :
2172 0 : void SvTreeListBox::KeyInput( const KeyEvent& rKEvt )
2173 : {
2174 : DBG_CHKTHIS(SvTreeListBox,0);
2175 : // under OS/2, we get key up/down even while editing
2176 0 : if( IsEditingActive() )
2177 0 : return;
2178 :
2179 0 : nImpFlags |= SVLBOX_IS_TRAVELSELECT;
2180 :
2181 : #ifdef OVDEBUG
2182 : sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
2183 : switch ( nCode )
2184 : {
2185 : case KEY_F1:
2186 : {
2187 : SvTreeListEntry* pEntry = First();
2188 : pEntry = NextVisible( pEntry );
2189 : SetEntryText( pEntry, "SetEntryText" );
2190 : }
2191 : break;
2192 : }
2193 : #endif
2194 :
2195 0 : if( !pImp->KeyInput( rKEvt ) )
2196 : {
2197 0 : bool bHandled = HandleKeyInput( rKEvt );
2198 0 : if ( !bHandled )
2199 0 : Control::KeyInput( rKEvt );
2200 : }
2201 :
2202 0 : nImpFlags &= ~SVLBOX_IS_TRAVELSELECT;
2203 : }
2204 :
2205 0 : void SvTreeListBox::RequestingChildren( SvTreeListEntry* pParent )
2206 : {
2207 : DBG_CHKTHIS(SvTreeListBox,0);
2208 0 : if( !pParent->HasChildren() )
2209 0 : InsertEntry( rtl::OUString("<dummy>"), pParent, sal_False, LIST_APPEND );
2210 0 : }
2211 :
2212 0 : void SvTreeListBox::GetFocus()
2213 : {
2214 : DBG_CHKTHIS(SvTreeListBox,0);
2215 0 : pImp->GetFocus();
2216 0 : Control::GetFocus();
2217 :
2218 0 : SvTreeListEntry* pEntry = FirstSelected();
2219 0 : if ( pEntry )
2220 0 : pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
2221 :
2222 0 : }
2223 :
2224 0 : void SvTreeListBox::LoseFocus()
2225 : {
2226 : DBG_CHKTHIS(SvTreeListBox,0);
2227 0 : pImp->LoseFocus();
2228 0 : Control::LoseFocus();
2229 0 : }
2230 :
2231 0 : void SvTreeListBox::ModelHasCleared()
2232 : {
2233 : DBG_CHKTHIS(SvTreeListBox,0);
2234 0 : pImp->pCursor = 0; // else we crash in GetFocus when editing in-place
2235 0 : delete pEdCtrl;
2236 0 : pEdCtrl = NULL;
2237 0 : pImp->Clear();
2238 0 : nFocusWidth = -1;
2239 :
2240 0 : nContextBmpWidthMax = 0;
2241 0 : SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() );
2242 0 : SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() );
2243 :
2244 0 : if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT ))
2245 0 : nEntryHeight = 0;
2246 0 : AdjustEntryHeight( GetFont() );
2247 0 : AdjustEntryHeight( GetDefaultExpandedEntryBmp() );
2248 0 : AdjustEntryHeight( GetDefaultCollapsedEntryBmp() );
2249 :
2250 0 : SvListView::ModelHasCleared();
2251 0 : }
2252 :
2253 0 : void SvTreeListBox::ShowTargetEmphasis( SvTreeListEntry* pEntry, sal_Bool /*bShow*/ )
2254 : {
2255 : DBG_CHKTHIS(SvTreeListBox,0);
2256 0 : pImp->PaintDDCursor( pEntry );
2257 0 : }
2258 :
2259 0 : void SvTreeListBox::ScrollOutputArea( short nDeltaEntries )
2260 : {
2261 : DBG_CHKTHIS(SvTreeListBox,0);
2262 0 : if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() )
2263 0 : return;
2264 :
2265 0 : long nThumb = pImp->aVerSBar.GetThumbPos();
2266 0 : long nMax = pImp->aVerSBar.GetRange().Max();
2267 :
2268 0 : NotifyBeginScroll();
2269 0 : if( nDeltaEntries < 0 )
2270 : {
2271 : // move window up
2272 0 : nDeltaEntries *= -1;
2273 0 : long nVis = pImp->aVerSBar.GetVisibleSize();
2274 0 : long nTemp = nThumb + nVis;
2275 0 : if( nDeltaEntries > (nMax - nTemp) )
2276 0 : nDeltaEntries = (short)(nMax - nTemp);
2277 0 : pImp->PageDown( (sal_uInt16)nDeltaEntries );
2278 : }
2279 : else
2280 : {
2281 0 : if( nDeltaEntries > nThumb )
2282 0 : nDeltaEntries = (short)nThumb;
2283 0 : pImp->PageUp( (sal_uInt16)nDeltaEntries );
2284 : }
2285 0 : pImp->SyncVerThumb();
2286 0 : NotifyEndScroll();
2287 : }
2288 :
2289 0 : void SvTreeListBox::ScrollToAbsPos( long nPos )
2290 : {
2291 0 : pImp->ScrollToAbsPos( nPos );
2292 0 : }
2293 :
2294 0 : void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode )
2295 : {
2296 : DBG_CHKTHIS(SvTreeListBox,0);
2297 0 : eSelMode = eSelectMode;
2298 0 : pImp->SetSelectionMode( eSelectMode );
2299 0 : }
2300 :
2301 0 : void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode )
2302 : {
2303 : DBG_CHKTHIS(SvTreeListBox,0);
2304 0 : nDragDropMode = nDDMode;
2305 0 : pImp->SetDragDropMode( nDDMode );
2306 0 : }
2307 :
2308 0 : short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic )
2309 : {
2310 : DBG_CHKTHIS(SvTreeListBox,0);
2311 0 : short nOffset = 0;
2312 0 : aSizeLogic = rBmp.GetSizePixel();
2313 0 : if( GetEntryHeight() > aSizeLogic.Height() )
2314 0 : nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
2315 0 : return nOffset;
2316 : }
2317 :
2318 0 : short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic )
2319 : {
2320 : DBG_CHKTHIS(SvTreeListBox,0);
2321 0 : short nOffset = 0;
2322 0 : aSizeLogic = Size(GetTextWidth(rtl::OUString('X')), GetTextHeight());
2323 0 : if( GetEntryHeight() > aSizeLogic.Height() )
2324 0 : nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2;
2325 0 : return nOffset;
2326 : }
2327 :
2328 0 : void SvTreeListBox::SetEntryHeight( SvTreeListEntry* pEntry )
2329 : {
2330 : DBG_CHKTHIS(SvTreeListBox,0);
2331 0 : short nHeight, nHeightMax=0;
2332 0 : sal_uInt16 nCount = pEntry->ItemCount();
2333 0 : sal_uInt16 nCur = 0;
2334 0 : SvViewDataEntry* pViewData = GetViewDataEntry( pEntry );
2335 0 : while( nCur < nCount )
2336 : {
2337 0 : SvLBoxItem* pItem = pEntry->GetItem( nCur );
2338 0 : nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height());
2339 0 : if( nHeight > nHeightMax )
2340 0 : nHeightMax = nHeight;
2341 0 : nCur++;
2342 : }
2343 :
2344 0 : if( nHeightMax > nEntryHeight )
2345 : {
2346 0 : nEntryHeight = nHeightMax;
2347 0 : Control::SetFont( GetFont() );
2348 0 : pImp->SetEntryHeight( nHeightMax );
2349 : }
2350 0 : }
2351 :
2352 0 : void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways )
2353 : {
2354 : DBG_CHKTHIS(SvTreeListBox,0);
2355 :
2356 0 : if( bAlways || nHeight > nEntryHeight )
2357 : {
2358 0 : nEntryHeight = nHeight;
2359 0 : if( nEntryHeight )
2360 0 : nTreeFlags |= TREEFLAG_FIXEDHEIGHT;
2361 : else
2362 0 : nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT;
2363 0 : Control::SetFont( GetFont() );
2364 0 : pImp->SetEntryHeight( nHeight );
2365 : }
2366 0 : }
2367 :
2368 :
2369 0 : void SvTreeListBox::AdjustEntryHeight( const Image& rBmp )
2370 : {
2371 : DBG_CHKTHIS(SvTreeListBox,0);
2372 0 : Size aSize;
2373 0 : GetHeightOffset( rBmp, aSize );
2374 0 : if( aSize.Height() > nEntryHeight )
2375 : {
2376 0 : nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
2377 0 : pImp->SetEntryHeight( nEntryHeight );
2378 : }
2379 0 : }
2380 :
2381 0 : void SvTreeListBox::AdjustEntryHeight( const Font& rFont )
2382 : {
2383 : DBG_CHKTHIS(SvTreeListBox,0);
2384 0 : Size aSize;
2385 0 : GetHeightOffset( rFont, aSize );
2386 0 : if( aSize.Height() > nEntryHeight )
2387 : {
2388 0 : nEntryHeight = (short)aSize.Height() + nEntryHeightOffs;
2389 0 : pImp->SetEntryHeight( nEntryHeight );
2390 : }
2391 0 : }
2392 :
2393 0 : sal_Bool SvTreeListBox::Expand( SvTreeListEntry* pParent )
2394 : {
2395 : DBG_CHKTHIS(SvTreeListBox,0);
2396 0 : pHdlEntry = pParent;
2397 0 : sal_Bool bExpanded = sal_False;
2398 : sal_uInt16 nFlags;
2399 :
2400 0 : if( pParent->HasChildrenOnDemand() )
2401 0 : RequestingChildren( pParent );
2402 0 : if( pParent->HasChildren() )
2403 : {
2404 0 : nImpFlags |= SVLBOX_IS_EXPANDING;
2405 0 : if( ExpandingHdl() )
2406 : {
2407 0 : bExpanded = sal_True;
2408 0 : SvListView::Expand( pParent );
2409 0 : pImp->EntryExpanded( pParent );
2410 0 : pHdlEntry = pParent;
2411 0 : ExpandedHdl();
2412 : }
2413 0 : nFlags = pParent->GetFlags();
2414 0 : nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP;
2415 0 : nFlags |= SV_ENTRYFLAG_HAD_CHILDREN;
2416 0 : pParent->SetFlags( nFlags );
2417 : }
2418 : else
2419 : {
2420 0 : nFlags = pParent->GetFlags();
2421 0 : nFlags |= SV_ENTRYFLAG_NO_NODEBMP;
2422 0 : pParent->SetFlags( nFlags );
2423 0 : GetModel()->InvalidateEntry( pParent ); // repaint
2424 : }
2425 :
2426 : // #i92103#
2427 0 : if ( bExpanded )
2428 : {
2429 0 : pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent );
2430 : }
2431 :
2432 0 : return bExpanded;
2433 : }
2434 :
2435 0 : sal_Bool SvTreeListBox::Collapse( SvTreeListEntry* pParent )
2436 : {
2437 : DBG_CHKTHIS(SvTreeListBox,0);
2438 0 : nImpFlags &= ~SVLBOX_IS_EXPANDING;
2439 0 : pHdlEntry = pParent;
2440 0 : sal_Bool bCollapsed = sal_False;
2441 :
2442 0 : if( ExpandingHdl() )
2443 : {
2444 0 : bCollapsed = sal_True;
2445 0 : pImp->CollapsingEntry( pParent );
2446 0 : SvListView::Collapse( pParent );
2447 0 : pImp->EntryCollapsed( pParent );
2448 0 : pHdlEntry = pParent;
2449 0 : ExpandedHdl();
2450 : }
2451 :
2452 : // #i92103#
2453 0 : if ( bCollapsed )
2454 : {
2455 0 : pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent );
2456 : }
2457 :
2458 0 : return bCollapsed;
2459 : }
2460 :
2461 0 : sal_Bool SvTreeListBox::Select( SvTreeListEntry* pEntry, sal_Bool bSelect )
2462 : {
2463 : DBG_CHKTHIS(SvTreeListBox,0);
2464 : DBG_ASSERT(pEntry,"Select: Null-Ptr");
2465 0 : sal_Bool bRetVal = SvListView::Select( pEntry, bSelect );
2466 : DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed");
2467 0 : if( bRetVal )
2468 : {
2469 0 : pImp->EntrySelected( pEntry, bSelect );
2470 0 : pHdlEntry = pEntry;
2471 0 : if( bSelect )
2472 : {
2473 0 : SelectHdl();
2474 0 : pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
2475 : }
2476 : else
2477 0 : DeselectHdl();
2478 : }
2479 0 : return bRetVal;
2480 : }
2481 :
2482 0 : sal_uLong SvTreeListBox::SelectChildren( SvTreeListEntry* pParent, sal_Bool bSelect )
2483 : {
2484 : DBG_CHKTHIS(SvTreeListBox,0);
2485 0 : pImp->DestroyAnchor();
2486 0 : sal_uLong nRet = 0;
2487 0 : if( !pParent->HasChildren() )
2488 0 : return 0;
2489 0 : sal_uInt16 nRefDepth = pModel->GetDepth( pParent );
2490 0 : SvTreeListEntry* pChild = FirstChild( pParent );
2491 0 : do {
2492 0 : nRet++;
2493 0 : Select( pChild, bSelect );
2494 0 : pChild = Next( pChild );
2495 0 : } while( pChild && pModel->GetDepth( pChild ) > nRefDepth );
2496 0 : return nRet;
2497 : }
2498 :
2499 0 : void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool )
2500 : {
2501 : DBG_CHKTHIS(SvTreeListBox,0);
2502 : pImp->SelAllDestrAnch(
2503 : bSelect,
2504 : sal_True, // delete anchor,
2505 0 : sal_True ); // even when using SINGLE_SELECTION, deselect the cursor
2506 0 : }
2507 :
2508 0 : void SvTreeListBox::ModelHasInsertedTree( SvTreeListEntry* pEntry )
2509 : {
2510 : DBG_CHKTHIS(SvTreeListBox,0);
2511 0 : sal_uInt16 nRefDepth = pModel->GetDepth( (SvTreeListEntry*)pEntry );
2512 0 : SvTreeListEntry* pTmp = (SvTreeListEntry*)pEntry;
2513 0 : do
2514 : {
2515 0 : ImpEntryInserted( pTmp );
2516 0 : pTmp = Next( pTmp );
2517 0 : } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) );
2518 0 : pImp->TreeInserted( (SvTreeListEntry*)pEntry );
2519 0 : }
2520 :
2521 0 : void SvTreeListBox::ModelHasInserted( SvTreeListEntry* pEntry )
2522 : {
2523 : DBG_CHKTHIS(SvTreeListBox,0);
2524 0 : ImpEntryInserted( (SvTreeListEntry*)pEntry );
2525 0 : pImp->EntryInserted( (SvTreeListEntry*)pEntry );
2526 0 : }
2527 :
2528 0 : void SvTreeListBox::ModelIsMoving(SvTreeListEntry* pSource,
2529 : SvTreeListEntry* /* pTargetParent */,
2530 : sal_uLong /* nChildPos */ )
2531 : {
2532 : DBG_CHKTHIS(SvTreeListBox,0);
2533 0 : pImp->MovingEntry( (SvTreeListEntry*)pSource );
2534 0 : }
2535 :
2536 0 : void SvTreeListBox::ModelHasMoved( SvTreeListEntry* pSource )
2537 : {
2538 : DBG_CHKTHIS(SvTreeListBox,0);
2539 0 : pImp->EntryMoved( (SvTreeListEntry*)pSource );
2540 0 : }
2541 :
2542 0 : void SvTreeListBox::ModelIsRemoving( SvTreeListEntry* pEntry )
2543 : {
2544 : DBG_CHKTHIS(SvTreeListBox,0);
2545 0 : if(pEdEntry == pEntry)
2546 0 : pEdEntry = NULL;
2547 :
2548 0 : pImp->RemovingEntry( (SvTreeListEntry*)pEntry );
2549 0 : NotifyRemoving( (SvTreeListEntry*)pEntry );
2550 0 : }
2551 :
2552 0 : void SvTreeListBox::ModelHasRemoved( SvTreeListEntry* pEntry )
2553 : {
2554 : DBG_CHKTHIS(SvTreeListBox,0);
2555 0 : if ( pEntry == pHdlEntry)
2556 0 : pHdlEntry = NULL;
2557 0 : pImp->EntryRemoved();
2558 0 : }
2559 :
2560 0 : void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp)
2561 : {
2562 : DBG_CHKTHIS(SvTreeListBox,0);
2563 0 : AdjustEntryHeight( rBmp );
2564 0 : pImp->SetCollapsedNodeBmp( rBmp );
2565 0 : }
2566 :
2567 0 : void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp )
2568 : {
2569 : DBG_CHKTHIS(SvTreeListBox,0);
2570 0 : AdjustEntryHeight( rBmp );
2571 0 : pImp->SetExpandedNodeBmp( rBmp );
2572 0 : }
2573 :
2574 :
2575 0 : void SvTreeListBox::SetFont( const Font& rFont )
2576 : {
2577 : DBG_CHKTHIS(SvTreeListBox,0);
2578 0 : Font aTempFont( rFont );
2579 0 : aTempFont.SetTransparent( sal_True );
2580 0 : Control::SetFont( aTempFont );
2581 0 : AdjustEntryHeight( aTempFont );
2582 : // always invalidate, else things go wrong in SetEntryHeight
2583 0 : RecalcViewData();
2584 0 : }
2585 :
2586 :
2587 0 : void SvTreeListBox::Paint( const Rectangle& rRect )
2588 : {
2589 : DBG_CHKTHIS(SvTreeListBox,0);
2590 0 : Control::Paint( rRect );
2591 0 : if( nTreeFlags & TREEFLAG_RECALCTABS )
2592 0 : SetTabs();
2593 0 : pImp->Paint( rRect );
2594 0 : }
2595 :
2596 0 : void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt )
2597 : {
2598 : DBG_CHKTHIS(SvTreeListBox,0);
2599 0 : pImp->MouseButtonDown( rMEvt );
2600 0 : }
2601 :
2602 0 : void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt )
2603 : {
2604 : DBG_CHKTHIS(SvTreeListBox,0);
2605 0 : pImp->MouseButtonUp( rMEvt );
2606 0 : }
2607 :
2608 0 : void SvTreeListBox::MouseMove( const MouseEvent& rMEvt )
2609 : {
2610 : DBG_CHKTHIS(SvTreeListBox,0);
2611 0 : pImp->MouseMove( rMEvt );
2612 0 : }
2613 :
2614 :
2615 0 : void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate )
2616 : {
2617 : DBG_CHKTHIS(SvTreeListBox,0);
2618 0 : pImp->SetUpdateMode( bUpdate );
2619 0 : }
2620 :
2621 0 : void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic )
2622 : {
2623 : DBG_CHKTHIS(SvTreeListBox,0);
2624 0 : if( nOffsLogic != nEntryHeightOffs )
2625 : {
2626 0 : nEntryHeight = nEntryHeight - nEntryHeightOffs;
2627 0 : nEntryHeightOffs = (short)nOffsLogic;
2628 0 : nEntryHeight = nEntryHeight + nOffsLogic;
2629 0 : AdjustEntryHeight( GetFont() );
2630 0 : RecalcViewData();
2631 0 : pImp->SetEntryHeight( nEntryHeight );
2632 : }
2633 0 : }
2634 :
2635 0 : void SvTreeListBox::SetCursor( SvTreeListEntry* pEntry, sal_Bool bForceNoSelect )
2636 : {
2637 : DBG_CHKTHIS(SvTreeListBox,0);
2638 0 : pImp->SetCursor(pEntry, bForceNoSelect);
2639 0 : }
2640 :
2641 0 : void SvTreeListBox::SetCurEntry( SvTreeListEntry* pEntry )
2642 : {
2643 : DBG_CHKTHIS(SvTreeListBox,0);
2644 0 : pImp->SetCurEntry( pEntry );
2645 0 : }
2646 :
2647 0 : Image SvTreeListBox::GetExpandedNodeBmp( ) const
2648 : {
2649 0 : return pImp->GetExpandedNodeBmp( );
2650 : }
2651 :
2652 0 : Point SvTreeListBox::GetEntryPosition( SvTreeListEntry* pEntry ) const
2653 : {
2654 0 : return pImp->GetEntryPosition( pEntry );
2655 : }
2656 :
2657 0 : void SvTreeListBox::ShowEntry( SvTreeListEntry* pEntry )
2658 : {
2659 0 : MakeVisible( pEntry );
2660 0 : }
2661 :
2662 0 : void SvTreeListBox::MakeVisible( SvTreeListEntry* pEntry )
2663 : {
2664 0 : pImp->MakeVisible(pEntry);
2665 0 : }
2666 :
2667 0 : void SvTreeListBox::MakeVisible( SvTreeListEntry* pEntry, sal_Bool bMoveToTop )
2668 : {
2669 0 : pImp->MakeVisible( pEntry, bMoveToTop );
2670 0 : }
2671 :
2672 0 : void SvTreeListBox::ModelHasEntryInvalidated( SvTreeListEntry* pEntry )
2673 : {
2674 : DBG_CHKTHIS(SvTreeListBox,0);
2675 :
2676 : // reinitialize the separate items of the entries
2677 0 : sal_uInt16 nCount = ((SvTreeListEntry*)pEntry)->ItemCount();
2678 0 : for( sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++ )
2679 : {
2680 0 : SvLBoxItem* pItem = ((SvTreeListEntry*)pEntry)->GetItem( nIdx );
2681 0 : pItem->InitViewData( this, (SvTreeListEntry*)pEntry, 0 );
2682 : }
2683 :
2684 : // repaint
2685 0 : pImp->InvalidateEntry( (SvTreeListEntry*)pEntry );
2686 0 : }
2687 :
2688 0 : void SvTreeListBox::EditItemText( SvTreeListEntry* pEntry, SvLBoxString* pItem,
2689 : const Selection& rSelection )
2690 : {
2691 : DBG_CHKTHIS(SvTreeListBox,0);
2692 : DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params");
2693 0 : if( IsSelected( pEntry ))
2694 : {
2695 0 : pImp->ShowCursor( sal_False );
2696 0 : SvListView::Select( pEntry, sal_False );
2697 0 : PaintEntry( pEntry );
2698 0 : SvListView::Select( pEntry, sal_True );
2699 0 : pImp->ShowCursor( sal_True );
2700 : }
2701 0 : pEdEntry = pEntry;
2702 0 : pEdItem = pItem;
2703 0 : SvLBoxTab* pTab = GetTab( pEntry, pItem );
2704 : DBG_ASSERT(pTab,"EditItemText:Tab not found");
2705 :
2706 0 : Size aItemSize( pItem->GetSize(this, pEntry) );
2707 0 : Point aPos = GetEntryPosition( pEntry );
2708 0 : aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2;
2709 0 : aPos.X() = GetTabPos( pEntry, pTab );
2710 0 : long nOutputWidth = pImp->GetOutputSize().Width();
2711 0 : Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() );
2712 0 : sal_uInt16 nPos = std::find( aTabs.begin(), aTabs.end(), pTab ) - aTabs.begin();
2713 0 : if( nPos+1 < (sal_uInt16)aTabs.size() )
2714 : {
2715 0 : SvLBoxTab* pRightTab = aTabs[ nPos + 1 ];
2716 0 : long nRight = GetTabPos( pEntry, pRightTab );
2717 0 : if( nRight <= nOutputWidth )
2718 0 : aSize.Width() = nRight - aPos.X();
2719 : }
2720 0 : Point aOrigin( GetMapMode().GetOrigin() );
2721 0 : aPos += aOrigin; // convert to win coordinates
2722 0 : aSize.Width() -= aOrigin.X();
2723 0 : Rectangle aRect( aPos, aSize );
2724 0 : EditText( pItem->GetText(), aRect, rSelection );
2725 0 : }
2726 :
2727 0 : void SvTreeListBox::EditEntry( SvTreeListEntry* pEntry )
2728 : {
2729 0 : pImp->aEditClickPos = Point( -1, -1 );
2730 0 : ImplEditEntry( pEntry );
2731 0 : }
2732 :
2733 0 : void SvTreeListBox::ImplEditEntry( SvTreeListEntry* pEntry )
2734 : {
2735 : DBG_CHKTHIS(SvTreeListBox,0);
2736 0 : if( IsEditingActive() )
2737 0 : EndEditing();
2738 0 : if( !pEntry )
2739 0 : pEntry = GetCurEntry();
2740 0 : if( pEntry )
2741 : {
2742 0 : long nClickX = pImp->aEditClickPos.X();
2743 0 : bool bIsMouseTriggered = nClickX >= 0;
2744 :
2745 0 : SvLBoxString* pItem = NULL;
2746 0 : sal_uInt16 nCount = pEntry->ItemCount();
2747 0 : long nTabPos, nNextTabPos = 0;
2748 0 : for( sal_uInt16 i = 0 ; i < nCount ; i++ )
2749 : {
2750 0 : SvLBoxItem* pTmpItem = pEntry->GetItem( i );
2751 0 : if (pTmpItem->GetType() != SV_ITEM_ID_LBOXSTRING)
2752 0 : continue;
2753 :
2754 0 : SvLBoxTab* pTab = GetTab( pEntry, pTmpItem );
2755 0 : nNextTabPos = -1;
2756 0 : if( i < nCount - 1 )
2757 : {
2758 0 : SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 );
2759 0 : SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem );
2760 0 : nNextTabPos = pNextTab->GetPos();
2761 : }
2762 :
2763 0 : if( pTab && pTab->IsEditable() )
2764 : {
2765 0 : nTabPos = pTab->GetPos();
2766 0 : if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) )
2767 : {
2768 0 : pItem = static_cast<SvLBoxString*>( pTmpItem );
2769 0 : break;
2770 : }
2771 : }
2772 : }
2773 :
2774 0 : Selection aSel( SELECTION_MIN, SELECTION_MAX );
2775 0 : if( pItem && EditingEntry( pEntry, aSel ) )
2776 : {
2777 0 : SelectAll( sal_False );
2778 0 : MakeVisible( pEntry );
2779 0 : EditItemText( pEntry, pItem, aSel );
2780 : }
2781 : }
2782 0 : }
2783 :
2784 0 : sal_Bool SvTreeListBox::AreChildrenTransient() const
2785 : {
2786 0 : return pImp->AreChildrenTransient();
2787 : }
2788 :
2789 0 : void SvTreeListBox::SetChildrenNotTransient()
2790 : {
2791 0 : pImp->SetChildrenNotTransient();
2792 0 : }
2793 :
2794 0 : void SvTreeListBox::EditedText( const XubString& rStr )
2795 :
2796 : {
2797 : DBG_CHKTHIS(SvTreeListBox,0);
2798 0 : if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing
2799 : {
2800 0 : if( EditedEntry( pEdEntry, rStr ) )
2801 : {
2802 0 : ((SvLBoxString*)pEdItem)->SetText( rStr );
2803 0 : pModel->InvalidateEntry( pEdEntry );
2804 : }
2805 0 : if( GetSelectionCount() == 0 )
2806 0 : Select( pEdEntry );
2807 0 : if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() )
2808 0 : SetCurEntry( pEdEntry );
2809 : }
2810 0 : }
2811 :
2812 0 : SvTreeListEntry* SvTreeListBox::GetDropTarget( const Point& rPos )
2813 : {
2814 : DBG_CHKTHIS(SvTreeListBox,0);
2815 : // scroll
2816 0 : if( rPos.Y() < 12 )
2817 : {
2818 0 : ImplShowTargetEmphasis(pTargetEntry, false);
2819 0 : ScrollOutputArea( +1 );
2820 : }
2821 : else
2822 : {
2823 0 : Size aSize( pImp->GetOutputSize() );
2824 0 : if( rPos.Y() > aSize.Height() - 12 )
2825 : {
2826 0 : ImplShowTargetEmphasis(pTargetEntry, false);
2827 0 : ScrollOutputArea( -1 );
2828 : }
2829 : }
2830 :
2831 0 : SvTreeListEntry* pTarget = pImp->GetEntry( rPos );
2832 : // when dropping in a vacant space, use the last entry
2833 0 : if( !pTarget )
2834 0 : return (SvTreeListEntry*)LastVisible();
2835 0 : else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) &&
2836 0 : pTarget == First() && rPos.Y() < 6 )
2837 0 : return 0;
2838 :
2839 0 : return pTarget;
2840 : }
2841 :
2842 :
2843 0 : SvTreeListEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const
2844 : {
2845 : DBG_CHKTHIS(SvTreeListBox,0);
2846 0 : SvTreeListEntry* pEntry = pImp->GetEntry( rPos );
2847 0 : if( pEntry && bHit )
2848 : {
2849 0 : long nLine = pImp->GetEntryLine( pEntry );
2850 0 : if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) )
2851 0 : return 0;
2852 : }
2853 0 : return pEntry;
2854 : }
2855 :
2856 0 : SvTreeListEntry* SvTreeListBox::GetCurEntry() const
2857 : {
2858 : DBG_CHKTHIS(SvTreeListBox,0);
2859 0 : return pImp->GetCurEntry();
2860 : }
2861 :
2862 0 : void SvTreeListBox::ImplInitStyle()
2863 : {
2864 : DBG_CHKTHIS(SvTreeListBox,0);
2865 :
2866 0 : const WinBits nWindowStyle = GetStyle();
2867 :
2868 0 : nTreeFlags |= TREEFLAG_RECALCTABS;
2869 0 : if( nWindowStyle & WB_SORT )
2870 : {
2871 0 : GetModel()->SetSortMode( SortAscending );
2872 0 : GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare));
2873 : }
2874 : else
2875 : {
2876 0 : GetModel()->SetSortMode( SortNone );
2877 0 : GetModel()->SetCompareHdl( Link() );
2878 : }
2879 0 : pImp->SetStyle( nWindowStyle );
2880 0 : pImp->Resize();
2881 0 : Invalidate();
2882 0 : }
2883 :
2884 0 : void SvTreeListBox::PaintEntry( SvTreeListEntry* pEntry )
2885 : {
2886 : DBG_CHKTHIS(SvTreeListBox,0);
2887 : DBG_ASSERT(pEntry,"PaintEntry:No Entry");
2888 0 : if( pEntry )
2889 0 : pImp->PaintEntry( pEntry );
2890 0 : }
2891 :
2892 0 : void SvTreeListBox::InvalidateEntry( SvTreeListEntry* pEntry )
2893 : {
2894 : DBG_CHKTHIS(SvTreeListBox,0);
2895 : DBG_ASSERT(pEntry,"InvalidateEntry:No Entry");
2896 0 : if( pEntry )
2897 : {
2898 0 : GetModel()->InvalidateEntry( pEntry );
2899 : }
2900 0 : }
2901 :
2902 0 : long SvTreeListBox::PaintEntry(SvTreeListEntry* pEntry,long nLine,sal_uInt16 nTabFlags)
2903 : {
2904 0 : return PaintEntry1(pEntry,nLine,nTabFlags);
2905 : }
2906 :
2907 0 : long SvTreeListBox::PaintEntry1(SvTreeListEntry* pEntry,long nLine,sal_uInt16 nTabFlags,
2908 : sal_Bool bHasClipRegion )
2909 : {
2910 : DBG_CHKTHIS(SvTreeListBox,0);
2911 :
2912 0 : Rectangle aRect; // multi purpose
2913 :
2914 0 : sal_Bool bHorSBar = pImp->HasHorScrollBar();
2915 0 : PreparePaint( pEntry );
2916 :
2917 0 : pImp->UpdateContextBmpWidthMax( pEntry );
2918 :
2919 0 : if( nTreeFlags & TREEFLAG_RECALCTABS )
2920 0 : SetTabs();
2921 :
2922 0 : short nTempEntryHeight = GetEntryHeight();
2923 0 : long nWidth = pImp->GetOutputSize().Width();
2924 :
2925 : // Did we turn on the scrollbar within PreparePaints? If yes, we have to set
2926 : // the ClipRegion anew.
2927 0 : if( !bHorSBar && pImp->HasHorScrollBar() )
2928 0 : SetClipRegion( Region(pImp->GetClipRegionRect()) );
2929 :
2930 0 : Point aEntryPos( GetMapMode().GetOrigin() );
2931 0 : aEntryPos.X() *= -1; // conversion document coordinates
2932 0 : long nMaxRight = nWidth + aEntryPos.X() - 1;
2933 :
2934 0 : Color aBackupTextColor( GetTextColor() );
2935 0 : Font aBackupFont( GetFont() );
2936 0 : Color aBackupColor = GetFillColor();
2937 :
2938 0 : bool bCurFontIsSel = false;
2939 0 : sal_Bool bInUse = pEntry->HasInUseEmphasis();
2940 : // if a ClipRegion was set from outside, we don't have to reset it
2941 0 : const WinBits nWindowStyle = GetStyle();
2942 0 : const sal_Bool bResetClipRegion = !bHasClipRegion;
2943 0 : const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0;
2944 0 : const StyleSettings& rSettings = GetSettings().GetStyleSettings();
2945 :
2946 0 : Font aHighlightFont( GetFont() );
2947 0 : const Color aHighlightTextColor( rSettings.GetHighlightTextColor() );
2948 0 : aHighlightFont.SetColor( aHighlightTextColor );
2949 :
2950 0 : Size aRectSize( 0, nTempEntryHeight );
2951 :
2952 0 : if( !bHasClipRegion && nWindowStyle & WB_HSCROLL )
2953 : {
2954 0 : SetClipRegion( Region(pImp->GetClipRegionRect()) );
2955 0 : bHasClipRegion = sal_True;
2956 : }
2957 :
2958 0 : SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry );
2959 :
2960 0 : sal_uInt16 nTabCount = aTabs.size();
2961 0 : sal_uInt16 nItemCount = pEntry->ItemCount();
2962 0 : sal_uInt16 nCurTab = 0;
2963 0 : sal_uInt16 nCurItem = 0;
2964 :
2965 0 : while( nCurTab < nTabCount && nCurItem < nItemCount )
2966 : {
2967 0 : SvLBoxTab* pTab = aTabs[ nCurTab ];
2968 0 : sal_uInt16 nNextTab = nCurTab + 1;
2969 0 : SvLBoxTab* pNextTab = nNextTab < nTabCount ? aTabs[nNextTab] : 0;
2970 0 : SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0;
2971 :
2972 0 : sal_uInt16 nFlags = pTab->nFlags;
2973 0 : Size aSize( pItem->GetSize( pViewDataEntry, nCurItem ));
2974 0 : long nTabPos = GetTabPos( pEntry, pTab );
2975 :
2976 : long nNextTabPos;
2977 0 : if( pNextTab )
2978 0 : nNextTabPos = GetTabPos( pEntry, pNextTab );
2979 : else
2980 : {
2981 0 : nNextTabPos = nMaxRight;
2982 0 : if( nTabPos > nMaxRight )
2983 0 : nNextTabPos += 50;
2984 : }
2985 :
2986 : long nX;
2987 0 : if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT )
2988 : // avoid cutting the right edge off the tab separation
2989 0 : nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos);
2990 : else
2991 0 : nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos);
2992 :
2993 0 : if( nFlags & nTabFlags )
2994 : {
2995 0 : if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight )
2996 : {
2997 0 : SetClipRegion( Region(pImp->GetClipRegionRect()) );
2998 0 : bHasClipRegion = sal_True;
2999 : }
3000 0 : aEntryPos.X() = nX;
3001 0 : aEntryPos.Y() = nLine;
3002 :
3003 : // set background pattern/color
3004 :
3005 0 : Wallpaper aWallpaper = GetBackground();
3006 :
3007 0 : int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION;
3008 0 : sal_uInt16 nItemType = pItem->GetType();
3009 :
3010 0 : if (pViewDataEntry->IsHighlighted() && bSelTab && !pViewDataEntry->IsCursored())
3011 : {
3012 0 : Color aNewWallColor = rSettings.GetHighlightColor();
3013 0 : if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP )
3014 : {
3015 : // if the face color is bright then the deactive color is also bright
3016 : // -> so you can't see any deactive selection
3017 0 : if ( bHideSelection && !rSettings.GetFaceColor().IsBright() &&
3018 0 : aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() )
3019 0 : aNewWallColor = rSettings.GetDeactiveColor();
3020 : // set font color to highlight
3021 0 : if ( !bCurFontIsSel )
3022 : {
3023 0 : SetTextColor( aHighlightTextColor );
3024 0 : Control::SetFont( aHighlightFont );
3025 0 : bCurFontIsSel = true;
3026 : }
3027 : }
3028 0 : aWallpaper.SetColor( aNewWallColor );
3029 : }
3030 : else // no selection
3031 : {
3032 0 : if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP )
3033 0 : aWallpaper.SetColor( rSettings.GetFieldColor() );
3034 0 : else if( bCurFontIsSel )
3035 : {
3036 0 : bCurFontIsSel = false;
3037 0 : SetTextColor( aBackupTextColor );
3038 0 : Control::SetFont( aBackupFont );
3039 : }
3040 : }
3041 :
3042 : // draw background
3043 0 : if( !(nTreeFlags & TREEFLAG_USESEL))
3044 : {
3045 : // only draw the area that is used by the item
3046 0 : aRectSize.Width() = aSize.Width();
3047 0 : aRect.SetPos( aEntryPos );
3048 0 : aRect.SetSize( aRectSize );
3049 : }
3050 : else
3051 : {
3052 : // draw from the current to the next tab
3053 0 : if( nCurTab != 0 )
3054 0 : aRect.Left() = nTabPos;
3055 : else
3056 : // if we're in the 0th tab, always draw from column 0 --
3057 : // else we get problems with centered tabs
3058 0 : aRect.Left() = 0;
3059 0 : aRect.Top() = nLine;
3060 0 : aRect.Bottom() = nLine + nTempEntryHeight - 1;
3061 0 : if( pNextTab )
3062 : {
3063 : long nRight;
3064 0 : nRight = GetTabPos(pEntry,pNextTab)-1;
3065 0 : if( nRight > nMaxRight )
3066 0 : nRight = nMaxRight;
3067 0 : aRect.Right() = nRight;
3068 : }
3069 : else
3070 0 : aRect.Right() = nMaxRight;
3071 : }
3072 : // A custom selection that starts at a tab position > 0, do not fill
3073 : // the background of the 0th item, else e.g. we might not be able to
3074 : // realize tab listboxes with lines.
3075 0 : if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) )
3076 : {
3077 0 : SetFillColor( aWallpaper.GetColor() );
3078 : // this case may occur for smaller horizontal resizes
3079 0 : if( aRect.Left() < aRect.Right() )
3080 0 : DrawRect( aRect );
3081 : }
3082 : // draw item
3083 : // center vertically
3084 0 : aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2;
3085 0 : pItem->Paint(aEntryPos, *this, pViewDataEntry, pEntry);
3086 :
3087 : // division line between tabs
3088 0 : if (pNextTab && pItem->GetType() == SV_ITEM_ID_LBOXSTRING &&
3089 : // not at the right edge of the window!
3090 0 : aRect.Right() < nMaxRight)
3091 : {
3092 0 : aRect.Left() = aRect.Right() - SV_TAB_BORDER;
3093 0 : DrawRect( aRect );
3094 : }
3095 :
3096 0 : SetFillColor( aBackupColor );
3097 : }
3098 0 : nCurItem++;
3099 0 : nCurTab++;
3100 : }
3101 0 : if( pViewDataEntry->IsCursored() && !HasFocus() )
3102 : {
3103 : // cursor emphasis
3104 0 : SetFillColor();
3105 0 : Color aOldLineColor = GetLineColor();
3106 0 : SetLineColor( Color( COL_BLACK ) );
3107 0 : aRect = GetFocusRect( pEntry, nLine );
3108 0 : aRect.Top()++;
3109 0 : aRect.Bottom()--;
3110 0 : DrawRect( aRect );
3111 0 : SetLineColor( aOldLineColor );
3112 0 : SetFillColor( aBackupColor );
3113 : }
3114 :
3115 0 : if( bCurFontIsSel )
3116 : {
3117 0 : SetTextColor( aBackupTextColor );
3118 0 : Control::SetFont( aBackupFont );
3119 : }
3120 :
3121 : sal_uInt16 nFirstDynTabPos;
3122 0 : SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos );
3123 0 : long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab );
3124 0 : nDynTabPos += pImp->nNodeBmpTabDistance;
3125 0 : nDynTabPos += pImp->nNodeBmpWidth / 2;
3126 0 : nDynTabPos += 4; // 4 pixels of buffer, so the node bitmap is not too close
3127 : // to the next tab
3128 :
3129 0 : if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) &&
3130 : (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab &&
3131 0 : ( pEntry->HasChildren() || pEntry->HasChildrenOnDemand() ) )
3132 : {
3133 : // find first tab and check if the node bitmap extends into it
3134 0 : sal_uInt16 nNextTab = nFirstDynTabPos;
3135 : SvLBoxTab* pNextTab;
3136 0 : do
3137 : {
3138 0 : nNextTab++;
3139 0 : pNextTab = nNextTab < nTabCount ? aTabs[nNextTab] : 0;
3140 0 : } while( pNextTab && pNextTab->IsDynamic() );
3141 :
3142 0 : if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) )
3143 : {
3144 0 : if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0)
3145 : {
3146 0 : Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine );
3147 0 : aPos.X() += pImp->nNodeBmpTabDistance;
3148 :
3149 0 : const Image* pImg = 0;
3150 :
3151 0 : if( IsExpanded(pEntry) )
3152 0 : pImg = &pImp->GetExpandedNodeBmp( );
3153 : else
3154 : {
3155 0 : if( (!pEntry->HasChildren()) && pEntry->HasChildrenOnDemand() &&
3156 0 : (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
3157 0 : pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
3158 0 : pImg = &pImp->GetDontKnowNodeBmp( );
3159 : else
3160 0 : pImg = &pImp->GetCollapsedNodeBmp( );
3161 : }
3162 0 : aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2;
3163 :
3164 0 : sal_uInt16 nStyle = 0;
3165 0 : if ( !IsEnabled() )
3166 0 : nStyle |= IMAGE_DRAW_DISABLE;
3167 :
3168 : //native
3169 0 : sal_Bool bNativeOK = sal_False;
3170 0 : if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) )
3171 : {
3172 0 : ImplControlValue aControlValue;
3173 0 : Rectangle aCtrlRegion( aPos, pImg->GetSizePixel() );
3174 0 : ControlState nState = 0;
3175 :
3176 0 : if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED;
3177 :
3178 0 : if ( IsExpanded(pEntry) )
3179 0 : aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node
3180 : else
3181 : {
3182 0 : if( (!pEntry->HasChildren() ) &&
3183 0 : pEntry->HasChildrenOnDemand() &&
3184 0 : (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
3185 0 : pImp->GetDontKnowNodeBmp().GetSizePixel().Width()
3186 : )
3187 0 : aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW ); //dont know
3188 : else
3189 0 : aControlValue.setTristateVal( BUTTONVALUE_OFF ); //collapsed node
3190 : }
3191 :
3192 : bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL,
3193 0 : aCtrlRegion, nState, aControlValue, rtl::OUString() );
3194 : }
3195 :
3196 0 : if( !bNativeOK) {
3197 0 : DrawImage( aPos, *pImg ,nStyle);
3198 : }
3199 : }
3200 : }
3201 : }
3202 :
3203 :
3204 0 : if( bHasClipRegion && bResetClipRegion )
3205 0 : SetClipRegion();
3206 0 : return 0; // nRowLen;
3207 : }
3208 :
3209 0 : void SvTreeListBox::PreparePaint( SvTreeListEntry* )
3210 : {
3211 0 : }
3212 :
3213 0 : Rectangle SvTreeListBox::GetFocusRect( SvTreeListEntry* pEntry, long nLine )
3214 : {
3215 : DBG_CHKTHIS(SvTreeListBox,0);
3216 0 : Size aSize;
3217 0 : Rectangle aRect;
3218 0 : aRect.Top() = nLine;
3219 0 : aSize.Height() = GetEntryHeight();
3220 :
3221 0 : long nRealWidth = pImp->GetOutputSize().Width();
3222 0 : nRealWidth -= GetMapMode().GetOrigin().X();
3223 :
3224 : sal_uInt16 nCurTab;
3225 0 : SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab );
3226 0 : long nTabPos = 0;
3227 0 : if( pTab )
3228 0 : nTabPos = GetTabPos( pEntry, pTab );
3229 : long nNextTabPos;
3230 0 : if( pTab && nCurTab < aTabs.size() - 1 )
3231 : {
3232 0 : SvLBoxTab* pNextTab = aTabs[ nCurTab + 1 ];
3233 0 : nNextTabPos = GetTabPos( pEntry, pNextTab );
3234 : }
3235 : else
3236 : {
3237 0 : nNextTabPos = nRealWidth;
3238 0 : if( nTabPos > nRealWidth )
3239 0 : nNextTabPos += 50;
3240 : }
3241 :
3242 0 : sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0;
3243 0 : if( !bUserSelection )
3244 : {
3245 0 : if( pTab && nCurTab < pEntry->ItemCount() )
3246 : {
3247 0 : SvLBoxItem* pItem = pEntry->GetItem( nCurTab );
3248 0 : aSize.Width() = pItem->GetSize( this, pEntry ).Width();
3249 0 : if( !aSize.Width() )
3250 0 : aSize.Width() = 15;
3251 0 : long nX = nTabPos; //GetTabPos( pEntry, pTab );
3252 : // alignment
3253 0 : nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos );
3254 0 : aRect.Left() = nX;
3255 : // make sure that first and last letter aren't cut off slightly
3256 0 : aRect.SetSize( aSize );
3257 0 : if( aRect.Left() > 0 )
3258 0 : aRect.Left()--;
3259 0 : aRect.Right()++;
3260 : }
3261 : }
3262 : else
3263 : {
3264 : // if SelTab != 0, we have to calculate also
3265 0 : if( nFocusWidth == -1 || nFirstSelTab )
3266 : {
3267 : sal_uInt16 nLastTab;
3268 0 : SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab);
3269 0 : nLastTab++;
3270 0 : if( nLastTab < aTabs.size() ) // is there another one?
3271 0 : pLastTab = aTabs[ nLastTab ];
3272 : else
3273 0 : pLastTab = 0; // select whole width
3274 0 : aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff;
3275 0 : nFocusWidth = (short)aSize.Width();
3276 0 : if( pTab )
3277 0 : nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos();
3278 : }
3279 : else
3280 : {
3281 0 : aSize.Width() = nFocusWidth;
3282 0 : if( pTab )
3283 : {
3284 0 : if( nCurTab )
3285 0 : aSize.Width() += nTabPos;
3286 : else
3287 0 : aSize.Width() += pTab->GetPos(); // Tab0 always from the leftmost position
3288 : }
3289 : }
3290 : // if selection starts with 0th tab, draw from column 0 on
3291 0 : if( nCurTab != 0 )
3292 : {
3293 0 : aRect.Left() = nTabPos;
3294 0 : aSize.Width() -= nTabPos;
3295 : }
3296 0 : aRect.SetSize( aSize );
3297 : }
3298 : // adjust right edge because of clipping
3299 0 : if( aRect.Right() >= nRealWidth )
3300 : {
3301 0 : aRect.Right() = nRealWidth-1;
3302 0 : nFocusWidth = (short)aRect.GetWidth();
3303 : }
3304 0 : return aRect;
3305 : }
3306 :
3307 :
3308 0 : long SvTreeListBox::GetTabPos( SvTreeListEntry* pEntry, SvLBoxTab* pTab)
3309 : {
3310 : DBG_CHKTHIS(SvTreeListBox,0);
3311 : DBG_ASSERT(pTab,"No Tab");
3312 0 : long nPos = pTab->GetPos();
3313 0 : if( pTab->IsDynamic() )
3314 : {
3315 0 : sal_uInt16 nDepth = pModel->GetDepth( pEntry );
3316 0 : nDepth = nDepth * (sal_uInt16)nIndent;
3317 0 : nPos += (long)nDepth;
3318 : }
3319 0 : return nPos;
3320 : }
3321 :
3322 0 : SvLBoxItem* SvTreeListBox::GetItem_Impl( SvTreeListEntry* pEntry, long nX,
3323 : SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth )
3324 : {
3325 : DBG_CHKTHIS(SvTreeListBox,0);
3326 0 : SvLBoxItem* pItemClicked = 0;
3327 0 : sal_uInt16 nTabCount = aTabs.size();
3328 0 : sal_uInt16 nItemCount = pEntry->ItemCount();
3329 0 : SvLBoxTab* pTab = aTabs.front();
3330 0 : SvLBoxItem* pItem = pEntry->GetItem(0);
3331 0 : sal_uInt16 nNextItem = 1;
3332 0 : nX -= GetMapMode().GetOrigin().X();
3333 0 : long nRealWidth = pImp->GetOutputSize().Width();
3334 0 : nRealWidth -= GetMapMode().GetOrigin().X();
3335 :
3336 0 : while( 1 )
3337 : {
3338 0 : SvLBoxTab* pNextTab=nNextItem<nTabCount ? aTabs[nNextItem] : 0;
3339 0 : long nStart = GetTabPos( pEntry, pTab );
3340 :
3341 : long nNextTabPos;
3342 0 : if( pNextTab )
3343 0 : nNextTabPos = GetTabPos( pEntry, pNextTab );
3344 : else
3345 : {
3346 0 : nNextTabPos = nRealWidth;
3347 0 : if( nStart > nRealWidth )
3348 0 : nNextTabPos += 50;
3349 : }
3350 :
3351 0 : Size aItemSize( pItem->GetSize(this, pEntry));
3352 0 : nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart );
3353 0 : long nLen = aItemSize.Width();
3354 0 : if( pNextTab )
3355 : {
3356 0 : long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart;
3357 0 : if( nTabWidth < nLen )
3358 0 : nLen = nTabWidth;
3359 : }
3360 :
3361 0 : if( !nLen )
3362 0 : nLen = nEmptyWidth;
3363 :
3364 0 : if( nX >= nStart && nX < (nStart+nLen ) )
3365 : {
3366 0 : pItemClicked = pItem;
3367 0 : if( ppTab )
3368 : {
3369 0 : *ppTab = pTab;
3370 : break;
3371 : }
3372 : }
3373 0 : if( nNextItem >= nItemCount || nNextItem >= nTabCount)
3374 : break;
3375 0 : pTab = aTabs[ nNextItem ];
3376 0 : pItem = pEntry->GetItem( nNextItem );
3377 0 : nNextItem++;
3378 : }
3379 0 : return pItemClicked;
3380 : }
3381 :
3382 0 : long SvTreeListBox::getPreferredDimensions(std::vector<long> &rWidths) const
3383 : {
3384 0 : long nHeight = 0;
3385 0 : rWidths.clear();
3386 0 : SvTreeListEntry* pEntry = First();
3387 0 : while (pEntry)
3388 : {
3389 0 : sal_uInt16 nCount = pEntry->ItemCount();
3390 0 : sal_uInt16 nCurPos = 0;
3391 0 : if (nCount > rWidths.size())
3392 0 : rWidths.resize(nCount);
3393 0 : while (nCurPos < nCount)
3394 : {
3395 0 : SvLBoxItem* pItem = pEntry->GetItem( nCurPos );
3396 0 : long nWidth = pItem->GetSize(this, pEntry).Width();
3397 0 : if (nWidth)
3398 : {
3399 0 : nWidth += SV_TAB_BORDER * 2;
3400 0 : if (nWidth > rWidths[nCurPos])
3401 0 : rWidths[nCurPos] = nWidth;
3402 : }
3403 0 : ++nCurPos;
3404 : }
3405 0 : pEntry = Next( pEntry );
3406 0 : nHeight += GetEntryHeight();
3407 : }
3408 0 : return nHeight;
3409 : }
3410 :
3411 0 : Size SvTreeListBox::GetOptimalSize(WindowSizeType eType) const
3412 : {
3413 0 : Size aRet;
3414 0 : switch (eType)
3415 : {
3416 : case WINDOWSIZE_MINIMUM:
3417 : case WINDOWSIZE_PREFERRED:
3418 : {
3419 0 : std::vector<long> aWidths;
3420 0 : aRet.Height() = getPreferredDimensions(aWidths);
3421 0 : for (size_t i = 0; i < aWidths.size(); ++i)
3422 0 : aRet.Width() += aWidths[i];
3423 0 : break;
3424 : }
3425 : default:
3426 0 : aRet = Control::GetOptimalSize(eType);
3427 0 : break;
3428 : }
3429 0 : return aRet;
3430 : }
3431 :
3432 0 : SvLBoxItem* SvTreeListBox::GetItem(SvTreeListEntry* pEntry,long nX,SvLBoxTab** ppTab)
3433 : {
3434 0 : return GetItem_Impl( pEntry, nX, ppTab, 0 );
3435 : }
3436 :
3437 0 : SvLBoxItem* SvTreeListBox::GetItem(SvTreeListEntry* pEntry,long nX )
3438 : {
3439 : DBG_CHKTHIS(SvTreeListBox,0);
3440 : SvLBoxTab* pDummyTab;
3441 0 : return GetItem_Impl( pEntry, nX, &pDummyTab, 0 );
3442 : }
3443 :
3444 0 : void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData )
3445 : {
3446 : DBG_CHKTHIS(SvTreeListBox,0);
3447 0 : nFocusWidth = -1;
3448 0 : SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags );
3449 0 : pTab->SetUserData( pUserData );
3450 0 : aTabs.push_back( pTab );
3451 0 : if( nTreeFlags & TREEFLAG_USESEL )
3452 : {
3453 0 : sal_uInt16 nPos = aTabs.size() - 1;
3454 0 : if( nPos >= nFirstSelTab && nPos <= nLastSelTab )
3455 0 : pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION;
3456 : else
3457 : // string items usually have to be selected -- turn this off
3458 : // explicitly
3459 0 : pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION;
3460 : }
3461 0 : }
3462 :
3463 :
3464 :
3465 0 : SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const
3466 : {
3467 : DBG_CHKTHIS(SvTreeListBox,0);
3468 0 : sal_uInt16 nCurTab = 0;
3469 0 : sal_uInt16 nTabCount = aTabs.size();
3470 0 : while( nCurTab < nTabCount )
3471 : {
3472 0 : SvLBoxTab* pTab = aTabs[nCurTab];
3473 0 : if( pTab->nFlags & SV_LBOXTAB_DYNAMIC )
3474 : {
3475 0 : rPos = nCurTab;
3476 0 : return pTab;
3477 : }
3478 0 : nCurTab++;
3479 : }
3480 0 : return 0;
3481 : }
3482 :
3483 0 : SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const
3484 : {
3485 : sal_uInt16 nDummy;
3486 0 : return GetFirstDynamicTab( nDummy );
3487 : }
3488 :
3489 0 : SvLBoxTab* SvTreeListBox::GetTab( SvTreeListEntry* pEntry, SvLBoxItem* pItem) const
3490 : {
3491 : DBG_CHKTHIS(SvTreeListBox,0);
3492 0 : sal_uInt16 nPos = pEntry->GetPos( pItem );
3493 0 : return aTabs[ nPos ];
3494 : }
3495 :
3496 0 : void SvTreeListBox::ClearTabList()
3497 : {
3498 : DBG_CHKTHIS(SvTreeListBox,0);
3499 0 : sal_uInt16 nTabCount = aTabs.size();
3500 0 : while( nTabCount )
3501 : {
3502 0 : nTabCount--;
3503 0 : SvLBoxTab* pDelTab = aTabs[ nTabCount ];
3504 0 : delete pDelTab;
3505 : }
3506 0 : aTabs.clear();
3507 0 : }
3508 :
3509 :
3510 0 : Size SvTreeListBox::GetOutputSizePixel() const
3511 : {
3512 : DBG_CHKTHIS(SvTreeListBox,0);
3513 0 : Size aSize = pImp->GetOutputSize();
3514 0 : return aSize;
3515 : }
3516 :
3517 0 : void SvTreeListBox::NotifyBeginScroll()
3518 : {
3519 : DBG_CHKTHIS(SvTreeListBox,0);
3520 0 : }
3521 :
3522 0 : void SvTreeListBox::NotifyEndScroll()
3523 : {
3524 : DBG_CHKTHIS(SvTreeListBox,0);
3525 0 : }
3526 :
3527 0 : void SvTreeListBox::NotifyScrolling( long )
3528 : {
3529 : DBG_CHKTHIS(SvTreeListBox,0);
3530 0 : }
3531 :
3532 0 : void SvTreeListBox::NotifyScrolled()
3533 : {
3534 : DBG_CHKTHIS(SvTreeListBox,0);
3535 0 : aScrolledHdl.Call( this );
3536 0 : }
3537 :
3538 0 : void SvTreeListBox::NotifyInvalidating()
3539 : {
3540 : DBG_CHKTHIS(SvTreeListBox,0);
3541 0 : }
3542 :
3543 0 : void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags )
3544 : {
3545 : DBG_CHKTHIS(SvTreeListBox,0);
3546 0 : if( nFocusWidth == -1 )
3547 : // to make sure that the control doesn't show the wrong focus rectangle
3548 : // after painting
3549 0 : pImp->RecalcFocusRect();
3550 0 : NotifyInvalidating();
3551 0 : Control::Invalidate( nInvalidateFlags );
3552 0 : pImp->Invalidate();
3553 0 : }
3554 :
3555 0 : void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags )
3556 : {
3557 : DBG_CHKTHIS(SvTreeListBox,0);
3558 0 : if( nFocusWidth == -1 )
3559 : // to make sure that the control doesn't show the wrong focus rectangle
3560 : // after painting
3561 0 : pImp->RecalcFocusRect();
3562 0 : NotifyInvalidating();
3563 0 : Control::Invalidate( rRect, nInvalidateFlags );
3564 0 : }
3565 :
3566 :
3567 0 : void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd)
3568 : {
3569 : DBG_CHKTHIS(SvTreeListBox,0);
3570 :
3571 : sal_uInt16 nTemp;
3572 0 : nTreeFlags |= TREEFLAG_USESEL;
3573 0 : if( nStart > nEnd )
3574 : {
3575 0 : nTemp = nStart;
3576 0 : nStart = nEnd;
3577 0 : nEnd = nTemp;
3578 : }
3579 : // select all tabs that lie within the area
3580 0 : nTreeFlags |= TREEFLAG_RECALCTABS;
3581 0 : nFirstSelTab = nStart;
3582 0 : nLastSelTab = nEnd;
3583 0 : pImp->RecalcFocusRect();
3584 0 : }
3585 :
3586 0 : sal_uLong SvTreeListBox::GetAscInsertionPos(SvTreeListEntry*,SvTreeListEntry*)
3587 : {
3588 0 : return LIST_APPEND;
3589 : }
3590 :
3591 0 : sal_uLong SvTreeListBox::GetDescInsertionPos(SvTreeListEntry*,SvTreeListEntry*)
3592 : {
3593 : DBG_CHKTHIS(SvTreeListBox,0);
3594 0 : return LIST_APPEND;
3595 : }
3596 :
3597 0 : Region SvTreeListBox::GetDragRegion() const
3598 : {
3599 : DBG_CHKTHIS(SvTreeListBox,0);
3600 0 : Rectangle aRect;
3601 0 : SvTreeListEntry* pEntry = GetCurEntry();
3602 0 : if( pEntry )
3603 : {
3604 0 : Point aPos = GetEntryPosition( pEntry );
3605 0 : aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() );
3606 : }
3607 0 : Region aRegion( aRect );
3608 0 : return aRegion;
3609 : }
3610 :
3611 :
3612 0 : void SvTreeListBox::Command( const CommandEvent& rCEvt )
3613 : {
3614 : DBG_CHKTHIS(SvTreeListBox,0);
3615 : // FIXME gnumake2 resync to DEV300_m84
3616 0 : pImp->Command( rCEvt );
3617 0 : }
3618 :
3619 :
3620 0 : void SvTreeListBox::RemoveParentKeepChildren( SvTreeListEntry* pParent )
3621 : {
3622 : DBG_CHKTHIS(SvTreeListBox,0);
3623 : DBG_ASSERT(pParent,"RemoveParentKeepChildren:No Parent");
3624 0 : SvTreeListEntry* pNewParent = GetParent( pParent );
3625 0 : if( pParent->HasChildren())
3626 : {
3627 0 : SvTreeListEntry* pChild = FirstChild( pParent );
3628 0 : while( pChild )
3629 : {
3630 0 : pModel->Move( pChild, pNewParent, LIST_APPEND );
3631 0 : pChild = FirstChild( pParent );
3632 : }
3633 : }
3634 0 : pModel->Remove( pParent );
3635 0 : }
3636 :
3637 0 : SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos )
3638 : {
3639 0 : sal_uInt16 nTabCount = aTabs.size();
3640 0 : for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ )
3641 : {
3642 0 : SvLBoxTab* pTab = aTabs[ nPos ];
3643 0 : if( (pTab->nFlags & nFlagMask) )
3644 : {
3645 0 : rPos = nPos;
3646 0 : return pTab;
3647 : }
3648 : }
3649 0 : rPos = 0xffff;
3650 0 : return 0;
3651 : }
3652 :
3653 0 : SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos )
3654 : {
3655 0 : sal_uInt16 nPos = (sal_uInt16)aTabs.size();
3656 0 : while( nPos )
3657 : {
3658 0 : --nPos;
3659 0 : SvLBoxTab* pTab = aTabs[ nPos ];
3660 0 : if( (pTab->nFlags & nFlagMask) )
3661 : {
3662 0 : rTabPos = nPos;
3663 0 : return pTab;
3664 : }
3665 : }
3666 0 : rTabPos = 0xffff;
3667 0 : return 0;
3668 : }
3669 :
3670 0 : void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
3671 : {
3672 0 : if( !pImp->RequestHelp( rHEvt ) )
3673 0 : Control::RequestHelp( rHEvt );
3674 0 : }
3675 :
3676 0 : void SvTreeListBox::CursorMoved( SvTreeListEntry* )
3677 : {
3678 0 : }
3679 :
3680 0 : IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData )
3681 : {
3682 0 : const SvTreeListEntry* pLeft = pData->pLeft;
3683 0 : const SvTreeListEntry* pRight = pData->pRight;
3684 0 : String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
3685 0 : String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText());
3686 0 : pImp->UpdateStringSorter();
3687 0 : return pImp->m_pStringSorter->compare(aLeft, aRight);
3688 : }
3689 :
3690 0 : void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvTreeListEntry* pEntry1,
3691 : SvTreeListEntry* pEntry2, sal_uLong nPos )
3692 : {
3693 0 : if( nActionId == LISTACTION_CLEARING )
3694 0 : CancelTextEditing();
3695 :
3696 0 : SvListView::ModelNotification( nActionId, pEntry1, pEntry2, nPos );
3697 0 : switch( nActionId )
3698 : {
3699 : case LISTACTION_INSERTED:
3700 : {
3701 0 : SvTreeListEntry* pEntry( dynamic_cast< SvTreeListEntry* >( pEntry1 ) );
3702 0 : if ( !pEntry )
3703 : {
3704 : SAL_WARN( "svtools.contnr", "SvTreeListBox::ModelNotification: invalid entry!" );
3705 0 : break;
3706 : }
3707 :
3708 0 : SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
3709 0 : if ( !pBmpItem )
3710 0 : break;
3711 0 : const Image& rBitmap1( pBmpItem->GetBitmap1() );
3712 0 : const Image& rBitmap2( pBmpItem->GetBitmap2() );
3713 0 : short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) );
3714 0 : nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth );
3715 0 : if( nMaxWidth > nContextBmpWidthMax )
3716 : {
3717 0 : nContextBmpWidthMax = nMaxWidth;
3718 0 : SetTabs();
3719 : }
3720 0 : queue_resize();
3721 : }
3722 0 : break;
3723 :
3724 : case LISTACTION_RESORTING:
3725 0 : SetUpdateMode( sal_False );
3726 0 : break;
3727 :
3728 : case LISTACTION_RESORTED:
3729 : // after a selection: show first entry and also keep the selection
3730 0 : MakeVisible( (SvTreeListEntry*)pModel->First(), sal_True );
3731 0 : SetUpdateMode( sal_True );
3732 0 : break;
3733 :
3734 : case LISTACTION_CLEARED:
3735 0 : if( IsUpdateMode() )
3736 0 : Update();
3737 0 : break;
3738 : }
3739 0 : }
3740 :
3741 0 : void SvTreeListBox::EndSelection()
3742 : {
3743 0 : pImp->EndSelection();
3744 0 : }
3745 :
3746 0 : void SvTreeListBox::RepaintScrollBars() const
3747 : {
3748 0 : ((SvTreeListBox*)this)->pImp->RepaintScrollBars();
3749 0 : }
3750 :
3751 0 : ScrollBar *SvTreeListBox::GetVScroll()
3752 : {
3753 0 : return &((SvTreeListBox*)this)->pImp->aVerSBar;
3754 : }
3755 :
3756 0 : ScrollBar *SvTreeListBox::GetHScroll()
3757 : {
3758 0 : return &((SvTreeListBox*)this)->pImp->aHorSBar;
3759 : }
3760 :
3761 0 : void SvTreeListBox::EnableAsyncDrag( sal_Bool b )
3762 : {
3763 0 : pImp->EnableAsyncDrag( b );
3764 0 : }
3765 :
3766 0 : SvTreeListEntry* SvTreeListBox::GetFirstEntryInView() const
3767 : {
3768 0 : Point aPos;
3769 0 : return GetEntry( aPos );
3770 : }
3771 :
3772 0 : SvTreeListEntry* SvTreeListBox::GetNextEntryInView(SvTreeListEntry* pEntry ) const
3773 : {
3774 0 : SvTreeListEntry* pNext = (SvTreeListEntry*)NextVisible( pEntry );
3775 0 : if( pNext )
3776 : {
3777 0 : Point aPos( GetEntryPosition(pNext) );
3778 0 : const Size& rSize = pImp->GetOutputSize();
3779 0 : if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
3780 0 : return 0;
3781 : }
3782 0 : return pNext;
3783 : }
3784 :
3785 0 : SvTreeListEntry* SvTreeListBox::GetLastEntryInView() const
3786 : {
3787 0 : SvTreeListEntry* pEntry = GetFirstEntryInView();
3788 0 : SvTreeListEntry* pNext = 0;
3789 0 : while( pEntry )
3790 : {
3791 0 : pNext = (SvTreeListEntry*)NextVisible( pEntry );
3792 0 : if( pNext )
3793 : {
3794 0 : Point aPos( GetEntryPosition(pNext) );
3795 0 : const Size& rSize = pImp->GetOutputSize();
3796 0 : if( aPos.Y() < 0 || aPos.Y() + GetEntryHeight() >= rSize.Height() )
3797 : break;
3798 : else
3799 0 : pEntry = pNext;
3800 : }
3801 : else
3802 0 : break;
3803 : }
3804 0 : return pEntry;
3805 : }
3806 :
3807 0 : void SvTreeListBox::ShowFocusRect( const SvTreeListEntry* pEntry )
3808 : {
3809 0 : pImp->ShowFocusRect( pEntry );
3810 0 : }
3811 :
3812 0 : void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt )
3813 : {
3814 0 : if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
3815 : {
3816 0 : nEntryHeight = 0; // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height
3817 : // forces complete recalc of heights!
3818 0 : InitSettings( sal_True, sal_True, sal_True );
3819 0 : Invalidate();
3820 : }
3821 : else
3822 0 : Control::DataChanged( rDCEvt );
3823 0 : }
3824 :
3825 0 : void SvTreeListBox::StateChanged( StateChangedType eType )
3826 : {
3827 0 : if( eType == STATE_CHANGE_ENABLE )
3828 0 : Invalidate( INVALIDATE_CHILDREN );
3829 :
3830 0 : Control::StateChanged( eType );
3831 :
3832 0 : if ( eType == STATE_CHANGE_STYLE )
3833 0 : ImplInitStyle();
3834 0 : }
3835 :
3836 0 : void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground)
3837 : {
3838 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
3839 0 : if( bFont )
3840 : {
3841 0 : Font aFont;
3842 0 : aFont = rStyleSettings.GetFieldFont();
3843 0 : aFont.SetColor( rStyleSettings.GetWindowTextColor() );
3844 0 : SetPointFont( aFont );
3845 0 : AdjustEntryHeight( aFont );
3846 0 : RecalcViewData();
3847 : }
3848 :
3849 0 : if( bForeground || bFont )
3850 : {
3851 0 : SetTextColor( rStyleSettings.GetFieldTextColor() );
3852 0 : SetTextFillColor();
3853 : }
3854 :
3855 0 : if( bBackground )
3856 0 : SetBackground( rStyleSettings.GetFieldColor() );
3857 :
3858 : // always try to re-create default-SvLBoxButtonData
3859 0 : if( pCheckButtonData && pCheckButtonData->HasDefaultImages() )
3860 0 : pCheckButtonData->SetDefaultImages( this );
3861 0 : }
3862 :
3863 0 : sal_Bool SvTreeListBox::IsCellFocusEnabled() const
3864 : {
3865 0 : return pImp->IsCellFocusEnabled();
3866 : }
3867 :
3868 0 : bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
3869 : {
3870 0 : return pImp->SetCurrentTabPos( _nNewPos );
3871 : }
3872 :
3873 0 : sal_uInt16 SvTreeListBox::GetCurrentTabPos() const
3874 : {
3875 0 : return pImp->GetCurrentTabPos();
3876 : }
3877 :
3878 0 : void SvTreeListBox::InitStartEntry()
3879 : {
3880 0 : if( !pImp->pStartEntry )
3881 0 : pImp->pStartEntry = GetModel()->First();
3882 0 : }
3883 :
3884 0 : PopupMenu* SvTreeListBox::CreateContextMenu( void )
3885 : {
3886 0 : return NULL;
3887 : }
3888 :
3889 0 : void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 )
3890 : {
3891 : DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" );
3892 0 : }
3893 :
3894 0 : void SvTreeListBox::EnableContextMenuHandling( void )
3895 : {
3896 : DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
3897 :
3898 0 : pImp->bContextMenuHandling = sal_True;
3899 0 : }
3900 :
3901 0 : void SvTreeListBox::EnableContextMenuHandling( sal_Bool b )
3902 : {
3903 : DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" );
3904 :
3905 0 : pImp->bContextMenuHandling = b;
3906 0 : }
3907 :
3908 0 : sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const
3909 : {
3910 : DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" );
3911 :
3912 0 : return pImp->bContextMenuHandling;
3913 : }
3914 :
3915 0 : void SvTreeListBox::EnableList( bool _bEnable )
3916 : {
3917 : // call base class method
3918 0 : Window::Enable( _bEnable != false );
3919 : // then paint immediately
3920 0 : Paint( Rectangle( Point(), GetSizePixel() ) );
3921 0 : }
3922 :
3923 0 : ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible()
3924 : {
3925 0 : Window* pParent = GetAccessibleParentWindow();
3926 : DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" );
3927 :
3928 0 : ::com::sun::star::uno::Reference< XAccessible > xAccessible;
3929 0 : if ( pParent )
3930 : {
3931 0 : ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
3932 0 : if ( xAccParent.is() )
3933 : {
3934 : // need to be done here to get the vclxwindow later on in the accessbile
3935 0 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface());
3936 0 : xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent );
3937 0 : }
3938 : }
3939 0 : return xAccessible;
3940 : }
3941 :
3942 0 : void SvTreeListBox::FillAccessibleEntryStateSet( SvTreeListEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const
3943 : {
3944 : DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" );
3945 :
3946 0 : if ( pEntry->HasChildrenOnDemand() || pEntry->HasChildren() )
3947 : {
3948 0 : rStateSet.AddState( AccessibleStateType::EXPANDABLE );
3949 0 : if ( IsExpanded( pEntry ) )
3950 0 : rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED );
3951 : }
3952 :
3953 0 : if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED )
3954 0 : rStateSet.AddState( AccessibleStateType::CHECKED );
3955 0 : if ( IsEntryVisible( pEntry ) )
3956 0 : rStateSet.AddState( AccessibleStateType::VISIBLE );
3957 0 : if ( IsSelected( pEntry ) )
3958 0 : rStateSet.AddState( AccessibleStateType::SELECTED );
3959 0 : }
3960 :
3961 0 : Rectangle SvTreeListBox::GetBoundingRect( SvTreeListEntry* pEntry )
3962 : {
3963 0 : Point aPos = GetEntryPosition( pEntry );
3964 0 : Rectangle aRect = GetFocusRect( pEntry, aPos.Y() );
3965 0 : return aRect;
3966 : }
3967 :
3968 0 : void SvTreeListBox::EnableCellFocus()
3969 : {
3970 0 : pImp->EnableCellFocus();
3971 0 : }
3972 :
3973 0 : void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData)
3974 : {
3975 0 : CallEventListeners(nEvent, pData);
3976 0 : }
3977 :
3978 0 : void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& /*rStateSet*/ ) const
3979 : {
3980 0 : }
3981 :
3982 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|