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