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