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/settings.hxx>
21 #include <vcl/outdev.hxx>
22 #include <vcl/decoview.hxx>
23 #include <vcl/window.hxx>
24 #include <vcl/ctrl.hxx>
25
26 constexpr auto BUTTON_DRAW_FLATTEST = DrawButtonFlags::Flat |
27 DrawButtonFlags::Pressed |
28 DrawButtonFlags::Checked |
29 DrawButtonFlags::Highlight;
30
31 using namespace std;
32
33 namespace {
34
AdjustRectToSquare(tools::Rectangle & rRect)35 tools::Long AdjustRectToSquare( tools::Rectangle &rRect )
36 {
37 const tools::Long nWidth = rRect.GetWidth();
38 const tools::Long nHeight = rRect.GetHeight();
39 tools::Long nSide = std::min( nWidth, nHeight );
40
41 if ( nSide && !(nSide & 1) )
42 {
43 // we prefer an odd size
44 --nSide;
45 }
46
47 // Make the rectangle a square
48 rRect.SetSize( Size( nSide, nSide ) );
49
50 // and place it at the center of the original rectangle
51 rRect.Move( (nWidth-nSide)/2, (nHeight-nSide)/2 );
52
53 return nSide;
54 }
55
ImplDrawSymbol(OutputDevice * pDev,tools::Rectangle nRect,const SymbolType eType)56 void ImplDrawSymbol( OutputDevice* pDev, tools::Rectangle nRect, const SymbolType eType )
57 {
58 const tools::Long nSide = AdjustRectToSquare( nRect );
59
60 if ( !nSide ) return;
61 if ( nSide==1 )
62 {
63 pDev->DrawPixel( Point( nRect.Left(), nRect.Top() ) );
64 return;
65 }
66
67 // Precalculate some values
68 const tools::Long n2 = nSide/2;
69 const tools::Long n4 = (n2+1)/2;
70 const tools::Long n8 = (n4+1)/2;
71 const tools::Long n16 = (n8+1)/2;
72 const Point aCenter = nRect.Center();
73
74 switch ( eType )
75 {
76 case SymbolType::ARROW_UP:
77 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
78 for ( tools::Long i=1; i <= n2; ++i )
79 {
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() ) );
85 }
86 pDev->DrawRect( tools::Rectangle( aCenter.X()-n8, nRect.Top()+1,
87 aCenter.X()+n8, nRect.Bottom() ) );
88 break;
89
90 case SymbolType::ARROW_DOWN:
91 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
92 for ( tools::Long i=1; i <= n2; ++i )
93 {
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() ) );
99 }
100 pDev->DrawRect( tools::Rectangle( aCenter.X()-n8, nRect.Top(),
101 aCenter.X()+n8, nRect.Bottom()-1 ) );
102 break;
103
104 case SymbolType::ARROW_LEFT:
105 pDev->DrawPixel( Point( nRect.Left(), aCenter.Y() ) );
106 for ( tools::Long i=1; i <= n2; ++i )
107 {
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 ) );
113 }
114 pDev->DrawRect( tools::Rectangle( nRect.Left()+1, aCenter.Y()-n8,
115 nRect.Right(), aCenter.Y()+n8 ) );
116 break;
117
118 case SymbolType::ARROW_RIGHT:
119 pDev->DrawPixel( Point( nRect.Right(), aCenter.Y() ) );
120 for ( tools::Long i=1; i <= n2; ++i )
121 {
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 ) );
127 }
128 pDev->DrawRect( tools::Rectangle( nRect.Left(), aCenter.Y()-n8,
129 nRect.Right()-1, aCenter.Y()+n8 ) );
130 break;
131
132 case SymbolType::SPIN_UP:
133 nRect.AdjustTop(n4 );
134 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
135 for ( tools::Long i=1; i <= n2; ++i )
136 {
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() ) );
142 }
143 break;
144
145 case SymbolType::SPIN_DOWN:
146 nRect.AdjustBottom( -n4 );
147 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
148 for ( tools::Long i=1; i <= n2; ++i )
149 {
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() ) );
155 }
156 break;
157
158 case SymbolType::SPIN_LEFT:
159 case SymbolType::FIRST:
160 case SymbolType::PREV:
161 {
162 nRect.AdjustLeft(n4 );
163 if ( eType==SymbolType::FIRST )
164 {
165 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
166 Point( nRect.Left(), nRect.Bottom() ) );
167 nRect.AdjustLeft( 1 );
168 }
169
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);
174
175 pDev->Push(PushFlags::LINECOLOR);
176 pDev->SetLineColor();
177 pDev->DrawPolygon(aTriangle);
178 pDev->Pop();
179
180 break;
181 }
182
183 case SymbolType::SPIN_RIGHT:
184 case SymbolType::LAST:
185 case SymbolType::NEXT:
186 case SymbolType::PLAY:
187 {
188 nRect.AdjustRight( -n4 );
189 if ( eType==SymbolType::LAST )
190 {
191 pDev->DrawLine( Point( nRect.Right(), nRect.Top() ),
192 Point( nRect.Right(), nRect.Bottom() ) );
193 nRect.AdjustRight( -1 );
194 }
195
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);
200
201 pDev->Push(PushFlags::LINECOLOR);
202 pDev->SetLineColor();
203 pDev->DrawPolygon(aTriangle);
204 pDev->Pop();
205 break;
206 }
207
208 case SymbolType::PAGEUP:
209 pDev->DrawPixel( Point( aCenter.X(), nRect.Top() ) );
210 pDev->DrawPixel( Point( aCenter.X(), nRect.Top()+n2 ) );
211 for ( tools::Long i=1; i < n2; ++i )
212 {
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 ) );
222 }
223 break;
224
225 case SymbolType::PAGEDOWN:
226 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom() ) );
227 pDev->DrawPixel( Point( aCenter.X(), nRect.Bottom()-n2 ) );
228 for ( tools::Long i=1; i < n2; ++i )
229 {
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 ) );
239 }
240 break;
241
242 case SymbolType::RADIOCHECKMARK:
243 {
244 // Midpoint circle algorithm
245 tools::Long x = 0;
246 tools::Long y = n2;
247 tools::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 )
252 {
253 if ( p>=0 )
254 {
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;
262 }
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 ) );
270 }
271 }
272 break;
273
274 case SymbolType::STOP:
275 pDev->DrawRect( nRect );
276 break;
277
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 ( tools::Long i=1; i<n8; ++i )
284 {
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() ) );
293 }
294 break;
295
296 case SymbolType::CHECKMARK:
297 {
298 tools::Long n3 = nSide/3;
299 nRect.AdjustTop( -(n3/2) );
300 nRect.AdjustBottom( -(n3/2) );
301 // #106953# never mirror checkmarks
302 if ( pDev->HasMirroredGraphics() && pDev->IsRTLEnabled() )
303 {
304 // Draw a mirrored checkmark so that it looks "normal" in a
305 // mirrored graphics device (double mirroring!)
306 pDev->DrawLine( Point( nRect.Right(), nRect.Bottom()-n3 ),
307 Point( nRect.Right()-n3, nRect.Bottom() ) );
308 pDev->DrawLine( Point( nRect.Right()-n3, nRect.Bottom() ),
309 Point( nRect.Left(), nRect.Top()+n3 ) );
310 nRect.AdjustTop( 1 );
311 nRect.AdjustBottom( 1 );
312 pDev->DrawLine( Point( nRect.Right(), nRect.Bottom()-n3 ),
313 Point( nRect.Right()-n3, nRect.Bottom() ) );
314 pDev->DrawLine( Point( nRect.Right()-n3, nRect.Bottom() ),
315 Point( nRect.Left(), nRect.Top()+n3 ) );
316 }
317 else
318 {
319 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom()-n3 ),
320 Point( nRect.Left()+n3, nRect.Bottom() ) );
321 pDev->DrawLine( Point( nRect.Left()+n3, nRect.Bottom() ),
322 Point( nRect.Right(), nRect.Top()+n3 ) );
323 nRect.AdjustTop( 1 );
324 nRect.AdjustBottom( 1 );
325 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom()-n3 ),
326 Point( nRect.Left()+n3, nRect.Bottom() ) );
327 pDev->DrawLine( Point( nRect.Left()+n3, nRect.Bottom() ),
328 Point( nRect.Right(), nRect.Top()+n3 ) );
329 }
330 }
331 break;
332
333 case SymbolType::FLOAT:
334 nRect.AdjustRight( -n4 );
335 nRect.AdjustTop(n4+1 );
336 pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(),
337 nRect.Right(), nRect.Top()+n8 ) );
338 pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ),
339 Point( nRect.Left(), nRect.Bottom() ) );
340 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
341 Point( nRect.Right(), nRect.Bottom() ) );
342 pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ),
343 Point( nRect.Right(), nRect.Bottom() ) );
344 nRect.AdjustRight(n4 );
345 nRect.AdjustTop( -(n4+1) );
346 nRect.AdjustLeft(n4 );
347 nRect.AdjustBottom( -(n4+1) );
348 pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(),
349 nRect.Right(), nRect.Top()+n8 ) );
350 pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ),
351 Point( nRect.Left(), nRect.Bottom() ) );
352 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
353 Point( nRect.Right(), nRect.Bottom() ) );
354 pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ),
355 Point( nRect.Right(), nRect.Bottom() ) );
356 break;
357
358 case SymbolType::DOCK:
359 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
360 Point( nRect.Right(), nRect.Top() ) );
361 pDev->DrawLine( Point( nRect.Left(), nRect.Top() ),
362 Point( nRect.Left(), nRect.Bottom() ) );
363 pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ),
364 Point( nRect.Right(), nRect.Bottom() ) );
365 pDev->DrawLine( Point( nRect.Right(), nRect.Top() ),
366 Point( nRect.Right(), nRect.Bottom() ) );
367 break;
368
369 case SymbolType::HIDE:
370 pDev->DrawRect( tools::Rectangle( nRect.Left()+n8, nRect.Bottom()-n8,
371 nRect.Right()-n8, nRect.Bottom() ) );
372 break;
373
374 case SymbolType::PLUS:
375 pDev->DrawRect( tools::Rectangle( nRect.Left(), aCenter.Y()-n16,
376 nRect.Right(), aCenter.Y()+n16 ) );
377 pDev->DrawRect( tools::Rectangle( aCenter.X()-n16, nRect.Top(),
378 aCenter.X()+n16, nRect.Bottom() ) );
379 break;
380 case SymbolType::DONTKNOW:
381 case SymbolType::IMAGE:
382 case SymbolType::HELP: break;
383 }
384 }
385
ImplDrawDPILineRect(OutputDevice * const pDev,tools::Rectangle & rRect,const Color * const pColor,const bool bRound=false)386 void ImplDrawDPILineRect( OutputDevice *const pDev, tools::Rectangle& rRect,
387 const Color *const pColor, const bool bRound = false )
388 {
389 tools::Long nLineWidth = pDev->GetDPIX()/300;
390 tools::Long nLineHeight = pDev->GetDPIY()/300;
391 if ( !nLineWidth )
392 nLineWidth = 1;
393 if ( !nLineHeight )
394 nLineHeight = 1;
395
396 if ( pColor )
397 {
398 if ( (nLineWidth == 1) && (nLineHeight == 1) )
399 {
400 pDev->SetLineColor( *pColor );
401 if( bRound )
402 {
403 pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()), Point( rRect.Right()-1, rRect.Top()) );
404 pDev->DrawLine( Point( rRect.Left()+1, rRect.Bottom()), Point( rRect.Right()-1, rRect.Bottom()) );
405 pDev->DrawLine( Point( rRect.Left(), rRect.Top()+1), Point( rRect.Left(), rRect.Bottom()-1) );
406 pDev->DrawLine( Point( rRect.Right(), rRect.Top()+1), Point( rRect.Right(), rRect.Bottom()-1) );
407 }
408 else
409 {
410 pDev->SetFillColor();
411 pDev->DrawRect( rRect );
412 }
413 }
414 else
415 {
416 const tools::Long nWidth = rRect.GetWidth();
417 const tools::Long nHeight = rRect.GetHeight();
418 pDev->SetLineColor();
419 pDev->SetFillColor( *pColor );
420 pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nWidth, nLineHeight ) ) );
421 pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nLineWidth, nHeight ) ) );
422 pDev->DrawRect( tools::Rectangle( Point( rRect.Left(), rRect.Bottom()-nLineHeight ),
423 Size( nWidth, nLineHeight ) ) );
424 pDev->DrawRect( tools::Rectangle( Point( rRect.Right()-nLineWidth, rRect.Top() ),
425 Size( nLineWidth, nHeight ) ) );
426 }
427 }
428
429 rRect.AdjustLeft(nLineWidth );
430 rRect.AdjustTop(nLineHeight );
431 rRect.AdjustRight( -nLineWidth );
432 rRect.AdjustBottom( -nLineHeight );
433 }
434
ImplDraw2ColorFrame(OutputDevice * const pDev,tools::Rectangle & rRect,const Color & rLeftTopColor,const Color & rRightBottomColor)435 void ImplDraw2ColorFrame( OutputDevice *const pDev, tools::Rectangle& rRect,
436 const Color& rLeftTopColor, const Color& rRightBottomColor )
437 {
438 pDev->SetLineColor( rLeftTopColor );
439 pDev->DrawLine( rRect.TopLeft(), rRect.BottomLeft() );
440 pDev->DrawLine( rRect.TopLeft(), rRect.TopRight() );
441 pDev->SetLineColor( rRightBottomColor );
442 pDev->DrawLine( rRect.BottomLeft(), rRect.BottomRight() );
443 pDev->DrawLine( rRect.TopRight(), rRect.BottomRight() );
444
445 // reduce drawing area
446 rRect.AdjustLeft( 1 );
447 rRect.AdjustTop( 1 );
448 rRect.AdjustRight( -1 );
449 rRect.AdjustBottom( -1 );
450 }
451
ImplDrawButton(OutputDevice * const pDev,tools::Rectangle aFillRect,const DrawButtonFlags nStyle)452 void ImplDrawButton( OutputDevice *const pDev, tools::Rectangle aFillRect,
453 const DrawButtonFlags nStyle )
454 {
455 const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
456
457 if ( (nStyle & DrawButtonFlags::Mono) ||
458 (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) )
459 {
460 const Color aBlackColor(COL_BLACK);
461
462 if ( nStyle & DrawButtonFlags::Default )
463 {
464 // default selection shows a wider border
465 ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
466 }
467
468 ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor );
469
470 Size aBrdSize(pDev->GetButtonBorderSize());
471
472 pDev->SetLineColor();
473 pDev->SetFillColor( aBlackColor );
474 const tools::Rectangle aOrigFillRect(aFillRect);
475 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
476 {
477 // shrink fill rect
478 aFillRect.AdjustLeft(aBrdSize.Width() );
479 aFillRect.AdjustTop(aBrdSize.Height() );
480 // draw top and left borders (aOrigFillRect-aFillRect)
481 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(),
482 aOrigFillRect.Right(), aFillRect.Top()-1 ) );
483 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(),
484 aFillRect.Left()-1, aOrigFillRect.Bottom() ) );
485 }
486 else
487 {
488 // shrink fill rect
489 aFillRect.AdjustRight( -(aBrdSize.Width()) );
490 aFillRect.AdjustBottom( -(aBrdSize.Height()) );
491 // draw bottom and right borders (aOrigFillRect-aFillRect)
492 pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aFillRect.Bottom()+1,
493 aOrigFillRect.Right(), aOrigFillRect.Bottom() ) );
494 pDev->DrawRect( tools::Rectangle( aFillRect.Right()+1, aOrigFillRect.Top(),
495 aOrigFillRect.Right(), aOrigFillRect.Bottom() ) );
496 }
497
498 // Hack: in monochrome mode on printers we like to have grey buttons
499 pDev->SetFillColor(pDev->GetMonochromeButtonColor());
500 pDev->DrawRect( aFillRect );
501 }
502 else
503 {
504 if ( nStyle & DrawButtonFlags::Default )
505 {
506 const Color aDefBtnColor = rStyleSettings.GetDarkShadowColor();
507 ImplDrawDPILineRect( pDev, aFillRect, &aDefBtnColor );
508 }
509
510 if ( nStyle & DrawButtonFlags::NoLeftLightBorder )
511 {
512 pDev->SetLineColor( rStyleSettings.GetLightBorderColor() );
513 pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Top() ),
514 Point( aFillRect.Left(), aFillRect.Bottom() ) );
515 aFillRect.AdjustLeft( 1 );
516 }
517
518 Color aColor1;
519 Color aColor2;
520 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
521 {
522 aColor1 = rStyleSettings.GetDarkShadowColor();
523 aColor2 = rStyleSettings.GetLightColor();
524 }
525 else
526 {
527 if ( nStyle & DrawButtonFlags::NoLightBorder )
528 aColor1 = rStyleSettings.GetLightBorderColor();
529 else
530 aColor1 = rStyleSettings.GetLightColor();
531 if ( (nStyle & BUTTON_DRAW_FLATTEST) == DrawButtonFlags::Flat )
532 aColor2 = rStyleSettings.GetShadowColor();
533 else
534 aColor2 = rStyleSettings.GetDarkShadowColor();
535 }
536
537 ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 );
538
539 if ( (nStyle & BUTTON_DRAW_FLATTEST) != DrawButtonFlags::Flat )
540 {
541 if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) )
542 {
543 aColor1 = rStyleSettings.GetShadowColor();
544 aColor2 = rStyleSettings.GetLightBorderColor();
545 }
546 else
547 {
548 if ( nStyle & DrawButtonFlags::NoLightBorder )
549 aColor1 = rStyleSettings.GetLightColor();
550 else
551 aColor1 = rStyleSettings.GetLightBorderColor();
552 aColor2 = rStyleSettings.GetShadowColor();
553 }
554 ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 );
555 }
556
557 pDev->SetLineColor();
558 if ( nStyle & (DrawButtonFlags::Checked | DrawButtonFlags::DontKnow) )
559 pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
560 else
561 pDev->SetFillColor( rStyleSettings.GetFaceColor() );
562 pDev->DrawRect( aFillRect );
563 }
564 }
565
ImplDrawFrame(OutputDevice * const pDev,tools::Rectangle & rRect,const StyleSettings & rStyleSettings,DrawFrameStyle nStyle,DrawFrameFlags nFlags)566 void ImplDrawFrame( OutputDevice *const pDev, tools::Rectangle& rRect,
567 const StyleSettings& rStyleSettings, DrawFrameStyle nStyle, DrawFrameFlags nFlags )
568 {
569 vcl::Window * pWin = pDev->GetOwnerWindow();
570
571 const bool bMenuStyle(nFlags & DrawFrameFlags::Menu);
572
573 // UseFlatBorders disables 3D style for all frames except menus
574 // menus may use different border colors (eg on XP)
575 // normal frames will be drawn using the shadow color
576 // whereas window frame borders will use black
577 bool bFlatBorders = !bMenuStyle && rStyleSettings.GetUseFlatBorders();
578
579 // no flat borders for standard VCL controls (ie formcontrols that keep their classic look)
580 // will not affect frame windows (like dropdowns)
581 if( bFlatBorders && pWin && pWin->GetType() == WindowType::BORDERWINDOW && (pWin != pWin->ImplGetFrameWindow()) )
582 {
583 // check for formcontrol, i.e., a control without NWF enabled
584 Control *const pControl = dynamic_cast< Control* >( pWin->GetWindow( GetWindowType::Client ) );
585 if( !pControl || !pControl->IsNativeWidgetEnabled() )
586 bFlatBorders = false;
587 }
588
589 const bool bNoDraw(nFlags & DrawFrameFlags::NoDraw);
590
591 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
592 (pDev->GetOutDevType() == OUTDEV_PRINTER) ||
593 bFlatBorders )
594 nFlags |= DrawFrameFlags::Mono;
595
596 if( nStyle != DrawFrameStyle::NWF &&
597 pWin && pWin->IsNativeControlSupported(ControlType::Frame, ControlPart::Border) )
598 {
599 tools::Long nControlFlags = static_cast<tools::Long>(nStyle);
600 nControlFlags |= static_cast<tools::Long>(nFlags);
601 nControlFlags |= static_cast<tools::Long>(pWin->GetType() == WindowType::BORDERWINDOW ?
602 DrawFrameFlags::BorderWindowBorder : DrawFrameFlags::NONE);
603 ImplControlValue aControlValue( nControlFlags );
604
605 tools::Rectangle aBound, aContent;
606 tools::Rectangle aNatRgn( rRect );
607 if( pWin->GetNativeControlRegion(ControlType::Frame, ControlPart::Border,
608 aNatRgn, ControlState::NONE, aControlValue, aBound, aContent) )
609 {
610 // if bNoDraw is true then don't call the drawing routine
611 // but just update the target rectangle
612 if( bNoDraw ||
613 pWin->GetOutDev()->DrawNativeControl( ControlType::Frame, ControlPart::Border, aBound, ControlState::ENABLED,
614 aControlValue, OUString()) )
615 {
616 rRect = aContent;
617 return;
618 }
619 }
620 }
621
622 if ( nFlags & DrawFrameFlags::Mono )
623 {
624 // no round corners for window frame borders
625 const bool bRound = bFlatBorders && !(nFlags & DrawFrameFlags::WindowBorder);
626
627 if ( bNoDraw )
628 {
629 ImplDrawDPILineRect( pDev, rRect, nullptr, bRound );
630 }
631 else
632 {
633 Color aColor = bRound ? rStyleSettings.GetShadowColor()
634 : pDev->GetSettings().GetStyleSettings().GetMonoColor();
635 // when the MonoColor wasn't set, check face color
636 if (
637 (bRound && aColor.IsDark()) ||
638 (
639 (aColor == COL_BLACK) &&
640 pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark()
641 )
642 )
643 {
644 aColor = COL_WHITE;
645 }
646 ImplDrawDPILineRect( pDev, rRect, &aColor, bRound );
647 }
648 }
649 else
650 {
651 if ( bNoDraw )
652 {
653 switch ( nStyle )
654 {
655 case DrawFrameStyle::In:
656 case DrawFrameStyle::Out:
657 rRect.AdjustLeft( 1 );
658 rRect.AdjustTop( 1 );
659 rRect.AdjustRight( -1 );
660 rRect.AdjustBottom( -1 );
661 break;
662
663 case DrawFrameStyle::Group:
664 case DrawFrameStyle::DoubleIn:
665 case DrawFrameStyle::DoubleOut:
666 rRect.AdjustLeft(2 );
667 rRect.AdjustTop(2 );
668 rRect.AdjustRight( -2 );
669 rRect.AdjustBottom( -2 );
670 break;
671
672 case DrawFrameStyle::NWF:
673 // enough space for the native rendering
674 rRect.AdjustLeft(4 );
675 rRect.AdjustTop(4 );
676 rRect.AdjustRight( -4 );
677 rRect.AdjustBottom( -4 );
678 break;
679 default: break;
680 }
681 }
682 else
683 {
684 switch ( nStyle )
685 {
686 case DrawFrameStyle::Group:
687 pDev->SetFillColor();
688 pDev->SetLineColor( rStyleSettings.GetLightColor() );
689 pDev->DrawRect( tools::Rectangle( rRect.Left()+1, rRect.Top()+1,
690 rRect.Right(), rRect.Bottom() ) );
691 pDev->SetLineColor( rStyleSettings.GetShadowColor() );
692 pDev->DrawRect( tools::Rectangle( rRect.Left(), rRect.Top(),
693 rRect.Right()-1, rRect.Bottom()-1 ) );
694
695 // adjust target rectangle
696 rRect.AdjustLeft(2 );
697 rRect.AdjustTop(2 );
698 rRect.AdjustRight( -2 );
699 rRect.AdjustBottom( -2 );
700 break;
701
702 case DrawFrameStyle::In:
703 ImplDraw2ColorFrame( pDev, rRect,
704 rStyleSettings.GetShadowColor(),
705 rStyleSettings.GetLightColor() );
706 break;
707
708 case DrawFrameStyle::Out:
709 ImplDraw2ColorFrame( pDev, rRect,
710 rStyleSettings.GetLightColor(),
711 rStyleSettings.GetShadowColor() );
712 break;
713
714 case DrawFrameStyle::DoubleIn:
715 if( bFlatBorders )
716 {
717 // no 3d effect
718 ImplDraw2ColorFrame( pDev, rRect,
719 rStyleSettings.GetShadowColor(),
720 rStyleSettings.GetShadowColor() );
721 ImplDraw2ColorFrame( pDev, rRect,
722 rStyleSettings.GetFaceColor(),
723 rStyleSettings.GetFaceColor() );
724 }
725 else
726 {
727 ImplDraw2ColorFrame( pDev, rRect,
728 rStyleSettings.GetShadowColor(),
729 rStyleSettings.GetLightColor() );
730 ImplDraw2ColorFrame( pDev, rRect,
731 rStyleSettings.GetDarkShadowColor(),
732 rStyleSettings.GetLightBorderColor() );
733 }
734 break;
735
736 case DrawFrameStyle::DoubleOut:
737 if( bMenuStyle )
738 {
739 ImplDraw2ColorFrame( pDev, rRect,
740 rStyleSettings.GetMenuBorderColor(),
741 rStyleSettings.GetDarkShadowColor() );
742 if ( !rStyleSettings.GetUseFlatMenus() )
743 {
744 ImplDraw2ColorFrame( pDev, rRect,
745 rStyleSettings.GetLightColor(),
746 rStyleSettings.GetShadowColor() );
747 }
748 }
749 else
750 {
751 ImplDraw2ColorFrame( pDev, rRect,
752 bFlatBorders ? // no 3d effect
753 rStyleSettings.GetDarkShadowColor() :
754 rStyleSettings.GetLightBorderColor(),
755 rStyleSettings.GetDarkShadowColor() );
756 ImplDraw2ColorFrame( pDev, rRect,
757 rStyleSettings.GetLightColor(),
758 rStyleSettings.GetShadowColor() );
759 }
760 break;
761
762 case DrawFrameStyle::NWF:
763 // no rendering, just enough space for the native rendering
764 rRect.AdjustLeft(4 );
765 rRect.AdjustTop(4 );
766 rRect.AdjustRight( -4 );
767 rRect.AdjustBottom( -4 );
768 break;
769 default: break;
770 }
771 }
772 }
773 }
774
775 } // end anonymous namespace
776
DecorationView(OutputDevice * pOutDev)777 DecorationView::DecorationView(OutputDevice* pOutDev) :
778 mpOutDev(pOutDev)
779 {}
780
DrawSymbol(const tools::Rectangle & rRect,SymbolType eType,const Color & rColor,DrawSymbolFlags nStyle)781 void DecorationView::DrawSymbol( const tools::Rectangle& rRect, SymbolType eType,
782 const Color& rColor, DrawSymbolFlags nStyle )
783 {
784 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
785 const tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect );
786 const Color aOldLineColor = mpOutDev->GetLineColor();
787 const Color aOldFillColor = mpOutDev->GetFillColor();
788 const bool bOldMapMode = mpOutDev->IsMapModeEnabled();
789 Color nColor(rColor);
790 mpOutDev->EnableMapMode( false );
791
792 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
793 (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
794 nStyle |= DrawSymbolFlags::Mono;
795
796 if ( nStyle & DrawSymbolFlags::Mono )
797 {
798 // Monochrome: set color to black if enabled, to gray if disabled
799 nColor = ( nStyle & DrawSymbolFlags::Disable ) ? COL_GRAY : COL_BLACK;
800 }
801 else
802 {
803 if ( nStyle & DrawSymbolFlags::Disable )
804 {
805 // Draw shifted and brighter symbol for embossed look
806 mpOutDev->SetLineColor( rStyleSettings.GetLightColor() );
807 mpOutDev->SetFillColor( rStyleSettings.GetLightColor() );
808 ImplDrawSymbol( mpOutDev, aRect + Point(1, 1) , eType );
809 nColor = rStyleSettings.GetShadowColor();
810 }
811 }
812
813 // Set selected color and draw the symbol
814 mpOutDev->SetLineColor( nColor );
815 mpOutDev->SetFillColor( nColor );
816 ImplDrawSymbol( mpOutDev, aRect, eType );
817
818 // Restore previous settings
819 mpOutDev->SetLineColor( aOldLineColor );
820 mpOutDev->SetFillColor( aOldFillColor );
821 mpOutDev->EnableMapMode( bOldMapMode );
822 }
823
DrawFrame(const tools::Rectangle & rRect,const Color & rLeftTopColor,const Color & rRightBottomColor)824 void DecorationView::DrawFrame( const tools::Rectangle& rRect,
825 const Color& rLeftTopColor,
826 const Color& rRightBottomColor )
827 {
828 tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect );
829 const Color aOldLineColor = mpOutDev->GetLineColor();
830 const bool bOldMapMode = mpOutDev->IsMapModeEnabled();
831 mpOutDev->EnableMapMode( false );
832 ImplDraw2ColorFrame( mpOutDev, aRect, rLeftTopColor, rRightBottomColor );
833 mpOutDev->SetLineColor( aOldLineColor );
834 mpOutDev->EnableMapMode( bOldMapMode );
835 }
836
DrawHighlightFrame(const tools::Rectangle & rRect,DrawHighlightFrameStyle nStyle)837 void DecorationView::DrawHighlightFrame( const tools::Rectangle& rRect,
838 DrawHighlightFrameStyle nStyle )
839 {
840 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
841 Color aLightColor = rStyleSettings.GetLightColor();
842 Color aShadowColor = rStyleSettings.GetShadowColor();
843
844 if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ||
845 (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) )
846 {
847 aLightColor = COL_BLACK;
848 aShadowColor = COL_BLACK;
849 }
850 else
851 {
852 Wallpaper aBackground = mpOutDev->GetBackground();
853 if ( aBackground.IsBitmap() || aBackground.IsGradient() )
854 {
855 aLightColor = rStyleSettings.GetFaceColor();
856 aShadowColor = COL_BLACK;
857 }
858 else
859 {
860 Color aBackColor = aBackground.GetColor();
861 if ( (aLightColor.GetColorError( aBackColor ) < 96) ||
862 (aShadowColor.GetColorError( aBackColor ) < 96) )
863 {
864 aLightColor = COL_WHITE;
865 aShadowColor = COL_BLACK;
866
867 if ( aLightColor.GetColorError( aBackColor ) < 96 )
868 aLightColor.DecreaseLuminance( 64 );
869 if ( aShadowColor.GetColorError( aBackColor ) < 96 )
870 aShadowColor.IncreaseLuminance( 64 );
871 }
872 }
873 }
874
875 if ( nStyle == DrawHighlightFrameStyle::In )
876 {
877 Color aTempColor = aLightColor;
878 aLightColor = aShadowColor;
879 aShadowColor = aTempColor;
880 }
881
882 DrawFrame( rRect, aLightColor, aShadowColor );
883 }
884
DrawFrame(const tools::Rectangle & rRect,DrawFrameStyle nStyle,DrawFrameFlags nFlags)885 tools::Rectangle DecorationView::DrawFrame( const tools::Rectangle& rRect, DrawFrameStyle nStyle, DrawFrameFlags nFlags )
886 {
887 tools::Rectangle aRect = rRect;
888 bool bOldMap = mpOutDev->IsMapModeEnabled();
889 if ( bOldMap )
890 {
891 aRect = mpOutDev->LogicToPixel( aRect );
892 mpOutDev->EnableMapMode( false );
893 }
894
895 if ( !rRect.IsEmpty() )
896 {
897 if ( nFlags & DrawFrameFlags::NoDraw )
898 ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags );
899 else
900 {
901 Color aOldLineColor = mpOutDev->GetLineColor();
902 Color aOldFillColor = mpOutDev->GetFillColor();
903 ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags );
904 mpOutDev->SetLineColor( aOldLineColor );
905 mpOutDev->SetFillColor( aOldFillColor );
906 }
907 }
908
909 if ( bOldMap )
910 {
911 mpOutDev->EnableMapMode( bOldMap );
912 aRect = mpOutDev->PixelToLogic( aRect );
913 }
914
915 return aRect;
916 }
917
DrawButton(const tools::Rectangle & rRect,DrawButtonFlags nStyle)918 tools::Rectangle DecorationView::DrawButton( const tools::Rectangle& rRect, DrawButtonFlags nStyle )
919 {
920 if ( rRect.IsEmpty() )
921 {
922 return rRect;
923 }
924
925 tools::Rectangle aRect = rRect;
926 const bool bOldMap = mpOutDev->IsMapModeEnabled();
927
928 if ( bOldMap )
929 {
930 aRect = mpOutDev->LogicToPixel( aRect );
931 mpOutDev->EnableMapMode( false );
932 }
933
934 const Color aOldLineColor = mpOutDev->GetLineColor();
935 const Color aOldFillColor = mpOutDev->GetFillColor();
936 ImplDrawButton( mpOutDev, aRect, nStyle );
937 mpOutDev->SetLineColor( aOldLineColor );
938 mpOutDev->SetFillColor( aOldFillColor );
939
940 // keep border free, although it is used at default representation
941 aRect.AdjustLeft( 1 );
942 aRect.AdjustTop( 1 );
943 aRect.AdjustRight( -1 );
944 aRect.AdjustBottom( -1 );
945
946 if ( nStyle & DrawButtonFlags::NoLightBorder )
947 {
948 aRect.AdjustLeft( 1 );
949 aRect.AdjustTop( 1 );
950 }
951 else if ( nStyle & DrawButtonFlags::NoLeftLightBorder )
952 {
953 aRect.AdjustLeft( 1 );
954 }
955
956 if ( nStyle & DrawButtonFlags::Pressed )
957 {
958 if ( (aRect.GetHeight() > 10) && (aRect.GetWidth() > 10) )
959 {
960 aRect.AdjustLeft(4 );
961 aRect.AdjustTop(4 );
962 aRect.AdjustRight( -1 );
963 aRect.AdjustBottom( -1 );
964 }
965 else
966 {
967 aRect.AdjustLeft(3 );
968 aRect.AdjustTop(3 );
969 aRect.AdjustRight( -2 );
970 aRect.AdjustBottom( -2 );
971 }
972 }
973 else if ( nStyle & DrawButtonFlags::Checked )
974 {
975 aRect.AdjustLeft(3 );
976 aRect.AdjustTop(3 );
977 aRect.AdjustRight( -2 );
978 aRect.AdjustBottom( -2 );
979 }
980 else
981 {
982 aRect.AdjustLeft(2 );
983 aRect.AdjustTop(2 );
984 aRect.AdjustRight( -3 );
985 aRect.AdjustBottom( -3 );
986 }
987
988 if ( bOldMap )
989 {
990 mpOutDev->EnableMapMode( bOldMap );
991 aRect = mpOutDev->PixelToLogic( aRect );
992 }
993
994 return aRect;
995 }
996
DrawSeparator(const Point & rStart,const Point & rStop,bool bVertical)997 void DecorationView::DrawSeparator( const Point& rStart, const Point& rStop, bool bVertical )
998 {
999 Point aStart( rStart ), aStop( rStop );
1000 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
1001 vcl::Window *const pWin = mpOutDev->GetOwnerWindow();
1002 if(pWin)
1003 {
1004 ControlPart nPart = ( bVertical ? ControlPart::SeparatorVert : ControlPart::SeparatorHorz );
1005 bool nativeSupported = pWin->IsNativeControlSupported( ControlType::Fixedline, nPart );
1006 ImplControlValue aValue;
1007 tools::Rectangle aRect(rStart,rStop);
1008 if(nativeSupported && pWin->GetOutDev()->DrawNativeControl(ControlType::Fixedline,nPart,aRect,ControlState::NONE,aValue,OUString()))
1009 return;
1010 }
1011
1012 mpOutDev->Push( PushFlags::LINECOLOR );
1013 if ( rStyleSettings.GetOptions() & StyleSettingsOptions::Mono )
1014 mpOutDev->SetLineColor( COL_BLACK );
1015 else
1016 mpOutDev->SetLineColor( rStyleSettings.GetShadowColor() );
1017
1018 mpOutDev->DrawLine( aStart, aStop );
1019 if ( !(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) )
1020 {
1021 mpOutDev->SetLineColor( rStyleSettings.GetLightColor() );
1022 if( bVertical )
1023 {
1024 aStart.AdjustX( 1 );
1025 aStop.AdjustX( 1 );
1026 }
1027 else
1028 {
1029 aStart.AdjustY( 1 );
1030 aStop.AdjustY( 1 );
1031 }
1032 mpOutDev->DrawLine( aStart, aStop );
1033 }
1034 mpOutDev->Pop();
1035 }
1036
DrawHandle(const tools::Rectangle & rRect)1037 void DecorationView::DrawHandle(const tools::Rectangle& rRect)
1038 {
1039 const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings();
1040
1041 Size aOutputSize = rRect.GetSize();
1042
1043 mpOutDev->SetLineColor(rStyleSettings.GetDarkShadowColor());
1044 mpOutDev->SetFillColor(rStyleSettings.GetDarkShadowColor());
1045
1046 const sal_Int32 nNumberOfPoints = 3;
1047
1048 tools::Long nHalfWidth = aOutputSize.Width() / 2.0f;
1049
1050 float fDistance = aOutputSize.Height();
1051 fDistance /= (nNumberOfPoints + 1);
1052
1053 tools::Long nRadius = aOutputSize.Width();
1054 nRadius /= (nNumberOfPoints + 2);
1055
1056 for (tools::Long i = 1; i <= nNumberOfPoints; i++)
1057 {
1058 tools::Rectangle aLocation(nHalfWidth - nRadius,
1059 round(fDistance * i) - nRadius,
1060 nHalfWidth + nRadius,
1061 round(fDistance * i) + nRadius);
1062 mpOutDev->DrawEllipse(aLocation);
1063 }
1064 }
1065
1066 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1067