bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / dialog / infobar.cxx
blobdf7839e05c1fdf79fbd250e90fc6d8e58027949d
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/.
8 */
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>
24 using namespace std;
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;
32 namespace
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();
48 else
50 rLightColor = constLightColor;
51 rDarkColor = constDarkColor;
55 class SfxCloseButton : public PushButton
57 public:
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);
76 BColor aLightColor;
77 BColor aDarkColor;
78 lclDetermineLightDarkColor(aLightColor, aDarkColor);
80 // Light background
81 B2DPolygon aPolygon;
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);
90 aSeq[0] = pBack;
92 LineAttribute aLineAttribute(aDarkColor, 2.0);
94 // Cross
95 B2DPolyPolygon aCross;
97 B2DPolygon aLine1;
98 aLine1.append(B2DPoint(aRect.Left(), aRect.Top()));
99 aLine1.append(B2DPoint(aRect.Right(), aRect.Bottom()));
100 aCross.append(aLine1);
102 B2DPolygon aLine2;
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());
110 aSeq[1] = pCross;
112 pProcessor->process(aSeq);
115 } // anonymous namespace
117 SfxInfoBarWindow::SfxInfoBarWindow(vcl::Window* pParent, const OUString& sId,
118 const OUString& sMessage) :
119 Window(pParent, 0),
120 m_sId(sId),
121 m_pMessage(VclPtr<FixedText>::Create(this, 0)),
122 m_pCloseBtn(VclPtr<SfxCloseButton>::Create(this)),
123 m_aActionBtns()
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);
130 m_pMessage->Show();
132 m_pCloseBtn->SetClickHdl(LINK(this, SfxInfoBarWindow, CloseHandler));
133 m_pCloseBtn->Show();
135 EnableChildTransparentMode();
137 Resize();
140 void SfxInfoBarWindow::addButton(PushButton* pButton) {
141 pButton->SetParent(this);
142 pButton->Show();
143 m_aActionBtns.push_back(pButton);
144 Resize();
147 SfxInfoBarWindow::~SfxInfoBarWindow()
149 disposeOnce();
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);
173 BColor aLightColor;
174 BColor aDarkColor;
175 lclDetermineLightDarkColor(aLightColor, aDarkColor);
177 // Light background
178 B2DPolygon aPolygon;
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);
187 aSeq[0] = pBack;
189 LineAttribute aLineAttribute(aDarkColor, 1.0);
191 // Bottom dark line
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();
220 nX -= nButtonWidth;
221 (*it)->SetPosSizePixel(Point(nX, 5 * nScaleFactor), Size(nButtonWidth, 30 * nScaleFactor));
222 nX -= nButtonGap;
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);
234 return 0;
237 SfxInfoBarContainerWindow::SfxInfoBarContainerWindow(SfxInfoBarContainerChild* pChildWin ) :
238 Window(pChildWin->GetParent(), 0),
239 m_pChildWin(pChildWin),
240 m_pInfoBars()
244 SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow()
246 disposeOnce();
249 void SfxInfoBarContainerWindow::dispose()
251 for ( auto it = m_pInfoBars.begin( ); it != m_pInfoBars.end( ); ++it )
252 it->disposeAndClear();
253 m_pInfoBars.clear( );
254 Window::dispose();
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()));
263 pInfoBar->Show();
264 m_pInfoBars.push_back(pInfoBar);
266 long nHeight = pInfoBar->GetSizePixel().getHeight();
267 aSize.setHeight(aSize.getHeight() + nHeight);
268 SetSizePixel(aSize);
269 return pInfoBar;
272 SfxInfoBarWindow* SfxInfoBarContainerWindow::getInfoBar(const OUString& sId)
274 for (auto it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
276 if ((*it)->getId() == sId)
277 return it->get();
279 return NULL;
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);
287 // Remove
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);
294 break;
298 // Resize
299 long nY = 0;
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();
307 aSize.setHeight(nY);
308 SetSizePixel(aSize);
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);
323 (*it)->Resize();
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));
335 pWindow->Show();
337 eChildAlignment = SfxChildAlignment::LOWESTTOP;
340 SfxInfoBarContainerChild::~SfxInfoBarContainerChild()
344 SfxChildWinInfo SfxInfoBarContainerChild::GetInfo() const
346 SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
347 return aInfo;
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: */