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