/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include namespace { tools::Long AdjustRectToSquare( tools::Rectangle &rRect ) { const tools::Long nWidth = rRect.GetWidth(); const tools::Long nHeight = rRect.GetHeight(); tools::Long nSide = std::min( nWidth, nHeight ); if ( nSide && !(nSide & 1) ) { // we prefer an odd size --nSide; } // Make the rectangle a square rRect.SetSize( Size( nSide, nSide ) ); // and place it at the center of the original rectangle rRect.Move( (nWidth-nSide)/2, (nHeight-nSide)/2 ); return nSide; } void ImplDrawSymbol( OutputDevice* pDev, tools::Rectangle nRect, const SymbolType eType ) { const tools::Long nSide = AdjustRectToSquare( nRect ); if ( !nSide ) return; if ( nSide==1 ) { pDev->DrawPixel( Point( nRect.Left(), nRect.Top() ) ); return; } // Precalculate some values const tools::Long n2 = nSide/2; const tools::Long n4 = (n2+1)/2; const tools::Long n8 = (n4+1)/2; const tools::Long n16 = (n8+1)/2; const Point aCenter = nRect.Center(); switch ( eType ) { case SymbolType::ARROW_UP: { tools::Polygon arrow(7); arrow.SetPoint( Point( aCenter.X(), nRect.Top()), 0 ); arrow.SetPoint( Point( aCenter.X() - n2, nRect.Top() + n2 ), 1 ); arrow.SetPoint( Point( aCenter.X() - n8, nRect.Top() + n2 ), 2 ); arrow.SetPoint( Point( aCenter.X() - n8, nRect.Bottom()), 3 ); arrow.SetPoint( Point( aCenter.X() + n8, nRect.Bottom()), 4 ); arrow.SetPoint( Point( aCenter.X() + n8, nRect.Top() + n2 ), 5 ); arrow.SetPoint( Point( aCenter.X() + n2, nRect.Top() + n2 ), 6 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( arrow ); pDev->Pop(); break; } case SymbolType::ARROW_DOWN: { tools::Polygon arrow(7); arrow.SetPoint( Point( aCenter.X(), nRect.Bottom()), 0 ); arrow.SetPoint( Point( aCenter.X() - n2, nRect.Bottom() - n2 ), 1 ); arrow.SetPoint( Point( aCenter.X() - n8, nRect.Bottom() - n2 ), 2 ); arrow.SetPoint( Point( aCenter.X() - n8, nRect.Top()), 3 ); arrow.SetPoint( Point( aCenter.X() + n8, nRect.Top()), 4 ); arrow.SetPoint( Point( aCenter.X() + n8, nRect.Bottom() - n2 ), 5 ); arrow.SetPoint( Point( aCenter.X() + n2, nRect.Bottom() - n2 ), 6 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( arrow ); pDev->Pop(); break; } case SymbolType::ARROW_LEFT: { tools::Polygon arrow(7); arrow.SetPoint( Point( nRect.Left(), aCenter.Y()), 0 ); arrow.SetPoint( Point( nRect.Left() + n2, aCenter.Y() - n2 ), 1 ); arrow.SetPoint( Point( nRect.Left() + n2, aCenter.Y() - n8 ), 2 ); arrow.SetPoint( Point( nRect.Right(), aCenter.Y() - n8 ), 3 ); arrow.SetPoint( Point( nRect.Right(), aCenter.Y() + n8 ), 4 ); arrow.SetPoint( Point( nRect.Left() + n2, aCenter.Y() + n8 ), 5 ); arrow.SetPoint( Point( nRect.Left() + n2, aCenter.Y() + n2 ), 6 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( arrow ); pDev->Pop(); break; } case SymbolType::ARROW_RIGHT: { tools::Polygon arrow(7); arrow.SetPoint( Point( nRect.Right(), aCenter.Y()), 0 ); arrow.SetPoint( Point( nRect.Right() - n2, aCenter.Y() - n2 ), 1 ); arrow.SetPoint( Point( nRect.Right() - n2, aCenter.Y() - n8 ), 2 ); arrow.SetPoint( Point( nRect.Left(), aCenter.Y() - n8 ), 3 ); arrow.SetPoint( Point( nRect.Left(), aCenter.Y() + n8 ), 4 ); arrow.SetPoint( Point( nRect.Right() - n2, aCenter.Y() + n8 ), 5 ); arrow.SetPoint( Point( nRect.Right() - n2, aCenter.Y() + n2 ), 6 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( arrow ); pDev->Pop(); break; } case SymbolType::SPIN_UP: { tools::Polygon triangle( 3 ); triangle.SetPoint( Point( aCenter.X(), nRect.Top() + n4 ), 0 ); triangle.SetPoint( Point( aCenter.X() - n2, nRect.Top() + n4 + n2 ), 1 ); triangle.SetPoint( Point( aCenter.X() + n2, nRect.Top() + n4 + n2 ), 2 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( triangle ); pDev->Pop(); break; } case SymbolType::SPIN_DOWN: { tools::Polygon triangle( 3 ); triangle.SetPoint( Point( aCenter.X(), nRect.Bottom() - n4 ), 0 ); triangle.SetPoint( Point( aCenter.X() - n2, nRect.Bottom() - n4 - n2 ), 1 ); triangle.SetPoint( Point( aCenter.X() + n2, nRect.Bottom() - n4 - n2 ), 2 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( triangle ); pDev->Pop(); break; } case SymbolType::SPIN_LEFT: case SymbolType::FIRST: case SymbolType::PREV: { nRect.AdjustLeft(n4 ); if ( eType==SymbolType::FIRST ) { pDev->DrawLine( Point( nRect.Left(), nRect.Top() ), Point( nRect.Left(), nRect.Bottom() ) ); nRect.AdjustLeft( 1 ); } tools::Polygon aTriangle(3); aTriangle.SetPoint(Point(nRect.Left() + n2, aCenter.Y() - n2), 0); aTriangle.SetPoint(Point(nRect.Left(), aCenter.Y()), 1); aTriangle.SetPoint(Point(nRect.Left() + n2, aCenter.Y() + n2), 2); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon(aTriangle); pDev->Pop(); break; } case SymbolType::SPIN_RIGHT: case SymbolType::LAST: case SymbolType::NEXT: case SymbolType::PLAY: { nRect.AdjustRight( -n4 ); if ( eType==SymbolType::LAST ) { pDev->DrawLine( Point( nRect.Right(), nRect.Top() ), Point( nRect.Right(), nRect.Bottom() ) ); nRect.AdjustRight( -1 ); } tools::Polygon aTriangle(3); aTriangle.SetPoint(Point(nRect.Right() - n2, aCenter.Y() - n2), 0); aTriangle.SetPoint(Point(nRect.Right(), aCenter.Y()), 1); aTriangle.SetPoint(Point(nRect.Right() - n2, aCenter.Y() + n2), 2); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon(aTriangle); pDev->Pop(); break; } case SymbolType::PAGEUP: { tools::Polygon triangle( 3 ); triangle.SetPoint( Point( aCenter.X(), nRect.Top()), 0 ); triangle.SetPoint( Point( aCenter.X() - n2, nRect.Top() + n2 ), 1 ); triangle.SetPoint( Point( aCenter.X() + n2, nRect.Top() + n2 ), 2 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( triangle ); triangle.Move( 0, n2 ); pDev->DrawPolygon( triangle ); pDev->Pop(); break; } case SymbolType::PAGEDOWN: { tools::Polygon triangle( 3 ); triangle.SetPoint( Point( aCenter.X(), nRect.Bottom()), 0 ); triangle.SetPoint( Point( aCenter.X() - n2, nRect.Bottom() - n2 ), 1 ); triangle.SetPoint( Point( aCenter.X() + n2, nRect.Bottom() - n2 ), 2 ); pDev->Push(vcl::PushFlags::LINECOLOR); pDev->SetLineColor(); pDev->DrawPolygon( triangle ); triangle.Move( 0, -n2 ); pDev->DrawPolygon( triangle ); pDev->Pop(); break; } case SymbolType::RADIOCHECKMARK: { pDev->DrawEllipse(nRect); break; } case SymbolType::STOP: pDev->DrawRect( nRect ); break; case SymbolType::CLOSE: { const tools::Long diff = std::max( 0, n8 - 1 ); tools::Polygon cross( 16 ); cross.SetPoint( Point( nRect.Left(), nRect.Top()), 0 ); cross.SetPoint( Point( nRect.Left(), nRect.Top() + diff ), 1 ); cross.SetPoint( Point( aCenter.X() - diff, aCenter.Y()), 2 ); cross.SetPoint( Point( nRect.Left(), nRect.Bottom() - diff ), 3 ); cross.SetPoint( Point( nRect.Left(), nRect.Bottom()), 4 ); cross.SetPoint( Point( nRect.Left() + diff, nRect.Bottom()), 5 ); cross.SetPoint( Point( aCenter.X(), aCenter.Y() + diff ), 6 ); cross.SetPoint( Point( nRect.Right() - diff, nRect.Bottom()), 7 ); cross.SetPoint( Point( nRect.Right(), nRect.Bottom()), 8 ); cross.SetPoint( Point( nRect.Right(), nRect.Bottom() - diff ), 9 ); cross.SetPoint( Point( aCenter.X() + diff, aCenter.Y()), 10 ); cross.SetPoint( Point( nRect.Right(), nRect.Top() + diff ), 11 ); cross.SetPoint( Point( nRect.Right(), nRect.Top()), 12 ); cross.SetPoint( Point( nRect.Right() - diff, nRect.Top()), 13 ); cross.SetPoint( Point( aCenter.X(), aCenter.Y() - diff ), 14 ); cross.SetPoint( Point( nRect.Left() + diff, nRect.Top()), 15 ); pDev->DrawPolygon( cross ); break; } case SymbolType::CHECKMARK: { tools::Long n3 = nSide/3; nRect.AdjustTop( -(n3/2) ); nRect.AdjustBottom( -(n3/2) ); tools::Polygon checkmark(6); // #106953# never mirror checkmarks if ( pDev->HasMirroredGraphics() && pDev->IsRTLEnabled() ) { // Draw a mirrored checkmark so that it looks "normal" in a // mirrored graphics device (double mirroring!) checkmark.SetPoint( Point( nRect.Right(), nRect.Bottom()-n3 ), 0 ); checkmark.SetPoint( Point( nRect.Right()-n3, nRect.Bottom()), 1 ); checkmark.SetPoint( Point( nRect.Left(), nRect.Top()+n3 ), 2 ); checkmark.SetPoint( Point( nRect.Left(), nRect.Top()+n3 + 1 ), 3 ); checkmark.SetPoint( Point( nRect.Right()-n3, nRect.Bottom() + 1 ), 4 ); checkmark.SetPoint( Point( nRect.Right(), nRect.Bottom()-n3 + 1 ), 5 ); } else { checkmark.SetPoint( Point( nRect.Left(), nRect.Bottom()-n3 ), 0 ); checkmark.SetPoint( Point( nRect.Left()+n3, nRect.Bottom()), 1 ); checkmark.SetPoint( Point( nRect.Right(), nRect.Top()+n3 ), 2 ); checkmark.SetPoint( Point( nRect.Right(), nRect.Top()+n3 + 1 ), 3 ); checkmark.SetPoint( Point( nRect.Left()+n3, nRect.Bottom() + 1 ), 4 ); checkmark.SetPoint( Point( nRect.Left(), nRect.Bottom()-n3 + 1 ), 5 ); } pDev->DrawPolygon( checkmark ); } break; case SymbolType::FLOAT: nRect.AdjustRight( -n4 ); nRect.AdjustTop(n4+1 ); pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(), nRect.Right(), nRect.Top()+n8 ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ), Point( nRect.Left(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ), Point( nRect.Right(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ), Point( nRect.Right(), nRect.Bottom() ) ); nRect.AdjustRight(n4 ); nRect.AdjustTop( -(n4+1) ); nRect.AdjustLeft(n4 ); nRect.AdjustBottom( -(n4+1) ); pDev->DrawRect( tools::Rectangle( nRect.Left(), nRect.Top(), nRect.Right(), nRect.Top()+n8 ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Top()+n8 ), Point( nRect.Left(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ), Point( nRect.Right(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Right(), nRect.Top()+n8 ), Point( nRect.Right(), nRect.Bottom() ) ); break; case SymbolType::DOCK: pDev->DrawLine( Point( nRect.Left(), nRect.Top() ), Point( nRect.Right(), nRect.Top() ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Top() ), Point( nRect.Left(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Left(), nRect.Bottom() ), Point( nRect.Right(), nRect.Bottom() ) ); pDev->DrawLine( Point( nRect.Right(), nRect.Top() ), Point( nRect.Right(), nRect.Bottom() ) ); break; case SymbolType::HIDE: pDev->DrawRect( tools::Rectangle( nRect.Left()+n8, nRect.Bottom()-n8, nRect.Right()-n8, nRect.Bottom() ) ); break; case SymbolType::PLUS: pDev->DrawRect( tools::Rectangle( nRect.Left(), aCenter.Y()-n16, nRect.Right(), aCenter.Y()+n16 ) ); pDev->DrawRect( tools::Rectangle( aCenter.X()-n16, nRect.Top(), aCenter.X()+n16, nRect.Bottom() ) ); break; case SymbolType::DONTKNOW: case SymbolType::IMAGE: case SymbolType::HELP: break; } } void ImplDrawDPILineRect( OutputDevice *const pDev, tools::Rectangle& rRect, const Color *const pColor, const bool bRound = false ) { tools::Long nLineWidth = pDev->GetDPIX()/300; tools::Long nLineHeight = pDev->GetDPIY()/300; if ( !nLineWidth ) nLineWidth = 1; if ( !nLineHeight ) nLineHeight = 1; if ( pColor ) { if ( (nLineWidth == 1) && (nLineHeight == 1) ) { pDev->SetLineColor( *pColor ); if( bRound ) { pDev->DrawLine( Point( rRect.Left()+1, rRect.Top()), Point( rRect.Right()-1, rRect.Top()) ); pDev->DrawLine( Point( rRect.Left()+1, rRect.Bottom()), Point( rRect.Right()-1, rRect.Bottom()) ); pDev->DrawLine( Point( rRect.Left(), rRect.Top()+1), Point( rRect.Left(), rRect.Bottom()-1) ); pDev->DrawLine( Point( rRect.Right(), rRect.Top()+1), Point( rRect.Right(), rRect.Bottom()-1) ); } else { pDev->SetFillColor(); pDev->DrawRect( rRect ); } } else { const tools::Long nWidth = rRect.GetWidth(); const tools::Long nHeight = rRect.GetHeight(); pDev->SetLineColor(); pDev->SetFillColor( *pColor ); pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nWidth, nLineHeight ) ) ); pDev->DrawRect( tools::Rectangle( rRect.TopLeft(), Size( nLineWidth, nHeight ) ) ); pDev->DrawRect( tools::Rectangle( Point( rRect.Left(), rRect.Bottom()-nLineHeight ), Size( nWidth, nLineHeight ) ) ); pDev->DrawRect( tools::Rectangle( Point( rRect.Right()-nLineWidth, rRect.Top() ), Size( nLineWidth, nHeight ) ) ); } } rRect.AdjustLeft(nLineWidth ); rRect.AdjustTop(nLineHeight ); rRect.AdjustRight( -nLineWidth ); rRect.AdjustBottom( -nLineHeight ); } void ImplDraw2ColorFrame( OutputDevice *const pDev, tools::Rectangle& rRect, const Color& rLeftTopColor, const Color& rRightBottomColor ) { pDev->SetLineColor( rLeftTopColor ); pDev->DrawLine( rRect.TopLeft(), rRect.BottomLeft() ); pDev->DrawLine( rRect.TopLeft(), rRect.TopRight() ); pDev->SetLineColor( rRightBottomColor ); pDev->DrawLine( rRect.BottomLeft(), rRect.BottomRight() ); pDev->DrawLine( rRect.TopRight(), rRect.BottomRight() ); // reduce drawing area rRect.AdjustLeft( 1 ); rRect.AdjustTop( 1 ); rRect.AdjustRight( -1 ); rRect.AdjustBottom( -1 ); } void ImplDrawButton( OutputDevice *const pDev, tools::Rectangle aFillRect, const DrawButtonFlags nStyle ) { const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings(); if ( (nStyle & DrawButtonFlags::Mono) || (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ) { const Color aBlackColor(COL_BLACK); if ( nStyle & DrawButtonFlags::Default ) { // default selection shows a wider border ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor ); } ImplDrawDPILineRect( pDev, aFillRect, &aBlackColor ); Size aBrdSize(pDev->GetButtonBorderSize()); pDev->SetLineColor(); pDev->SetFillColor( aBlackColor ); const tools::Rectangle aOrigFillRect(aFillRect); if ( nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked) ) { // shrink fill rect aFillRect.AdjustLeft(aBrdSize.Width() ); aFillRect.AdjustTop(aBrdSize.Height() ); // draw top and left borders (aOrigFillRect-aFillRect) pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(), aOrigFillRect.Right(), aFillRect.Top()-1 ) ); pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aOrigFillRect.Top(), aFillRect.Left()-1, aOrigFillRect.Bottom() ) ); } else { // shrink fill rect aFillRect.AdjustRight( -(aBrdSize.Width()) ); aFillRect.AdjustBottom( -(aBrdSize.Height()) ); // draw bottom and right borders (aOrigFillRect-aFillRect) pDev->DrawRect( tools::Rectangle( aOrigFillRect.Left(), aFillRect.Bottom()+1, aOrigFillRect.Right(), aOrigFillRect.Bottom() ) ); pDev->DrawRect( tools::Rectangle( aFillRect.Right()+1, aOrigFillRect.Top(), aOrigFillRect.Right(), aOrigFillRect.Bottom() ) ); } // Hack: in monochrome mode on printers we like to have grey buttons pDev->SetFillColor(pDev->GetMonochromeButtonColor()); pDev->DrawRect( aFillRect ); } else { const bool bFlat(nStyle & DrawButtonFlags::Flat); const bool bDepressed(nStyle & (DrawButtonFlags::Pressed | DrawButtonFlags::Checked)); if ( nStyle & DrawButtonFlags::Default ) { const Color aDefBtnColor = rStyleSettings.GetDarkShadowColor(); ImplDrawDPILineRect( pDev, aFillRect, &aDefBtnColor ); } if ( nStyle & DrawButtonFlags::NoLeftLightBorder ) { pDev->SetLineColor( rStyleSettings.GetLightBorderColor() ); pDev->DrawLine( Point( aFillRect.Left(), aFillRect.Top() ), Point( aFillRect.Left(), aFillRect.Bottom() ) ); aFillRect.AdjustLeft( 1 ); } bool bNoFace = false; Color aColor1; Color aColor2; if (!bFlat) { if (bDepressed) { aColor1 = rStyleSettings.GetDarkShadowColor(); aColor2 = rStyleSettings.GetLightColor(); } else { if ( nStyle & DrawButtonFlags::NoLightBorder ) aColor1 = rStyleSettings.GetLightBorderColor(); else aColor1 = rStyleSettings.GetLightColor(); aColor2 = rStyleSettings.GetDarkShadowColor(); } ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 ); if (bDepressed) { aColor1 = rStyleSettings.GetShadowColor(); aColor2 = rStyleSettings.GetLightBorderColor(); } else { if ( nStyle & DrawButtonFlags::NoLightBorder ) aColor1 = rStyleSettings.GetLightColor(); else aColor1 = rStyleSettings.GetLightBorderColor(); aColor2 = rStyleSettings.GetShadowColor(); } ImplDraw2ColorFrame( pDev, aFillRect, aColor1, aColor2 ); } else // flat buttons { // draw a border if the flat button is highlighted if (nStyle & DrawButtonFlags::Highlight) { aColor1 = rStyleSettings.GetShadowColor(); ImplDraw2ColorFrame(pDev, aFillRect, aColor1, aColor1); } // fill in the button if it is pressed in bNoFace = !bDepressed; } pDev->SetLineColor(); if ( nStyle & (DrawButtonFlags::Checked | DrawButtonFlags::DontKnow) ) pDev->SetFillColor( rStyleSettings.GetCheckedColor() ); else if (!bNoFace) pDev->SetFillColor( rStyleSettings.GetFaceColor() ); pDev->DrawRect( aFillRect ); } } void ImplDrawFrame( OutputDevice *const pDev, tools::Rectangle& rRect, const StyleSettings& rStyleSettings, DrawFrameStyle nStyle, DrawFrameFlags nFlags ) { vcl::Window * pWin = pDev->GetOwnerWindow(); const bool bMenuStyle(nFlags & DrawFrameFlags::Menu); // UseFlatBorders disables 3D style for all frames except menus // menus may use different border colors (eg on XP) // normal frames will be drawn using the shadow color // whereas window frame borders will use black bool bFlatBorders = !bMenuStyle && rStyleSettings.GetUseFlatBorders(); // no flat borders for standard VCL controls (ie formcontrols that keep their classic look) // will not affect frame windows (like dropdowns) if( bFlatBorders && pWin && pWin->GetType() == WindowType::BORDERWINDOW && (pWin != pWin->ImplGetFrameWindow()) ) { // check for formcontrol, i.e., a control without NWF enabled Control *const pControl = dynamic_cast< Control* >( pWin->GetWindow( GetWindowType::Client ) ); if( !pControl || !pControl->IsNativeWidgetEnabled() ) bFlatBorders = false; } const bool bNoDraw(nFlags & DrawFrameFlags::NoDraw); if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) || (pDev->GetOutDevType() == OUTDEV_PRINTER) || bFlatBorders ) nFlags |= DrawFrameFlags::Mono; if( nStyle != DrawFrameStyle::NWF && pWin && pWin->IsNativeControlSupported(ControlType::Frame, ControlPart::Border) ) { tools::Long nControlFlags = static_cast(nStyle); nControlFlags |= static_cast(nFlags); nControlFlags |= static_cast(pWin->GetType() == WindowType::BORDERWINDOW ? DrawFrameFlags::BorderWindowBorder : DrawFrameFlags::NONE); ImplControlValue aControlValue( nControlFlags ); tools::Rectangle aBound, aContent; tools::Rectangle aNatRgn( rRect ); if( pWin->GetNativeControlRegion(ControlType::Frame, ControlPart::Border, aNatRgn, ControlState::NONE, aControlValue, aBound, aContent) ) { // if bNoDraw is true then don't call the drawing routine // but just update the target rectangle if( bNoDraw || pWin->GetOutDev()->DrawNativeControl( ControlType::Frame, ControlPart::Border, aBound, ControlState::ENABLED, aControlValue, OUString()) ) { rRect = aContent; return; } } } if ( nFlags & DrawFrameFlags::Mono ) { // no round corners for window frame borders const bool bRound = bFlatBorders && !(nFlags & DrawFrameFlags::WindowBorder); if ( bNoDraw ) { ImplDrawDPILineRect( pDev, rRect, nullptr, bRound ); } else { Color aColor = bRound ? rStyleSettings.GetShadowColor() : pDev->GetSettings().GetStyleSettings().GetMonoColor(); // when the MonoColor wasn't set, check face color if ( (bRound && aColor.IsDark()) || ( (aColor == COL_BLACK) && pDev->GetSettings().GetStyleSettings().GetFaceColor().IsDark() ) ) { aColor = COL_WHITE; } ImplDrawDPILineRect( pDev, rRect, &aColor, bRound ); } } else { if ( bNoDraw ) { switch ( nStyle ) { case DrawFrameStyle::In: case DrawFrameStyle::Out: rRect.AdjustLeft( 1 ); rRect.AdjustTop( 1 ); rRect.AdjustRight( -1 ); rRect.AdjustBottom( -1 ); break; case DrawFrameStyle::Group: case DrawFrameStyle::DoubleIn: case DrawFrameStyle::DoubleOut: rRect.AdjustLeft(2 ); rRect.AdjustTop(2 ); rRect.AdjustRight( -2 ); rRect.AdjustBottom( -2 ); break; case DrawFrameStyle::NWF: // enough space for the native rendering rRect.AdjustLeft(4 ); rRect.AdjustTop(4 ); rRect.AdjustRight( -4 ); rRect.AdjustBottom( -4 ); break; default: break; } } else { switch ( nStyle ) { case DrawFrameStyle::Group: pDev->SetFillColor(); pDev->SetLineColor( rStyleSettings.GetLightColor() ); pDev->DrawRect( tools::Rectangle( rRect.Left()+1, rRect.Top()+1, rRect.Right(), rRect.Bottom() ) ); pDev->SetLineColor( rStyleSettings.GetShadowColor() ); pDev->DrawRect( tools::Rectangle( rRect.Left(), rRect.Top(), rRect.Right()-1, rRect.Bottom()-1 ) ); // adjust target rectangle rRect.AdjustLeft(2 ); rRect.AdjustTop(2 ); rRect.AdjustRight( -2 ); rRect.AdjustBottom( -2 ); break; case DrawFrameStyle::In: ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetShadowColor(), rStyleSettings.GetLightColor() ); break; case DrawFrameStyle::Out: ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetLightColor(), rStyleSettings.GetShadowColor() ); break; case DrawFrameStyle::DoubleIn: if( bFlatBorders ) { // no 3d effect ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetShadowColor(), rStyleSettings.GetShadowColor() ); ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetFaceColor(), rStyleSettings.GetFaceColor() ); } else { ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetShadowColor(), rStyleSettings.GetLightColor() ); ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetDarkShadowColor(), rStyleSettings.GetLightBorderColor() ); } break; case DrawFrameStyle::DoubleOut: if( bMenuStyle ) { ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetMenuBorderColor(), rStyleSettings.GetDarkShadowColor() ); if ( !rStyleSettings.GetUseFlatMenus() ) { ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetLightColor(), rStyleSettings.GetShadowColor() ); } } else { ImplDraw2ColorFrame( pDev, rRect, bFlatBorders ? // no 3d effect rStyleSettings.GetDarkShadowColor() : rStyleSettings.GetLightBorderColor(), rStyleSettings.GetDarkShadowColor() ); ImplDraw2ColorFrame( pDev, rRect, rStyleSettings.GetLightColor(), rStyleSettings.GetShadowColor() ); } break; case DrawFrameStyle::NWF: // no rendering, just enough space for the native rendering rRect.AdjustLeft(4 ); rRect.AdjustTop(4 ); rRect.AdjustRight( -4 ); rRect.AdjustBottom( -4 ); break; default: break; } } } } } // end anonymous namespace DecorationView::DecorationView(OutputDevice* pOutDev) : mpOutDev(pOutDev) {} void DecorationView::DrawSymbol( const tools::Rectangle& rRect, SymbolType eType, const Color& rColor, DrawSymbolFlags nStyle ) { const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings(); const tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect ); const Color aOldLineColor = mpOutDev->GetLineColor(); const Color aOldFillColor = mpOutDev->GetFillColor(); const bool bOldMapMode = mpOutDev->IsMapModeEnabled(); Color nColor(rColor); mpOutDev->EnableMapMode( false ); if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) || (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) ) nStyle |= DrawSymbolFlags::Mono; if ( nStyle & DrawSymbolFlags::Mono ) { // Monochrome: set color to black if enabled, to gray if disabled nColor = ( nStyle & DrawSymbolFlags::Disable ) ? COL_GRAY : COL_BLACK; } else { if ( nStyle & DrawSymbolFlags::Disable ) { // Draw shifted and brighter symbol for embossed look mpOutDev->SetLineColor( rStyleSettings.GetLightColor() ); mpOutDev->SetFillColor( rStyleSettings.GetLightColor() ); ImplDrawSymbol( mpOutDev, aRect + Point(1, 1) , eType ); nColor = rStyleSettings.GetShadowColor(); } } // Set selected color and draw the symbol mpOutDev->SetLineColor( nColor ); mpOutDev->SetFillColor( nColor ); ImplDrawSymbol( mpOutDev, aRect, eType ); // Restore previous settings mpOutDev->SetLineColor( aOldLineColor ); mpOutDev->SetFillColor( aOldFillColor ); mpOutDev->EnableMapMode( bOldMapMode ); } void DecorationView::DrawFrame( const tools::Rectangle& rRect, const Color& rLeftTopColor, const Color& rRightBottomColor ) { tools::Rectangle aRect = mpOutDev->LogicToPixel( rRect ); const Color aOldLineColor = mpOutDev->GetLineColor(); const bool bOldMapMode = mpOutDev->IsMapModeEnabled(); mpOutDev->EnableMapMode( false ); ImplDraw2ColorFrame( mpOutDev, aRect, rLeftTopColor, rRightBottomColor ); mpOutDev->SetLineColor( aOldLineColor ); mpOutDev->EnableMapMode( bOldMapMode ); } void DecorationView::DrawHighlightFrame( const tools::Rectangle& rRect, DrawHighlightFrameStyle nStyle ) { const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings(); Color aLightColor = rStyleSettings.GetLightColor(); Color aShadowColor = rStyleSettings.GetShadowColor(); if ( (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) || (mpOutDev->GetOutDevType() == OUTDEV_PRINTER) ) { aLightColor = COL_BLACK; aShadowColor = COL_BLACK; } else { Wallpaper aBackground = mpOutDev->GetBackground(); if ( aBackground.IsBitmap() || aBackground.IsGradient() ) { aLightColor = rStyleSettings.GetFaceColor(); aShadowColor = COL_BLACK; } else { Color aBackColor = aBackground.GetColor(); if ( (aLightColor.GetColorError( aBackColor ) < 96) || (aShadowColor.GetColorError( aBackColor ) < 96) ) { aLightColor = COL_WHITE; aShadowColor = COL_BLACK; if ( aLightColor.GetColorError( aBackColor ) < 96 ) aLightColor.DecreaseLuminance( 64 ); if ( aShadowColor.GetColorError( aBackColor ) < 96 ) aShadowColor.IncreaseLuminance( 64 ); } } } if ( nStyle == DrawHighlightFrameStyle::In ) std::swap( aLightColor, aShadowColor ); DrawFrame( rRect, aLightColor, aShadowColor ); } tools::Rectangle DecorationView::DrawFrame( const tools::Rectangle& rRect, DrawFrameStyle nStyle, DrawFrameFlags nFlags ) { tools::Rectangle aRect = rRect; bool bOldMap = mpOutDev->IsMapModeEnabled(); if ( bOldMap ) { aRect = mpOutDev->LogicToPixel( aRect ); mpOutDev->EnableMapMode( false ); } if ( !rRect.IsEmpty() ) { if ( nFlags & DrawFrameFlags::NoDraw ) ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags ); else { Color aOldLineColor = mpOutDev->GetLineColor(); Color aOldFillColor = mpOutDev->GetFillColor(); ImplDrawFrame( mpOutDev, aRect, mpOutDev->GetSettings().GetStyleSettings(), nStyle, nFlags ); mpOutDev->SetLineColor( aOldLineColor ); mpOutDev->SetFillColor( aOldFillColor ); } } if ( bOldMap ) { mpOutDev->EnableMapMode( bOldMap ); aRect = mpOutDev->PixelToLogic( aRect ); } return aRect; } tools::Rectangle DecorationView::DrawButton( const tools::Rectangle& rRect, DrawButtonFlags nStyle ) { if ( rRect.IsEmpty() ) { return rRect; } tools::Rectangle aRect = rRect; const bool bOldMap = mpOutDev->IsMapModeEnabled(); if ( bOldMap ) { aRect = mpOutDev->LogicToPixel( aRect ); mpOutDev->EnableMapMode( false ); } const Color aOldLineColor = mpOutDev->GetLineColor(); const Color aOldFillColor = mpOutDev->GetFillColor(); ImplDrawButton( mpOutDev, aRect, nStyle ); mpOutDev->SetLineColor( aOldLineColor ); mpOutDev->SetFillColor( aOldFillColor ); // keep border free, although it is used at default representation aRect.AdjustLeft( 1 ); aRect.AdjustTop( 1 ); aRect.AdjustRight( -1 ); aRect.AdjustBottom( -1 ); if ( nStyle & DrawButtonFlags::NoLightBorder ) { aRect.AdjustLeft( 1 ); aRect.AdjustTop( 1 ); } else if ( nStyle & DrawButtonFlags::NoLeftLightBorder ) { aRect.AdjustLeft( 1 ); } if ( nStyle & DrawButtonFlags::Pressed ) { if ( (aRect.GetHeight() > 10) && (aRect.GetWidth() > 10) ) { aRect.AdjustLeft(4 ); aRect.AdjustTop(4 ); aRect.AdjustRight( -1 ); aRect.AdjustBottom( -1 ); } else { aRect.AdjustLeft(3 ); aRect.AdjustTop(3 ); aRect.AdjustRight( -2 ); aRect.AdjustBottom( -2 ); } } else if ( nStyle & DrawButtonFlags::Checked ) { aRect.AdjustLeft(3 ); aRect.AdjustTop(3 ); aRect.AdjustRight( -2 ); aRect.AdjustBottom( -2 ); } else { aRect.AdjustLeft(2 ); aRect.AdjustTop(2 ); aRect.AdjustRight( -3 ); aRect.AdjustBottom( -3 ); } if ( bOldMap ) { mpOutDev->EnableMapMode( bOldMap ); aRect = mpOutDev->PixelToLogic( aRect ); } return aRect; } void DecorationView::DrawSeparator( const Point& rStart, const Point& rStop, bool bVertical ) { Point aStart( rStart ), aStop( rStop ); const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings(); vcl::Window *const pWin = mpOutDev->GetOwnerWindow(); if(pWin) { ControlPart nPart = ( bVertical ? ControlPart::SeparatorVert : ControlPart::SeparatorHorz ); bool nativeSupported = pWin->IsNativeControlSupported( ControlType::Fixedline, nPart ); ImplControlValue aValue; tools::Rectangle aRect(rStart,rStop); if(nativeSupported && pWin->GetOutDev()->DrawNativeControl(ControlType::Fixedline,nPart,aRect,ControlState::NONE,aValue,OUString())) return; } mpOutDev->Push( vcl::PushFlags::LINECOLOR ); if ( rStyleSettings.GetOptions() & StyleSettingsOptions::Mono ) mpOutDev->SetLineColor( COL_BLACK ); else mpOutDev->SetLineColor( rStyleSettings.GetShadowColor() ); mpOutDev->DrawLine( aStart, aStop ); if ( !(rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) ) { mpOutDev->SetLineColor( rStyleSettings.GetLightColor() ); if( bVertical ) { aStart.AdjustX( 1 ); aStop.AdjustX( 1 ); } else { aStart.AdjustY( 1 ); aStop.AdjustY( 1 ); } mpOutDev->DrawLine( aStart, aStop ); } mpOutDev->Pop(); } void DecorationView::DrawHandle(const tools::Rectangle& rRect) { const StyleSettings& rStyleSettings = mpOutDev->GetSettings().GetStyleSettings(); Size aOutputSize = rRect.GetSize(); mpOutDev->SetLineColor(rStyleSettings.GetDarkShadowColor()); mpOutDev->SetFillColor(rStyleSettings.GetDarkShadowColor()); const sal_Int32 nNumberOfPoints = 3; tools::Long nHalfWidth = aOutputSize.Width() / 2.0f; float fDistance = aOutputSize.Height(); fDistance /= (nNumberOfPoints + 1); tools::Long nRadius = aOutputSize.Width(); nRadius /= (nNumberOfPoints + 2); for (tools::Long i = 1; i <= nNumberOfPoints; i++) { tools::Rectangle aLocation(nHalfWidth - nRadius, round(fDistance * i) - nRadius, nHalfWidth + nRadius, round(fDistance * i) + nRadius); mpOutDev->DrawEllipse(aLocation); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */