Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "tools/rc.h"
21 : #include "tools/debug.hxx"
22 :
23 : #include "vcl/decoview.hxx"
24 : #include "vcl/dialog.hxx"
25 : #include "vcl/event.hxx"
26 : #include "vcl/scrbar.hxx"
27 : #include "vcl/button.hxx"
28 : #include "vcl/edit.hxx"
29 : #include "vcl/lstbox.hxx"
30 : #include "vcl/combobox.hxx"
31 : #include "vcl/settings.hxx"
32 :
33 : #include "svdata.hxx"
34 : #include "controldata.hxx"
35 : #include "ilstbox.hxx"
36 : #include "dndevdis.hxx"
37 :
38 : #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
39 :
40 0 : void ListBox::EnableQuickSelection( const bool& b )
41 : {
42 0 : mpImplLB->GetMainWindow()->EnableQuickSelection(b);
43 0 : }
44 :
45 0 : ListBox::ListBox(WindowType nType)
46 : : Control(nType)
47 0 : , mpImplLB(NULL)
48 : {
49 0 : ImplInitListBoxData();
50 0 : }
51 :
52 314 : ListBox::ListBox( vcl::Window* pParent, WinBits nStyle ) : Control( WINDOW_LISTBOX )
53 : {
54 314 : ImplInitListBoxData();
55 314 : ImplInit( pParent, nStyle );
56 314 : }
57 :
58 9 : ListBox::ListBox( vcl::Window* pParent, const ResId& rResId ) :
59 9 : Control( WINDOW_LISTBOX )
60 : {
61 9 : rResId.SetRT( RSC_LISTBOX );
62 9 : WinBits nStyle = ImplInitRes( rResId );
63 9 : ImplInitListBoxData();
64 9 : ImplInit( pParent, nStyle );
65 9 : ImplLoadRes( rResId );
66 :
67 9 : if ( !(nStyle & WB_HIDE ) )
68 9 : Show();
69 9 : }
70 :
71 850 : ListBox::~ListBox()
72 : {
73 323 : disposeOnce();
74 527 : }
75 :
76 323 : void ListBox::dispose()
77 : {
78 323 : CallEventListeners( VCLEVENT_OBJECT_DYING );
79 :
80 323 : mpImplLB.disposeAndClear();
81 323 : mpFloatWin.disposeAndClear();
82 323 : mpImplWin.disposeAndClear();
83 323 : mpBtn.disposeAndClear();
84 :
85 323 : Control::dispose();
86 323 : }
87 :
88 323 : void ListBox::ImplInitListBoxData()
89 : {
90 323 : mpFloatWin = NULL;
91 323 : mpImplWin = NULL;
92 323 : mpBtn = NULL;
93 323 : mnDDHeight = 0;
94 323 : mnSaveValue = LISTBOX_ENTRY_NOTFOUND;
95 323 : mnLineCount = 0;
96 323 : m_nMaxWidthChars = -1;
97 323 : mbDDAutoSize = true;
98 323 : mbEdgeBlending = false;
99 323 : }
100 :
101 323 : void ListBox::ImplInit( vcl::Window* pParent, WinBits nStyle )
102 : {
103 323 : nStyle = ImplInitStyle( nStyle );
104 323 : if ( !(nStyle & WB_NOBORDER) && ( nStyle & WB_DROPDOWN ) )
105 309 : nStyle |= WB_BORDER;
106 :
107 323 : Control::ImplInit( pParent, nStyle, NULL );
108 :
109 323 : ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener> xDrop = new DNDEventDispatcher(this);
110 :
111 323 : if( nStyle & WB_DROPDOWN )
112 : {
113 : sal_Int32 nLeft, nTop, nRight, nBottom;
114 309 : GetBorder( nLeft, nTop, nRight, nBottom );
115 309 : mnDDHeight = (sal_uInt16)(GetTextHeight() + nTop + nBottom + 4);
116 :
117 618 : if( IsNativeWidgetEnabled() &&
118 309 : IsNativeControlSupported( CTRL_LISTBOX, PART_ENTIRE_CONTROL ) )
119 : {
120 0 : ImplControlValue aControlValue;
121 0 : Rectangle aCtrlRegion( Point( 0, 0 ), Size( 20, mnDDHeight ) );
122 0 : Rectangle aBoundingRgn( aCtrlRegion );
123 0 : Rectangle aContentRgn( aCtrlRegion );
124 0 : if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
125 : ControlState::ENABLED, aControlValue, OUString(),
126 0 : aBoundingRgn, aContentRgn ) )
127 : {
128 0 : sal_Int32 nHeight = aBoundingRgn.GetHeight();
129 0 : if( nHeight > mnDDHeight )
130 0 : mnDDHeight = static_cast<sal_uInt16>(nHeight);
131 0 : }
132 : }
133 :
134 309 : mpFloatWin = VclPtr<ImplListBoxFloatingWindow>::Create( this );
135 309 : mpFloatWin->SetAutoWidth( true );
136 309 : mpFloatWin->SetPopupModeEndHdl( LINK( this, ListBox, ImplPopupModeEndHdl ) );
137 309 : mpFloatWin->GetDropTarget()->addDropTargetListener(xDrop);
138 :
139 309 : mpImplWin = VclPtr<ImplWin>::Create( this, (nStyle & (WB_LEFT|WB_RIGHT|WB_CENTER))|WB_NOBORDER );
140 309 : mpImplWin->buttonDownSignal.connect( boost::bind( &ListBox::ImplClickButtonHandler, this, _1 ));
141 309 : mpImplWin->userDrawSignal.connect( boost::bind( &ListBox::ImplUserDrawHandler, this, _1 ) );
142 309 : mpImplWin->Show();
143 309 : mpImplWin->GetDropTarget()->addDropTargetListener(xDrop);
144 309 : mpImplWin->SetEdgeBlending(GetEdgeBlending());
145 :
146 309 : mpBtn = VclPtr<ImplBtn>::Create( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
147 309 : ImplInitDropDownButton( mpBtn );
148 309 : mpBtn->buttonDownSignal.connect( boost::bind( &ListBox::ImplClickButtonHandler, this, _1 ));
149 309 : mpBtn->Show();
150 309 : mpBtn->GetDropTarget()->addDropTargetListener(xDrop);
151 : }
152 :
153 323 : vcl::Window* pLBParent = this;
154 323 : if ( mpFloatWin )
155 309 : pLBParent = mpFloatWin;
156 323 : mpImplLB = VclPtr<ImplListBox>::Create( pLBParent, nStyle&(~WB_BORDER) );
157 323 : mpImplLB->SetSelectHdl( LINK( this, ListBox, ImplSelectHdl ) );
158 323 : mpImplLB->SetScrollHdl( LINK( this, ListBox, ImplScrollHdl ) );
159 323 : mpImplLB->SetCancelHdl( LINK( this, ListBox, ImplCancelHdl ) );
160 323 : mpImplLB->SetDoubleClickHdl( LINK( this, ListBox, ImplDoubleClickHdl ) );
161 323 : mpImplLB->userDrawSignal.connect( boost::bind( &ListBox::ImplUserDrawHandler, this, _1 ) );
162 323 : mpImplLB->SetFocusHdl( LINK( this, ListBox, ImplFocusHdl ) );
163 323 : mpImplLB->SetListItemSelectHdl( LINK( this, ListBox, ImplListItemSelectHdl ) );
164 323 : mpImplLB->SetPosPixel( Point() );
165 323 : mpImplLB->SetEdgeBlending(GetEdgeBlending());
166 323 : mpImplLB->Show();
167 :
168 323 : mpImplLB->GetDropTarget()->addDropTargetListener(xDrop);
169 323 : mpImplLB->SetDropTraget(xDrop);
170 :
171 323 : if ( mpFloatWin )
172 : {
173 309 : mpFloatWin->SetImplListBox( mpImplLB );
174 309 : mpImplLB->SetSelectionChangedHdl( LINK( this, ListBox, ImplSelectionChangedHdl ) );
175 : }
176 : else
177 14 : mpImplLB->GetMainWindow()->AllowGrabFocus( true );
178 :
179 323 : SetCompoundControl( true );
180 323 : }
181 :
182 384 : WinBits ListBox::ImplInitStyle( WinBits nStyle )
183 : {
184 384 : if ( !(nStyle & WB_NOTABSTOP) )
185 384 : nStyle |= WB_TABSTOP;
186 384 : if ( !(nStyle & WB_NOGROUP) )
187 384 : nStyle |= WB_GROUP;
188 384 : return nStyle;
189 : }
190 :
191 9 : void ListBox::ImplLoadRes( const ResId& rResId )
192 : {
193 9 : Control::ImplLoadRes( rResId );
194 :
195 : // The resource short is actually to be treated as unsigned short.
196 9 : sal_uInt16 nResPos = static_cast<sal_uInt16>(ReadShortRes());
197 9 : sal_Int32 nSelPos = (nResPos == SAL_MAX_UINT16) ? LISTBOX_ENTRY_NOTFOUND : nResPos;
198 9 : sal_Int32 nNumber = ReadLongRes();
199 :
200 9 : for( sal_Int32 i = 0; i < nNumber; i++ )
201 : {
202 0 : sal_Int32 nPos = InsertEntry( ReadStringRes(), LISTBOX_APPEND );
203 :
204 0 : sal_IntPtr nId = ReadLongRes();
205 0 : if( nId )
206 0 : SetEntryData( nPos, reinterpret_cast<void *>(nId) ); // ID as UserData
207 : }
208 :
209 9 : if( nSelPos < nNumber )
210 0 : SelectEntryPos( nSelPos );
211 9 : }
212 :
213 0 : IMPL_LINK_NOARG(ListBox, ImplSelectHdl)
214 : {
215 0 : bool bPopup = IsInDropDown();
216 0 : if( IsDropDownBox() )
217 : {
218 0 : if( !mpImplLB->IsTravelSelect() )
219 : {
220 0 : mpFloatWin->EndPopupMode();
221 0 : mpImplWin->GrabFocus();
222 : }
223 :
224 0 : mpImplWin->SetItemPos( GetSelectEntryPos() );
225 0 : mpImplWin->SetString( GetSelectEntry() );
226 0 : if( mpImplLB->GetEntryList()->HasImages() )
227 : {
228 0 : Image aImage = mpImplLB->GetEntryList()->GetEntryImage( GetSelectEntryPos() );
229 0 : mpImplWin->SetImage( aImage );
230 : }
231 0 : mpImplWin->Invalidate();
232 : }
233 :
234 0 : if ( ( !IsTravelSelect() || mpImplLB->IsSelectionChanged() ) || ( bPopup && !IsMultiSelectionEnabled() ) )
235 0 : Select();
236 :
237 0 : return 1;
238 : }
239 :
240 0 : IMPL_LINK( ListBox, ImplFocusHdl, void *, nPos )
241 : {
242 0 : CallEventListeners( VCLEVENT_LISTBOX_FOCUS , nPos);
243 0 : return 1;
244 : }
245 :
246 0 : IMPL_LINK_NOARG( ListBox, ImplListItemSelectHdl )
247 : {
248 0 : CallEventListeners( VCLEVENT_DROPDOWN_SELECT );
249 0 : return 1;
250 : }
251 :
252 208 : IMPL_LINK_NOARG(ListBox, ImplScrollHdl)
253 : {
254 104 : CallEventListeners( VCLEVENT_LISTBOX_SCROLLED );
255 104 : return 1;
256 : }
257 :
258 0 : IMPL_LINK_NOARG(ListBox, ImplCancelHdl)
259 : {
260 0 : if( IsInDropDown() )
261 0 : mpFloatWin->EndPopupMode();
262 :
263 0 : return 1;
264 : }
265 :
266 504 : IMPL_LINK( ListBox, ImplSelectionChangedHdl, void*, n )
267 : {
268 252 : if ( !mpImplLB->IsTrackingSelect() )
269 : {
270 252 : sal_Int32 nChanged = (sal_Int32)reinterpret_cast<sal_uLong>(n);
271 252 : const ImplEntryList* pEntryList = mpImplLB->GetEntryList();
272 252 : if ( pEntryList->IsEntryPosSelected( nChanged ) )
273 : {
274 : // FIXME? This should've been turned into an ImplPaintEntry some time ago...
275 241 : if ( nChanged < pEntryList->GetMRUCount() )
276 0 : nChanged = pEntryList->FindEntry( pEntryList->GetEntryText( nChanged ) );
277 241 : mpImplWin->SetItemPos( nChanged );
278 241 : mpImplWin->SetString( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
279 241 : if( mpImplLB->GetEntryList()->HasImages() )
280 : {
281 3 : Image aImage = mpImplLB->GetEntryList()->GetEntryImage( nChanged );
282 3 : mpImplWin->SetImage( aImage );
283 : }
284 : }
285 : else
286 : {
287 11 : mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
288 11 : mpImplWin->SetString( OUString() );
289 11 : Image aImage;
290 11 : mpImplWin->SetImage( aImage );
291 : }
292 252 : mpImplWin->Invalidate();
293 : }
294 252 : return 1;
295 : }
296 :
297 0 : IMPL_LINK_NOARG(ListBox, ImplDoubleClickHdl)
298 : {
299 0 : DoubleClick();
300 0 : return 1;
301 : }
302 :
303 0 : void ListBox::ImplClickButtonHandler( Control* )
304 : {
305 0 : if( !mpFloatWin->IsInPopupMode() )
306 : {
307 0 : CallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
308 0 : mpImplWin->GrabFocus();
309 0 : mpBtn->SetPressed( true );
310 0 : mpFloatWin->StartFloat( true );
311 0 : CallEventListeners( VCLEVENT_DROPDOWN_OPEN );
312 :
313 0 : ImplClearLayoutData();
314 0 : if( mpImplLB )
315 0 : mpImplLB->GetMainWindow()->ImplClearLayoutData();
316 0 : if( mpImplWin )
317 0 : mpImplWin->ImplClearLayoutData();
318 : }
319 0 : }
320 :
321 2 : IMPL_LINK_NOARG(ListBox, ImplPopupModeEndHdl)
322 : {
323 1 : if( mpFloatWin->IsPopupModeCanceled() )
324 : {
325 0 : if ( ( mpFloatWin->GetPopupModeStartSaveSelection() != LISTBOX_ENTRY_NOTFOUND )
326 0 : && !IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
327 : {
328 0 : mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), true );
329 0 : bool bTravelSelect = mpImplLB->IsTravelSelect();
330 0 : mpImplLB->SetTravelSelect( true );
331 :
332 0 : ImplDelData aCheckDelete;
333 0 : ImplAddDel( &aCheckDelete );
334 0 : Select();
335 0 : if ( aCheckDelete.IsDead() )
336 0 : return 0;
337 0 : ImplRemoveDel( &aCheckDelete );
338 :
339 0 : mpImplLB->SetTravelSelect( bTravelSelect );
340 : }
341 : }
342 :
343 1 : ImplClearLayoutData();
344 1 : if( mpImplLB )
345 1 : mpImplLB->GetMainWindow()->ImplClearLayoutData();
346 1 : if( mpImplWin )
347 1 : mpImplWin->ImplClearLayoutData();
348 :
349 1 : mpBtn->SetPressed( false );
350 1 : CallEventListeners( VCLEVENT_DROPDOWN_CLOSE );
351 1 : return 0;
352 : }
353 :
354 3 : void ListBox::ToggleDropDown()
355 : {
356 3 : if( IsDropDownBox() )
357 : {
358 3 : if( mpFloatWin->IsInPopupMode() )
359 1 : mpFloatWin->EndPopupMode();
360 : else
361 : {
362 2 : CallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
363 2 : mpImplWin->GrabFocus();
364 2 : mpBtn->SetPressed( true );
365 2 : mpFloatWin->StartFloat( true );
366 2 : CallEventListeners( VCLEVENT_DROPDOWN_OPEN );
367 : }
368 : }
369 3 : }
370 :
371 56 : void ListBox::ApplySettings(vcl::RenderContext& rRenderContext)
372 : {
373 56 : rRenderContext.SetBackground();
374 56 : }
375 :
376 0 : void ListBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
377 : {
378 0 : mpImplLB->GetMainWindow()->ApplySettings(*pDev);
379 :
380 0 : Point aPos = pDev->LogicToPixel( rPos );
381 0 : Size aSize = pDev->LogicToPixel( rSize );
382 0 : vcl::Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
383 0 : OutDevType eOutDevType = pDev->GetOutDevType();
384 :
385 0 : pDev->Push();
386 0 : pDev->SetMapMode();
387 0 : pDev->SetFont( aFont );
388 0 : pDev->SetTextFillColor();
389 :
390 : // Border/Background
391 0 : pDev->SetLineColor();
392 0 : pDev->SetFillColor();
393 0 : bool bBorder = !(nFlags & DrawFlags::NoBorder ) && (GetStyle() & WB_BORDER);
394 0 : bool bBackground = !(nFlags & DrawFlags::NoBackground) && IsControlBackground();
395 0 : if ( bBorder || bBackground )
396 : {
397 0 : Rectangle aRect( aPos, aSize );
398 0 : if ( bBorder )
399 : {
400 0 : ImplDrawFrame( pDev, aRect );
401 : }
402 0 : if ( bBackground )
403 : {
404 0 : pDev->SetFillColor( GetControlBackground() );
405 0 : pDev->DrawRect( aRect );
406 : }
407 : }
408 :
409 : // Content
410 0 : if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
411 : {
412 0 : pDev->SetTextColor( Color( COL_BLACK ) );
413 : }
414 : else
415 : {
416 0 : if ( !(nFlags & DrawFlags::NoDisable ) && !IsEnabled() )
417 : {
418 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
419 0 : pDev->SetTextColor( rStyleSettings.GetDisableColor() );
420 : }
421 : else
422 : {
423 0 : pDev->SetTextColor( GetTextColor() );
424 : }
425 : }
426 :
427 0 : long nOnePixel = GetDrawPixel( pDev, 1 );
428 0 : DrawTextFlags nTextStyle = DrawTextFlags::VCenter;
429 0 : Rectangle aTextRect( aPos, aSize );
430 :
431 0 : if ( GetStyle() & WB_CENTER )
432 0 : nTextStyle |= DrawTextFlags::Center;
433 0 : else if ( GetStyle() & WB_RIGHT )
434 0 : nTextStyle |= DrawTextFlags::Right;
435 : else
436 0 : nTextStyle |= DrawTextFlags::Left;
437 :
438 0 : aTextRect.Left() += 3*nOnePixel;
439 0 : aTextRect.Right() -= 3*nOnePixel;
440 :
441 0 : if ( IsDropDownBox() )
442 : {
443 0 : OUString aText = GetSelectEntry();
444 0 : long nTextHeight = pDev->GetTextHeight();
445 0 : long nTextWidth = pDev->GetTextWidth( aText );
446 0 : long nOffX = 3*nOnePixel;
447 0 : long nOffY = (aSize.Height()-nTextHeight) / 2;
448 :
449 : // Clipping?
450 0 : if ( (nOffY < 0) ||
451 0 : ((nOffY+nTextHeight) > aSize.Height()) ||
452 0 : ((nOffX+nTextWidth) > aSize.Width()) )
453 : {
454 0 : Rectangle aClip( aPos, aSize );
455 0 : if ( nTextHeight > aSize.Height() )
456 0 : aClip.Bottom() += nTextHeight-aSize.Height()+1; // So that HP Printers don't optimize this away
457 0 : pDev->IntersectClipRegion( aClip );
458 : }
459 :
460 0 : pDev->DrawText( aTextRect, aText, nTextStyle );
461 : }
462 : else
463 : {
464 0 : long nTextHeight = pDev->GetTextHeight();
465 0 : sal_uInt16 nLines = ( nTextHeight > 0 ) ? (sal_uInt16)(aSize.Height() / nTextHeight) : 1;
466 0 : Rectangle aClip( aPos, aSize );
467 :
468 0 : pDev->IntersectClipRegion( aClip );
469 :
470 0 : if ( !nLines )
471 0 : nLines = 1;
472 :
473 0 : for ( sal_uInt16 n = 0; n < nLines; n++ )
474 : {
475 0 : sal_Int32 nEntry = n+mpImplLB->GetTopEntry();
476 0 : bool bSelected = mpImplLB->GetEntryList()->IsEntryPosSelected( nEntry );
477 0 : if ( bSelected )
478 : {
479 0 : pDev->SetFillColor( COL_BLACK );
480 0 : pDev->DrawRect( Rectangle( Point( aPos.X(), aPos.Y() + n*nTextHeight ),
481 0 : Point( aPos.X() + aSize.Width(), aPos.Y() + (n+1)*nTextHeight + 2*nOnePixel ) ) );
482 0 : pDev->SetFillColor();
483 0 : pDev->SetTextColor( COL_WHITE );
484 : }
485 :
486 0 : aTextRect.Top() = aPos.Y() + n*nTextHeight;
487 0 : aTextRect.Bottom() = aTextRect.Top() + nTextHeight;
488 :
489 0 : pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( nEntry ), nTextStyle );
490 :
491 0 : if ( bSelected )
492 0 : pDev->SetTextColor( COL_BLACK );
493 : }
494 : }
495 :
496 0 : pDev->Pop();
497 0 : }
498 :
499 1 : void ListBox::GetFocus()
500 : {
501 1 : if ( mpImplLB )
502 : {
503 0 : if( IsDropDownBox() )
504 0 : mpImplWin->GrabFocus();
505 : else
506 0 : mpImplLB->GrabFocus();
507 : }
508 :
509 1 : Control::GetFocus();
510 1 : }
511 :
512 0 : vcl::Window* ListBox::GetPreferredKeyInputWindow()
513 : {
514 0 : if ( mpImplLB )
515 : {
516 0 : if( IsDropDownBox() )
517 0 : return mpImplWin->GetPreferredKeyInputWindow();
518 : else
519 0 : return mpImplLB->GetPreferredKeyInputWindow();
520 : }
521 :
522 0 : return Control::GetPreferredKeyInputWindow();
523 : }
524 :
525 0 : void ListBox::LoseFocus()
526 : {
527 0 : if( IsDropDownBox() )
528 : {
529 0 : if (mpImplWin)
530 0 : mpImplWin->HideFocus();
531 : }
532 : else
533 : {
534 0 : if (mpImplLB)
535 0 : mpImplLB->HideFocus();
536 : }
537 :
538 0 : Control::LoseFocus();
539 0 : }
540 :
541 364 : void ListBox::DataChanged( const DataChangedEvent& rDCEvt )
542 : {
543 364 : Control::DataChanged( rDCEvt );
544 :
545 1456 : if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
546 1456 : (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
547 1092 : ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
548 1456 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
549 : {
550 364 : SetBackground(); // Due to a hack in Window::UpdateSettings the background must be reset
551 : // otherwise it will overpaint NWF drawn listboxes
552 364 : Resize();
553 364 : mpImplLB->Resize(); // Is not called by ListBox::Resize() if the ImplLB does not change
554 :
555 364 : if ( mpImplWin )
556 : {
557 219 : mpImplWin->SetSettings( GetSettings() ); // If not yet set...
558 219 : mpImplWin->ApplySettings(*mpImplWin);
559 :
560 219 : mpBtn->SetSettings( GetSettings() );
561 219 : ImplInitDropDownButton( mpBtn );
562 : }
563 :
564 364 : if ( IsDropDownBox() )
565 219 : Invalidate();
566 : }
567 364 : }
568 :
569 195 : void ListBox::EnableAutoSize( bool bAuto )
570 : {
571 195 : mbDDAutoSize = bAuto;
572 195 : if ( mpFloatWin )
573 : {
574 181 : if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
575 : {
576 : // use GetListBoxMaximumLineCount here; before, was on fixed number of five
577 174 : AdaptDropDownLineCountToMaximum();
578 : }
579 7 : else if ( !bAuto )
580 : {
581 7 : mpFloatWin->SetDropDownLineCount( 0 );
582 : }
583 : }
584 195 : }
585 :
586 0 : void ListBox::EnableDDAutoWidth( bool b )
587 : {
588 0 : if ( mpFloatWin )
589 0 : mpFloatWin->SetAutoWidth( b );
590 0 : }
591 :
592 1266 : void ListBox::SetDropDownLineCount( sal_uInt16 nLines )
593 : {
594 1266 : mnLineCount = nLines;
595 1266 : if ( mpFloatWin )
596 1251 : mpFloatWin->SetDropDownLineCount( mnLineCount );
597 1266 : }
598 :
599 228 : void ListBox::AdaptDropDownLineCountToMaximum()
600 : {
601 : // adapt to maximum allowed number
602 228 : SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
603 228 : }
604 :
605 0 : sal_uInt16 ListBox::GetDropDownLineCount() const
606 : {
607 0 : if ( mpFloatWin )
608 0 : return mpFloatWin->GetDropDownLineCount();
609 0 : return mnLineCount;
610 : }
611 :
612 358 : void ListBox::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags )
613 : {
614 358 : if( IsDropDownBox() && ( nFlags & PosSizeFlags::Size ) )
615 : {
616 259 : Size aPrefSz = mpFloatWin->GetPrefSize();
617 259 : if ( ( nFlags & PosSizeFlags::Height ) && ( nHeight >= 2*mnDDHeight ) )
618 140 : aPrefSz.Height() = nHeight-mnDDHeight;
619 259 : if ( nFlags & PosSizeFlags::Width )
620 259 : aPrefSz.Width() = nWidth;
621 259 : mpFloatWin->SetPrefSize( aPrefSz );
622 :
623 259 : if ( IsAutoSizeEnabled() && ! (nFlags & PosSizeFlags::Dropdown) )
624 245 : nHeight = mnDDHeight;
625 : }
626 :
627 358 : Control::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
628 358 : }
629 :
630 1403 : void ListBox::Resize()
631 : {
632 1403 : Size aOutSz = GetOutputSizePixel();
633 1403 : if( IsDropDownBox() )
634 : {
635 : // Initialize the dropdown button size with the standard scrollbar width
636 1171 : long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
637 1171 : long nBottom = aOutSz.Height();
638 :
639 : // Note: in case of no border, pBorder will actually be this
640 1171 : vcl::Window *pBorder = GetWindow( GetWindowType::Border );
641 1171 : ImplControlValue aControlValue;
642 1171 : Point aPoint;
643 1171 : Rectangle aContent, aBound;
644 :
645 : // Use the full extent of the control
646 1171 : Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
647 :
648 2342 : if ( GetNativeControlRegion( CTRL_LISTBOX, PART_BUTTON_DOWN,
649 2342 : aArea, ControlState::NONE, aControlValue, OUString(), aBound, aContent) )
650 : {
651 0 : long nTop = 0;
652 : // Convert back from border space to local coordinates
653 0 : aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
654 0 : aContent.Move( -aPoint.X(), -aPoint.Y() );
655 :
656 : // Use the themes drop down size for the button
657 0 : aOutSz.Width() = aContent.Left();
658 0 : mpBtn->setPosSizePixel( aContent.Left(), nTop, aContent.Right(), (nBottom-nTop) );
659 :
660 : // Adjust the size of the edit field
661 0 : if ( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT,
662 0 : aArea, ControlState::NONE, aControlValue, OUString(), aBound, aContent) )
663 : {
664 : // Convert back from border space to local coordinates
665 0 : aContent.Move( -aPoint.X(), -aPoint.Y() );
666 :
667 : // Use the themes drop down size
668 0 : if( ! (GetStyle() & WB_BORDER) && ImplGetSVData()->maNWFData.mbNoFocusRects )
669 : {
670 : // No border but focus ring behavior -> we have a problem; the
671 : // native rect relies on the border to draw the focus
672 : // let's do the best we can and center vertically, so it doesn't look
673 : // completely wrong.
674 0 : Size aSz( GetOutputSizePixel() );
675 0 : long nDiff = aContent.Top() - (aSz.Height() - aContent.GetHeight())/2;
676 0 : aContent.Top() -= nDiff;
677 0 : aContent.Bottom() -= nDiff;
678 : }
679 0 : mpImplWin->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() );
680 : }
681 : else
682 0 : mpImplWin->SetSizePixel( aOutSz );
683 : }
684 : else
685 : {
686 1171 : nSBWidth = CalcZoom( nSBWidth );
687 1171 : mpImplWin->setPosSizePixel( 0, 0, aOutSz.Width() - nSBWidth, aOutSz.Height() );
688 1171 : mpBtn->setPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
689 1171 : }
690 : }
691 : else
692 : {
693 232 : mpImplLB->SetSizePixel( aOutSz );
694 : }
695 :
696 : // Retain FloatingWindow size even when it's invisible, as we still process KEY_PGUP/DOWN ...
697 1403 : if ( mpFloatWin )
698 1171 : mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
699 :
700 1403 : Control::Resize();
701 1403 : }
702 :
703 0 : void ListBox::FillLayoutData() const
704 : {
705 0 : mpControlData->mpLayoutData = new vcl::ControlLayoutData();
706 0 : const ImplListBoxWindow* rMainWin = mpImplLB->GetMainWindow();
707 0 : if( mpFloatWin )
708 : {
709 : // Dropdown mode
710 0 : AppendLayoutData( *mpImplWin );
711 0 : mpImplWin->SetLayoutDataParent( this );
712 0 : if( mpFloatWin->IsReallyVisible() )
713 : {
714 0 : AppendLayoutData( *rMainWin );
715 0 : rMainWin->SetLayoutDataParent( this );
716 : }
717 : }
718 : else
719 : {
720 0 : AppendLayoutData( *rMainWin );
721 0 : rMainWin->SetLayoutDataParent( this );
722 : }
723 0 : }
724 :
725 0 : long ListBox::GetIndexForPoint( const Point& rPoint, sal_Int32& rPos ) const
726 : {
727 0 : if( !HasLayoutData() )
728 0 : FillLayoutData();
729 :
730 : // Check whether rPoint fits at all
731 0 : long nIndex = Control::GetIndexForPoint( rPoint );
732 0 : if( nIndex != -1 )
733 : {
734 : // Point must be either in main list window
735 : // or in impl window (dropdown case)
736 0 : ImplListBoxWindow* rMain = mpImplLB->GetMainWindow();
737 :
738 : // Convert coordinates to ImplListBoxWindow pixel coordinate space
739 0 : Point aConvPoint = LogicToPixel( rPoint );
740 0 : aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
741 0 : aConvPoint = rMain->AbsoluteScreenToOutputPixel( aConvPoint );
742 0 : aConvPoint = rMain->PixelToLogic( aConvPoint );
743 :
744 : // Try to find entry
745 0 : sal_Int32 nEntry = rMain->GetEntryPosForPoint( aConvPoint );
746 0 : if( nEntry == LISTBOX_ENTRY_NOTFOUND )
747 : {
748 : // Not found, maybe dropdown case
749 0 : if( mpImplWin && mpImplWin->IsReallyVisible() )
750 : {
751 : // Convert to impl window pixel coordinates
752 0 : aConvPoint = LogicToPixel( rPoint );
753 0 : aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
754 0 : aConvPoint = mpImplWin->AbsoluteScreenToOutputPixel( aConvPoint );
755 :
756 : // Check whether converted point is inside impl window
757 0 : Size aImplWinSize = mpImplWin->GetOutputSizePixel();
758 0 : if( aConvPoint.X() >= 0 && aConvPoint.Y() >= 0 && aConvPoint.X() < aImplWinSize.Width() && aConvPoint.Y() < aImplWinSize.Height() )
759 : {
760 : // Inside the impl window, the position is the current item pos
761 0 : rPos = mpImplWin->GetItemPos();
762 : }
763 : else
764 0 : nIndex = -1;
765 : }
766 : else
767 0 : nIndex = -1;
768 : }
769 : else
770 0 : rPos = nEntry;
771 :
772 : DBG_ASSERT( nIndex != -1, "found index for point, but relative index failed" );
773 : }
774 :
775 : // Get line relative index
776 0 : if( nIndex != -1 )
777 0 : nIndex = ToRelativeLineIndex( nIndex );
778 :
779 0 : return nIndex;
780 : }
781 :
782 1597 : void ListBox::StateChanged( StateChangedType nType )
783 : {
784 1597 : if( nType == StateChangedType::ReadOnly )
785 : {
786 12 : if( mpImplWin )
787 6 : mpImplWin->Enable( !IsReadOnly() );
788 12 : if( mpBtn )
789 6 : mpBtn->Enable( !IsReadOnly() );
790 : }
791 1585 : else if( nType == StateChangedType::Enable )
792 : {
793 16 : mpImplLB->Enable( IsEnabled() );
794 16 : if( mpImplWin )
795 : {
796 10 : mpImplWin->Enable( IsEnabled() );
797 20 : if ( IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL)
798 10 : && ! IsNativeControlSupported(CTRL_LISTBOX, PART_BUTTON_DOWN) )
799 : {
800 0 : GetWindow( GetWindowType::Border )->Invalidate( InvalidateFlags::NoErase );
801 : }
802 : else
803 10 : mpImplWin->Invalidate();
804 : }
805 16 : if( mpBtn )
806 10 : mpBtn->Enable( IsEnabled() );
807 : }
808 1569 : else if( nType == StateChangedType::UpdateMode )
809 : {
810 124 : mpImplLB->SetUpdateMode( IsUpdateMode() );
811 : }
812 1445 : else if ( nType == StateChangedType::Zoom )
813 : {
814 1 : mpImplLB->SetZoom( GetZoom() );
815 1 : if ( mpImplWin )
816 : {
817 0 : mpImplWin->SetZoom( GetZoom() );
818 0 : mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
819 0 : mpImplWin->Invalidate();
820 : }
821 1 : Resize();
822 : }
823 1444 : else if ( nType == StateChangedType::ControlFont )
824 : {
825 156 : mpImplLB->SetControlFont( GetControlFont() );
826 156 : if ( mpImplWin )
827 : {
828 116 : mpImplWin->SetControlFont( GetControlFont() );
829 116 : mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
830 116 : mpImplWin->Invalidate();
831 : }
832 156 : Resize();
833 : }
834 1288 : else if ( nType == StateChangedType::ControlForeground )
835 : {
836 2 : mpImplLB->SetControlForeground( GetControlForeground() );
837 2 : if ( mpImplWin )
838 : {
839 0 : mpImplWin->SetControlForeground( GetControlForeground() );
840 0 : mpImplWin->SetTextColor( GetControlForeground() );
841 0 : mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
842 0 : mpImplWin->Invalidate();
843 : }
844 : }
845 1286 : else if ( nType == StateChangedType::ControlBackground )
846 : {
847 2 : mpImplLB->SetControlBackground( GetControlBackground() );
848 2 : if ( mpImplWin )
849 : {
850 0 : if ( mpImplWin->IsNativeControlSupported(CTRL_LISTBOX, PART_ENTIRE_CONTROL) )
851 : {
852 : // Transparent background
853 0 : mpImplWin->SetBackground();
854 0 : mpImplWin->SetControlBackground();
855 : }
856 : else
857 : {
858 0 : mpImplWin->SetBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
859 0 : mpImplWin->SetControlBackground( mpImplLB->GetMainWindow()->GetControlBackground() );
860 : }
861 0 : mpImplWin->SetFont( mpImplLB->GetMainWindow()->GetFont() );
862 0 : mpImplWin->Invalidate();
863 : }
864 : }
865 1284 : else if ( nType == StateChangedType::Style )
866 : {
867 61 : SetStyle( ImplInitStyle( GetStyle() ) );
868 61 : mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) != 0 );
869 61 : bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0;
870 61 : mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
871 : }
872 1223 : else if( nType == StateChangedType::Mirroring )
873 : {
874 50 : if( mpBtn )
875 : {
876 18 : mpBtn->EnableRTL( IsRTLEnabled() );
877 18 : ImplInitDropDownButton( mpBtn );
878 : }
879 50 : mpImplLB->EnableRTL( IsRTLEnabled() );
880 50 : if( mpImplWin )
881 18 : mpImplWin->EnableRTL( IsRTLEnabled() );
882 50 : Resize();
883 : }
884 :
885 1597 : Control::StateChanged( nType );
886 1597 : }
887 :
888 3 : bool ListBox::PreNotify( NotifyEvent& rNEvt )
889 : {
890 3 : bool nDone = false;
891 3 : if ( mpImplLB )
892 : {
893 1 : if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && ( rNEvt.GetWindow() == mpImplWin ) )
894 : {
895 0 : KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
896 0 : switch( aKeyEvt.GetKeyCode().GetCode() )
897 : {
898 : case KEY_DOWN:
899 : {
900 0 : if( mpFloatWin && !mpFloatWin->IsInPopupMode() &&
901 0 : aKeyEvt.GetKeyCode().IsMod2() )
902 : {
903 0 : CallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
904 0 : mpBtn->SetPressed( true );
905 0 : mpFloatWin->StartFloat( false );
906 0 : CallEventListeners( VCLEVENT_DROPDOWN_OPEN );
907 0 : nDone = true;
908 : }
909 : else
910 : {
911 0 : nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
912 : }
913 : }
914 0 : break;
915 : case KEY_UP:
916 : {
917 0 : if( mpFloatWin && mpFloatWin->IsInPopupMode() &&
918 0 : aKeyEvt.GetKeyCode().IsMod2() )
919 : {
920 0 : mpFloatWin->EndPopupMode();
921 0 : nDone = true;
922 : }
923 : else
924 : {
925 0 : nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
926 : }
927 : }
928 0 : break;
929 : case KEY_RETURN:
930 : {
931 0 : if( IsInDropDown() )
932 : {
933 0 : mpImplLB->ProcessKeyInput( aKeyEvt );
934 0 : nDone = true;
935 : }
936 : }
937 0 : break;
938 :
939 : default:
940 : {
941 0 : nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
942 : }
943 : }
944 : }
945 1 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
946 : {
947 0 : if ( IsInDropDown() && !HasChildPathFocus( true ) )
948 0 : mpFloatWin->EndPopupMode();
949 : }
950 2 : else if ( (rNEvt.GetType() == MouseNotifyEvent::COMMAND) &&
951 1 : (rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel) &&
952 0 : (rNEvt.GetWindow() == mpImplWin) )
953 : {
954 0 : MouseWheelBehaviour nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
955 0 : if ( ( nWheelBehavior == MouseWheelBehaviour::ALWAYS )
956 0 : || ( ( nWheelBehavior == MouseWheelBehaviour::FocusOnly )
957 0 : && HasChildPathFocus()
958 : )
959 : )
960 : {
961 0 : nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
962 : }
963 : else
964 : {
965 0 : nDone = false; // Don't consume this event, let the default handling take it (i.e. scroll the context)
966 : }
967 : }
968 : }
969 :
970 3 : return nDone || Control::PreNotify( rNEvt );
971 : }
972 :
973 53 : void ListBox::Select()
974 : {
975 53 : ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_SELECT, maSelectHdl, this );
976 53 : }
977 :
978 0 : void ListBox::DoubleClick()
979 : {
980 0 : ImplCallEventListenersAndHandler( VCLEVENT_LISTBOX_DOUBLECLICK, maDoubleClickHdl, this );
981 0 : }
982 :
983 875 : void ListBox::Clear()
984 : {
985 875 : mpImplLB->Clear();
986 875 : if( IsDropDownBox() )
987 : {
988 848 : mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
989 848 : mpImplWin->SetString( OUString() );
990 848 : Image aImage;
991 848 : mpImplWin->SetImage( aImage );
992 848 : mpImplWin->Invalidate();
993 : }
994 875 : CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, reinterpret_cast<void*>(-1) );
995 875 : }
996 :
997 45 : void ListBox::SetNoSelection()
998 : {
999 45 : mpImplLB->SetNoSelection();
1000 45 : if( IsDropDownBox() )
1001 : {
1002 20 : mpImplWin->SetItemPos( LISTBOX_ENTRY_NOTFOUND );
1003 20 : mpImplWin->SetString( OUString() );
1004 20 : Image aImage;
1005 20 : mpImplWin->SetImage( aImage );
1006 20 : mpImplWin->Invalidate();
1007 : }
1008 45 : CallEventListeners(VCLEVENT_LISTBOX_STATEUPDATE);
1009 45 : }
1010 :
1011 9543 : sal_Int32 ListBox::InsertEntry( const OUString& rStr, sal_Int32 nPos )
1012 : {
1013 9543 : sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
1014 9543 : nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1015 9543 : CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, reinterpret_cast<void*>(nRealPos) );
1016 9543 : return nRealPos;
1017 : }
1018 :
1019 107 : sal_Int32 ListBox::InsertEntry( const OUString& rStr, const Image& rImage, sal_Int32 nPos )
1020 : {
1021 107 : sal_Int32 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
1022 107 : nRealPos = sal::static_int_cast<sal_Int32>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
1023 107 : CallEventListeners( VCLEVENT_LISTBOX_ITEMADDED, reinterpret_cast<void*>(nRealPos) );
1024 107 : return nRealPos;
1025 : }
1026 :
1027 0 : void ListBox::RemoveEntry( const OUString& rStr )
1028 : {
1029 0 : RemoveEntry( GetEntryPos( rStr ) );
1030 0 : }
1031 :
1032 0 : void ListBox::RemoveEntry( sal_Int32 nPos )
1033 : {
1034 0 : mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1035 0 : CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, reinterpret_cast<void*>(nPos) );
1036 0 : }
1037 :
1038 0 : Image ListBox::GetEntryImage( sal_Int32 nPos ) const
1039 : {
1040 0 : if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) )
1041 0 : return mpImplLB->GetEntryList()->GetEntryImage( nPos );
1042 0 : return Image();
1043 : }
1044 :
1045 24 : sal_Int32 ListBox::GetEntryPos( const OUString& rStr ) const
1046 : {
1047 24 : sal_Int32 nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
1048 24 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1049 24 : nPos = nPos - mpImplLB->GetEntryList()->GetMRUCount();
1050 24 : return nPos;
1051 : }
1052 :
1053 0 : sal_Int32 ListBox::GetEntryPos( const void* pData ) const
1054 : {
1055 0 : sal_Int32 nPos = mpImplLB->GetEntryList()->FindEntry( pData );
1056 0 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1057 0 : nPos = nPos - mpImplLB->GetEntryList()->GetMRUCount();
1058 0 : return nPos;
1059 : }
1060 :
1061 24 : OUString ListBox::GetEntry( sal_Int32 nPos ) const
1062 : {
1063 24 : return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1064 : }
1065 :
1066 1125 : sal_Int32 ListBox::GetEntryCount() const
1067 : {
1068 1125 : return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
1069 : }
1070 :
1071 0 : OUString ListBox::GetSelectEntry(sal_Int32 nIndex) const
1072 : {
1073 0 : return GetEntry( GetSelectEntryPos( nIndex ) );
1074 : }
1075 :
1076 1315 : sal_Int32 ListBox::GetSelectEntryCount() const
1077 : {
1078 1315 : return mpImplLB->GetEntryList()->GetSelectEntryCount();
1079 : }
1080 :
1081 832 : sal_Int32 ListBox::GetSelectEntryPos( sal_Int32 nIndex ) const
1082 : {
1083 832 : sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
1084 832 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1085 : {
1086 11 : if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1087 0 : nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
1088 11 : nPos = nPos - mpImplLB->GetEntryList()->GetMRUCount();
1089 : }
1090 832 : return nPos;
1091 : }
1092 :
1093 0 : bool ListBox::IsEntrySelected(const OUString& rStr) const
1094 : {
1095 0 : return IsEntryPosSelected( GetEntryPos( rStr ) );
1096 : }
1097 :
1098 166 : bool ListBox::IsEntryPosSelected( sal_Int32 nPos ) const
1099 : {
1100 166 : return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1101 : }
1102 :
1103 24 : void ListBox::SelectEntry( const OUString& rStr, bool bSelect )
1104 : {
1105 24 : SelectEntryPos( GetEntryPos( rStr ), bSelect );
1106 24 : }
1107 :
1108 746 : void ListBox::SelectEntryPos( sal_Int32 nPos, bool bSelect )
1109 : {
1110 746 : if ( 0 <= nPos && nPos < mpImplLB->GetEntryList()->GetEntryCount() )
1111 : {
1112 610 : sal_Int32 oldSelectCount = GetSelectEntryCount(), newSelectCount = 0, nCurrentPos = mpImplLB->GetCurrentPos();
1113 610 : mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
1114 610 : newSelectCount = GetSelectEntryCount();
1115 610 : if (oldSelectCount == 0 && newSelectCount > 0)
1116 243 : CallEventListeners(VCLEVENT_LISTBOX_STATEUPDATE);
1117 : //Only when bSelect == true, send both Selection & Focus events
1118 610 : if (nCurrentPos != nPos && bSelect)
1119 : {
1120 240 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, reinterpret_cast<void*>(nPos));
1121 240 : if (HasFocus())
1122 0 : CallEventListeners( VCLEVENT_LISTBOX_FOCUS, reinterpret_cast<void*>(nPos));
1123 : }
1124 : }
1125 746 : }
1126 :
1127 0 : void ListBox::SetEntryData( sal_Int32 nPos, void* pNewData )
1128 : {
1129 0 : mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
1130 0 : }
1131 :
1132 0 : void* ListBox::GetEntryData( sal_Int32 nPos ) const
1133 : {
1134 0 : return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1135 : }
1136 :
1137 0 : void ListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
1138 : {
1139 0 : mpImplLB->SetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount(), nFlags );
1140 0 : }
1141 :
1142 0 : ListBoxEntryFlags ListBox::GetEntryFlags( sal_Int32 nPos ) const
1143 : {
1144 0 : return mpImplLB->GetEntryList()->GetEntryFlags( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1145 : }
1146 :
1147 84 : void ListBox::SetTopEntry( sal_Int32 nPos )
1148 : {
1149 84 : mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1150 84 : }
1151 :
1152 24 : sal_Int32 ListBox::GetTopEntry() const
1153 : {
1154 24 : sal_Int32 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
1155 24 : if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1156 0 : nPos = 0;
1157 24 : return nPos;
1158 : }
1159 :
1160 0 : bool ListBox::IsTravelSelect() const
1161 : {
1162 0 : return mpImplLB->IsTravelSelect();
1163 : }
1164 :
1165 8 : bool ListBox::IsInDropDown() const
1166 : {
1167 8 : return mpFloatWin && mpFloatWin->IsInPopupMode();
1168 : }
1169 :
1170 0 : Rectangle ListBox::GetBoundingRectangle( sal_Int32 nItem ) const
1171 : {
1172 0 : Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1173 0 : Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( static_cast<vcl::Window*>(const_cast<ListBox *>(this)) );
1174 0 : aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1175 0 : return aRect;
1176 : }
1177 :
1178 33 : void ListBox::EnableMultiSelection( bool bMulti )
1179 : {
1180 33 : EnableMultiSelection( bMulti, false );
1181 33 : }
1182 :
1183 33 : void ListBox::EnableMultiSelection( bool bMulti, bool bStackSelection )
1184 : {
1185 33 : mpImplLB->EnableMultiSelection( bMulti, bStackSelection );
1186 :
1187 : // WB_SIMPLEMODE:
1188 : // The MultiListBox behaves just like a normal ListBox
1189 : // MultiSelection is possible via corresponding additional keys
1190 33 : bool bSimpleMode = ( GetStyle() & WB_SIMPLEMODE ) != 0;
1191 33 : mpImplLB->SetMultiSelectionSimpleMode( bSimpleMode );
1192 :
1193 : // In a MultiSelection, we can't see us travelling without focus
1194 33 : if ( mpFloatWin )
1195 12 : mpImplLB->GetMainWindow()->AllowGrabFocus( bMulti );
1196 33 : }
1197 :
1198 4 : bool ListBox::IsMultiSelectionEnabled() const
1199 : {
1200 4 : return mpImplLB->IsMultiSelectionEnabled();
1201 : }
1202 :
1203 276 : Size ListBox::CalcMinimumSize() const
1204 : {
1205 276 : Size aSz;
1206 :
1207 276 : if (!mpImplLB)
1208 0 : return aSz;
1209 :
1210 276 : aSz = CalcSubEditSize();
1211 :
1212 276 : bool bAddScrollWidth = false;
1213 :
1214 276 : if (IsDropDownBox())
1215 : {
1216 276 : aSz.Height() += 4; // add a space between entry and border
1217 276 : aSz.Width() += 4; // add a little breathing space
1218 276 : bAddScrollWidth = true;
1219 : }
1220 : else
1221 0 : bAddScrollWidth = (GetStyle() & WB_VSCROLL) == WB_VSCROLL;
1222 :
1223 276 : if (bAddScrollWidth)
1224 : {
1225 : // Try native borders; scrollbar size may not be a good indicator
1226 : // See how large the edit area inside is to estimate what is needed for the dropdown
1227 276 : ImplControlValue aControlValue;
1228 276 : Point aPoint;
1229 276 : Rectangle aContent, aBound;
1230 276 : Size aTestSize( 100, 20 );
1231 276 : Rectangle aArea( aPoint, aTestSize );
1232 552 : if( GetNativeControlRegion( CTRL_LISTBOX, PART_SUB_EDIT, aArea, ControlState::NONE,
1233 552 : aControlValue, OUString(), aBound, aContent) )
1234 : {
1235 : // use the themes drop down size
1236 0 : aSz.Width() += aTestSize.Width() - aContent.GetWidth();
1237 : }
1238 : else
1239 276 : aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1240 : }
1241 :
1242 276 : aSz = CalcWindowSize( aSz );
1243 :
1244 276 : if (IsDropDownBox()) // Check minimum height of dropdown box
1245 : {
1246 276 : ImplControlValue aControlValue;
1247 276 : Rectangle aRect( Point( 0, 0 ), aSz );
1248 276 : Rectangle aContent, aBound;
1249 552 : if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL, aRect, ControlState::NONE,
1250 552 : aControlValue, OUString(), aBound, aContent) )
1251 : {
1252 0 : if( aBound.GetHeight() > aSz.Height() )
1253 0 : aSz.Height() = aBound.GetHeight();
1254 276 : }
1255 : }
1256 :
1257 276 : return aSz;
1258 : }
1259 :
1260 276 : Size ListBox::CalcSubEditSize() const
1261 : {
1262 276 : Size aSz;
1263 :
1264 276 : if (!mpImplLB)
1265 0 : return aSz;
1266 :
1267 276 : if ( !IsDropDownBox() )
1268 0 : aSz = mpImplLB->CalcSize (mnLineCount ? mnLineCount : mpImplLB->GetEntryList()->GetEntryCount());
1269 : else
1270 : {
1271 276 : aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
1272 : // Size to maxmimum entry width
1273 276 : aSz.Width() = mpImplLB->GetMaxEntryWidth();
1274 :
1275 276 : if (m_nMaxWidthChars != -1)
1276 : {
1277 0 : long nMaxWidth = m_nMaxWidthChars * approximate_char_width();
1278 0 : aSz.Width() = std::min(aSz.Width(), nMaxWidth);
1279 : }
1280 :
1281 : // Do not create ultrathin ListBoxes, it doesn't look good
1282 276 : if( aSz.Width() < GetSettings().GetStyleSettings().GetScrollBarSize() )
1283 0 : aSz.Width() = GetSettings().GetStyleSettings().GetScrollBarSize();
1284 : }
1285 :
1286 276 : return aSz;
1287 : }
1288 :
1289 276 : Size ListBox::GetOptimalSize() const
1290 : {
1291 276 : return CalcMinimumSize();
1292 : }
1293 :
1294 0 : Size ListBox::CalcAdjustedSize( const Size& rPrefSize ) const
1295 : {
1296 0 : Size aSz = rPrefSize;
1297 : sal_Int32 nLeft, nTop, nRight, nBottom;
1298 0 : static_cast<vcl::Window*>(const_cast<ListBox *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1299 0 : aSz.Height() -= nTop+nBottom;
1300 0 : if ( !IsDropDownBox() )
1301 : {
1302 0 : long nEntryHeight = CalcBlockSize( 1, 1 ).Height();
1303 0 : long nLines = aSz.Height() / nEntryHeight;
1304 0 : if ( nLines < 1 )
1305 0 : nLines = 1;
1306 0 : aSz.Height() = nLines * nEntryHeight;
1307 : }
1308 : else
1309 : {
1310 0 : aSz.Height() = mnDDHeight;
1311 : }
1312 0 : aSz.Height() += nTop+nBottom;
1313 :
1314 0 : aSz = CalcWindowSize( aSz );
1315 0 : return aSz;
1316 : }
1317 :
1318 0 : Size ListBox::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1319 : {
1320 : // ScrollBars are shown if needed
1321 0 : Size aMinSz = CalcMinimumSize();
1322 : // aMinSz = ImplCalcOutSz( aMinSz );
1323 :
1324 0 : Size aSz;
1325 :
1326 : // Height
1327 0 : if ( nLines )
1328 : {
1329 0 : if ( !IsDropDownBox() )
1330 0 : aSz.Height() = mpImplLB->CalcSize( nLines ).Height();
1331 : else
1332 0 : aSz.Height() = mnDDHeight;
1333 : }
1334 : else
1335 0 : aSz.Height() = aMinSz.Height();
1336 :
1337 : // Width
1338 0 : if ( nColumns )
1339 0 : aSz.Width() = nColumns * GetTextWidth( OUString('X') );
1340 : else
1341 0 : aSz.Width() = aMinSz.Width();
1342 :
1343 0 : if ( IsDropDownBox() )
1344 0 : aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1345 :
1346 0 : if ( !IsDropDownBox() )
1347 : {
1348 0 : if ( aSz.Width() < aMinSz.Width() )
1349 0 : aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
1350 0 : if ( aSz.Height() < aMinSz.Height() )
1351 0 : aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1352 : }
1353 :
1354 0 : aSz = CalcWindowSize( aSz );
1355 0 : return aSz;
1356 : }
1357 :
1358 0 : void ListBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1359 : {
1360 0 : float nCharWidth = approximate_char_width();
1361 0 : if ( !IsDropDownBox() )
1362 : {
1363 0 : Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
1364 0 : rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1365 0 : rnLines = (sal_uInt16) (aOutSz.Height()/mpImplLB->GetEntryHeight());
1366 : }
1367 : else
1368 : {
1369 0 : Size aOutSz = mpImplWin->GetOutputSizePixel();
1370 0 : rnCols = (sal_uInt16) (aOutSz.Width()/nCharWidth);
1371 0 : rnLines = 1;
1372 : }
1373 0 : }
1374 :
1375 1 : void ListBox::ImplUserDrawHandler( UserDrawEvent* pEvent )
1376 : {
1377 1 : UserDraw( *pEvent );
1378 1 : }
1379 :
1380 0 : void ListBox::UserDraw( const UserDrawEvent& )
1381 : {
1382 0 : }
1383 :
1384 1 : void ListBox::DrawEntry(const UserDrawEvent& rEvt, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos)
1385 : {
1386 1 : if (rEvt.GetDevice() == mpImplLB->GetMainWindow())
1387 0 : mpImplLB->GetMainWindow()->DrawEntry(*rEvt.GetDevice(), rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
1388 1 : else if (rEvt.GetDevice() == mpImplWin)
1389 1 : mpImplWin->DrawEntry(*rEvt.GetDevice(), bDrawImage, bDrawText, bDrawTextAtImagePos);
1390 1 : }
1391 :
1392 51 : void ListBox::SetUserItemSize( const Size& rSz )
1393 : {
1394 51 : mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
1395 51 : if ( mpImplWin )
1396 51 : mpImplWin->SetUserItemSize( rSz );
1397 51 : }
1398 :
1399 51 : void ListBox::EnableUserDraw( bool bUserDraw )
1400 : {
1401 51 : mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
1402 51 : if ( mpImplWin )
1403 51 : mpImplWin->EnableUserDraw( bUserDraw );
1404 51 : }
1405 :
1406 29 : void ListBox::SetReadOnly( bool bReadOnly )
1407 : {
1408 29 : if ( mpImplLB->IsReadOnly() != bReadOnly )
1409 : {
1410 12 : mpImplLB->SetReadOnly( bReadOnly );
1411 12 : CompatStateChanged( StateChangedType::ReadOnly );
1412 : }
1413 29 : }
1414 :
1415 12 : bool ListBox::IsReadOnly() const
1416 : {
1417 12 : return mpImplLB->IsReadOnly();
1418 : }
1419 :
1420 0 : void ListBox::SetSeparatorPos( sal_Int32 n )
1421 : {
1422 0 : mpImplLB->SetSeparatorPos( n );
1423 0 : }
1424 :
1425 0 : sal_Int32 ListBox::GetSeparatorPos() const
1426 : {
1427 0 : return mpImplLB->GetSeparatorPos();
1428 : }
1429 :
1430 34 : sal_uInt16 ListBox::GetDisplayLineCount() const
1431 : {
1432 34 : return mpImplLB->GetDisplayLineCount();
1433 : }
1434 :
1435 0 : void ListBox::EnableMirroring()
1436 : {
1437 0 : mpImplLB->EnableMirroring();
1438 0 : }
1439 :
1440 0 : Rectangle ListBox::GetDropDownPosSizePixel() const
1441 : {
1442 0 : return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ListBox*>(this) ) : Rectangle();
1443 : }
1444 :
1445 0 : const Wallpaper& ListBox::GetDisplayBackground() const
1446 : {
1447 : // !!! Recursion does not occur because the ImplListBox is initialized by default
1448 : // to a non-transparent color in Window::ImplInitData
1449 0 : return mpImplLB->GetDisplayBackground();
1450 : }
1451 :
1452 0 : void ListBox::setMaxWidthChars(sal_Int32 nWidth)
1453 : {
1454 0 : if (nWidth != m_nMaxWidthChars)
1455 : {
1456 0 : m_nMaxWidthChars = nWidth;
1457 0 : queue_resize();
1458 : }
1459 0 : }
1460 :
1461 993 : bool ListBox::set_property(const OString &rKey, const OString &rValue)
1462 : {
1463 993 : if (rKey == "active")
1464 0 : SelectEntryPos(rValue.toInt32());
1465 993 : else if (rKey == "max-width-chars")
1466 0 : setMaxWidthChars(rValue.toInt32());
1467 : else
1468 993 : return Control::set_property(rKey, rValue);
1469 0 : return true;
1470 : }
1471 :
1472 51 : void ListBox::SetEdgeBlending(bool bNew)
1473 : {
1474 51 : if(mbEdgeBlending != bNew)
1475 : {
1476 51 : mbEdgeBlending = bNew;
1477 :
1478 51 : if(IsDropDownBox())
1479 : {
1480 : assert(mpImplWin);
1481 51 : mpImplWin->Invalidate();
1482 : }
1483 : else
1484 : {
1485 0 : mpImplLB->Invalidate();
1486 : }
1487 :
1488 51 : if(mpImplWin)
1489 : {
1490 51 : mpImplWin->SetEdgeBlending(GetEdgeBlending());
1491 : }
1492 :
1493 51 : if(mpImplLB)
1494 : {
1495 51 : mpImplLB->SetEdgeBlending(GetEdgeBlending());
1496 : }
1497 :
1498 51 : Invalidate();
1499 : }
1500 51 : }
1501 :
1502 0 : MultiListBox::MultiListBox( vcl::Window* pParent, WinBits nStyle ) :
1503 0 : ListBox( WINDOW_MULTILISTBOX )
1504 : {
1505 0 : ImplInit( pParent, nStyle );
1506 0 : EnableMultiSelection( true );
1507 801 : }
1508 :
1509 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|