1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <basegfx/polygon/b2dpolygon.hxx>
11 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
12 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
13 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
14 #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
15 #include <sfx2/bindings.hxx>
16 #include <sfx2/dispatch.hxx>
17 #include <sfx2/infobar.hxx>
18 #include <sfx2/objsh.hxx>
19 #include <sfx2/sfx.hrc>
20 #include <sfx2/viewsh.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/settings.hxx>
25 using namespace drawinglayer::geometry
;
26 using namespace drawinglayer::processor2d
;
27 using namespace drawinglayer::primitive2d
;
28 using namespace drawinglayer::attribute
;
29 using namespace drawinglayer::geometry
;
30 using namespace basegfx
;
35 const long INFO_BAR_BASE_HEIGHT
= 40;
37 const BColor
constLightColor(1.0, 1.0, 191.0 / 255.0);
38 const BColor
constDarkColor(217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0);
40 void lclDetermineLightDarkColor(BColor
& rLightColor
, BColor
& rDarkColor
)
42 const StyleSettings
& rSettings
= Application::GetSettings().GetStyleSettings();
43 if (rSettings
.GetHighContrastMode())
45 rLightColor
= rSettings
.GetLightColor().getBColor();
46 rDarkColor
= rSettings
.GetDialogTextColor().getBColor();
50 rLightColor
= constLightColor
;
51 rDarkColor
= constDarkColor
;
55 class SfxCloseButton
: public PushButton
58 SfxCloseButton(vcl::Window
* pParent
) : PushButton(pParent
, 0)
61 virtual ~SfxCloseButton() {}
63 virtual void Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rRect
) SAL_OVERRIDE
;
66 void SfxCloseButton::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
&)
68 const ViewInformation2D aNewViewInfos
;
69 const unique_ptr
<BaseProcessor2D
> pProcessor(
70 createBaseProcessor2DFromOutputDevice(rRenderContext
, aNewViewInfos
));
72 const Rectangle
aRect(Point(0, 0), PixelToLogic(GetSizePixel()));
74 drawinglayer::primitive2d::Primitive2DSequence
aSeq(2);
78 lclDetermineLightDarkColor(aLightColor
, aDarkColor
);
82 aPolygon
.append(B2DPoint(aRect
.Left(), aRect
.Top()));
83 aPolygon
.append(B2DPoint(aRect
.Right(), aRect
.Top()));
84 aPolygon
.append(B2DPoint(aRect
.Right(), aRect
.Bottom()));
85 aPolygon
.append(B2DPoint(aRect
.Left(), aRect
.Bottom()));
86 aPolygon
.setClosed(true);
88 PolyPolygonColorPrimitive2D
* pBack
=
89 new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon
), aLightColor
);
92 LineAttribute
aLineAttribute(aDarkColor
, 2.0);
95 B2DPolyPolygon aCross
;
98 aLine1
.append(B2DPoint(aRect
.Left(), aRect
.Top()));
99 aLine1
.append(B2DPoint(aRect
.Right(), aRect
.Bottom()));
100 aCross
.append(aLine1
);
103 aLine2
.append(B2DPoint(aRect
.Right(), aRect
.Top()));
104 aLine2
.append(B2DPoint(aRect
.Left(), aRect
.Bottom()));
105 aCross
.append(aLine2
);
107 PolyPolygonStrokePrimitive2D
* pCross
=
108 new PolyPolygonStrokePrimitive2D(aCross
, aLineAttribute
, StrokeAttribute());
112 pProcessor
->process(aSeq
);
115 } // anonymous namespace
117 SfxInfoBarWindow::SfxInfoBarWindow(vcl::Window
* pParent
, const OUString
& sId
,
118 const OUString
& sMessage
) :
121 m_pMessage(VclPtr
<FixedText
>::Create(this, 0)),
122 m_pCloseBtn(VclPtr
<SfxCloseButton
>::Create(this)),
125 sal_Int32 nScaleFactor
= GetDPIScaleFactor();
126 long nWidth
= pParent
->GetSizePixel().getWidth();
127 SetPosSizePixel(Point(0, 0), Size(nWidth
, INFO_BAR_BASE_HEIGHT
* nScaleFactor
));
129 m_pMessage
->SetText(sMessage
);
132 m_pCloseBtn
->SetClickHdl(LINK(this, SfxInfoBarWindow
, CloseHandler
));
135 EnableChildTransparentMode();
140 void SfxInfoBarWindow::addButton(PushButton
* pButton
) {
141 pButton
->SetParent(this);
143 m_aActionBtns
.push_back(pButton
);
147 SfxInfoBarWindow::~SfxInfoBarWindow()
152 void SfxInfoBarWindow::dispose()
154 for ( auto it
= m_aActionBtns
.begin( ); it
!= m_aActionBtns
.end( ); ++it
)
155 it
->disposeAndClear();
157 m_pMessage
.disposeAndClear();
158 m_pCloseBtn
.disposeAndClear();
159 m_aActionBtns
.clear( );
160 vcl::Window::dispose();
163 void SfxInfoBarWindow::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& rPaintRect
)
165 const ViewInformation2D aNewViewInfos
;
166 const unique_ptr
<BaseProcessor2D
> pProcessor(
167 createBaseProcessor2DFromOutputDevice(rRenderContext
, aNewViewInfos
));
169 const Rectangle
aRect(Point(0, 0), PixelToLogic(GetSizePixel()));
171 drawinglayer::primitive2d::Primitive2DSequence
aSeq(2);
175 lclDetermineLightDarkColor(aLightColor
, aDarkColor
);
179 aPolygon
.append(B2DPoint(aRect
.Left(), aRect
.Top()));
180 aPolygon
.append(B2DPoint(aRect
.Right(), aRect
.Top()));
181 aPolygon
.append(B2DPoint(aRect
.Right(), aRect
.Bottom()));
182 aPolygon
.append(B2DPoint(aRect
.Left(), aRect
.Bottom()));
183 aPolygon
.setClosed(true);
185 PolyPolygonColorPrimitive2D
* pBack
=
186 new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon
), aLightColor
);
189 LineAttribute
aLineAttribute(aDarkColor
, 1.0);
192 B2DPolygon aPolygonBottom
;
193 aPolygonBottom
.append(B2DPoint(aRect
.Left(), aRect
.Bottom()));
194 aPolygonBottom
.append(B2DPoint(aRect
.Right(), aRect
.Bottom()));
196 PolygonStrokePrimitive2D
* pLineBottom
=
197 new PolygonStrokePrimitive2D (aPolygonBottom
, aLineAttribute
);
199 aSeq
[1] = pLineBottom
;
201 pProcessor
->process(aSeq
);
203 Window::Paint(rRenderContext
, rPaintRect
);
206 void SfxInfoBarWindow::Resize()
208 sal_Int32 nScaleFactor
= GetDPIScaleFactor();
210 long nWidth
= GetSizePixel().getWidth();
211 m_pCloseBtn
->SetPosSizePixel(Point(nWidth
- 25 * nScaleFactor
, 15 * nScaleFactor
), Size(10 * nScaleFactor
, 10 * nScaleFactor
));
213 // Reparent the buttons and place them on the right of the bar
214 long nX
= m_pCloseBtn
->GetPosPixel().getX() - 15 * nScaleFactor
;
215 long nButtonGap
= 5 * nScaleFactor
;
217 for (auto it
= m_aActionBtns
.begin(); it
!= m_aActionBtns
.end(); ++it
)
219 long nButtonWidth
= (*it
)->GetSizePixel().getWidth();
221 (*it
)->SetPosSizePixel(Point(nX
, 5 * nScaleFactor
), Size(nButtonWidth
, 30 * nScaleFactor
));
225 Point
aMessagePosition(10 * nScaleFactor
, 10 * nScaleFactor
);
226 Size
aMessageSize(nX
- 20 * nScaleFactor
, 20 * nScaleFactor
);
228 m_pMessage
->SetPosSizePixel(aMessagePosition
, aMessageSize
);
231 IMPL_LINK_NOARG(SfxInfoBarWindow
, CloseHandler
)
233 static_cast<SfxInfoBarContainerWindow
*>(GetParent())->removeInfoBar(this);
237 SfxInfoBarContainerWindow::SfxInfoBarContainerWindow(SfxInfoBarContainerChild
* pChildWin
) :
238 Window(pChildWin
->GetParent(), 0),
239 m_pChildWin(pChildWin
),
244 SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow()
249 void SfxInfoBarContainerWindow::dispose()
251 for ( auto it
= m_pInfoBars
.begin( ); it
!= m_pInfoBars
.end( ); ++it
)
252 it
->disposeAndClear();
253 m_pInfoBars
.clear( );
257 SfxInfoBarWindow
* SfxInfoBarContainerWindow::appendInfoBar(const OUString
& sId
, const OUString
& sMessage
)
259 Size aSize
= GetSizePixel();
261 VclPtrInstance
<SfxInfoBarWindow
> pInfoBar(this, sId
, sMessage
);
262 pInfoBar
->SetPosPixel(Point(0, aSize
.getHeight()));
264 m_pInfoBars
.push_back(pInfoBar
);
266 long nHeight
= pInfoBar
->GetSizePixel().getHeight();
267 aSize
.setHeight(aSize
.getHeight() + nHeight
);
272 SfxInfoBarWindow
* SfxInfoBarContainerWindow::getInfoBar(const OUString
& sId
)
274 for (auto it
= m_pInfoBars
.begin(); it
!= m_pInfoBars
.end(); ++it
)
276 if ((*it
)->getId() == sId
)
282 void SfxInfoBarContainerWindow::removeInfoBar(SfxInfoBarWindow
* pInfoBar
)
284 // Store a VclPtr to the pInfoBar while we remove it from m_pInfoBars
285 ScopedVclPtr
<SfxInfoBarWindow
> pTmp(pInfoBar
);
288 for (auto it
= m_pInfoBars
.begin(); it
!= m_pInfoBars
.end(); ++it
)
290 if (pInfoBar
== it
->get())
292 it
->disposeAndClear();
293 m_pInfoBars
.erase(it
);
300 for (auto it
= m_pInfoBars
.begin(); it
!= m_pInfoBars
.end(); ++it
)
302 (*it
)->SetPosPixel(Point(0, nY
));
303 nY
+= (*it
)->GetSizePixel().getHeight();
306 Size aSize
= GetSizePixel();
310 m_pChildWin
->Update();
313 void SfxInfoBarContainerWindow::Resize()
315 // Only need to change the width of the infobars
316 long nWidth
= GetSizePixel().getWidth();
318 for (auto it
= m_pInfoBars
.begin(); it
!= m_pInfoBars
.end(); ++it
)
320 Size aSize
= (*it
)->GetSizePixel();
321 aSize
.setWidth(nWidth
);
322 (*it
)->SetSizePixel(aSize
);
327 SFX_IMPL_POS_CHILDWINDOW_WITHID(SfxInfoBarContainerChild
, SID_INFOBAR
, SFX_OBJECTBAR_OBJECT
);
329 SfxInfoBarContainerChild::SfxInfoBarContainerChild( vcl::Window
* _pParent
, sal_uInt16 nId
, SfxBindings
* pBindings
, SfxChildWinInfo
* ) :
330 SfxChildWindow(_pParent
, nId
),
331 m_pBindings(pBindings
)
333 pWindow
= VclPtr
<SfxInfoBarContainerWindow
>::Create(this);
334 pWindow
->SetPosSizePixel(Point(0, 0), Size(_pParent
->GetSizePixel().getWidth(), 0));
337 eChildAlignment
= SfxChildAlignment::LOWESTTOP
;
340 SfxInfoBarContainerChild::~SfxInfoBarContainerChild()
344 SfxChildWinInfo
SfxInfoBarContainerChild::GetInfo() const
346 SfxChildWinInfo aInfo
= SfxChildWindow::GetInfo();
350 void SfxInfoBarContainerChild::Update()
352 // Refresh the frame to take the infobars container height change into account
353 const sal_uInt16 nId
= GetChildWindowId();
354 SfxViewFrame
* pVFrame
= m_pBindings
->GetDispatcher()->GetFrame();
355 pVFrame
->ShowChildWindow(nId
);
357 // Give the focus to the document view
358 pVFrame
->GetWindow().GrabFocusToDocument();
361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */