Line data Source code
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 :
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>
23 :
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;
31 :
32 : namespace
33 : {
34 :
35 : const long INFO_BAR_BASE_HEIGHT = 40;
36 :
37 216 : const BColor constLightColor(1.0, 1.0, 191.0 / 255.0);
38 216 : const BColor constDarkColor(217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0);
39 :
40 6 : void lclDetermineLightDarkColor(BColor& rLightColor, BColor& rDarkColor)
41 : {
42 6 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
43 6 : if (rSettings.GetHighContrastMode())
44 : {
45 0 : rLightColor = rSettings.GetLightColor().getBColor();
46 0 : rDarkColor = rSettings.GetDialogTextColor().getBColor();
47 : }
48 : else
49 : {
50 6 : rLightColor = constLightColor;
51 6 : rDarkColor = constDarkColor;
52 : }
53 6 : }
54 :
55 : class SfxCloseButton : public PushButton
56 : {
57 : public:
58 1 : SfxCloseButton(vcl::Window* pParent) : PushButton(pParent, 0)
59 1 : {}
60 :
61 2 : virtual ~SfxCloseButton() {}
62 :
63 : virtual void Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect) SAL_OVERRIDE;
64 : };
65 :
66 3 : void SfxCloseButton::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
67 : {
68 3 : const ViewInformation2D aNewViewInfos;
69 : const unique_ptr<BaseProcessor2D> pProcessor(
70 6 : createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
71 :
72 3 : const Rectangle aRect(Point(0, 0), PixelToLogic(GetSizePixel()));
73 :
74 6 : drawinglayer::primitive2d::Primitive2DSequence aSeq(2);
75 :
76 6 : BColor aLightColor;
77 6 : BColor aDarkColor;
78 3 : lclDetermineLightDarkColor(aLightColor, aDarkColor);
79 :
80 : // Light background
81 6 : B2DPolygon aPolygon;
82 3 : aPolygon.append(B2DPoint(aRect.Left(), aRect.Top()));
83 3 : aPolygon.append(B2DPoint(aRect.Right(), aRect.Top()));
84 3 : aPolygon.append(B2DPoint(aRect.Right(), aRect.Bottom()));
85 3 : aPolygon.append(B2DPoint(aRect.Left(), aRect.Bottom()));
86 3 : aPolygon.setClosed(true);
87 :
88 : PolyPolygonColorPrimitive2D* pBack =
89 3 : new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aLightColor);
90 3 : aSeq[0] = pBack;
91 :
92 6 : LineAttribute aLineAttribute(aDarkColor, 2.0);
93 :
94 : // Cross
95 6 : B2DPolyPolygon aCross;
96 :
97 6 : B2DPolygon aLine1;
98 3 : aLine1.append(B2DPoint(aRect.Left(), aRect.Top()));
99 3 : aLine1.append(B2DPoint(aRect.Right(), aRect.Bottom()));
100 3 : aCross.append(aLine1);
101 :
102 6 : B2DPolygon aLine2;
103 3 : aLine2.append(B2DPoint(aRect.Right(), aRect.Top()));
104 3 : aLine2.append(B2DPoint(aRect.Left(), aRect.Bottom()));
105 3 : aCross.append(aLine2);
106 :
107 : PolyPolygonStrokePrimitive2D* pCross =
108 3 : new PolyPolygonStrokePrimitive2D(aCross, aLineAttribute, StrokeAttribute());
109 :
110 3 : aSeq[1] = pCross;
111 :
112 6 : pProcessor->process(aSeq);
113 3 : }
114 :
115 : } // anonymous namespace
116 :
117 1 : 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 1 : m_aActionBtns()
124 : {
125 1 : sal_Int32 nScaleFactor = GetDPIScaleFactor();
126 1 : long nWidth = pParent->GetSizePixel().getWidth();
127 1 : SetPosSizePixel(Point(0, 0), Size(nWidth, INFO_BAR_BASE_HEIGHT * nScaleFactor));
128 :
129 1 : m_pMessage->SetText(sMessage);
130 1 : m_pMessage->SetBackground(Wallpaper(Color(constLightColor)));
131 1 : m_pMessage->Show();
132 :
133 1 : m_pCloseBtn->SetClickHdl(LINK(this, SfxInfoBarWindow, CloseHandler));
134 1 : m_pCloseBtn->Show();
135 :
136 1 : Resize();
137 1 : }
138 :
139 1 : void SfxInfoBarWindow::addButton(PushButton* pButton) {
140 1 : pButton->SetParent(this);
141 1 : pButton->Show();
142 1 : m_aActionBtns.push_back(pButton);
143 1 : Resize();
144 1 : }
145 :
146 3 : SfxInfoBarWindow::~SfxInfoBarWindow()
147 : {
148 1 : disposeOnce();
149 2 : }
150 :
151 1 : void SfxInfoBarWindow::dispose()
152 : {
153 2 : for ( auto it = m_aActionBtns.begin( ); it != m_aActionBtns.end( ); ++it )
154 1 : it->disposeAndClear();
155 :
156 1 : m_pMessage.disposeAndClear();
157 1 : m_pCloseBtn.disposeAndClear();
158 1 : m_aActionBtns.clear( );
159 1 : vcl::Window::dispose();
160 1 : }
161 :
162 3 : void SfxInfoBarWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rPaintRect)
163 : {
164 3 : const ViewInformation2D aNewViewInfos;
165 : const unique_ptr<BaseProcessor2D> pProcessor(
166 6 : createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
167 :
168 3 : const Rectangle aRect(Point(0, 0), PixelToLogic(GetSizePixel()));
169 :
170 6 : drawinglayer::primitive2d::Primitive2DSequence aSeq(2);
171 :
172 6 : BColor aLightColor;
173 6 : BColor aDarkColor;
174 3 : lclDetermineLightDarkColor(aLightColor, aDarkColor);
175 :
176 : // Update the label background color
177 3 : m_pMessage->SetBackground(Wallpaper(Color(aLightColor)));
178 :
179 : // Light background
180 6 : B2DPolygon aPolygon;
181 3 : aPolygon.append(B2DPoint(aRect.Left(), aRect.Top()));
182 3 : aPolygon.append(B2DPoint(aRect.Right(), aRect.Top()));
183 3 : aPolygon.append(B2DPoint(aRect.Right(), aRect.Bottom()));
184 3 : aPolygon.append(B2DPoint(aRect.Left(), aRect.Bottom()));
185 3 : aPolygon.setClosed(true);
186 :
187 : PolyPolygonColorPrimitive2D* pBack =
188 3 : new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aLightColor);
189 3 : aSeq[0] = pBack;
190 :
191 6 : LineAttribute aLineAttribute(aDarkColor, 1.0);
192 :
193 : // Bottom dark line
194 6 : B2DPolygon aPolygonBottom;
195 3 : aPolygonBottom.append(B2DPoint(aRect.Left(), aRect.Bottom()));
196 3 : aPolygonBottom.append(B2DPoint(aRect.Right(), aRect.Bottom()));
197 :
198 : PolygonStrokePrimitive2D* pLineBottom =
199 3 : new PolygonStrokePrimitive2D (aPolygonBottom, aLineAttribute);
200 :
201 3 : aSeq[1] = pLineBottom;
202 :
203 3 : pProcessor->process(aSeq);
204 :
205 6 : Window::Paint(rRenderContext, rPaintRect);
206 3 : }
207 :
208 4 : void SfxInfoBarWindow::Resize()
209 : {
210 4 : sal_Int32 nScaleFactor = GetDPIScaleFactor();
211 :
212 4 : long nWidth = GetSizePixel().getWidth();
213 4 : m_pCloseBtn->SetPosSizePixel(Point(nWidth - 25 * nScaleFactor, 15 * nScaleFactor), Size(10 * nScaleFactor, 10 * nScaleFactor));
214 :
215 : // Reparent the buttons and place them on the right of the bar
216 4 : long nX = m_pCloseBtn->GetPosPixel().getX() - 15 * nScaleFactor;
217 4 : long nButtonGap = 5 * nScaleFactor;
218 :
219 5 : for (auto it = m_aActionBtns.begin(); it != m_aActionBtns.end(); ++it)
220 : {
221 1 : long nButtonWidth = (*it)->GetSizePixel().getWidth();
222 1 : nX -= nButtonWidth;
223 1 : (*it)->SetPosSizePixel(Point(nX, 5 * nScaleFactor), Size(nButtonWidth, 30 * nScaleFactor));
224 1 : nX -= nButtonGap;
225 : }
226 :
227 4 : Point aMessagePosition(10 * nScaleFactor, 10 * nScaleFactor);
228 4 : Size aMessageSize(nX - 20 * nScaleFactor, 20 * nScaleFactor);
229 :
230 4 : m_pMessage->SetPosSizePixel(aMessagePosition, aMessageSize);
231 4 : }
232 :
233 0 : IMPL_LINK_NOARG(SfxInfoBarWindow, CloseHandler)
234 : {
235 0 : static_cast<SfxInfoBarContainerWindow*>(GetParent())->removeInfoBar(this);
236 0 : return 0;
237 : }
238 :
239 3157 : SfxInfoBarContainerWindow::SfxInfoBarContainerWindow(SfxInfoBarContainerChild* pChildWin ) :
240 : Window(pChildWin->GetParent(), 0),
241 : m_pChildWin(pChildWin),
242 3157 : m_pInfoBars()
243 : {
244 3157 : }
245 :
246 9459 : SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow()
247 : {
248 3153 : disposeOnce();
249 6306 : }
250 :
251 3153 : void SfxInfoBarContainerWindow::dispose()
252 : {
253 3154 : for ( auto it = m_pInfoBars.begin( ); it != m_pInfoBars.end( ); ++it )
254 1 : it->disposeAndClear();
255 3153 : m_pInfoBars.clear( );
256 3153 : Window::dispose();
257 3153 : }
258 :
259 1 : SfxInfoBarWindow* SfxInfoBarContainerWindow::appendInfoBar(const OUString& sId, const OUString& sMessage)
260 : {
261 1 : Size aSize = GetSizePixel();
262 :
263 1 : VclPtrInstance<SfxInfoBarWindow> pInfoBar(this, sId, sMessage);
264 1 : pInfoBar->SetPosPixel(Point(0, aSize.getHeight()));
265 1 : pInfoBar->Show();
266 1 : m_pInfoBars.push_back(pInfoBar);
267 :
268 1 : long nHeight = pInfoBar->GetSizePixel().getHeight();
269 1 : aSize.setHeight(aSize.getHeight() + nHeight);
270 1 : SetSizePixel(aSize);
271 1 : return pInfoBar;
272 : }
273 :
274 0 : SfxInfoBarWindow* SfxInfoBarContainerWindow::getInfoBar(const OUString& sId)
275 : {
276 0 : for (auto it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
277 : {
278 0 : if ((*it)->getId() == sId)
279 0 : return it->get();
280 : }
281 0 : return NULL;
282 : }
283 :
284 0 : void SfxInfoBarContainerWindow::removeInfoBar(SfxInfoBarWindow* pInfoBar)
285 : {
286 : // Store a VclPtr to the pInfoBar while we remove it from m_pInfoBars
287 0 : ScopedVclPtr<SfxInfoBarWindow> pTmp(pInfoBar);
288 :
289 : // Remove
290 0 : for (auto it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
291 : {
292 0 : if (pInfoBar == it->get())
293 : {
294 0 : it->disposeAndClear();
295 0 : m_pInfoBars.erase(it);
296 0 : break;
297 : }
298 : }
299 :
300 : // Resize
301 0 : long nY = 0;
302 0 : for (auto it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
303 : {
304 0 : (*it)->SetPosPixel(Point(0, nY));
305 0 : nY += (*it)->GetSizePixel().getHeight();
306 : }
307 :
308 0 : Size aSize = GetSizePixel();
309 0 : aSize.setHeight(nY);
310 0 : SetSizePixel(aSize);
311 :
312 0 : m_pChildWin->Update();
313 0 : }
314 :
315 6522 : void SfxInfoBarContainerWindow::Resize()
316 : {
317 : // Only need to change the width of the infobars
318 6522 : long nWidth = GetSizePixel().getWidth();
319 :
320 6523 : for (auto it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
321 : {
322 1 : Size aSize = (*it)->GetSizePixel();
323 1 : aSize.setWidth(nWidth);
324 1 : (*it)->SetSizePixel(aSize);
325 1 : (*it)->Resize();
326 : }
327 6522 : }
328 :
329 3599 : SFX_IMPL_POS_CHILDWINDOW_WITHID(SfxInfoBarContainerChild, SID_INFOBAR, SFX_OBJECTBAR_OBJECT);
330 :
331 3157 : SfxInfoBarContainerChild::SfxInfoBarContainerChild( vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* ) :
332 : SfxChildWindow(_pParent, nId),
333 3157 : m_pBindings(pBindings)
334 : {
335 3157 : pWindow = VclPtr<SfxInfoBarContainerWindow>::Create(this);
336 3157 : pWindow->SetPosSizePixel(Point(0, 0), Size(_pParent->GetSizePixel().getWidth(), 0));
337 3157 : pWindow->Show();
338 :
339 3157 : eChildAlignment = SfxChildAlignment::LOWESTTOP;
340 3157 : }
341 :
342 6306 : SfxInfoBarContainerChild::~SfxInfoBarContainerChild()
343 : {
344 6306 : }
345 :
346 3166 : SfxChildWinInfo SfxInfoBarContainerChild::GetInfo() const
347 : {
348 3166 : SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
349 3166 : return aInfo;
350 : }
351 :
352 0 : void SfxInfoBarContainerChild::Update()
353 : {
354 : // Refresh the frame to take the infobars container height change into account
355 0 : const sal_uInt16 nId = GetChildWindowId();
356 0 : SfxViewFrame* pVFrame = m_pBindings->GetDispatcher()->GetFrame();
357 0 : pVFrame->ShowChildWindow(nId);
358 :
359 : // Give the focus to the document view
360 0 : pVFrame->GetWindow().GrabFocusToDocument();
361 648 : }
362 :
363 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|