1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/headbar.hxx>
21 #include <tools/debug.hxx>
22 
23 #include <vcl/svapp.hxx>
24 #include <vcl/help.hxx>
25 #include <vcl/image.hxx>
26 #include <vcl/salnativewidgets.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/commandevent.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/ptrstyle.hxx>
31 
32 #include <com/sun/star/accessibility/XAccessible.hpp>
33 
34 class ImplHeadItem
35 {
36 public:
37     sal_uInt16          mnId;
38     HeaderBarItemBits   mnBits;
39     long                mnSize;
40     OString const       maHelpId;
41     Image const         maImage;
42     OUString            maOutText;
43     OUString            maText;
44     OUString            maHelpText;
45 };
46 
47 #define HEAD_ARROWSIZE1             4
48 #define HEAD_ARROWSIZE2             7
49 
50 #define HEADERBAR_TEXTOFF           2
51 #define HEADERBAR_ARROWOFF          5
52 #define HEADERBAR_SPLITOFF          3
53 
54 #define HEADERBAR_DRAGOUTOFF        15
55 
56 #define HEAD_HITTEST_ITEM           (sal_uInt16(0x0001))
57 #define HEAD_HITTEST_DIVIDER        (sal_uInt16(0x0002))
58 
ImplInit(WinBits nWinStyle)59 void HeaderBar::ImplInit( WinBits nWinStyle )
60 {
61     mnBorderOff1    = 0;
62     mnBorderOff2    = 0;
63     mnOffset        = 0;
64     mnDX            = 0;
65     mnDY            = 0;
66     mnDragSize      = 0;
67     mnStartPos      = 0;
68     mnDragPos       = 0;
69     mnMouseOff      = 0;
70     mnCurItemId     = 0;
71     mnItemDragPos   = HEADERBAR_ITEM_NOTFOUND;
72     mbDrag          = false;
73     mbItemDrag      = false;
74     mbOutDrag       = false;
75     mbItemMode      = false;
76 
77     // evaluate StyleBits
78     if ( nWinStyle & WB_DRAG )
79         mbDragable = true;
80     else
81         mbDragable = false;
82     if ( nWinStyle & WB_BUTTONSTYLE )
83         mbButtonStyle = true;
84     else
85         mbButtonStyle = false;
86     if ( nWinStyle & WB_BORDER )
87     {
88         mnBorderOff1 = 1;
89         mnBorderOff2 = 1;
90     }
91     else
92     {
93         if ( nWinStyle & WB_BOTTOMBORDER )
94             mnBorderOff2 = 1;
95     }
96 
97     ImplInitSettings( true, true, true );
98 }
99 
HeaderBar(vcl::Window * pParent,WinBits nWinStyle)100 HeaderBar::HeaderBar(vcl::Window* pParent, WinBits nWinStyle)
101     : Window(pParent, nWinStyle & WB_3DLOOK)
102 {
103     SetType(WindowType::HEADERBAR);
104     ImplInit(nWinStyle);
105     SetSizePixel( CalcWindowSizePixel() );
106 }
107 
GetOptimalSize() const108 Size HeaderBar::GetOptimalSize() const
109 {
110     return CalcWindowSizePixel();
111 }
112 
113 HeaderBar::~HeaderBar() = default;
114 
ApplySettings(vcl::RenderContext & rRenderContext)115 void HeaderBar::ApplySettings(vcl::RenderContext& rRenderContext)
116 {
117     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
118 
119     ApplyControlFont(rRenderContext, rStyleSettings.GetToolFont());
120 
121     ApplyControlForeground(rRenderContext, rStyleSettings.GetButtonTextColor());
122     SetTextFillColor();
123 
124     ApplyControlBackground(rRenderContext, rStyleSettings.GetFaceColor());
125 }
126 
ImplInitSettings(bool bFont,bool bForeground,bool bBackground)127 void HeaderBar::ImplInitSettings(bool bFont, bool bForeground, bool bBackground)
128 {
129     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
130 
131     if (bFont)
132         ApplyControlFont(*this, rStyleSettings.GetToolFont());
133 
134     if (bForeground || bFont)
135     {
136         ApplyControlForeground(*this, rStyleSettings.GetButtonTextColor());
137         SetTextFillColor();
138     }
139 
140     if (bBackground)
141         ApplyControlBackground(*this, rStyleSettings.GetFaceColor());
142 }
143 
ImplGetItemPos(sal_uInt16 nPos) const144 long HeaderBar::ImplGetItemPos( sal_uInt16 nPos ) const
145 {
146     long nX = -mnOffset;
147     for ( size_t i = 0; i < nPos; i++ )
148         nX += mvItemList[ i ]->mnSize;
149     return nX;
150 }
151 
ImplGetItemRect(sal_uInt16 nPos) const152 tools::Rectangle HeaderBar::ImplGetItemRect( sal_uInt16 nPos ) const
153 {
154     tools::Rectangle aRect( ImplGetItemPos( nPos ), 0, 0, mnDY-1 );
155     aRect.SetRight( aRect.Left() + mvItemList[ nPos ]->mnSize - 1 );
156     // check for overflow on various systems
157     if ( aRect.Right() > 16000 )
158         aRect.SetRight( 16000 );
159     return aRect;
160 }
161 
ImplHitTest(const Point & rPos,long & nMouseOff,sal_uInt16 & nPos) const162 sal_uInt16 HeaderBar::ImplHitTest( const Point& rPos,
163                                long& nMouseOff, sal_uInt16& nPos ) const
164 {
165     size_t          nCount = static_cast<sal_uInt16>(mvItemList.size());
166     bool            bLastFixed = true;
167     long            nX = -mnOffset;
168 
169     for ( size_t i = 0; i < nCount; i++ )
170     {
171         auto& pItem = mvItemList[ i ];
172 
173         if ( rPos.X() < (nX+pItem->mnSize) )
174         {
175             sal_uInt16 nMode;
176 
177             if ( !bLastFixed && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
178             {
179                 nMode = HEAD_HITTEST_DIVIDER;
180                 nPos = i-1;
181                 nMouseOff = rPos.X()-nX+1;
182             }
183             else
184             {
185                 nPos = i;
186 
187                 if ( rPos.X() >= (nX+pItem->mnSize-HEADERBAR_SPLITOFF) )
188                 {
189                     nMode = HEAD_HITTEST_DIVIDER;
190                     nMouseOff = rPos.X()-(nX+pItem->mnSize);
191                 }
192                 else
193                 {
194                     nMode = HEAD_HITTEST_ITEM;
195                     nMouseOff = rPos.X()-nX;
196                 }
197             }
198 
199             return nMode;
200         }
201 
202         bLastFixed = false;
203 
204         nX += pItem->mnSize;
205     }
206 
207     if ( !bLastFixed )
208     {
209         auto& pItem = mvItemList[ nCount-1 ];
210         if ( (pItem->mnSize < 4)  && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
211         {
212             nPos = nCount-1;
213             nMouseOff = rPos.X()-nX+1;
214             return HEAD_HITTEST_DIVIDER;
215         }
216     }
217 
218     return 0;
219 }
220 
ImplInvertDrag(sal_uInt16 nStartPos,sal_uInt16 nEndPos)221 void HeaderBar::ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos )
222 {
223     tools::Rectangle aRect1 = ImplGetItemRect( nStartPos );
224     tools::Rectangle aRect2 = ImplGetItemRect( nEndPos );
225     Point     aStartPos = aRect1.Center();
226     Point     aEndPos = aStartPos;
227     tools::Rectangle aStartRect( aStartPos.X()-2, aStartPos.Y()-2,
228                           aStartPos.X()+2, aStartPos.Y()+2 );
229 
230     if ( nEndPos > nStartPos )
231     {
232         aStartPos.AdjustX(3 );
233         aEndPos.setX( aRect2.Right()-6 );
234     }
235     else
236     {
237         aStartPos.AdjustX( -3 );
238         aEndPos.setX( aRect2.Left()+6 );
239     }
240 
241     SetRasterOp( RasterOp::Invert );
242     DrawRect( aStartRect );
243     DrawLine( aStartPos, aEndPos );
244     if ( nEndPos > nStartPos )
245     {
246         DrawLine( Point( aEndPos.X()+1, aEndPos.Y()-3 ),
247                   Point( aEndPos.X()+1, aEndPos.Y()+3 ) );
248         DrawLine( Point( aEndPos.X()+2, aEndPos.Y()-2 ),
249                   Point( aEndPos.X()+2, aEndPos.Y()+2 ) );
250         DrawLine( Point( aEndPos.X()+3, aEndPos.Y()-1 ),
251                   Point( aEndPos.X()+3, aEndPos.Y()+1 ) );
252         DrawPixel( Point( aEndPos.X()+4, aEndPos.Y() ) );
253     }
254     else
255     {
256         DrawLine( Point( aEndPos.X()-1, aEndPos.Y()-3 ),
257                   Point( aEndPos.X()-1, aEndPos.Y()+3 ) );
258         DrawLine( Point( aEndPos.X()-2, aEndPos.Y()-2 ),
259                   Point( aEndPos.X()-2, aEndPos.Y()+2 ) );
260         DrawLine( Point( aEndPos.X()-3, aEndPos.Y()-1 ),
261                   Point( aEndPos.X()-3, aEndPos.Y()+1 ) );
262         DrawPixel( Point( aEndPos.X()-4, aEndPos.Y() ) );
263     }
264     SetRasterOp( RasterOp::OverPaint );
265 }
266 
ImplDrawItem(vcl::RenderContext & rRenderContext,sal_uInt16 nPos,bool bHigh,const tools::Rectangle & rItemRect,const tools::Rectangle * pRect)267 void HeaderBar::ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh,
268                              const tools::Rectangle& rItemRect, const tools::Rectangle* pRect )
269 {
270     ImplControlValue aControlValue(0);
271     tools::Rectangle aCtrlRegion;
272     ControlState nState(ControlState::NONE);
273 
274     tools::Rectangle aRect = rItemRect;
275 
276     // do not display if there is no space
277     if (aRect.GetWidth() <= 1)
278         return;
279 
280     // check of rectangle is visible
281     if (pRect)
282     {
283         if (aRect.Right() < pRect->Left())
284             return;
285         else if (aRect.Left() > pRect->Right())
286             return;
287     }
288     else
289     {
290         if (aRect.Right() < 0)
291             return;
292         else if (aRect.Left() > mnDX)
293             return;
294     }
295 
296     auto& pItem  = mvItemList[nPos];
297     HeaderBarItemBits nBits = pItem->mnBits;
298     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
299 
300     if (rRenderContext.IsNativeControlSupported(ControlType::WindowBackground, ControlPart::Entire))
301     {
302         aCtrlRegion = aRect;
303         rRenderContext.DrawNativeControl(ControlType::WindowBackground, ControlPart::Entire,
304                                          aCtrlRegion, nState, aControlValue, OUString());
305 
306     }
307     else
308     {
309         // do not draw border
310         aRect.AdjustTop(mnBorderOff1 );
311         aRect.AdjustBottom( -mnBorderOff2 );
312 
313         // delete background
314         if ( !pRect )
315         {
316             rRenderContext.DrawWallpaper(aRect, rRenderContext.GetBackground());
317         }
318     }
319 
320     Color aSelectionTextColor(COL_TRANSPARENT);
321 
322     if (rRenderContext.IsNativeControlSupported(ControlType::ListHeader, ControlPart::Button))
323     {
324         aCtrlRegion = aRect;
325         aControlValue.setTristateVal(ButtonValue::On);
326         nState |= ControlState::ENABLED;
327         if (bHigh)
328             nState |= ControlState::PRESSED;
329         rRenderContext.DrawNativeControl(ControlType::ListHeader, ControlPart::Button,
330                                          aCtrlRegion, nState, aControlValue, OUString());
331     }
332     else
333     {
334         // draw separation line
335         rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
336         rRenderContext.DrawLine(Point(aRect.Right(), aRect.Top()), Point(aRect.Right(), aRect.Bottom()));
337 
338         // draw ButtonStyle
339         // avoid 3D borders
340         if (bHigh)
341             vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, aRect, 1, true, false, false, &aSelectionTextColor);
342         else if (!mbButtonStyle || (nBits & HeaderBarItemBits::FLAT))
343             vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, aRect, 0, true, false, false, &aSelectionTextColor);
344     }
345 
346     // do not draw if there is no space
347     if (aRect.GetWidth() < 1)
348         return;
349 
350     // calculate size and position and draw content
351     pItem->maOutText = pItem->maText;
352     Size aImageSize = pItem->maImage.GetSizePixel();
353     Size aTxtSize(rRenderContext.GetTextWidth(pItem->maOutText), 0);
354     if (!pItem->maOutText.isEmpty())
355         aTxtSize.setHeight( rRenderContext.GetTextHeight() );
356     long nArrowWidth = 0;
357     if (nBits & (HeaderBarItemBits::UPARROW | HeaderBarItemBits::DOWNARROW))
358         nArrowWidth = HEAD_ARROWSIZE2 + HEADERBAR_ARROWOFF;
359 
360     // do not draw if there is not enough space for the image
361     long nTestHeight = aImageSize.Height();
362     if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
363         nTestHeight += aTxtSize.Height();
364     if ((aImageSize.Width() > aRect.GetWidth()) || (nTestHeight > aRect.GetHeight()))
365     {
366         aImageSize.setWidth( 0 );
367         aImageSize.setHeight( 0 );
368     }
369 
370     // cut text to correct length
371     bool bLeftText = false;
372     long nMaxTxtWidth = aRect.GetWidth() - (HEADERBAR_TEXTOFF * 2) - nArrowWidth;
373     if (nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE))
374         nMaxTxtWidth -= aImageSize.Width();
375     long nTxtWidth = aTxtSize.Width();
376     if (nTxtWidth > nMaxTxtWidth)
377     {
378         bLeftText = true;
379         OUStringBuffer aBuf(pItem->maOutText);
380         aBuf.append("...");
381         do
382         {
383             aBuf.remove(aBuf.getLength() - 3 - 1, 1);
384             nTxtWidth = rRenderContext.GetTextWidth(aBuf.toString());
385         }
386         while ((nTxtWidth > nMaxTxtWidth) && (aBuf.getLength() > 3));
387         pItem->maOutText = aBuf.makeStringAndClear();
388         if (pItem->maOutText.getLength() == 3)
389         {
390             nTxtWidth = 0;
391             pItem->maOutText.clear();
392         }
393     }
394 
395     // calculate text/imageposition
396     long nTxtPos;
397     if (!bLeftText && (nBits & HeaderBarItemBits::RIGHT))
398     {
399         nTxtPos = aRect.Right() - nTxtWidth - HEADERBAR_TEXTOFF;
400         if (nBits & HeaderBarItemBits::RIGHTIMAGE)
401             nTxtPos -= aImageSize.Width();
402     }
403     else if (!bLeftText && (nBits & HeaderBarItemBits::CENTER))
404     {
405         long nTempWidth = nTxtWidth;
406         if (nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE))
407             nTempWidth += aImageSize.Width();
408         nTxtPos = aRect.Left() + (aRect.GetWidth() - nTempWidth) / 2;
409         if (nBits & HeaderBarItemBits::LEFTIMAGE)
410             nTxtPos += aImageSize.Width();
411         if (nArrowWidth)
412         {
413             if (nTxtPos + nTxtWidth + nArrowWidth >= aRect.Right())
414             {
415                 nTxtPos = aRect.Left() + HEADERBAR_TEXTOFF;
416                 if (nBits & HeaderBarItemBits::LEFTIMAGE)
417                     nTxtPos += aImageSize.Width();
418             }
419         }
420     }
421     else
422     {
423         nTxtPos = aRect.Left() + HEADERBAR_TEXTOFF;
424         if (nBits & HeaderBarItemBits::LEFTIMAGE)
425             nTxtPos += aImageSize.Width();
426         if (nBits & HeaderBarItemBits::RIGHT)
427             nTxtPos += nArrowWidth;
428     }
429 
430     // calculate text/imageposition
431     long nTxtPosY = 0;
432     if (!pItem->maOutText.isEmpty() || (nArrowWidth && aTxtSize.Height()))
433     {
434         long nTempHeight = aTxtSize.Height();
435         nTempHeight += aImageSize.Height();
436         nTxtPosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
437         if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
438             nTxtPosY += aImageSize.Height();
439     }
440 
441     // display text
442     if (!pItem->maOutText.isEmpty())
443     {
444         if (aSelectionTextColor != COL_TRANSPARENT)
445         {
446             rRenderContext.Push(PushFlags::TEXTCOLOR);
447             rRenderContext.SetTextColor(aSelectionTextColor);
448         }
449         if (IsEnabled())
450             rRenderContext.DrawText(Point(nTxtPos, nTxtPosY), pItem->maOutText);
451         else
452             rRenderContext.DrawCtrlText(Point(nTxtPos, nTxtPosY), pItem->maOutText, 0, pItem->maOutText.getLength(), DrawTextFlags::Disable);
453         if (aSelectionTextColor != COL_TRANSPARENT)
454             rRenderContext.Pop();
455     }
456 
457     // calculate the position and draw image if it is available
458     long nImagePosY = 0;
459     if (aImageSize.Width() && aImageSize.Height())
460     {
461         long nImagePos = nTxtPos;
462         if (nBits & HeaderBarItemBits::LEFTIMAGE)
463         {
464             nImagePos -= aImageSize.Width();
465             if (nBits & HeaderBarItemBits::RIGHT)
466                 nImagePos -= nArrowWidth;
467         }
468         else if (nBits & HeaderBarItemBits::RIGHTIMAGE)
469         {
470             nImagePos += nTxtWidth;
471             if (!(nBits & HeaderBarItemBits::RIGHT))
472                 nImagePos += nArrowWidth;
473         }
474         else
475         {
476             if (nBits & HeaderBarItemBits::RIGHT )
477                 nImagePos = aRect.Right()-aImageSize.Width();
478             else if (nBits & HeaderBarItemBits::CENTER)
479                 nImagePos = aRect.Left() + (aRect.GetWidth() - aImageSize.Width()) / 2;
480             else
481                 nImagePos = aRect.Left() + HEADERBAR_TEXTOFF;
482         }
483 
484         long nTempHeight = aImageSize.Height();
485         if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)))
486             nTempHeight += aTxtSize.Height();
487         nImagePosY = aRect.Top() + ((aRect.GetHeight() - nTempHeight) / 2);
488 
489         if (nImagePos + aImageSize.Width() <= aRect.Right())
490         {
491             DrawImageFlags nStyle = DrawImageFlags::NONE;
492             if (!IsEnabled())
493                 nStyle |= DrawImageFlags::Disable;
494             rRenderContext.DrawImage(Point(nImagePos, nImagePosY), pItem->maImage, nStyle);
495         }
496     }
497 
498     if (!(nBits & (HeaderBarItemBits::UPARROW | HeaderBarItemBits::DOWNARROW)))
499         return;
500 
501     long nArrowX = nTxtPos;
502     if (nBits & HeaderBarItemBits::RIGHT)
503         nArrowX -= nArrowWidth;
504     else
505         nArrowX += nTxtWidth + HEADERBAR_ARROWOFF;
506     if (!(nBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)) && pItem->maText.isEmpty())
507     {
508         if (nBits & HeaderBarItemBits::RIGHT)
509             nArrowX -= aImageSize.Width();
510         else
511             nArrowX += aImageSize.Width();
512     }
513 
514     // is there enough space to draw the item?
515     bool bDraw = true;
516     if (nArrowX < aRect.Left() + HEADERBAR_TEXTOFF)
517         bDraw = false;
518     else if (nArrowX + HEAD_ARROWSIZE2 > aRect.Right())
519         bDraw = false;
520 
521     if (!bDraw)
522         return;
523 
524     if (rRenderContext.IsNativeControlSupported(ControlType::ListHeader, ControlPart::Arrow))
525     {
526         aCtrlRegion = tools::Rectangle(Point(nArrowX, aRect.Top()), Size(nArrowWidth, aRect.GetHeight()));
527         // control value passes 1 if arrow points down, 0 otherwise
528         aControlValue.setNumericVal((nBits & HeaderBarItemBits::DOWNARROW) ? 1 : 0);
529         nState |= ControlState::ENABLED;
530         if (bHigh)
531             nState |= ControlState::PRESSED;
532         rRenderContext.DrawNativeControl(ControlType::ListHeader, ControlPart::Arrow, aCtrlRegion,
533                                          nState, aControlValue, OUString());
534     }
535     else
536     {
537         long nArrowY;
538         if (aTxtSize.Height())
539             nArrowY = nTxtPosY + (aTxtSize.Height() / 2);
540         else if (aImageSize.Width() && aImageSize.Height())
541             nArrowY = nImagePosY + (aImageSize.Height() / 2);
542         else
543             nArrowY = aRect.Top() + ((aRect.GetHeight() - HEAD_ARROWSIZE2) / 2);
544         nArrowY -= HEAD_ARROWSIZE1 - 1;
545         if (nBits & HeaderBarItemBits::DOWNARROW)
546         {
547             rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
548             rRenderContext.DrawLine(Point(nArrowX, nArrowY),
549                                     Point(nArrowX + HEAD_ARROWSIZE2, nArrowY));
550             rRenderContext.DrawLine(Point(nArrowX, nArrowY),
551                                     Point(nArrowX + HEAD_ARROWSIZE1, nArrowY + HEAD_ARROWSIZE2));
552             rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
553             rRenderContext.DrawLine(Point(nArrowX + HEAD_ARROWSIZE1, nArrowY + HEAD_ARROWSIZE2),
554                                     Point(nArrowX + HEAD_ARROWSIZE2, nArrowY));
555         }
556         else
557         {
558             rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
559             rRenderContext.DrawLine(Point(nArrowX, nArrowY + HEAD_ARROWSIZE2),
560                                     Point(nArrowX + HEAD_ARROWSIZE1, nArrowY));
561             rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
562             rRenderContext.DrawLine(Point(nArrowX, nArrowY + HEAD_ARROWSIZE2),
563                                     Point(nArrowX + HEAD_ARROWSIZE2, nArrowY + HEAD_ARROWSIZE2));
564             rRenderContext.DrawLine(Point(nArrowX + HEAD_ARROWSIZE2, nArrowY + HEAD_ARROWSIZE2),
565                                     Point(nArrowX + HEAD_ARROWSIZE1, nArrowY));
566         }
567     }
568 }
569 
ImplDrawItem(vcl::RenderContext & rRenderContext,sal_uInt16 nPos,bool bHigh,const tools::Rectangle * pRect)570 void HeaderBar::ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos,
571                              bool bHigh, const tools::Rectangle* pRect )
572 {
573     tools::Rectangle aRect = ImplGetItemRect(nPos);
574     ImplDrawItem(rRenderContext, nPos, bHigh, aRect, pRect );
575 }
576 
ImplUpdate(sal_uInt16 nPos,bool bEnd)577 void HeaderBar::ImplUpdate(sal_uInt16 nPos, bool bEnd)
578 {
579     if (!(IsVisible() && IsUpdateMode()))
580         return;
581 
582     tools::Rectangle aRect;
583     size_t nItemCount = mvItemList.size();
584     if (nPos < nItemCount)
585         aRect = ImplGetItemRect(nPos);
586     else
587     {
588         aRect.SetBottom( mnDY - 1 );
589         if (nItemCount)
590             aRect.SetLeft( ImplGetItemRect(nItemCount - 1).Right() );
591     }
592     if (bEnd)
593         aRect.SetRight( mnDX - 1 );
594     aRect.AdjustTop(mnBorderOff1 );
595     aRect.AdjustBottom( -mnBorderOff2 );
596     Invalidate(aRect);
597 }
598 
ImplStartDrag(const Point & rMousePos,bool bCommand)599 void HeaderBar::ImplStartDrag( const Point& rMousePos, bool bCommand )
600 {
601     sal_uInt16  nPos;
602     sal_uInt16  nHitTest = ImplHitTest( rMousePos, mnMouseOff, nPos );
603     if ( !nHitTest )
604         return;
605 
606     mbDrag = false;
607     auto& pItem = mvItemList[ nPos ];
608     if ( nHitTest & HEAD_HITTEST_DIVIDER )
609         mbDrag = true;
610     else
611     {
612         if ( ((pItem->mnBits & HeaderBarItemBits::CLICKABLE) && !(pItem->mnBits & HeaderBarItemBits::FLAT)) ||
613              mbDragable )
614         {
615             mbItemMode = true;
616             mbDrag = true;
617             if ( bCommand )
618             {
619                 if ( mbDragable )
620                     mbItemDrag = true;
621                 else
622                 {
623                     mbItemMode = false;
624                     mbDrag = false;
625                 }
626             }
627         }
628         else
629         {
630             if ( !bCommand )
631             {
632                 mnCurItemId = pItem->mnId;
633                 Select();
634                 mnCurItemId = 0;
635             }
636         }
637     }
638 
639     if ( mbDrag )
640     {
641         mbOutDrag = false;
642         mnCurItemId = pItem->mnId;
643         mnItemDragPos = nPos;
644         StartTracking();
645         mnStartPos = rMousePos.X()-mnMouseOff;
646         mnDragPos = mnStartPos;
647         maStartDragHdl.Call( this );
648         if (mbItemMode)
649             Invalidate();
650         else
651         {
652             tools::Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
653             ShowTracking( aSizeRect, ShowTrackFlags::Split );
654         }
655     }
656     else
657         mnMouseOff = 0;
658 }
659 
ImplDrag(const Point & rMousePos)660 void HeaderBar::ImplDrag( const Point& rMousePos )
661 {
662     sal_uInt16  nPos = GetItemPos( mnCurItemId );
663 
664     mnDragPos = rMousePos.X()-mnMouseOff;
665     if ( mbItemMode )
666     {
667         bool bNewOutDrag;
668 
669         tools::Rectangle aItemRect = ImplGetItemRect( nPos );
670         bNewOutDrag = !aItemRect.IsInside( rMousePos );
671 
672         //  if needed switch on ItemDrag
673         if ( bNewOutDrag && mbDragable && !mbItemDrag )
674         {
675             if ( (rMousePos.Y() >= aItemRect.Top()) && (rMousePos.Y() <= aItemRect.Bottom()) )
676             {
677                 mbItemDrag = true;
678                 Invalidate();
679             }
680         }
681 
682         sal_uInt16 nOldItemDragPos = mnItemDragPos;
683         if ( mbItemDrag )
684         {
685             bNewOutDrag = (rMousePos.Y() < -HEADERBAR_DRAGOUTOFF) || (rMousePos.Y() > mnDY+HEADERBAR_DRAGOUTOFF);
686 
687             if ( bNewOutDrag )
688                 mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
689             else
690             {
691                 sal_uInt16 nTempId = GetItemId( Point( rMousePos.X(), 2 ) );
692                 if ( nTempId )
693                     mnItemDragPos = GetItemPos( nTempId );
694                 else
695                 {
696                     if ( rMousePos.X() <= 0 )
697                         mnItemDragPos = 0;
698                     else
699                         mnItemDragPos = GetItemCount()-1;
700                 }
701             }
702 
703             if ( (mnItemDragPos != nOldItemDragPos) &&
704                  (nOldItemDragPos != nPos) &&
705                  (nOldItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
706             {
707                 ImplInvertDrag( nPos, nOldItemDragPos );
708                 Invalidate();
709             }
710         }
711 
712         if ( bNewOutDrag != mbOutDrag )
713             Invalidate();
714 
715         if ( mbItemDrag  )
716         {
717             if ( (mnItemDragPos != nOldItemDragPos) &&
718                  (mnItemDragPos != nPos) &&
719                  (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
720             {
721                 Invalidate();
722                 ImplInvertDrag( nPos, mnItemDragPos );
723             }
724         }
725 
726         mbOutDrag = bNewOutDrag;
727     }
728     else
729     {
730         tools::Rectangle aItemRect = ImplGetItemRect( nPos );
731         if ( mnDragPos < aItemRect.Left() )
732             mnDragPos = aItemRect.Left();
733         if ( (mnDragPos < 0) || (mnDragPos > mnDX-1) )
734             HideTracking();
735         else
736         {
737             tools::Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
738             ShowTracking( aSizeRect, ShowTrackFlags::Split );
739         }
740     }
741 
742     maDragHdl.Call( this );
743 }
744 
ImplEndDrag(bool bCancel)745 void HeaderBar::ImplEndDrag( bool bCancel )
746 {
747     HideTracking();
748 
749     if ( bCancel || mbOutDrag )
750     {
751         if ( mbItemMode && (!mbOutDrag || mbItemDrag) )
752         {
753             Invalidate();
754         }
755 
756         mnCurItemId = 0;
757     }
758     else
759     {
760         sal_uInt16 nPos = GetItemPos( mnCurItemId );
761         if ( mbItemMode )
762         {
763             if ( mbItemDrag )
764             {
765                 SetPointer( PointerStyle::Arrow );
766                 if ( (mnItemDragPos != nPos) &&
767                      (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
768                 {
769                     ImplInvertDrag( nPos, mnItemDragPos );
770                     MoveItem( mnCurItemId, mnItemDragPos );
771                 }
772                 else
773                     Invalidate();
774             }
775             else
776             {
777                 Select();
778                 ImplUpdate( nPos );
779             }
780         }
781         else
782         {
783             long nDelta = mnDragPos - mnStartPos;
784             if ( nDelta )
785             {
786                 auto& pItem = mvItemList[ nPos ];
787                 pItem->mnSize += nDelta;
788                 ImplUpdate( nPos, true );
789             }
790         }
791     }
792 
793     mbDrag          = false;
794     EndDrag();
795     mnCurItemId     = 0;
796     mnItemDragPos   = HEADERBAR_ITEM_NOTFOUND;
797     mbOutDrag       = false;
798     mbItemMode      = false;
799     mbItemDrag      = false;
800 }
801 
MouseButtonDown(const MouseEvent & rMEvt)802 void HeaderBar::MouseButtonDown( const MouseEvent& rMEvt )
803 {
804     if ( !rMEvt.IsLeft() )
805         return;
806 
807     if ( rMEvt.GetClicks() == 2 )
808     {
809         long    nTemp;
810         sal_uInt16  nPos;
811         sal_uInt16  nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp, nPos );
812         if ( nHitTest )
813         {
814             auto& pItem = mvItemList[ nPos ];
815             if ( nHitTest & HEAD_HITTEST_DIVIDER )
816                 mbItemMode = false;
817             else
818                 mbItemMode = true;
819             mnCurItemId = pItem->mnId;
820             DoubleClick();
821             mbItemMode = false;
822             mnCurItemId = 0;
823         }
824     }
825     else
826         ImplStartDrag( rMEvt.GetPosPixel(), false );
827 }
828 
MouseMove(const MouseEvent & rMEvt)829 void HeaderBar::MouseMove( const MouseEvent& rMEvt )
830 {
831     long            nTemp1;
832     sal_uInt16          nTemp2;
833     PointerStyle    eStyle = PointerStyle::Arrow;
834     sal_uInt16          nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp1, nTemp2 );
835 
836     if ( nHitTest & HEAD_HITTEST_DIVIDER )
837         eStyle = PointerStyle::HSizeBar;
838     SetPointer( eStyle );
839 }
840 
Tracking(const TrackingEvent & rTEvt)841 void HeaderBar::Tracking( const TrackingEvent& rTEvt )
842 {
843     Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
844 
845     if ( rTEvt.IsTrackingEnded() )
846         ImplEndDrag( rTEvt.IsTrackingCanceled() );
847     else
848         ImplDrag( aMousePos );
849 }
850 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)851 void HeaderBar::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
852 {
853     if (mnBorderOff1 || mnBorderOff2)
854     {
855         rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetDarkShadowColor());
856         if (mnBorderOff1)
857             rRenderContext.DrawLine(Point(0, 0), Point(mnDX - 1, 0));
858         if (mnBorderOff2)
859             rRenderContext.DrawLine(Point(0, mnDY - 1), Point(mnDX - 1, mnDY - 1));
860         // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
861         if (mnBorderOff1 && mnBorderOff2)
862         {
863             rRenderContext.DrawLine(Point(0, 0), Point(0, mnDY - 1));
864             rRenderContext.DrawLine(Point(mnDX - 1, 0), Point(mnDX - 1, mnDY - 1));
865         }
866     }
867 
868     sal_uInt16 nCurItemPos;
869     if (mbDrag)
870         nCurItemPos = GetItemPos(mnCurItemId);
871     else
872         nCurItemPos = HEADERBAR_ITEM_NOTFOUND;
873     sal_uInt16 nItemCount = static_cast<sal_uInt16>(mvItemList.size());
874     for (sal_uInt16 i = 0; i < nItemCount; i++)
875         ImplDrawItem(rRenderContext, i, (i == nCurItemPos), &rRect);
876 }
877 
Draw(OutputDevice * pDev,const Point & rPos,const Size & rSize,DrawFlags nFlags)878 void HeaderBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
879                       DrawFlags nFlags )
880 {
881     Point       aPos  = pDev->LogicToPixel( rPos );
882     Size        aSize = pDev->LogicToPixel( rSize );
883     tools::Rectangle   aRect( aPos, aSize );
884     vcl::Font   aFont = GetDrawPixelFont( pDev );
885 
886     pDev->Push();
887     pDev->SetMapMode();
888     pDev->SetFont( aFont );
889     if ( nFlags & DrawFlags::Mono )
890         pDev->SetTextColor( COL_BLACK );
891     else
892         pDev->SetTextColor( GetTextColor() );
893     pDev->SetTextFillColor();
894 
895     // draw background
896     {
897         pDev->DrawWallpaper( aRect, GetBackground() );
898         if ( mnBorderOff1 || mnBorderOff2 )
899         {
900             pDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
901             if ( mnBorderOff1 )
902                 pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
903             if ( mnBorderOff2 )
904                 pDev->DrawLine( Point( aRect.Left(), aRect.Bottom() ), Point( aRect.Right(), aRect.Bottom() ) );
905             // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
906             if ( mnBorderOff1 && mnBorderOff2 )
907             {
908                 pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
909                 pDev->DrawLine( Point( aRect.Right(), aRect.Top() ), Point( aRect.Right(), aRect.Bottom() ) );
910             }
911         }
912     }
913 
914     tools::Rectangle aItemRect( aRect );
915     size_t nItemCount = mvItemList.size();
916     for ( size_t i = 0; i < nItemCount; i++ )
917     {
918         aItemRect.SetLeft( aRect.Left()+ImplGetItemPos( i ) );
919         aItemRect.SetRight( aItemRect.Left() + mvItemList[ i ]->mnSize - 1 );
920         // check for overflow on some systems
921         if ( aItemRect.Right() > 16000 )
922             aItemRect.SetRight( 16000 );
923         vcl::Region aRegion( aRect );
924         pDev->SetClipRegion( aRegion );
925         ImplDrawItem(*pDev, i, false, aItemRect, &aRect );
926         pDev->SetClipRegion();
927     }
928 
929     pDev->Pop();
930 }
931 
Resize()932 void HeaderBar::Resize()
933 {
934     Size aSize = GetOutputSizePixel();
935     if ( IsVisible() && (mnDY != aSize.Height()) )
936         Invalidate();
937     mnDX = aSize.Width();
938     mnDY = aSize.Height();
939 }
940 
Command(const CommandEvent & rCEvt)941 void HeaderBar::Command( const CommandEvent& rCEvt )
942 {
943     if ( rCEvt.IsMouseEvent() && (rCEvt.GetCommand() == CommandEventId::StartDrag) && !mbDrag )
944     {
945         ImplStartDrag( rCEvt.GetMousePosPixel(), true );
946         return;
947     }
948 
949     Window::Command( rCEvt );
950 }
951 
RequestHelp(const HelpEvent & rHEvt)952 void HeaderBar::RequestHelp( const HelpEvent& rHEvt )
953 {
954     sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
955     if ( nItemId )
956     {
957         if ( rHEvt.GetMode() & (HelpEventMode::QUICK | HelpEventMode::BALLOON) )
958         {
959             tools::Rectangle aItemRect = GetItemRect( nItemId );
960             Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
961             aItemRect.SetLeft( aPt.X() );
962             aItemRect.SetTop( aPt.Y() );
963             aPt = OutputToScreenPixel( aItemRect.BottomRight() );
964             aItemRect.SetRight( aPt.X() );
965             aItemRect.SetBottom( aPt.Y() );
966 
967             OUString aStr = GetHelpText( nItemId );
968             if ( aStr.isEmpty() || !(rHEvt.GetMode() & HelpEventMode::BALLOON) )
969             {
970                 auto& pItem = mvItemList[ GetItemPos( nItemId ) ];
971                 // Quick-help is only displayed if the text is not fully visible.
972                 // Otherwise we display Helptext only if the items do not contain text
973                 if ( pItem->maOutText != pItem->maText )
974                     aStr = pItem->maText;
975                 else if (!pItem->maText.isEmpty())
976                     aStr.clear();
977             }
978 
979             if (!aStr.isEmpty())
980             {
981                 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
982                     Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
983                 else
984                     Help::ShowQuickHelp( this, aItemRect, aStr );
985                 return;
986             }
987         }
988     }
989 
990     Window::RequestHelp( rHEvt );
991 }
992 
StateChanged(StateChangedType nType)993 void HeaderBar::StateChanged( StateChangedType nType )
994 {
995     Window::StateChanged( nType );
996 
997     if ( nType == StateChangedType::Enable )
998         Invalidate();
999     else if ( (nType == StateChangedType::Zoom) ||
1000               (nType == StateChangedType::ControlFont) )
1001     {
1002         ImplInitSettings( true, false, false );
1003         Invalidate();
1004     }
1005     else if ( nType == StateChangedType::ControlForeground )
1006     {
1007         ImplInitSettings( false, true, false );
1008         Invalidate();
1009     }
1010     else if ( nType == StateChangedType::ControlBackground )
1011     {
1012         ImplInitSettings( false, false, true );
1013         Invalidate();
1014     }
1015 }
1016 
DataChanged(const DataChangedEvent & rDCEvt)1017 void HeaderBar::DataChanged( const DataChangedEvent& rDCEvt )
1018 {
1019     Window::DataChanged( rDCEvt );
1020 
1021     if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1022          (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1023          ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1024           (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1025     {
1026         ImplInitSettings( true, true, true );
1027         Invalidate();
1028     }
1029 }
1030 
EndDrag()1031 void HeaderBar::EndDrag()
1032 {
1033     maEndDragHdl.Call( this );
1034 }
1035 
Select()1036 void HeaderBar::Select()
1037 {
1038     maSelectHdl.Call( this );
1039 }
1040 
DoubleClick()1041 void HeaderBar::DoubleClick()
1042 {
1043 }
1044 
InsertItem(sal_uInt16 nItemId,const OUString & rText,long nSize,HeaderBarItemBits nBits,sal_uInt16 nPos)1045 void HeaderBar::InsertItem( sal_uInt16 nItemId, const OUString& rText,
1046                             long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
1047 {
1048     DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
1049     DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
1050                 "HeaderBar::InsertItem(): ItemId already exists" );
1051 
1052     // create item and insert in the list
1053     std::unique_ptr<ImplHeadItem> pItem(new ImplHeadItem);
1054     pItem->mnId         = nItemId;
1055     pItem->mnBits       = nBits;
1056     pItem->mnSize       = nSize;
1057     pItem->maText       = rText;
1058     if ( nPos < mvItemList.size() ) {
1059         auto it = mvItemList.begin();
1060         it += nPos;
1061         mvItemList.insert( it, std::move(pItem) );
1062     } else {
1063         mvItemList.push_back( std::move(pItem) );
1064     }
1065 
1066     // update display
1067     ImplUpdate( nPos, true );
1068 }
1069 
RemoveItem(sal_uInt16 nItemId)1070 void HeaderBar::RemoveItem( sal_uInt16 nItemId )
1071 {
1072     sal_uInt16 nPos = GetItemPos( nItemId );
1073     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1074     {
1075         if ( nPos < mvItemList.size() ) {
1076             auto it = mvItemList.begin();
1077             it += nPos;
1078             mvItemList.erase( it );
1079         }
1080     }
1081 }
1082 
MoveItem(sal_uInt16 nItemId,sal_uInt16 nNewPos)1083 void HeaderBar::MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos )
1084 {
1085     sal_uInt16 nPos = GetItemPos( nItemId );
1086     if ( nPos == HEADERBAR_ITEM_NOTFOUND )
1087         return;
1088 
1089     if ( nPos == nNewPos )
1090         return;
1091 
1092     auto it = mvItemList.begin();
1093     it += nPos;
1094     std::unique_ptr<ImplHeadItem> pItem = std::move(*it);
1095     mvItemList.erase( it );
1096     if ( nNewPos < nPos )
1097         nPos = nNewPos;
1098     it = mvItemList.begin();
1099     it += nNewPos;
1100     mvItemList.insert( it, std::move(pItem) );
1101     ImplUpdate( nPos, true);
1102 }
1103 
Clear()1104 void HeaderBar::Clear()
1105 {
1106     // delete all items
1107     mvItemList.clear();
1108 
1109     ImplUpdate( 0, true );
1110 }
1111 
SetOffset(long nNewOffset)1112 void HeaderBar::SetOffset( long nNewOffset )
1113 {
1114     // move area
1115     tools::Rectangle aRect( 0, mnBorderOff1, mnDX-1, mnDY-mnBorderOff1-mnBorderOff2-1 );
1116     long nDelta = mnOffset-nNewOffset;
1117     mnOffset = nNewOffset;
1118     Scroll( nDelta, 0, aRect );
1119 }
1120 
GetItemCount() const1121 sal_uInt16 HeaderBar::GetItemCount() const
1122 {
1123     return static_cast<sal_uInt16>(mvItemList.size());
1124 }
1125 
GetItemPos(sal_uInt16 nItemId) const1126 sal_uInt16 HeaderBar::GetItemPos( sal_uInt16 nItemId ) const
1127 {
1128     for ( size_t i = 0, n = mvItemList.size(); i < n; ++i ) {
1129         auto& pItem = mvItemList[ i ];
1130         if ( pItem->mnId == nItemId )
1131             return static_cast<sal_uInt16>(i);
1132     }
1133     return HEADERBAR_ITEM_NOTFOUND;
1134 }
1135 
GetItemId(sal_uInt16 nPos) const1136 sal_uInt16 HeaderBar::GetItemId( sal_uInt16 nPos ) const
1137 {
1138     ImplHeadItem* pItem = (nPos < mvItemList.size() ) ? mvItemList[ nPos ].get() : nullptr;
1139     if ( pItem )
1140         return pItem->mnId;
1141     else
1142         return 0;
1143 }
1144 
GetItemId(const Point & rPos) const1145 sal_uInt16 HeaderBar::GetItemId( const Point& rPos ) const
1146 {
1147     for ( size_t i = 0, n = mvItemList.size(); i < n; ++i ) {
1148         if ( ImplGetItemRect( i ).IsInside( rPos ) ) {
1149             return GetItemId( i );
1150         }
1151     }
1152     return 0;
1153 }
1154 
GetItemRect(sal_uInt16 nItemId) const1155 tools::Rectangle HeaderBar::GetItemRect( sal_uInt16 nItemId ) const
1156 {
1157     tools::Rectangle aRect;
1158     sal_uInt16 nPos = GetItemPos( nItemId );
1159     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1160         aRect = ImplGetItemRect( nPos );
1161     return aRect;
1162 }
1163 
SetItemSize(sal_uInt16 nItemId,long nNewSize)1164 void HeaderBar::SetItemSize( sal_uInt16 nItemId, long nNewSize )
1165 {
1166     sal_uInt16 nPos = GetItemPos( nItemId );
1167     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1168     {
1169         auto& pItem = mvItemList[ nPos ];
1170         if ( pItem->mnSize != nNewSize )
1171         {
1172             pItem->mnSize = nNewSize;
1173             ImplUpdate( nPos, true );
1174         }
1175     }
1176 }
1177 
GetItemSize(sal_uInt16 nItemId) const1178 long HeaderBar::GetItemSize( sal_uInt16 nItemId ) const
1179 {
1180     sal_uInt16 nPos = GetItemPos( nItemId );
1181     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1182         return mvItemList[ nPos ]->mnSize;
1183     else
1184         return 0;
1185 }
1186 
SetItemBits(sal_uInt16 nItemId,HeaderBarItemBits nNewBits)1187 void HeaderBar::SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits )
1188 {
1189     sal_uInt16 nPos = GetItemPos( nItemId );
1190     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1191     {
1192         auto& pItem = mvItemList[ nPos ];
1193         if ( pItem->mnBits != nNewBits )
1194         {
1195             pItem->mnBits = nNewBits;
1196             ImplUpdate( nPos );
1197         }
1198     }
1199 }
1200 
GetItemBits(sal_uInt16 nItemId) const1201 HeaderBarItemBits HeaderBar::GetItemBits( sal_uInt16 nItemId ) const
1202 {
1203     sal_uInt16 nPos = GetItemPos( nItemId );
1204     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1205         return mvItemList[ nPos ]->mnBits;
1206     else
1207         return HeaderBarItemBits::NONE;
1208 }
1209 
SetItemText(sal_uInt16 nItemId,const OUString & rText)1210 void HeaderBar::SetItemText( sal_uInt16 nItemId, const OUString& rText )
1211 {
1212     sal_uInt16 nPos = GetItemPos( nItemId );
1213     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1214     {
1215         mvItemList[ nPos ]->maText = rText;
1216         ImplUpdate( nPos );
1217     }
1218 }
1219 
GetItemText(sal_uInt16 nItemId) const1220 OUString HeaderBar::GetItemText( sal_uInt16 nItemId ) const
1221 {
1222     sal_uInt16 nPos = GetItemPos( nItemId );
1223     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1224         return mvItemList[ nPos ]->maText;
1225     return OUString();
1226 }
1227 
GetHelpText(sal_uInt16 nItemId) const1228 OUString HeaderBar::GetHelpText( sal_uInt16 nItemId ) const
1229 {
1230     sal_uInt16 nPos = GetItemPos( nItemId );
1231     if ( nPos != HEADERBAR_ITEM_NOTFOUND )
1232     {
1233         auto& pItem = mvItemList[ nPos ];
1234         if ( pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty() )
1235         {
1236             Help* pHelp = Application::GetHelp();
1237             if ( pHelp )
1238                 pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
1239         }
1240 
1241         return pItem->maHelpText;
1242     }
1243 
1244     return OUString();
1245 }
1246 
CalcWindowSizePixel() const1247 Size HeaderBar::CalcWindowSizePixel() const
1248 {
1249     long nMaxImageSize = 0;
1250     Size aSize( 0, GetTextHeight() );
1251 
1252     for (auto& pItem : mvItemList)
1253     {
1254         // take image size into account
1255         long nImageHeight = pItem->maImage.GetSizePixel().Height();
1256         if ( !(pItem->mnBits & (HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::RIGHTIMAGE)) && !pItem->maText.isEmpty() )
1257             nImageHeight += aSize.Height();
1258         if ( nImageHeight > nMaxImageSize )
1259             nMaxImageSize = nImageHeight;
1260 
1261         // add width
1262         aSize.AdjustWidth(pItem->mnSize );
1263     }
1264 
1265     if ( nMaxImageSize > aSize.Height() )
1266         aSize.setHeight( nMaxImageSize );
1267 
1268     // add border
1269     if ( mbButtonStyle )
1270         aSize.AdjustHeight(4 );
1271     else
1272         aSize.AdjustHeight(2 );
1273     aSize.AdjustHeight(mnBorderOff1+mnBorderOff2 );
1274 
1275     return aSize;
1276 }
1277 
CreateAccessible()1278 css::uno::Reference< css::accessibility::XAccessible > HeaderBar::CreateAccessible()
1279 {
1280     if ( !mxAccessible.is() )
1281     {
1282         maCreateAccessibleHdl.Call( this );
1283 
1284         if ( !mxAccessible.is() )
1285             mxAccessible = Window::CreateAccessible();
1286     }
1287 
1288     return mxAccessible;
1289 }
1290 
SetAccessible(const css::uno::Reference<css::accessibility::XAccessible> & _xAccessible)1291 void HeaderBar::SetAccessible( const css::uno::Reference< css::accessibility::XAccessible >& _xAccessible )
1292 {
1293     mxAccessible = _xAccessible;
1294 }
1295 
1296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1297