xref: /AOO41X/main/svtools/source/control/headbar.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #define _SV_HEADBAR_CXX
28 #include <svtools/headbar.hxx>
29 #include <tools/debug.hxx>
30 #ifndef _TOOLS_LIST_HXX
31 #include <tools/list.hxx>
32 #endif
33 
34 #ifndef _VCL_APP_HXX
35 #include <vcl/svapp.hxx>
36 #endif
37 #ifndef _VCL_HELP_HXX
38 #include <vcl/help.hxx>
39 #endif
40 #ifndef _VCL_IMAGE_HXX
41 #include <vcl/image.hxx>
42 #endif
43 #include <com/sun/star/accessibility/XAccessible.hpp>
44 
45 // =======================================================================
46 
47 struct ImplHeadItem
48 {
49     sal_uInt16              mnId;
50     HeaderBarItemBits   mnBits;
51     long                mnSize;
52     rtl::OString        maHelpId;
53     Image               maImage;
54     XubString           maOutText;
55     XubString           maText;
56     XubString           maHelpText;
57     void*               mpUserData;
58 };
59 
60 DECLARE_LIST( ImplHeadItemList, ImplHeadItem* )
61 
62 // =======================================================================
63 
64 #define HEAD_ARROWSIZE1             4
65 #define HEAD_ARROWSIZE2             7
66 
67 #define HEADERBAR_TEXTOFF           2
68 #define HEADERBAR_ARROWOFF          5
69 #define HEADERBAR_SPLITOFF          3
70 
71 #define HEADERBAR_DRAGOFF           4
72 #define HEADERBAR_DRAGOUTOFF        15
73 
74 #define HEAD_HITTEST_ITEM           ((sal_uInt16)0x0001)
75 #define HEAD_HITTEST_DIVIDER        ((sal_uInt16)0x0002)
76 
77 // =======================================================================
78 
79 void HeaderBar::ImplInit( WinBits nWinStyle )
80 {
81     mpItemList      = new ImplHeadItemList;
82     mnBorderOff1    = 0;
83     mnBorderOff2    = 0;
84     mnOffset        = 0;
85     mnDX            = 0;
86     mnDY            = 0;
87     mnDragSize      = 0;
88     mnStartPos      = 0;
89     mnDragPos       = 0;
90     mnMouseOff      = 0;
91     mnCurItemId     = 0;
92     mnItemDragPos   = HEADERBAR_ITEM_NOTFOUND;
93     mbDrag          = sal_False;
94     mbItemDrag      = sal_False;
95     mbOutDrag       = sal_False;
96     mbItemMode      = sal_False;
97 
98     // StyleBits auswerten
99     if ( nWinStyle & WB_DRAG )
100         mbDragable = sal_True;
101     else
102         mbDragable = sal_False;
103     if ( nWinStyle & WB_BUTTONSTYLE )
104         mbButtonStyle = sal_True;
105     else
106         mbButtonStyle = sal_False;
107     if ( nWinStyle & WB_BORDER )
108     {
109         mnBorderOff1 = 1;
110         mnBorderOff2 = 1;
111     }
112     else
113     {
114         if ( nWinStyle & WB_BOTTOMBORDER )
115             mnBorderOff2 = 1;
116     }
117 
118     ImplInitSettings( sal_True, sal_True, sal_True );
119 }
120 
121 // -----------------------------------------------------------------------
122 
123 HeaderBar::HeaderBar( Window* pParent, WinBits nWinStyle ) :
124     Window( pParent, nWinStyle & WB_3DLOOK )
125 {
126     ImplInit( nWinStyle );
127     SetSizePixel( CalcWindowSizePixel() );
128 }
129 
130 // -----------------------------------------------------------------------
131 
132 HeaderBar::HeaderBar( Window* pParent, const ResId& rResId ) :
133     Window( pParent, rResId )
134 {
135     ImplInit( rResId.GetWinBits() );
136 }
137 
138 // -----------------------------------------------------------------------
139 
140 HeaderBar::~HeaderBar()
141 {
142     // Alle Items loeschen
143     ImplHeadItem* pItem = mpItemList->First();
144     while ( pItem )
145     {
146         delete pItem;
147         pItem = mpItemList->Next();
148     }
149 
150     delete mpItemList;
151 }
152 
153 // -----------------------------------------------------------------------
154 
155 void HeaderBar::ImplInitSettings( sal_Bool bFont,
156                                   sal_Bool bForeground, sal_Bool bBackground )
157 {
158     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
159 
160     if ( bFont )
161     {
162         Font aFont;
163         aFont = rStyleSettings.GetToolFont();
164         if ( IsControlFont() )
165             aFont.Merge( GetControlFont() );
166         SetZoomedPointFont( aFont );
167     }
168 
169     if ( bForeground || bFont )
170     {
171         Color aColor;
172         if ( IsControlForeground() )
173             aColor = GetControlForeground();
174         else
175             aColor = rStyleSettings.GetButtonTextColor();
176         SetTextColor( aColor );
177         SetTextFillColor();
178     }
179 
180     if ( bBackground )
181     {
182         Color aColor;
183         if ( IsControlBackground() )
184             aColor = GetControlBackground();
185         else
186             aColor = rStyleSettings.GetFaceColor();
187         SetBackground( aColor );
188     }
189 }
190 
191 // -----------------------------------------------------------------------
192 
193 long HeaderBar::ImplGetItemPos( sal_uInt16 nPos ) const
194 {
195     long nX = -mnOffset;
196     for ( sal_uInt16 i = 0; i < nPos; i++ )
197         nX += mpItemList->GetObject( i )->mnSize;
198     return nX;
199 }
200 
201 // -----------------------------------------------------------------------
202 
203 Rectangle HeaderBar::ImplGetItemRect( sal_uInt16 nPos ) const
204 {
205     Rectangle aRect( ImplGetItemPos( nPos ), 0, 0, mnDY-1 );
206     aRect.Right() = aRect.Left() + mpItemList->GetObject( nPos )->mnSize - 1;
207     // Gegen Ueberlauf auf einigen Systemen testen
208     if ( aRect.Right() > 16000 )
209         aRect.Right() = 16000;
210     return aRect;
211 }
212 
213 // -----------------------------------------------------------------------
214 
215 sal_uInt16 HeaderBar::ImplHitTest( const Point& rPos,
216                                long& nMouseOff, sal_uInt16& nPos ) const
217 {
218     ImplHeadItem*   pItem;
219     sal_uInt16          nCount = (sal_uInt16)mpItemList->Count();
220     sal_Bool            bLastFixed = sal_True;
221     long            nX = -mnOffset;
222 
223     for ( sal_uInt16 i = 0; i < nCount; i++ )
224     {
225         pItem = mpItemList->GetObject( i );
226 
227         if ( rPos.X() < (nX+pItem->mnSize) )
228         {
229             sal_uInt16 nMode;
230 
231             if ( !bLastFixed && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
232             {
233                 nMode = HEAD_HITTEST_DIVIDER;
234                 nPos = i-1;
235                 nMouseOff = rPos.X()-nX+1;
236             }
237             else
238             {
239                 nPos = i;
240 
241                 if ( !(pItem->mnBits & HIB_FIXED) && (rPos.X() >= (nX+pItem->mnSize-HEADERBAR_SPLITOFF)) )
242                 {
243                     nMode = HEAD_HITTEST_DIVIDER;
244                     nMouseOff = rPos.X()-(nX+pItem->mnSize);
245                 }
246                 else
247                 {
248                     nMode = HEAD_HITTEST_ITEM;
249                     nMouseOff = rPos.X()-nX;
250                 }
251             }
252 
253             return nMode;
254         }
255 
256         if ( pItem->mnBits & HIB_FIXED )
257             bLastFixed = sal_True;
258         else
259             bLastFixed = sal_False;
260 
261         nX += pItem->mnSize;
262     }
263 
264     if ( !bLastFixed )
265     {
266         pItem = mpItemList->GetObject( nCount-1 );
267         if ( (pItem->mnSize < 4)  && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
268         {
269             nPos = nCount-1;
270             nMouseOff = rPos.X()-nX+1;
271             return HEAD_HITTEST_DIVIDER;
272         }
273     }
274 
275     return 0;
276 }
277 
278 // -----------------------------------------------------------------------
279 
280 void HeaderBar::ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos )
281 {
282     Rectangle aRect1 = ImplGetItemRect( nStartPos );
283     Rectangle aRect2 = ImplGetItemRect( nEndPos );
284     Point     aStartPos = aRect1.Center();
285     Point     aEndPos = aStartPos;
286     Rectangle aStartRect( aStartPos.X()-2, aStartPos.Y()-2,
287                           aStartPos.X()+2, aStartPos.Y()+2 );
288 
289     if ( nEndPos > nStartPos )
290     {
291         aStartPos.X() += 3;
292         aEndPos.X() = aRect2.Right()-6;
293     }
294     else
295     {
296         aStartPos.X() -= 3;
297         aEndPos.X() = aRect2.Left()+6;
298     }
299 
300     SetRasterOp( ROP_INVERT );
301     DrawRect( aStartRect );
302     DrawLine( aStartPos, aEndPos );
303     if ( nEndPos > nStartPos )
304     {
305         DrawLine( Point( aEndPos.X()+1, aEndPos.Y()-3 ),
306                   Point( aEndPos.X()+1, aEndPos.Y()+3 ) );
307         DrawLine( Point( aEndPos.X()+2, aEndPos.Y()-2 ),
308                   Point( aEndPos.X()+2, aEndPos.Y()+2 ) );
309         DrawLine( Point( aEndPos.X()+3, aEndPos.Y()-1 ),
310                   Point( aEndPos.X()+3, aEndPos.Y()+1 ) );
311         DrawPixel( Point( aEndPos.X()+4, aEndPos.Y() ) );
312     }
313     else
314     {
315         DrawLine( Point( aEndPos.X()-1, aEndPos.Y()-3 ),
316                   Point( aEndPos.X()-1, aEndPos.Y()+3 ) );
317         DrawLine( Point( aEndPos.X()-2, aEndPos.Y()-2 ),
318                   Point( aEndPos.X()-2, aEndPos.Y()+2 ) );
319         DrawLine( Point( aEndPos.X()-3, aEndPos.Y()-1 ),
320                   Point( aEndPos.X()-3, aEndPos.Y()+1 ) );
321         DrawPixel( Point( aEndPos.X()-4, aEndPos.Y() ) );
322     }
323     SetRasterOp( ROP_OVERPAINT );
324 }
325 
326 // -----------------------------------------------------------------------
327 
328 void HeaderBar::ImplDrawItem( OutputDevice* pDev,
329                               sal_uInt16 nPos, sal_Bool bHigh, sal_Bool bDrag,
330                               const Rectangle& rItemRect,
331                               const Rectangle* pRect,
332                               sal_uLong )
333 {
334     Rectangle aRect = rItemRect;
335 
336     // Wenn kein Platz, dann brauchen wir auch nichts ausgeben
337     if ( aRect.GetWidth() <= 1 )
338         return;
339 
340     // Feststellen, ob Rectangle ueberhaupt sichtbar
341     if ( pRect )
342     {
343         if ( aRect.Right() < pRect->Left() )
344             return;
345         else if ( aRect.Left() > pRect->Right() )
346             return;
347     }
348     else
349     {
350         if ( aRect.Right() < 0 )
351             return;
352         else if ( aRect.Left() > mnDX )
353             return;
354     }
355 
356     ImplHeadItem*           pItem  = mpItemList->GetObject( nPos );
357     HeaderBarItemBits       nBits = pItem->mnBits;
358     const StyleSettings&    rStyleSettings = GetSettings().GetStyleSettings();
359 
360     // Border muss nicht gemalt werden
361     aRect.Top()     += mnBorderOff1;
362     aRect.Bottom()  -= mnBorderOff2;
363 
364     // Hintergrund loeschen
365     if ( !pRect || bDrag )
366     {
367         if ( bDrag )
368         {
369             pDev->SetLineColor();
370             pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
371             pDev->DrawRect( aRect );
372         }
373         else
374             pDev->DrawWallpaper( aRect, GetBackground() );
375     }
376 
377     // Trennlinie malen
378     pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
379     pDev->DrawLine( Point( aRect.Right(), aRect.Top() ),
380                     Point( aRect.Right(), aRect.Bottom() ) );
381 
382     // ButtonStyle malen
383     // avoid 3D borders
384     Color aSelectionTextColor( COL_TRANSPARENT );
385     if( bHigh )
386         DrawSelectionBackground( aRect, 1, sal_True, sal_False, sal_False, &aSelectionTextColor );
387     else if ( !mbButtonStyle || (nBits & HIB_FLAT) )
388         DrawSelectionBackground( aRect, 0, sal_True, sal_False, sal_False, &aSelectionTextColor );
389 
390     // Wenn kein Platz, dann brauchen wir auch nichts ausgeben
391     if ( aRect.GetWidth() < 1 )
392         return;
393 
394     // Positionen und Groessen berechnen und Inhalt ausgeben
395     pItem->maOutText = pItem->maText;
396     Size aImageSize = pItem->maImage.GetSizePixel();
397     Size aTxtSize( pDev->GetTextWidth( pItem->maOutText ), 0  );
398     if ( pItem->maOutText.Len() )
399         aTxtSize.Height() = pDev->GetTextHeight();
400     long nArrowWidth = 0;
401     if ( nBits & (HIB_UPARROW | HIB_DOWNARROW) )
402         nArrowWidth = HEAD_ARROWSIZE2+HEADERBAR_ARROWOFF;
403 
404     // Wenn kein Platz fuer Image, dann nicht ausgeben
405     long nTestHeight = aImageSize.Height();
406     if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
407         nTestHeight += aTxtSize.Height();
408     if ( (aImageSize.Width() > aRect.GetWidth()) || (nTestHeight > aRect.GetHeight()) )
409     {
410         aImageSize.Width() = 0;
411         aImageSize.Height() = 0;
412     }
413 
414     // Text auf entsprechende Laenge kuerzen
415     sal_Bool bLeftText = sal_False;
416     long nMaxTxtWidth = aRect.GetWidth()-(HEADERBAR_TEXTOFF*2)-nArrowWidth;
417     if ( nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE) )
418         nMaxTxtWidth -= aImageSize.Width();
419     long nTxtWidth = aTxtSize.Width();
420     if ( nTxtWidth > nMaxTxtWidth )
421     {
422         bLeftText = sal_True;
423         // 3 == Len of "..."
424         pItem->maOutText.AppendAscii( "..." );
425         do
426         {
427             pItem->maOutText.Erase( pItem->maOutText.Len()-3-1, 1 );
428             nTxtWidth = pDev->GetTextWidth( pItem->maOutText );
429         }
430         while ( (nTxtWidth > nMaxTxtWidth) && (pItem->maOutText.Len() > 3) );
431         if ( pItem->maOutText.Len() == 3 )
432         {
433             nTxtWidth = 0;
434             pItem->maOutText.Erase();
435         }
436     }
437 
438     // Text/Imageposition berechnen
439     long nTxtPos;
440     if ( !bLeftText && (nBits & HIB_RIGHT) )
441     {
442         nTxtPos = aRect.Right()-nTxtWidth-HEADERBAR_TEXTOFF;
443         if ( nBits & HIB_RIGHTIMAGE )
444             nTxtPos -= aImageSize.Width();
445     }
446     else if ( !bLeftText && (nBits & HIB_CENTER) )
447     {
448         long nTempWidth = nTxtWidth;
449         if ( nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE) )
450             nTempWidth += aImageSize.Width();
451         nTxtPos = aRect.Left()+(aRect.GetWidth()-nTempWidth)/2;
452         if ( nBits & HIB_LEFTIMAGE )
453             nTxtPos += aImageSize.Width();
454         if ( nArrowWidth )
455         {
456             if ( nTxtPos+nTxtWidth+nArrowWidth >= aRect.Right() )
457             {
458                 nTxtPos = aRect.Left()+HEADERBAR_TEXTOFF;
459                 if ( nBits & HIB_LEFTIMAGE )
460                     nTxtPos += aImageSize.Width();
461             }
462         }
463     }
464     else
465     {
466         nTxtPos = aRect.Left()+HEADERBAR_TEXTOFF;
467         if ( nBits & HIB_LEFTIMAGE )
468             nTxtPos += aImageSize.Width();
469         if ( nBits & HIB_RIGHT )
470             nTxtPos += nArrowWidth;
471     }
472 
473     // TextPosition berechnen
474     long nTxtPosY = 0;
475     if ( pItem->maOutText.Len() || (nArrowWidth && aTxtSize.Height()) )
476     {
477         if ( nBits & HIB_TOP )
478         {
479             nTxtPosY = aRect.Top();
480             if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
481                 nTxtPosY += aImageSize.Height();
482         }
483         else if ( nBits & HIB_BOTTOM )
484             nTxtPosY = aRect.Bottom()-aTxtSize.Height();
485         else
486         {
487             long nTempHeight = aTxtSize.Height();
488             if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
489                 nTempHeight += aImageSize.Height();
490             nTxtPosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
491             if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
492                 nTxtPosY += aImageSize.Height();
493         }
494     }
495 
496     // Text ausgebeben
497     if ( pItem->maOutText.Len() )
498     {
499         if( aSelectionTextColor != Color( COL_TRANSPARENT ) )
500         {
501             pDev->Push( PUSH_TEXTCOLOR );
502             pDev->SetTextColor( aSelectionTextColor );
503         }
504         if ( IsEnabled() )
505             pDev->DrawText( Point( nTxtPos, nTxtPosY ), pItem->maOutText );
506         else
507             pDev->DrawCtrlText( Point( nTxtPos, nTxtPosY ), pItem->maOutText, 0, STRING_LEN, TEXT_DRAW_DISABLE );
508         if( aSelectionTextColor != Color( COL_TRANSPARENT ) )
509             pDev->Pop();
510     }
511 
512     // Wenn Image vorhanden, Position berechnen und ausgeben
513     long nImagePosY = 0;
514     if ( aImageSize.Width() && aImageSize.Height() )
515     {
516         long nImagePos = nTxtPos;
517         if ( nBits & HIB_LEFTIMAGE )
518         {
519             nImagePos -= aImageSize.Width();
520             if ( nBits & HIB_RIGHT )
521                 nImagePos -= nArrowWidth;
522         }
523         else if ( nBits & HIB_RIGHTIMAGE )
524         {
525             nImagePos += nTxtWidth;
526             if ( !(nBits & HIB_RIGHT) )
527                 nImagePos += nArrowWidth;
528         }
529         else
530         {
531             if ( nBits & HIB_RIGHT )
532                 nImagePos = aRect.Right()-aImageSize.Width();
533             else if ( nBits & HIB_CENTER )
534                 nImagePos = aRect.Left()+(aRect.GetWidth()-aImageSize.Width())/2;
535             else
536                 nImagePos = aRect.Left()+HEADERBAR_TEXTOFF;
537         }
538 
539         if ( nBits & HIB_TOP )
540             nImagePosY = aRect.Top();
541         else if ( nBits & HIB_BOTTOM )
542         {
543             nImagePosY = aRect.Bottom()-aImageSize.Height();
544             if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
545                 nImagePosY -= aTxtSize.Height();
546         }
547         else
548         {
549             long nTempHeight = aImageSize.Height();
550             if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
551                 nTempHeight += aTxtSize.Height();
552             nImagePosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
553         }
554         if ( nImagePos+aImageSize.Width() <= aRect.Right() )
555         {
556             sal_uInt16 nStyle = 0;
557             if ( !IsEnabled() )
558                 nStyle |= IMAGE_DRAW_DISABLE;
559             pDev->DrawImage( Point( nImagePos, nImagePosY ), pItem->maImage, nStyle );
560         }
561     }
562 
563     if ( nBits & (HIB_UPARROW | HIB_DOWNARROW) )
564     {
565         long nArrowX = nTxtPos;
566         if ( nBits & HIB_RIGHT )
567             nArrowX -= nArrowWidth;
568         else
569             nArrowX += nTxtWidth+HEADERBAR_ARROWOFF;
570         if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) && !pItem->maText.Len() )
571         {
572             if ( nBits & HIB_RIGHT )
573                 nArrowX -= aImageSize.Width();
574             else
575                 nArrowX += aImageSize.Width();
576         }
577 
578         // Feststellen, ob Platz genug ist, das Item zu malen
579         sal_Bool bDraw = sal_True;
580         if ( nArrowX < aRect.Left()+HEADERBAR_TEXTOFF )
581             bDraw = sal_False;
582         else if ( nArrowX+HEAD_ARROWSIZE2 > aRect.Right() )
583             bDraw = sal_False;
584 
585         if ( bDraw )
586         {
587             long nArrowY;
588             if ( aTxtSize.Height() )
589                 nArrowY = nTxtPosY+(aTxtSize.Height()/2);
590             else if ( aImageSize.Width() && aImageSize.Height() )
591                 nArrowY = nImagePosY+(aImageSize.Height()/2);
592             else
593             {
594                 if ( nBits & HIB_TOP )
595                     nArrowY = aRect.Top()+1;
596                 else if ( nBits & HIB_BOTTOM )
597                     nArrowY = aRect.Bottom()-HEAD_ARROWSIZE2-1;
598                 else
599                     nArrowY = aRect.Top()+((aRect.GetHeight()-HEAD_ARROWSIZE2)/2);;
600             }
601             nArrowY -= HEAD_ARROWSIZE1-1;
602             if ( nBits & HIB_DOWNARROW )
603             {
604                 pDev->SetLineColor( rStyleSettings.GetLightColor() );
605                 pDev->DrawLine( Point( nArrowX, nArrowY ),
606                                 Point( nArrowX+HEAD_ARROWSIZE2, nArrowY ) );
607                 pDev->DrawLine( Point( nArrowX, nArrowY ),
608                                 Point( nArrowX+HEAD_ARROWSIZE1, nArrowY+HEAD_ARROWSIZE2 ) );
609                 pDev->SetLineColor( rStyleSettings.GetShadowColor() );
610                 pDev->DrawLine( Point( nArrowX+HEAD_ARROWSIZE1, nArrowY+HEAD_ARROWSIZE2 ),
611                                 Point( nArrowX+HEAD_ARROWSIZE2, nArrowY ) );
612             }
613             else
614             {
615                 pDev->SetLineColor( rStyleSettings.GetLightColor() );
616                 pDev->DrawLine( Point( nArrowX, nArrowY+HEAD_ARROWSIZE2 ),
617                                 Point( nArrowX+HEAD_ARROWSIZE1, nArrowY ) );
618                 pDev->SetLineColor( rStyleSettings.GetShadowColor() );
619                 pDev->DrawLine( Point( nArrowX, nArrowY+HEAD_ARROWSIZE2 ),
620                                 Point( nArrowX+HEAD_ARROWSIZE2, nArrowY+HEAD_ARROWSIZE2 ) );
621                 pDev->DrawLine( Point( nArrowX+HEAD_ARROWSIZE2, nArrowY+HEAD_ARROWSIZE2 ),
622                                 Point( nArrowX+HEAD_ARROWSIZE1, nArrowY ) );
623             }
624         }
625     }
626 
627     // Gegebenenfalls auch UserDraw aufrufen
628     if ( nBits & HIB_USERDRAW )
629     {
630         Region aRegion( aRect );
631         if ( pRect )
632             aRegion.Intersect( *pRect );
633         pDev->SetClipRegion( aRegion );
634         UserDrawEvent aODEvt( pDev, aRect, pItem->mnId );
635         UserDraw( aODEvt );
636         pDev->SetClipRegion();
637     }
638 }
639 
640 // -----------------------------------------------------------------------
641 
642 void HeaderBar::ImplDrawItem( sal_uInt16 nPos, sal_Bool bHigh, sal_Bool bDrag,
643                               const Rectangle* pRect )
644 {
645     Rectangle aRect = ImplGetItemRect( nPos );
646     ImplDrawItem( this, nPos, bHigh, bDrag, aRect, pRect, 0 );
647 }
648 
649 // -----------------------------------------------------------------------
650 
651 void HeaderBar::ImplUpdate( sal_uInt16 nPos, sal_Bool bEnd, sal_Bool bDirect )
652 {
653     if ( IsVisible() && IsUpdateMode() )
654     {
655         if ( !bDirect )
656         {
657             Rectangle   aRect;
658             sal_uInt16      nItemCount = (sal_uInt16)(mpItemList->Count());
659             if ( nPos < nItemCount )
660                 aRect = ImplGetItemRect( nPos );
661             else
662             {
663                 aRect.Bottom() = mnDY-1;
664                 if ( nItemCount )
665                     aRect.Left() = ImplGetItemRect( nItemCount-1 ).Right();
666             }
667             if ( bEnd )
668                 aRect.Right() = mnDX-1;
669             aRect.Top()     += mnBorderOff1;
670             aRect.Bottom()  -= mnBorderOff2;
671             Invalidate( aRect );
672         }
673         else
674         {
675             for ( sal_uInt16 i = nPos; i < mpItemList->Count(); i++ )
676                 ImplDrawItem( i );
677             if ( bEnd )
678             {
679                 Rectangle aRect = ImplGetItemRect( (sal_uInt16)mpItemList->Count() );
680                 aRect.Left()  = aRect.Right();
681                 aRect.Right() = mnDX-1;
682                 if ( aRect.Left() < aRect.Right() )
683                 {
684                     aRect.Top()     += mnBorderOff1;
685                     aRect.Bottom()  -= mnBorderOff2;
686                     Erase( aRect );
687                 }
688             }
689         }
690     }
691 }
692 
693 // -----------------------------------------------------------------------
694 
695 void HeaderBar::ImplStartDrag( const Point& rMousePos, sal_Bool bCommand )
696 {
697     sal_uInt16  nPos;
698     sal_uInt16  nHitTest = ImplHitTest( rMousePos, mnMouseOff, nPos );
699     if ( nHitTest )
700     {
701         mbDrag = sal_False;
702         ImplHeadItem* pItem = mpItemList->GetObject( nPos );
703         if ( nHitTest & HEAD_HITTEST_DIVIDER )
704             mbDrag = sal_True;
705         else
706         {
707             if ( ((pItem->mnBits & HIB_CLICKABLE) && !(pItem->mnBits & HIB_FLAT)) ||
708                  (mbDragable && !(pItem->mnBits & HIB_FIXEDPOS)) )
709             {
710                 mbItemMode = sal_True;
711                 mbDrag = sal_True;
712                 if ( bCommand )
713                 {
714                     if ( mbDragable )
715                         mbItemDrag = sal_True;
716                     else
717                     {
718                         mbItemMode = sal_False;
719                         mbDrag = sal_False;
720                     }
721                 }
722             }
723             else
724             {
725                 if ( !bCommand )
726                 {
727                     mnCurItemId = pItem->mnId;
728                     Select();
729                     mnCurItemId = 0;
730                 }
731             }
732         }
733 
734         if ( mbDrag )
735         {
736             mbOutDrag = sal_False;
737             mnCurItemId = pItem->mnId;
738             mnItemDragPos = nPos;
739             StartTracking();
740             mnStartPos = rMousePos.X()-mnMouseOff;
741             mnDragPos = mnStartPos;
742             StartDrag();
743             if ( mbItemMode )
744                 ImplDrawItem( nPos, sal_True, mbItemDrag );
745             else
746             {
747                 Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
748                 ShowTracking( aSizeRect, SHOWTRACK_SPLIT );
749             }
750         }
751         else
752             mnMouseOff = 0;
753     }
754 }
755 
756 // -----------------------------------------------------------------------
757 
758 void HeaderBar::ImplDrag( const Point& rMousePos )
759 {
760     sal_Bool    bNewOutDrag;
761     sal_uInt16  nPos = GetItemPos( mnCurItemId );
762 
763     mnDragPos = rMousePos.X()-mnMouseOff;
764     if ( mbItemMode )
765     {
766         Rectangle aItemRect = ImplGetItemRect( nPos );
767         if ( aItemRect.IsInside( rMousePos ) )
768             bNewOutDrag = sal_False;
769         else
770             bNewOutDrag = sal_True;
771 
772         // Evt. ItemDrag anschalten
773         if ( bNewOutDrag && mbDragable && !mbItemDrag &&
774              !(mpItemList->GetObject(nPos)->mnBits & HIB_FIXEDPOS) )
775         {
776             if ( (rMousePos.Y() >= aItemRect.Top()) && (rMousePos.Y() <= aItemRect.Bottom()) )
777             {
778                 mbItemDrag = sal_True;
779                 ImplDrawItem( nPos, sal_True, mbItemDrag );
780             }
781         }
782 
783         sal_uInt16 nOldItemDragPos = mnItemDragPos;
784         if ( mbItemDrag )
785         {
786             if ( (rMousePos.Y() < -HEADERBAR_DRAGOUTOFF) || (rMousePos.Y() > mnDY+HEADERBAR_DRAGOUTOFF) )
787                 bNewOutDrag = sal_True;
788             else
789                 bNewOutDrag = sal_False;
790 
791             if ( bNewOutDrag )
792                 mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
793             else
794             {
795                 sal_uInt16 nTempId = GetItemId( Point( rMousePos.X(), 2 ) );
796                 if ( nTempId )
797                     mnItemDragPos = GetItemPos( nTempId );
798                 else
799                 {
800                     if ( rMousePos.X() <= 0 )
801                         mnItemDragPos = 0;
802                     else
803                         mnItemDragPos = GetItemCount()-1;
804                 }
805 
806                 // Nicht verschiebbare Items aussparen
807                 if ( mnItemDragPos < nPos )
808                 {
809                     while ( (mpItemList->GetObject(mnItemDragPos)->mnBits & HIB_FIXEDPOS) &&
810                             (mnItemDragPos < nPos) )
811                         mnItemDragPos++;
812                 }
813                 else if ( mnItemDragPos > nPos )
814                 {
815                     while ( (mpItemList->GetObject(mnItemDragPos)->mnBits & HIB_FIXEDPOS) &&
816                             (mnItemDragPos > nPos) )
817                         mnItemDragPos--;
818                 }
819             }
820 
821             if ( (mnItemDragPos != nOldItemDragPos) &&
822                  (nOldItemDragPos != nPos) &&
823                  (nOldItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
824             {
825                 ImplInvertDrag( nPos, nOldItemDragPos );
826                 ImplDrawItem( nOldItemDragPos );
827             }
828         }
829 
830         if ( bNewOutDrag != mbOutDrag )
831             ImplDrawItem( nPos, !bNewOutDrag, mbItemDrag );
832 
833         if ( mbItemDrag  )
834         {
835             if ( (mnItemDragPos != nOldItemDragPos) &&
836                  (mnItemDragPos != nPos) &&
837                  (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
838             {
839                 ImplDrawItem( mnItemDragPos, sal_False, sal_True );
840                 ImplInvertDrag( nPos, mnItemDragPos );
841             }
842         }
843 
844         mbOutDrag = bNewOutDrag;
845     }
846     else
847     {
848         Rectangle aItemRect = ImplGetItemRect( nPos );
849         if ( mnDragPos < aItemRect.Left() )
850             mnDragPos = aItemRect.Left();
851         if ( (mnDragPos < 0) || (mnDragPos > mnDX-1) )
852             HideTracking();
853         else
854         {
855             Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
856             ShowTracking( aSizeRect, SHOWTRACK_SPLIT );
857         }
858     }
859 
860     Drag();
861 }
862 
863 // -----------------------------------------------------------------------
864 
865 void HeaderBar::ImplEndDrag( sal_Bool bCancel )
866 {
867     HideTracking();
868 
869     if ( bCancel || mbOutDrag )
870     {
871         if ( mbItemMode && (!mbOutDrag || mbItemDrag) )
872         {
873             sal_uInt16 nPos = GetItemPos( mnCurItemId );
874             ImplDrawItem( nPos );
875         }
876 
877         mnCurItemId = 0;
878     }
879     else
880     {
881         sal_uInt16 nPos = GetItemPos( mnCurItemId );
882         if ( mbItemMode )
883         {
884             if ( mbItemDrag )
885             {
886                 Pointer aPointer( POINTER_ARROW );
887                 SetPointer( aPointer );
888                 if ( (mnItemDragPos != nPos) &&
889                      (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
890                 {
891                     ImplInvertDrag( nPos, mnItemDragPos );
892                     MoveItem( mnCurItemId, mnItemDragPos );
893                 }
894                 else
895                     ImplDrawItem( nPos );
896             }
897             else
898             {
899                 Select();
900                 ImplUpdate( nPos );
901             }
902         }
903         else
904         {
905             long nDelta = mnDragPos - mnStartPos;
906             if ( nDelta )
907             {
908                 ImplHeadItem* pItem = mpItemList->GetObject( nPos );
909                 pItem->mnSize += nDelta;
910                 ImplUpdate( nPos, sal_True );
911             }
912         }
913     }
914 
915     mbDrag          = sal_False;
916     EndDrag();
917     mnCurItemId     = 0;
918     mnItemDragPos   = HEADERBAR_ITEM_NOTFOUND;
919     mbOutDrag       = sal_False;
920     mbItemMode      = sal_False;
921     mbItemDrag      = sal_False;
922 }
923 
924 // -----------------------------------------------------------------------
925 
926 void HeaderBar::MouseButtonDown( const MouseEvent& rMEvt )
927 {
928     if ( rMEvt.IsLeft() )
929     {
930         if ( rMEvt.GetClicks() == 2 )
931         {
932             long    nTemp;
933             sal_uInt16  nPos;
934             sal_uInt16  nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp, nPos );
935             if ( nHitTest )
936             {
937                 ImplHeadItem* pItem = mpItemList->GetObject( nPos );
938                 if ( nHitTest & HEAD_HITTEST_DIVIDER )
939                     mbItemMode = sal_False;
940                 else
941                     mbItemMode = sal_True;
942                 mnCurItemId = pItem->mnId;
943                 DoubleClick();
944                 mbItemMode = sal_False;
945                 mnCurItemId = 0;
946             }
947         }
948         else
949             ImplStartDrag( rMEvt.GetPosPixel(), sal_False );
950     }
951 }
952 
953 // -----------------------------------------------------------------------
954 
955 void HeaderBar::MouseMove( const MouseEvent& rMEvt )
956 {
957     long            nTemp1;
958     sal_uInt16          nTemp2;
959     PointerStyle    eStyle = POINTER_ARROW;
960     sal_uInt16          nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp1, nTemp2 );
961 
962     if ( nHitTest & HEAD_HITTEST_DIVIDER )
963         eStyle = POINTER_HSIZEBAR;
964     Pointer aPtr( eStyle );
965     SetPointer( aPtr );
966 }
967 
968 // -----------------------------------------------------------------------
969 
970 void HeaderBar::Tracking( const TrackingEvent& rTEvt )
971 {
972     Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
973 
974     if ( rTEvt.IsTrackingEnded() )
975         ImplEndDrag( rTEvt.IsTrackingCanceled() );
976     else
977         ImplDrag( aMousePos );
978 }
979 
980 // -----------------------------------------------------------------------
981 
982 void HeaderBar::Paint( const Rectangle& rRect )
983 {
984     if ( mnBorderOff1 || mnBorderOff2 )
985     {
986         SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
987         if ( mnBorderOff1 )
988             DrawLine( Point( 0, 0 ), Point( mnDX-1, 0 ) );
989         if ( mnBorderOff2 )
990             DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) );
991         // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
992         if ( mnBorderOff1 && mnBorderOff2 )
993         {
994             DrawLine( Point( 0, 0 ), Point( 0, mnDY-1 ) );
995             DrawLine( Point( mnDX-1, 0 ), Point( mnDX-1, mnDY-1 ) );
996         }
997     }
998 
999     sal_uInt16 nCurItemPos;
1000     if ( mbDrag )
1001         nCurItemPos = GetItemPos( mnCurItemId );
1002     else
1003         nCurItemPos = HEADERBAR_ITEM_NOTFOUND;
1004     sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
1005     for ( sal_uInt16 i = 0; i < nItemCount; i++ )
1006         ImplDrawItem( i, (i == nCurItemPos) ? sal_True : sal_False, sal_False, &rRect );
1007 }
1008 
1009 // -----------------------------------------------------------------------
1010 
1011 void HeaderBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
1012                       sal_uLong nFlags )
1013 {
1014     Point       aPos  = pDev->LogicToPixel( rPos );
1015     Size        aSize = pDev->LogicToPixel( rSize );
1016     Rectangle   aRect( aPos, aSize );
1017     Font        aFont = GetDrawPixelFont( pDev );
1018 
1019     pDev->Push();
1020     pDev->SetMapMode();
1021     pDev->SetFont( aFont );
1022     if ( nFlags & WINDOW_DRAW_MONO )
1023         pDev->SetTextColor( Color( COL_BLACK ) );
1024     else
1025         pDev->SetTextColor( GetTextColor() );
1026     pDev->SetTextFillColor();
1027 
1028     if ( !(nFlags & WINDOW_DRAW_NOBACKGROUND) )
1029     {
1030         pDev->DrawWallpaper( aRect, GetBackground() );
1031         if ( mnBorderOff1 || mnBorderOff2 )
1032         {
1033             pDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
1034             if ( mnBorderOff1 )
1035                 pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
1036             if ( mnBorderOff2 )
1037                 pDev->DrawLine( Point( aRect.Left(), aRect.Bottom() ), Point( aRect.Right(), aRect.Bottom() ) );
1038             // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
1039             if ( mnBorderOff1 && mnBorderOff2 )
1040             {
1041                 pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
1042                 pDev->DrawLine( Point( aRect.Right(), aRect.Top() ), Point( aRect.Right(), aRect.Bottom() ) );
1043             }
1044         }
1045     }
1046 
1047     Rectangle aItemRect( aRect );
1048 //    aItemRect.Bottom()--;
1049     sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
1050     for ( sal_uInt16 i = 0; i < nItemCount; i++ )
1051     {
1052         aItemRect.Left() = aRect.Left()+ImplGetItemPos( i );
1053         aItemRect.Right() = aItemRect.Left() + mpItemList->GetObject( i )->mnSize - 1;
1054         // Gegen Ueberlauf auf einigen Systemen testen
1055         if ( aItemRect.Right() > 16000 )
1056             aItemRect.Right() = 16000;
1057         Region aRegion( aRect );
1058         pDev->SetClipRegion( aRegion );
1059         ImplDrawItem( pDev, i, sal_False, sal_False, aItemRect, &aRect, nFlags );
1060         pDev->SetClipRegion();
1061     }
1062 
1063     pDev->Pop();
1064 }
1065 
1066 // -----------------------------------------------------------------------
1067 
1068 void HeaderBar::Resize()
1069 {
1070     Size aSize = GetOutputSizePixel();
1071     if ( IsVisible() && (mnDY != aSize.Height()) )
1072         Invalidate();
1073     mnDX = aSize.Width();
1074     mnDY = aSize.Height();
1075 }
1076 
1077 // -----------------------------------------------------------------------
1078 
1079 void HeaderBar::Command( const CommandEvent& rCEvt )
1080 {
1081     if ( rCEvt.IsMouseEvent() && (rCEvt.GetCommand() == COMMAND_STARTDRAG) && !mbDrag )
1082     {
1083         ImplStartDrag( rCEvt.GetMousePosPixel(), sal_True );
1084         return;
1085     }
1086 
1087     Window::Command( rCEvt );
1088 }
1089 
1090 // -----------------------------------------------------------------------
1091 
1092 void HeaderBar::RequestHelp( const HelpEvent& rHEvt )
1093 {
1094     sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
1095     if ( nItemId )
1096     {
1097         if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1098         {
1099             Rectangle aItemRect = GetItemRect( nItemId );
1100             Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1101             aItemRect.Left()   = aPt.X();
1102             aItemRect.Top()    = aPt.Y();
1103             aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1104             aItemRect.Right()  = aPt.X();
1105             aItemRect.Bottom() = aPt.Y();
1106 
1107             XubString aStr = GetHelpText( nItemId );
1108             if ( !aStr.Len() || !(rHEvt.GetMode() & HELPMODE_BALLOON) )
1109             {
1110                 ImplHeadItem* pItem = mpItemList->GetObject( GetItemPos( nItemId ) );
1111                 // Wir zeigen die Quick-Hilfe nur an, wenn Text nicht
1112                 // vollstaendig sichtbar, ansonsten zeigen wir den Hilfetext
1113                 // an, wenn das Item keinen Text besitzt
1114                 if ( pItem->maOutText != pItem->maText )
1115                     aStr = pItem->maText;
1116                 else if ( pItem->maText.Len() )
1117                     aStr.Erase();
1118             }
1119 
1120             if ( aStr.Len() )
1121             {
1122                 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1123                     Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1124                 else
1125                     Help::ShowQuickHelp( this, aItemRect, aStr );
1126                 return;
1127             }
1128         }
1129         else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
1130         {
1131             rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
1132             if ( aHelpId.getLength() )
1133             {
1134                 // Wenn eine Hilfe existiert, dann ausloesen
1135                 Help* pHelp = Application::GetHelp();
1136                 if ( pHelp )
1137                     pHelp->Start( aHelpId, this );
1138                 return;
1139             }
1140         }
1141     }
1142 
1143     Window::RequestHelp( rHEvt );
1144 }
1145 
1146 // -----------------------------------------------------------------------
1147 
1148 void HeaderBar::StateChanged( StateChangedType nType )
1149 {
1150     Window::StateChanged( nType );
1151 
1152     if ( nType == STATE_CHANGE_ENABLE )
1153         Invalidate();
1154     else if ( (nType == STATE_CHANGE_ZOOM) ||
1155               (nType == STATE_CHANGE_CONTROLFONT) )
1156     {
1157         ImplInitSettings( sal_True, sal_False, sal_False );
1158         Invalidate();
1159     }
1160     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1161     {
1162         ImplInitSettings( sal_False, sal_True, sal_False );
1163         Invalidate();
1164     }
1165     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1166     {
1167         ImplInitSettings( sal_False, sal_False, sal_True );
1168         Invalidate();
1169     }
1170 }
1171 
1172 // -----------------------------------------------------------------------
1173 
1174 void HeaderBar::DataChanged( const DataChangedEvent& rDCEvt )
1175 {
1176     Window::DataChanged( rDCEvt );
1177 
1178     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1179          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1180          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1181           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1182     {
1183         ImplInitSettings( sal_True, sal_True, sal_True );
1184         Invalidate();
1185     }
1186 }
1187 
1188 // -----------------------------------------------------------------------
1189 
1190 void HeaderBar::UserDraw( const UserDrawEvent& )
1191 {
1192 }
1193 
1194 // -----------------------------------------------------------------------
1195 
1196 void HeaderBar::StartDrag()
1197 {
1198     maStartDragHdl.Call( this );
1199 }
1200 
1201 // -----------------------------------------------------------------------
1202 
1203 void HeaderBar::Drag()
1204 {
1205     maDragHdl.Call( this );
1206 }
1207 
1208 // -----------------------------------------------------------------------
1209 
1210 void HeaderBar::EndDrag()
1211 {
1212     maEndDragHdl.Call( this );
1213 }
1214 
1215 // -----------------------------------------------------------------------
1216 
1217 void HeaderBar::Select()
1218 {
1219     maSelectHdl.Call( this );
1220 }
1221 
1222 // -----------------------------------------------------------------------
1223 
1224 void HeaderBar::DoubleClick()
1225 {
1226     maDoubleClickHdl.Call( this );
1227 }
1228 
1229 // -----------------------------------------------------------------------
1230 
1231 void HeaderBar::InsertItem( sal_uInt16 nItemId, const Image& rImage,
1232                             long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
1233 {
1234     DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
1235     DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
1236                 "HeaderBar::InsertItem(): ItemId already exists" );
1237 
1238     // Item anlegen und in die Liste einfuegen
1239     ImplHeadItem* pItem = new ImplHeadItem;
1240     pItem->mnId         = nItemId;
1241     pItem->mnBits       = nBits;
1242     pItem->mnSize       = nSize;
1243     pItem->maImage      = rImage;
1244     pItem->mpUserData   = 0;
1245     mpItemList->Insert( pItem, nPos );
1246 
1247     // Ausgabe updaten
1248     ImplUpdate( nPos, sal_True );
1249 }
1250 
1251 // -----------------------------------------------------------------------
1252 
1253 void HeaderBar::InsertItem( sal_uInt16 nItemId, const XubString& rText,
1254                             long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
1255 {
1256     DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
1257     DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
1258                 "HeaderBar::InsertItem(): ItemId already exists" );
1259 
1260     // Item anlegen und in die Liste einfuegen
1261     ImplHeadItem* pItem = new ImplHeadItem;
1262     pItem->mnId         = nItemId;
1263     pItem->mnBits       = nBits;
1264     pItem->mnSize       = nSize;
1265     pItem->maText       = rText;
1266     pItem->mpUserData   = 0;
1267     mpItemList->Insert( pItem, nPos );
1268 
1269     // Ausgabe updaten
1270     ImplUpdate( nPos, sal_True );
1271 }
1272 
1273 // -----------------------------------------------------------------------
1274 
1275 void HeaderBar::InsertItem( sal_uInt16 nItemId,
1276                             const Image& rImage, const XubString& rText,
1277                             long nSize, HeaderBarItemBits nBits,
1278                             sal_uInt16 nPos )
1279 {
1280     DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
1281     DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
1282                 "HeaderBar::InsertItem(): ItemId already exists" );
1283 
1284     // Item anlegen und in die Liste einfuegen
1285     ImplHeadItem* pItem = new ImplHeadItem;
1286     pItem->mnId         = nItemId;
1287     pItem->mnBits       = nBits;
1288     pItem->mnSize       = nSize;
1289     pItem->maImage      = rImage;
1290     pItem->maText       = rText;
1291     pItem->mpUserData   = 0;
1292     mpItemList->Insert( pItem, nPos );
1293 
1294     // Ausgabe updaten
1295     ImplUpdate( nPos, sal_True );
1296 }
1297 
1298 // -----------------------------------------------------------------------
1299 
1300 void HeaderBar::RemoveItem( sal_uInt16 nItemId )
1301 {
1302     sal_uInt16 nPos = GetItemPos( nItemId );
1303     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1304     {
1305         ImplHeadItem* pItem = mpItemList->Remove( nPos );
1306         delete pItem;
1307         ImplUpdate( nPos, sal_True );
1308     }
1309 }
1310 
1311 // -----------------------------------------------------------------------
1312 
1313 void HeaderBar::MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos )
1314 {
1315     sal_uInt16 nPos = GetItemPos( nItemId );
1316     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1317     {
1318         if ( nPos != nNewPos )
1319         {
1320             ImplHeadItem* pItem = mpItemList->Remove( nPos );
1321             if ( nNewPos < nPos )
1322                 nPos = nNewPos;
1323             mpItemList->Insert( pItem, nNewPos );
1324             ImplUpdate( nPos, sal_True );
1325         }
1326     }
1327 }
1328 
1329 // -----------------------------------------------------------------------
1330 
1331 void HeaderBar::Clear()
1332 {
1333     // Alle Items loeschen
1334     ImplHeadItem* pItem = mpItemList->First();
1335     while ( pItem )
1336     {
1337         delete pItem;
1338         pItem = mpItemList->Next();
1339     }
1340     mpItemList->Clear();
1341 
1342     ImplUpdate( 0, sal_True );
1343 }
1344 
1345 // -----------------------------------------------------------------------
1346 
1347 void HeaderBar::SetOffset( long nNewOffset )
1348 {
1349     // Hier erstmal neu zeichnen, damit mit alten Offset noch das
1350     // richtige gemalt wird
1351     //Update();
1352 
1353     // Bereich verschieben
1354     Rectangle aRect( 0, mnBorderOff1, mnDX-1, mnDY-mnBorderOff1-mnBorderOff2-1 );
1355     long nDelta = mnOffset-nNewOffset;
1356     mnOffset = nNewOffset;
1357     Scroll( nDelta, 0, aRect );
1358 }
1359 
1360 // -----------------------------------------------------------------------
1361 
1362 sal_uInt16 HeaderBar::GetItemCount() const
1363 {
1364     return (sal_uInt16)mpItemList->Count();
1365 }
1366 
1367 // -----------------------------------------------------------------------
1368 
1369 sal_uInt16 HeaderBar::GetItemPos( sal_uInt16 nItemId ) const
1370 {
1371     ImplHeadItem* pItem = mpItemList->First();
1372     while ( pItem )
1373     {
1374         if ( pItem->mnId == nItemId )
1375             return (sal_uInt16)mpItemList->GetCurPos();
1376         pItem = mpItemList->Next();
1377     }
1378 
1379     return HEADERBAR_ITEM_NOTFOUND;
1380 }
1381 
1382 // -----------------------------------------------------------------------
1383 
1384 sal_uInt16 HeaderBar::GetItemId( sal_uInt16 nPos ) const
1385 {
1386     ImplHeadItem* pItem = mpItemList->GetObject( nPos );
1387     if ( pItem )
1388         return pItem->mnId;
1389     else
1390         return 0;
1391 }
1392 
1393 // -----------------------------------------------------------------------
1394 
1395 sal_uInt16 HeaderBar::GetItemId( const Point& rPos ) const
1396 {
1397     sal_uInt16 nPos = 0;
1398     while ( nPos < mpItemList->Count() )
1399     {
1400         if ( ImplGetItemRect( nPos ).IsInside( rPos ) )
1401             return GetItemId( nPos );
1402 
1403         nPos++;
1404     }
1405 
1406     return 0;
1407 }
1408 
1409 // -----------------------------------------------------------------------
1410 
1411 Rectangle HeaderBar::GetItemRect( sal_uInt16 nItemId ) const
1412 {
1413     Rectangle aRect;
1414     sal_uInt16 nPos = GetItemPos( nItemId );
1415     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1416         aRect = ImplGetItemRect( nPos );
1417     return aRect;
1418 }
1419 
1420 // -----------------------------------------------------------------------
1421 
1422 void HeaderBar::SetItemSize( sal_uInt16 nItemId, long nNewSize )
1423 {
1424     sal_uInt16 nPos = GetItemPos( nItemId );
1425     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1426     {
1427         ImplHeadItem* pItem = mpItemList->GetObject( nPos );
1428         if ( pItem->mnSize != nNewSize )
1429         {
1430             pItem->mnSize = nNewSize;
1431             ImplUpdate( nPos, sal_True );
1432         }
1433     }
1434 }
1435 
1436 // -----------------------------------------------------------------------
1437 
1438 long HeaderBar::GetItemSize( sal_uInt16 nItemId ) const
1439 {
1440     sal_uInt16 nPos = GetItemPos( nItemId );
1441     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1442         return mpItemList->GetObject( nPos )->mnSize;
1443     else
1444         return 0;
1445 }
1446 
1447 // -----------------------------------------------------------------------
1448 
1449 void HeaderBar::SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits )
1450 {
1451     sal_uInt16 nPos = GetItemPos( nItemId );
1452     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1453     {
1454         ImplHeadItem* pItem = mpItemList->GetObject( nPos );
1455         if ( pItem->mnBits != nNewBits )
1456         {
1457             pItem->mnBits = nNewBits;
1458             ImplUpdate( nPos );
1459         }
1460     }
1461 }
1462 
1463 // -----------------------------------------------------------------------
1464 
1465 HeaderBarItemBits HeaderBar::GetItemBits( sal_uInt16 nItemId ) const
1466 {
1467     sal_uInt16 nPos = GetItemPos( nItemId );
1468     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1469         return mpItemList->GetObject( nPos )->mnBits;
1470     else
1471         return 0;
1472 }
1473 
1474 // -----------------------------------------------------------------------
1475 
1476 void HeaderBar::SetItemData( sal_uInt16 nItemId, void* pNewData )
1477 {
1478     sal_uInt16 nPos = GetItemPos( nItemId );
1479     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1480     {
1481         mpItemList->GetObject( nPos )->mpUserData = pNewData;
1482         ImplUpdate( nPos );
1483     }
1484 }
1485 
1486 // -----------------------------------------------------------------------
1487 
1488 void* HeaderBar::GetItemData( sal_uInt16 nItemId ) const
1489 {
1490     sal_uInt16 nPos = GetItemPos( nItemId );
1491     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1492         return mpItemList->GetObject( nPos )->mpUserData;
1493     else
1494         return NULL;
1495 }
1496 
1497 // -----------------------------------------------------------------------
1498 
1499 void HeaderBar::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1500 {
1501     sal_uInt16 nPos = GetItemPos( nItemId );
1502     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1503     {
1504         mpItemList->GetObject( nPos )->maImage = rImage;
1505         ImplUpdate( nPos );
1506     }
1507 }
1508 
1509 // -----------------------------------------------------------------------
1510 
1511 Image HeaderBar::GetItemImage( sal_uInt16 nItemId ) const
1512 {
1513     sal_uInt16 nPos = GetItemPos( nItemId );
1514     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1515         return mpItemList->GetObject( nPos )->maImage;
1516     else
1517         return Image();
1518 }
1519 
1520 // -----------------------------------------------------------------------
1521 
1522 void HeaderBar::SetItemText( sal_uInt16 nItemId, const XubString& rText )
1523 {
1524     sal_uInt16 nPos = GetItemPos( nItemId );
1525     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1526     {
1527         mpItemList->GetObject( nPos )->maText = rText;
1528         ImplUpdate( nPos );
1529     }
1530 }
1531 
1532 // -----------------------------------------------------------------------
1533 
1534 XubString HeaderBar::GetItemText( sal_uInt16 nItemId ) const
1535 {
1536     sal_uInt16 nPos = GetItemPos( nItemId );
1537     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1538         return mpItemList->GetObject( nPos )->maText;
1539     else
1540         return String();
1541 }
1542 
1543 // -----------------------------------------------------------------------
1544 
1545 void HeaderBar::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
1546 {
1547     sal_uInt16 nPos = GetItemPos( nItemId );
1548     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1549         mpItemList->GetObject( nPos )->maHelpText = rText;
1550 }
1551 
1552 // -----------------------------------------------------------------------
1553 
1554 XubString HeaderBar::GetHelpText( sal_uInt16 nItemId ) const
1555 {
1556     sal_uInt16 nPos = GetItemPos( nItemId );
1557     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1558     {
1559         ImplHeadItem* pItem = mpItemList->GetObject( nPos );
1560         if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
1561         {
1562             Help* pHelp = Application::GetHelp();
1563             if ( pHelp )
1564                 pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
1565         }
1566 
1567         return pItem->maHelpText;
1568     }
1569     else
1570         return XubString();
1571 }
1572 
1573 // -----------------------------------------------------------------------
1574 
1575 void HeaderBar::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
1576 {
1577     sal_uInt16 nPos = GetItemPos( nItemId );
1578     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1579         mpItemList->GetObject( nPos )->maHelpId = rHelpId;
1580 }
1581 
1582 // -----------------------------------------------------------------------
1583 
1584 rtl::OString HeaderBar::GetHelpId( sal_uInt16 nItemId ) const
1585 {
1586     sal_uInt16 nPos = GetItemPos( nItemId );
1587     rtl::OString aRet;
1588     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1589         aRet = mpItemList->GetObject( nPos )->maHelpId;
1590     return aRet;
1591 }
1592 
1593 // -----------------------------------------------------------------------
1594 
1595 Size HeaderBar::CalcWindowSizePixel() const
1596 {
1597     long nMaxImageSize = 0;
1598     Size aSize( 0, GetTextHeight() );
1599 
1600     ImplHeadItem* pItem = mpItemList->First();
1601     while ( pItem )
1602     {
1603         // Image-Groessen beruecksichtigen
1604         long nImageHeight = pItem->maImage.GetSizePixel().Height();
1605         if ( !(pItem->mnBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) && pItem->maText.Len() )
1606             nImageHeight += aSize.Height();
1607         if ( nImageHeight > nMaxImageSize )
1608             nMaxImageSize = nImageHeight;
1609 
1610         // Breite aufaddieren
1611         aSize.Width() += pItem->mnSize;
1612 
1613         pItem = mpItemList->Next();
1614     }
1615 
1616     if ( nMaxImageSize > aSize.Height() )
1617         aSize.Height() = nMaxImageSize;
1618 
1619     // Border aufaddieren
1620     if ( mbButtonStyle )
1621         aSize.Height() += 4;
1622     else
1623         aSize.Height() += 2;
1624     aSize.Height() += mnBorderOff1+mnBorderOff2;
1625 
1626     return aSize;
1627 }
1628 
1629 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HeaderBar::CreateAccessible()
1630 {
1631     if ( !mxAccessible.is() )
1632     {
1633         if ( maCreateAccessibleHdl.IsSet() )
1634             maCreateAccessibleHdl.Call( this );
1635 
1636         if ( !mxAccessible.is() )
1637             mxAccessible = Window::CreateAccessible();
1638     }
1639 
1640     return mxAccessible;
1641 }
1642 
1643 void HeaderBar::SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > _xAccessible )
1644 {
1645     mxAccessible = _xAccessible;
1646 }
1647 
1648