bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / decoview.cxx
blob9111f74027f6186f81af42f252bbefb3a355a62c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/settings.hxx>
21 #include <vcl/outdev.hxx>
22 #include <vcl/decoview.hxx>
23 #include <vcl/window.hxx>
24 #include <vcl/ctrl.hxx>
26 static constexpr auto BUTTON_DRAW_FLATTEST = DrawButtonFlags::Flat |
27 DrawButtonFlags::Pressed |
28 DrawButtonFlags::Checked |
29 DrawButtonFlags::Highlight;
31 using namespace std;
33 namespace {
35 long AdjustRectToSquare( tools::Rectangle &rRect )
37 const long nWidth = rRect.GetWidth();
38 const long nHeight = rRect.GetHeight();
39 long nSide = std::min( nWidth, nHeight );
41 if ( nSide && !(nSide & 1) )
43 // we prefer an odd size
44 --nSide;
47 // Make the rectangle a square
48 rRect.SetSize( Size( nSide, nSide ) );
50 // and place it at the center of the original rectangle
51 rRect.Move( (nWidth-nSide)/2, (nHeight-nSide)/2 );
53 return nSide;
56 void ImplDrawSymbol( OutputDevice* pDev, tools::Rectangle nRect, const SymbolType eType )
58 const long nSide = AdjustRectToSquare( nRect );
60 if ( !nSide ) return;
61 if ( nSide==1 )
63 pDev->DrawPixel( Point( nRect.Left(), nRect.Top() ) );
64 return;
67 // Precalculate some values
68 const long n2 = nSide/2;
69 const long n4 = (n2+1)/2;
70 const long n8 = (n4+1)/2;
71 const long n16 = (n8+1)/2;
72 const Point aCenter = nRect.Center();
74 switch ( eType )
76 case SymbolType::ARROW_UP:
77 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
78 for ( long i=1; i <= n2; ++i )
80 nRect.AdjustTop( 1 );
81 pDev->DrawLine( Point( aCenter.X()-i, nRect.Top() ),
82 Point( aCenter.X()+i, nRect.Top() ) );
83 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Top() ) );
84 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Top() ) );
86 pDev->DrawRect( tools::Rectangle( aCenter.X()-n8, nRect.Top()+1,
87 aCenter.X()+n8, nRect.Bottom() ) );
88 break;
90 case SymbolType::ARROW_DOWN:
91 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
92 for ( long i=1; i <= n2; ++i )
94 nRect.AdjustBottom( -1 );
95 pDev->DrawLine( Point( aCenter.X()-i, nRect.Bottom() ),
96 Point( aCenter.X()+i, nRect.Bottom() ) );
97 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Bottom() ) );
98 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Bottom() ) );
100 pDev->DrawRect( tools::Rectangle( aCenter.X()-n8, nRect.Top(),
101 aCenter.X()+n8, nRect.Bottom()-1 ) );
102 break;
104 case SymbolType::ARROW_LEFT:
105 pDev->DrawPixel( Point( nRect.Left(), aCenter.Y() ) );
106 for ( long i=1; i <= n2; ++i )
108 nRect.AdjustLeft( 1 );
109 pDev->DrawLine( Point( nRect.Left(), aCenter.Y()-i ),
110 Point( nRect.Left(), aCenter.Y()+i ) );
111 pDev->DrawPixel( Point( nRect.Left(), aCenter.Y()-i ) );
112 pDev->DrawPixel( Point( nRect.Left(), aCenter.Y()+i ) );
114 pDev->DrawRect( tools::Rectangle( nRect.Left()+1, aCenter.Y()-n8,
115 nRect.Right(), aCenter.Y()+n8 ) );
116 break;
118 case SymbolType::ARROW_RIGHT:
119 pDev->DrawPixel( Point( nRect.Right(), aCenter.Y() ) );
120 for ( long i=1; i <= n2; ++i )
122 nRect.AdjustRight( -1 );
123 pDev->DrawLine( Point( nRect.Right(), aCenter.Y()-i ),
124 Point( nRect.Right(), aCenter.Y()+i ) );
125 pDev->DrawPixel( Point( nRect.Right(), aCenter.Y()-i ) );
126 pDev->DrawPixel( Point( nRect.Right(), aCenter.Y()+i ) );
128 pDev->DrawRect( tools::Rectangle( nRect.Left(), aCenter.Y()-n8,
129 nRect.Right()-1, aCenter.Y()+n8 ) );
130 break;
132 case SymbolType::SPIN_UP:
133 nRect.AdjustTop(n4 );
134 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
135 for ( long i=1; i <= n2; ++i )
137 nRect.AdjustTop( 1 );
138 pDev->DrawLine( Point( aCenter.X()-i, nRect.Top() ),
139 Point( aCenter.X()+i, nRect.Top() ) );
140 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Top() ) );
141 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Top() ) );
143 break;
145 case SymbolType::SPIN_DOWN:
146 nRect.AdjustBottom( -n4 );
147 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
148 for ( long i=1; i <= n2; ++i )
150 nRect.AdjustBottom( -1 );
151 pDev->DrawLine( Point( aCenter.X()-i, nRect.Bottom() ),
152 Point( aCenter.X()+i, nRect.Bottom() ) );
153 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Bottom() ) );
154 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Bottom() ) );
156 break;
158 case SymbolType::SPIN_LEFT:
159 case SymbolType::FIRST:
160 case SymbolType::PREV:
162 nRect.AdjustLeft(n4 );
163 if ( eType==SymbolType::FIRST )
165 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
166 Point( nRect.Left(), nRect.Bottom() ) );
167 nRect.AdjustLeft( 1 );
170 tools::Polygon aTriangle(3);
171 aTriangle.SetPoint(Point(nRect.Left() + n2, aCenter.Y() - n2), 0);
172 aTriangle.SetPoint(Point(nRect.Left(), aCenter.Y()), 1);
173 aTriangle.SetPoint(Point(nRect.Left() + n2, aCenter.Y() + n2), 2);
175 pDev->Push(PushFlags::LINECOLOR);
176 pDev->SetLineColor();
177 pDev->DrawPolygon(aTriangle);
178 pDev->Pop();
180 break;
183 case SymbolType::SPIN_RIGHT:
184 case SymbolType::LAST:
185 case SymbolType::NEXT:
186 case SymbolType::PLAY:
188 nRect.AdjustRight( -n4 );
189 if ( eType==SymbolType::LAST )
191 pDev->DrawLine( Point( nRect.Right(), nRect.Top() ),
192 Point( nRect.Right(), nRect.Bottom() ) );
193 nRect.AdjustRight( -1 );
196 tools::Polygon aTriangle(3);
197 aTriangle.SetPoint(Point(nRect.Right() - n2, aCenter.Y() - n2), 0);
198 aTriangle.SetPoint(Point(nRect.Right(), aCenter.Y()), 1);
199 aTriangle.SetPoint(Point(nRect.Right() - n2, aCenter.Y() + n2), 2);
201 pDev->Push(PushFlags::LINECOLOR);
202 pDev->SetLineColor();
203 pDev->DrawPolygon(aTriangle);
204 pDev->Pop();
205 break;
208 case SymbolType::PAGEUP:
209 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
210 pDev->DrawPixel( Point( aCenter.X(), nRect.Top()+n2 ) );
211 for ( long i=1; i < n2; ++i )
213 nRect.AdjustTop( 1 );
214 pDev->DrawLine( Point( aCenter.X()-i, nRect.Top() ),
215 Point( aCenter.X()+i, nRect.Top() ) );
216 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Top() ) );
217 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Top() ) );
218 pDev->DrawLine( Point( aCenter.X()-i, nRect.Top()+n2 ),
219 Point( aCenter.X()+i, nRect.Top()+n2 ) );
220 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Top()+n2 ) );
221 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Top()+n2 ) );
223 break;
225 case SymbolType::PAGEDOWN:
226 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
227 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom()-n2 ) );
228 for ( long i=1; i < n2; ++i )
230 nRect.AdjustBottom( -1 );
231 pDev->DrawLine( Point( aCenter.X()-i, nRect.Bottom() ),
232 Point( aCenter.X()+i, nRect.Bottom() ) );
233 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Bottom() ) );
234 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Bottom() ) );
235 pDev->DrawLine( Point( aCenter.X()-i, nRect.Bottom()-n2 ),
236 Point( aCenter.X()+i, nRect.Bottom()-n2 ) );
237 pDev->DrawPixel( Point( aCenter.X()-i, nRect.Bottom()-n2 ) );
238 pDev->DrawPixel( Point( aCenter.X()+i, nRect.Bottom()-n2 ) );
240 break;
242 case SymbolType::RADIOCHECKMARK:
244 // Midpoint circle algorithm
245 long x = 0;
246 long y = n2;
247 long p = 1 - n2;
248 // Draw central line
249 pDev->DrawLine( Point( aCenter.X(), aCenter.Y()-y ),
250 Point( aCenter.X(), aCenter.Y()+y ) );
251 while ( x<y )
253 if ( p>=0 )
255 // Draw vertical lines close to sides
256 pDev->DrawLine( Point( aCenter.X()+y, aCenter.Y()-x ),
257 Point( aCenter.X()+y, aCenter.Y()+x ) );
258 pDev->DrawLine( Point( aCenter.X()-y, aCenter.Y()-x ),
259 Point( aCenter.X()-y, aCenter.Y()+x ) );
260 --y;
261 p -= 2*y;
263 ++x;
264 p += 2*x+1;
265 // Draw vertical lines close to center
266 pDev->DrawLine( Point( aCenter.X()-x, aCenter.Y()-y ),
267 Point( aCenter.X()-x, aCenter.Y()+y ) );
268 pDev->DrawLine( Point( aCenter.X()+x, aCenter.Y()-y ),
269 Point( aCenter.X()+x, aCenter.Y()+y ) );
272 break;
274 case SymbolType::STOP:
275 pDev->DrawRect( nRect );
276 break;
278 case SymbolType::CLOSE:
279 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
280 Point( nRect.Right(), nRect.Bottom() ) );
281 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
282 Point( nRect.Right(), nRect.Top() ) );
283 for ( long i=1; i<n8; ++i )
285 pDev->DrawLine( Point( nRect.Left()+i, nRect.Top() ),
286 Point( nRect.Right(), nRect.Bottom()-i ) );
287 pDev->DrawLine( Point( nRect.Left(), nRect.Top()+i ),
288 Point( nRect.Right()-i, nRect.Bottom() ) );
289 pDev->DrawLine( Point( nRect.Left()+i, nRect.Bottom() ),
290 Point( nRect.Right(), nRect.Top()+i ) );
291 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom()-i ),
292 Point( nRect.Right()-i, nRect.Top() ) );
294 break;
296 case SymbolType::ROLLDOWN:
297 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
298 Point( nRect.Left(), nRect.Bottom() ) );
299 pDev->DrawLine( Point( nRect.Right(), nRect.Top() ),
300 Point( nRect.Right(), nRect.Bottom() ) );
301 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
302 Point( nRect.Right(), nRect.Bottom() ) );
303 [[fallthrough]];
304 case SymbolType::ROLLUP:
305 pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(),
306 nRect.Right(), nRect.Top()+n8 ) );
307 break;
309 case SymbolType::CHECKMARK:
311 long n3 = nSide/3;
312 nRect.AdjustTop( -(n3/2) );
313 nRect.AdjustBottom( -(n3/2) );
314 // #106953# never mirror checkmarks
315 if ( pDev->HasMirroredGraphics() && pDev->IsRTLEnabled() )
317 // Draw a mirrored checkmark so that it looks "normal" in a
318 // mirrored graphics device (double mirroring!)
319 pDev->DrawLine( Point( nRect.Right(), nRect.Bottom()-n3 ),
320 Point( nRect.Right()-n3, nRect.Bottom() ) );
321 pDev->DrawLine( Point( nRect.Right()-n3, nRect.Bottom() ),
322 Point( nRect.Left(), nRect.Top()+n3 ) );
323 nRect.AdjustTop( 1 );
324 nRect.AdjustBottom( 1 );
325 pDev->DrawLine( Point( nRect.Right(), nRect.Bottom()-n3 ),
326 Point( nRect.Right()-n3, nRect.Bottom() ) );
327 pDev->DrawLine( Point( nRect.Right()-n3, nRect.Bottom() ),
328 Point( nRect.Left(), nRect.Top()+n3 ) );
330 else
332 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom()-n3 ),
333 Point( nRect.Left()+n3, nRect.Bottom() ) );
334 pDev->DrawLine( Point( nRect.Left()+n3, nRect.Bottom() ),
335 Point( nRect.Right(), nRect.Top()+n3 ) );
336 nRect.AdjustTop( 1 );
337 nRect.AdjustBottom( 1 );
338 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom()-n3 ),
339 Point( nRect.Left()+n3, nRect.Bottom() ) );
340 pDev->DrawLine( Point( nRect.Left()+n3, nRect.Bottom() ),
341 Point( nRect.Right(), nRect.Top()+n3 ) );
344 break;
346 case SymbolType::FLOAT:
347 nRect.AdjustRight( -n4 );
348 nRect.AdjustTop(n4+1 );
349 pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(),
350 nRect.Right(), nRect.Top()+n8 ) );
351 pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ),
352 Point( nRect.Left(), nRect.Bottom() ) );
353 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
354 Point( nRect.Right(), nRect.Bottom() ) );
355 pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ),
356 Point( nRect.Right(), nRect.Bottom() ) );
357 nRect.AdjustRight(n4 );
358 nRect.AdjustTop( -(n4+1) );
359 nRect.AdjustLeft(n4 );
360 nRect.AdjustBottom( -(n4+1) );
361 pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(),
362 nRect.Right(), nRect.Top()+n8 ) );
363 pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ),
364 Point( nRect.Left(), nRect.Bottom() ) );
365 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
366 Point( nRect.Right(), nRect.Bottom() ) );
367 pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ),
368 Point( nRect.Right(), nRect.Bottom() ) );
369 break;
371 case SymbolType::DOCK:
372 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
373 Point( nRect.Right(), nRect.Top() ) );
374 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
375 Point( nRect.Left(), nRect.Bottom() ) );
376 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
377 Point( nRect.Right(), nRect.Bottom() ) );
378 pDev->DrawLine( Point( nRect.Right(), nRect.Top() ),
379 Point( nRect.Right(), nRect.Bottom() ) );
380 break;
382 case SymbolType::HIDE:
383 pDev->DrawRect( tools::Rectangle( nRect.Left()+n8, nRect.Bottom()-n8,
384 nRect.Right()-n8, nRect.Bottom() ) );
385 break;
387 case SymbolType::PLUS:
388 pDev->DrawRect( tools::Rectangle( nRect.Left(), aCenter.Y()-n16,
389 nRect.Right(), aCenter.Y()+n16 ) );
390 pDev->DrawRect( tools::Rectangle( aCenter.X()-n16, nRect.Top(),
391 aCenter.X()+n16, nRect.Bottom() ) );
392 break;
393 case SymbolType::DONTKNOW:
394 case SymbolType::IMAGE:
395 case SymbolType::HELP: break;
399 void ImplDrawDPILineRect( OutputDevice *const pDev, tools::Rectangle& rRect,
400 const Color *const pColor, const bool bRound = false )
402 long nLineWidth = pDev->GetDPIX()/300;
403 long nLineHeight = pDev->GetDPIY()/300;
404 if ( !nLineWidth )
405 nLineWidth = 1;
406 if ( !nLineHeight )
407 nLineHeight = 1;
409 if ( pColor )
411 if ( (nLineWidth == 1) && (nLineHeight == 1) )
413 pDev->SetLineColor( *pColor );
414 if( bRound )
416 pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()), Point( rRect.Right()-1, rRect.Top()) );
417 pDev->DrawLine( Point( rRect.Left()+1, rRect.Bottom()), Point( rRect.Right()-1, rRect.Bottom()) );
418 pDev->DrawLine( Point( rRect.Left(), rRect.Top()+1), Point( rRect.Left(), rRect.Bottom()-1) );
419 pDev->DrawLine( Point( rRect.Right(), rRect.Top()+1), Point( rRect.Right(), rRect.Bottom()-1) );
421 else
423 pDev->SetFillColor();
424 pDev->DrawRect( rRect );
427 else
429 const long nWidth = rRect.GetWidth();
430 const long nHeight = rRect.GetHeight();
431 pDev->SetLineColor();
432 pDev->SetFillColor( *pColor );
433 pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nWidth, nLineHeight ) ) );
434 pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nLineWidth, nHeight ) ) );
435 pDev->DrawRect( tools::Rectangle( Point( rRect.Left(), rRect.Bottom()-nLineHeight ),
436 Size( nWidth, nLineHeight ) ) );
437 pDev->DrawRect( tools::Rectangle( Point( rRect.Right()-nLineWidth, rRect.Top() ),
438 Size( nLineWidth, nHeight ) ) );
442 rRect.AdjustLeft(nLineWidth );
443 rRect.AdjustTop(nLineHeight );
444 rRect.AdjustRight( -nLineWidth );
445 rRect.AdjustBottom( -nLineHeight );
448 void ImplDraw2ColorFrame( OutputDevice *const pDev, tools::Rectangle& rRect,
449 const Color& rLeftTopColor, const Color& rRightBottomColor )
451 pDev->SetLineColor( rLeftTopColor );
452 pDev->DrawLine( rRect.TopLeft(), rRect.BottomLeft() );
453 pDev->DrawLine( rRect.TopLeft(), rRect.TopRight() );
454 pDev->SetLineColor( rRightBottomColor );
455 pDev->DrawLine( rRect.BottomLeft(), rRect.BottomRight() );
456 pDev->DrawLine( rRect.TopRight(), rRect.BottomRight() );
458 // reduce drawing area
459 rRect.AdjustLeft( 1 );
460 rRect.AdjustTop( 1 );
461 rRect.AdjustRight( -1 );
462 rRect.AdjustBottom( -1 );
465 void ImplDrawButton( OutputDevice *const pDev, tools::Rectangle aFillRect,
466 const DrawButtonFlags nStyle )
468 const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
470 if ( (nStyle & DrawButtonFlags::Mono) ||
471 (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) )
473 const Color aBlackColor(COL_BLACK);
475 if ( nStyle & DrawButtonFlags::Default )
477 // default selection shows a wider border
478 ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
481 ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
483 Size aBrdSize( 1, 1 );
484 if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
486 aBrdSize = pDev->LogicToPixel( Size( 20, 20 ), MapMode(MapUnit::Map100thMM) );
487 if ( !aBrdSize.Width() )
488 aBrdSize.setWidth( 1 );
489 if ( !aBrdSize.Height() )
490 aBrdSize.setHeight( 1 );
493 pDev->SetLineColor();
494 pDev->SetFillColor( aBlackColor );
495 const tools::Rectangle aOrigFillRect(aFillRect);
496 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
498 // shrink fill rect
499 aFillRect.AdjustLeft(aBrdSize.Width() );
500 aFillRect.AdjustTop(aBrdSize.Height() );
501 // draw top and left borders (aOrigFillRect-aFillRect)
502 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(),
503 aOrigFillRect.Right(), aFillRect.Top()-1 ) );
504 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(),
505 aFillRect.Left()-1, aOrigFillRect.Bottom() ) );
507 else
509 // shrink fill rect
510 aFillRect.AdjustRight( -(aBrdSize.Width()) );
511 aFillRect.AdjustBottom( -(aBrdSize.Height()) );
512 // draw bottom and right borders (aOrigFillRect-aFillRect)
513 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aFillRect.Bottom()+1,
514 aOrigFillRect.Right(), aOrigFillRect.Bottom() ) );
515 pDev->DrawRect( tools::Rectangle( aFillRect.Right()+1, aOrigFillRect.Top(),
516 aOrigFillRect.Right(), aOrigFillRect.Bottom() ) );
519 // Hack: in monochrome mode on printers we like to have grey buttons
520 if ( pDev->GetOutDevType() == OUTDEV_PRINTER )
521 pDev->SetFillColor( COL_LIGHTGRAY );
522 else
523 pDev->SetFillColor( COL_WHITE );
524 pDev->DrawRect( aFillRect );
526 else
528 if ( nStyle & DrawButtonFlags::Default )
530 const Color aDefBtnColor = rStyleSettings.GetDarkShadowColor();
531 ImplDrawDPILineRect( pDev, aFillRect, &aDefBtnColor );
534 if ( nStyle & DrawButtonFlags::NoLeftLightBorder )
536 pDev->SetLineColor( rStyleSettings.GetLightBorderColor() );
537 pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Top() ),
538 Point( aFillRect.Left(), aFillRect.Bottom() ) );
539 aFillRect.AdjustLeft( 1 );
542 Color aColor1;
543 Color aColor2;
544 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
546 aColor1 = rStyleSettings.GetDarkShadowColor();
547 aColor2 = rStyleSettings.GetLightColor();
549 else
551 if ( nStyle & DrawButtonFlags::NoLightBorder )
552 aColor1 = rStyleSettings.GetLightBorderColor();
553 else
554 aColor1 = rStyleSettings.GetLightColor();
555 if ( (nStyle & BUTTON_DRAW_FLATTEST) == DrawButtonFlags::Flat )
556 aColor2 = rStyleSettings.GetShadowColor();
557 else
558 aColor2 = rStyleSettings.GetDarkShadowColor();
561 ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 );
563 if ( (nStyle & BUTTON_DRAW_FLATTEST) != DrawButtonFlags::Flat )
565 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
567 aColor1 = rStyleSettings.GetShadowColor();
568 aColor2 = rStyleSettings.GetLightBorderColor();
570 else
572 if ( nStyle & DrawButtonFlags::NoLightBorder )
573 aColor1 = rStyleSettings.GetLightColor();
574 else
575 aColor1 = rStyleSettings.GetLightBorderColor();
576 aColor2 = rStyleSettings.GetShadowColor();
578 ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 );
581 pDev->SetLineColor();
582 if ( nStyle & (DrawButtonFlags::Checked | DrawButtonFlags::DontKnow) )
583 pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
584 else
585 pDev->SetFillColor( rStyleSettings.GetFaceColor() );
586 pDev->DrawRect( aFillRect );
590 void ImplDrawFrame( OutputDevice *const pDev, tools::Rectangle& rRect,
591 const StyleSettings& rStyleSettings, DrawFrameStyle nStyle, DrawFrameFlags nFlags )
593 vcl::Window *const pWin = (pDev->GetOutDevType()==OUTDEV_WINDOW) ? static_cast<vcl::Window*>(pDev) : nullptr;
595 const bool bMenuStyle(nFlags & DrawFrameFlags::Menu);
597 // UseFlatBorders disables 3D style for all frames except menus
598 // menus may use different border colors (eg on XP)
599 // normal frames will be drawn using the shadow color
600 // whereas window frame borders will use black
601 bool bFlatBorders = !bMenuStyle && rStyleSettings.GetUseFlatBorders();
603 // no flat borders for standard VCL controls (ie formcontrols that keep their classic look)
604 // will not affect frame windows (like dropdowns)
605 if( bFlatBorders && pWin && pWin->GetType() == WindowType::BORDERWINDOW && (pWin != pWin->ImplGetFrameWindow()) )
607 // check for formcontrol, i.e., a control without NWF enabled
608 Control *const pControl = dynamic_cast< Control* >( pWin->GetWindow( GetWindowType::Client ) );
609 if( !pControl || !pControl->IsNativeWidgetEnabled() )
610 bFlatBorders = false;
613 const bool bNoDraw(nFlags & DrawFrameFlags::NoDraw);
615 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
616 (pDev->GetOutDevType() == OUTDEV_PRINTER) ||
617 bFlatBorders )
618 nFlags |= DrawFrameFlags::Mono;
620 if( nStyle != DrawFrameStyle::NWF &&
621 pWin && pWin->IsNativeControlSupported(ControlType::Frame, ControlPart::Border) )
623 long nControlFlags = static_cast<long>(nStyle);
624 nControlFlags |= static_cast<long>(nFlags);
625 nControlFlags |= static_cast<long>(pWin->GetType() == WindowType::BORDERWINDOW ?
626 DrawFrameFlags::BorderWindowBorder : DrawFrameFlags::NONE);
627 ImplControlValue aControlValue( nControlFlags );
629 tools::Rectangle aBound, aContent;
630 tools::Rectangle aNatRgn( rRect );
631 if( pWin->GetNativeControlRegion(ControlType::Frame, ControlPart::Border,
632 aNatRgn, ControlState::NONE, aControlValue, aBound, aContent) )
634 // if bNoDraw is true then don't call the drawing routine
635 // but just update the target rectangle
636 if( bNoDraw ||
637 pWin->DrawNativeControl( ControlType::Frame, ControlPart::Border, aContent, ControlState::ENABLED,
638 aControlValue, OUString()) )
640 rRect = aContent;
641 return;
646 if ( nFlags & DrawFrameFlags::Mono )
648 // no round corners for window frame borders
649 const bool bRound = bFlatBorders && !(nFlags & DrawFrameFlags::WindowBorder);
651 if ( bNoDraw )
653 ImplDrawDPILineRect( pDev, rRect, nullptr, bRound );
655 else
657 Color aColor = bRound ? rStyleSettings.GetShadowColor()
658 : pDev->GetSettings().GetStyleSettings().GetMonoColor();
659 // when the MonoColor wasn't set, check face color
660 if (
661 (bRound && aColor.IsDark()) ||
663 (aColor == COL_BLACK) &&
664 pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark()
668 aColor = COL_WHITE;
670 ImplDrawDPILineRect( pDev, rRect, &aColor, bRound );
673 else
675 if ( bNoDraw )
677 switch ( nStyle )
679 case DrawFrameStyle::In:
680 case DrawFrameStyle::Out:
681 rRect.AdjustLeft( 1 );
682 rRect.AdjustTop( 1 );
683 rRect.AdjustRight( -1 );
684 rRect.AdjustBottom( -1 );
685 break;
687 case DrawFrameStyle::Group:
688 case DrawFrameStyle::DoubleIn:
689 case DrawFrameStyle::DoubleOut:
690 rRect.AdjustLeft(2 );
691 rRect.AdjustTop(2 );
692 rRect.AdjustRight( -2 );
693 rRect.AdjustBottom( -2 );
694 break;
696 case DrawFrameStyle::NWF:
697 // enough space for the native rendering
698 rRect.AdjustLeft(4 );
699 rRect.AdjustTop(4 );
700 rRect.AdjustRight( -4 );
701 rRect.AdjustBottom( -4 );
702 break;
703 default: break;
706 else
708 switch ( nStyle )
710 case DrawFrameStyle::Group:
711 pDev->SetFillColor();
712 pDev->SetLineColor( rStyleSettings.GetLightColor() );
713 pDev->DrawRect( tools::Rectangle( rRect.Left()+1, rRect.Top()+1,
714 rRect.Right(), rRect.Bottom() ) );
715 pDev->SetLineColor( rStyleSettings.GetShadowColor() );
716 pDev->DrawRect( tools::Rectangle( rRect.Left(), rRect.Top(),
717 rRect.Right()-1, rRect.Bottom()-1 ) );
719 // adjust target rectangle
720 rRect.AdjustLeft(2 );
721 rRect.AdjustTop(2 );
722 rRect.AdjustRight( -2 );
723 rRect.AdjustBottom( -2 );
724 break;
726 case DrawFrameStyle::In:
727 ImplDraw2ColorFrame( pDev, rRect,
728 rStyleSettings.GetShadowColor(),
729 rStyleSettings.GetLightColor() );
730 break;
732 case DrawFrameStyle::Out:
733 ImplDraw2ColorFrame( pDev, rRect,
734 rStyleSettings.GetLightColor(),
735 rStyleSettings.GetShadowColor() );
736 break;
738 case DrawFrameStyle::DoubleIn:
739 if( bFlatBorders )
741 // no 3d effect
742 ImplDraw2ColorFrame( pDev, rRect,
743 rStyleSettings.GetShadowColor(),
744 rStyleSettings.GetShadowColor() );
745 ImplDraw2ColorFrame( pDev, rRect,
746 rStyleSettings.GetFaceColor(),
747 rStyleSettings.GetFaceColor() );
749 else
751 ImplDraw2ColorFrame( pDev, rRect,
752 rStyleSettings.GetShadowColor(),
753 rStyleSettings.GetLightColor() );
754 ImplDraw2ColorFrame( pDev, rRect,
755 rStyleSettings.GetDarkShadowColor(),
756 rStyleSettings.GetLightBorderColor() );
758 break;
760 case DrawFrameStyle::DoubleOut:
761 if( bMenuStyle )
763 ImplDraw2ColorFrame( pDev, rRect,
764 rStyleSettings.GetMenuBorderColor(),
765 rStyleSettings.GetDarkShadowColor() );
766 if ( !rStyleSettings.GetUseFlatMenus() )
768 ImplDraw2ColorFrame( pDev, rRect,
769 rStyleSettings.GetLightColor(),
770 rStyleSettings.GetShadowColor() );
773 else
775 ImplDraw2ColorFrame( pDev, rRect,
776 bFlatBorders ? // no 3d effect
777 rStyleSettings.GetDarkShadowColor() :
778 rStyleSettings.GetLightBorderColor(),
779 rStyleSettings.GetDarkShadowColor() );
780 ImplDraw2ColorFrame( pDev, rRect,
781 rStyleSettings.GetLightColor(),
782 rStyleSettings.GetShadowColor() );
784 break;
786 case DrawFrameStyle::NWF:
787 // no rendering, just enough space for the native rendering
788 rRect.AdjustLeft(4 );
789 rRect.AdjustTop(4 );
790 rRect.AdjustRight( -4 );
791 rRect.AdjustBottom( -4 );
792 break;
793 default: break;
799 } // end anonymous namespace
801 DecorationView::DecorationView(OutputDevice* pOutDev) :
802 mpOutDev(pOutDev)
805 void DecorationView::DrawSymbol( const tools::Rectangle& rRect, SymbolType eType,
806 const Color& rColor, DrawSymbolFlags nStyle )
808 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
809 const tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect );
810 const Color aOldLineColor = mpOutDev->GetLineColor();
811 const Color aOldFillColor = mpOutDev->GetFillColor();
812 const bool bOldMapMode = mpOutDev->IsMapModeEnabled();
813 Color nColor(rColor);
814 mpOutDev->EnableMapMode( false );
816 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
817 (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
818 nStyle |= DrawSymbolFlags::Mono;
820 if ( nStyle & DrawSymbolFlags::Mono )
822 // Monochrome: set color to black if enabled, to gray if disabled
823 nColor = ( nStyle & DrawSymbolFlags::Disable ) ? COL_GRAY : COL_BLACK;
825 else
827 if ( nStyle & DrawSymbolFlags::Disable )
829 // Draw shifted and brighter symbol for embossed look
830 mpOutDev->SetLineColor( rStyleSettings.GetLightColor() );
831 mpOutDev->SetFillColor( rStyleSettings.GetLightColor() );
832 ImplDrawSymbol( mpOutDev, aRect + Point(1, 1) , eType );
833 nColor = rStyleSettings.GetShadowColor();
837 // Set selected color and draw the symbol
838 mpOutDev->SetLineColor( nColor );
839 mpOutDev->SetFillColor( nColor );
840 ImplDrawSymbol( mpOutDev, aRect, eType );
842 // Restore previous settings
843 mpOutDev->SetLineColor( aOldLineColor );
844 mpOutDev->SetFillColor( aOldFillColor );
845 mpOutDev->EnableMapMode( bOldMapMode );
848 void DecorationView::DrawFrame( const tools::Rectangle& rRect,
849 const Color& rLeftTopColor,
850 const Color& rRightBottomColor )
852 tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect );
853 const Color aOldLineColor = mpOutDev->GetLineColor();
854 const bool bOldMapMode = mpOutDev->IsMapModeEnabled();
855 mpOutDev->EnableMapMode( false );
856 ImplDraw2ColorFrame( mpOutDev, aRect, rLeftTopColor, rRightBottomColor );
857 mpOutDev->SetLineColor( aOldLineColor );
858 mpOutDev->EnableMapMode( bOldMapMode );
861 void DecorationView::DrawHighlightFrame( const tools::Rectangle& rRect,
862 DrawHighlightFrameStyle nStyle )
864 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
865 Color aLightColor = rStyleSettings.GetLightColor();
866 Color aShadowColor = rStyleSettings.GetShadowColor();
868 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
869 (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
871 aLightColor = COL_BLACK;
872 aShadowColor = COL_BLACK;
874 else
876 Wallpaper aBackground = mpOutDev->GetBackground();
877 if ( aBackground.IsBitmap() || aBackground.IsGradient() )
879 aLightColor = rStyleSettings.GetFaceColor();
880 aShadowColor = COL_BLACK;
882 else
884 Color aBackColor = aBackground.GetColor();
885 if ( (aLightColor.GetColorError( aBackColor ) < 96) ||
886 (aShadowColor.GetColorError( aBackColor ) < 96) )
888 aLightColor = COL_WHITE;
889 aShadowColor = COL_BLACK;
891 if ( aLightColor.GetColorError( aBackColor ) < 96 )
892 aLightColor.DecreaseLuminance( 64 );
893 if ( aShadowColor.GetColorError( aBackColor ) < 96 )
894 aShadowColor.IncreaseLuminance( 64 );
899 if ( nStyle == DrawHighlightFrameStyle::In )
901 Color aTempColor = aLightColor;
902 aLightColor = aShadowColor;
903 aShadowColor = aTempColor;
906 DrawFrame( rRect, aLightColor, aShadowColor );
909 tools::Rectangle DecorationView::DrawFrame( const tools::Rectangle& rRect, DrawFrameStyle nStyle, DrawFrameFlags nFlags )
911 tools::Rectangle aRect = rRect;
912 bool bOldMap = mpOutDev->IsMapModeEnabled();
913 if ( bOldMap )
915 aRect = mpOutDev->LogicToPixel( aRect );
916 mpOutDev->EnableMapMode( false );
919 if ( !rRect.IsEmpty() )
921 if ( nFlags & DrawFrameFlags::NoDraw )
922 ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags );
923 else
925 Color aOldLineColor = mpOutDev->GetLineColor();
926 Color aOldFillColor = mpOutDev->GetFillColor();
927 ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags );
928 mpOutDev->SetLineColor( aOldLineColor );
929 mpOutDev->SetFillColor( aOldFillColor );
933 if ( bOldMap )
935 mpOutDev->EnableMapMode( bOldMap );
936 aRect = mpOutDev->PixelToLogic( aRect );
939 return aRect;
942 tools::Rectangle DecorationView::DrawButton( const tools::Rectangle& rRect, DrawButtonFlags nStyle )
944 if ( rRect.IsEmpty() )
946 return rRect;
949 tools::Rectangle aRect = rRect;
950 const bool bOldMap = mpOutDev->IsMapModeEnabled();
952 if ( bOldMap )
954 aRect = mpOutDev->LogicToPixel( aRect );
955 mpOutDev->EnableMapMode( false );
958 const Color aOldLineColor = mpOutDev->GetLineColor();
959 const Color aOldFillColor = mpOutDev->GetFillColor();
960 ImplDrawButton( mpOutDev, aRect, nStyle );
961 mpOutDev->SetLineColor( aOldLineColor );
962 mpOutDev->SetFillColor( aOldFillColor );
964 // keep border free, although it is used at default representation
965 aRect.AdjustLeft( 1 );
966 aRect.AdjustTop( 1 );
967 aRect.AdjustRight( -1 );
968 aRect.AdjustBottom( -1 );
970 if ( nStyle & DrawButtonFlags::NoLightBorder )
972 aRect.AdjustLeft( 1 );
973 aRect.AdjustTop( 1 );
975 else if ( nStyle & DrawButtonFlags::NoLeftLightBorder )
977 aRect.AdjustLeft( 1 );
980 if ( nStyle & DrawButtonFlags::Pressed )
982 if ( (aRect.GetHeight() > 10) && (aRect.GetWidth() > 10) )
984 aRect.AdjustLeft(4 );
985 aRect.AdjustTop(4 );
986 aRect.AdjustRight( -1 );
987 aRect.AdjustBottom( -1 );
989 else
991 aRect.AdjustLeft(3 );
992 aRect.AdjustTop(3 );
993 aRect.AdjustRight( -2 );
994 aRect.AdjustBottom( -2 );
997 else if ( nStyle & DrawButtonFlags::Checked )
999 aRect.AdjustLeft(3 );
1000 aRect.AdjustTop(3 );
1001 aRect.AdjustRight( -2 );
1002 aRect.AdjustBottom( -2 );
1004 else
1006 aRect.AdjustLeft(2 );
1007 aRect.AdjustTop(2 );
1008 aRect.AdjustRight( -3 );
1009 aRect.AdjustBottom( -3 );
1012 if ( bOldMap )
1014 mpOutDev->EnableMapMode( bOldMap );
1015 aRect = mpOutDev->PixelToLogic( aRect );
1018 return aRect;
1021 void DecorationView::DrawSeparator( const Point& rStart, const Point& rStop, bool bVertical )
1023 Point aStart( rStart ), aStop( rStop );
1024 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
1025 vcl::Window *const pWin = (mpOutDev->GetOutDevType()==OUTDEV_WINDOW) ? static_cast<vcl::Window*>(mpOutDev.get()) : nullptr;
1026 if(pWin)
1028 ControlPart nPart = ( bVertical ? ControlPart::SeparatorVert : ControlPart::SeparatorHorz );
1029 bool nativeSupported = pWin->IsNativeControlSupported( ControlType::Fixedline, nPart );
1030 ImplControlValue aValue;
1031 tools::Rectangle aRect(rStart,rStop);
1032 if(nativeSupported && pWin->DrawNativeControl(ControlType::Fixedline,nPart,aRect,ControlState::NONE,aValue,OUString()))
1033 return;
1036 mpOutDev->Push( PushFlags::LINECOLOR );
1037 if ( rStyleSettings.GetOptions() & StyleSettingsOptions::Mono )
1038 mpOutDev->SetLineColor( COL_BLACK );
1039 else
1040 mpOutDev->SetLineColor( rStyleSettings.GetShadowColor() );
1042 mpOutDev->DrawLine( aStart, aStop );
1043 if ( !(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) )
1045 mpOutDev->SetLineColor( rStyleSettings.GetLightColor() );
1046 if( bVertical )
1048 aStart.AdjustX( 1 );
1049 aStop.AdjustX( 1 );
1051 else
1053 aStart.AdjustY( 1 );
1054 aStop.AdjustY( 1 );
1056 mpOutDev->DrawLine( aStart, aStop );
1058 mpOutDev->Pop();
1061 void DecorationView::DrawHandle(const tools::Rectangle& rRect)
1063 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
1065 Size aOutputSize = rRect.GetSize();
1067 mpOutDev->SetLineColor(rStyleSettings.GetDarkShadowColor());
1068 mpOutDev->SetFillColor(rStyleSettings.GetDarkShadowColor());
1070 const sal_Int32 nNumberOfPoints = 3;
1072 long nHalfWidth = aOutputSize.Width() / 2.0f;
1074 float fDistance = aOutputSize.Height();
1075 fDistance /= (nNumberOfPoints + 1);
1077 long nRadius = aOutputSize.Width();
1078 nRadius /= (nNumberOfPoints + 2);
1080 for (long i = 1; i <= nNumberOfPoints; i++)
1082 tools::Rectangle aLocation(nHalfWidth - nRadius,
1083 round(fDistance * i) - nRadius,
1084 nHalfWidth + nRadius,
1085 round(fDistance * i) + nRadius);
1086 mpOutDev->DrawEllipse(aLocation);
1090 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */