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