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 <ChartWindow.hxx>
21 #include <ChartController.hxx>
22 #include <helpids.h>
23 #include <uiobject.hxx>
24
25 #include <vcl/help.hxx>
26 #include <vcl/settings.hxx>
27
28 #include <sfx2/ipclient.hxx>
29 #include <sfx2/viewsh.hxx>
30 #include <sfx2/lokhelper.hxx>
31 #include <comphelper/lok.hxx>
32
33 #define TWIPS_PER_PIXEL 15
34
35 using namespace ::com::sun::star;
36
37 namespace
38 {
lcl_AWTRectToVCLRect(const css::awt::Rectangle & rAWTRect)39 ::tools::Rectangle lcl_AWTRectToVCLRect( const css::awt::Rectangle & rAWTRect )
40 {
41 ::tools::Rectangle aResult;
42 aResult.setX( rAWTRect.X );
43 aResult.setY( rAWTRect.Y );
44 aResult.setWidth( rAWTRect.Width );
45 aResult.setHeight( rAWTRect.Height );
46 return aResult;
47 }
48 } // anonymous namespace
49
50 namespace chart
51 {
52
ChartWindow(ChartController * pController,vcl::Window * pParent,WinBits nStyle)53 ChartWindow::ChartWindow( ChartController* pController, vcl::Window* pParent, WinBits nStyle )
54 : Window(pParent, nStyle)
55 , m_pWindowController( pController )
56 , m_bInPaint(false)
57 , m_pViewShellWindow( nullptr )
58 {
59 set_id("chart_window");
60 SetHelpId( HID_SCH_WIN_DOCUMENT );
61 SetMapMode( MapMode(MapUnit::Map100thMM) );
62 adjustHighContrastMode();
63 // chart does not depend on exact pixel painting => enable antialiased drawing
64 GetOutDev()->SetAntialiasing( AntialiasingFlags::Enable | GetOutDev()->GetAntialiasing() );
65 EnableRTL( false );
66 if( pParent )
67 pParent->EnableRTL( false );// #i96215# necessary for a correct position of the context menu in rtl mode
68 }
69
~ChartWindow()70 ChartWindow::~ChartWindow()
71 {
72 disposeOnce();
73 }
74
dispose()75 void ChartWindow::dispose()
76 {
77 m_pWindowController = nullptr;
78 m_pViewShellWindow.clear();
79 vcl::Window::dispose();
80 }
81
PrePaint(vcl::RenderContext &)82 void ChartWindow::PrePaint(vcl::RenderContext& )
83 {
84 // forward VCLs PrePaint window event to DrawingLayer
85 if (m_pWindowController)
86 {
87 m_pWindowController->PrePaint();
88 }
89 }
90
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)91 void ChartWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
92 {
93 if (comphelper::LibreOfficeKit::isActive() && !rRenderContext.IsVirtual())
94 return;
95
96 m_bInPaint = true;
97 if (m_pWindowController)
98 {
99 m_pWindowController->execute_Paint(rRenderContext, rRect);
100 }
101 else
102 {
103 Window::Paint(rRenderContext, rRect);
104 }
105 m_bInPaint = false;
106 }
107
MouseButtonDown(const MouseEvent & rMEvt)108 void ChartWindow::MouseButtonDown(const MouseEvent& rMEvt)
109 {
110 if( m_pWindowController )
111 m_pWindowController->execute_MouseButtonDown(rMEvt);
112 else
113 Window::MouseButtonDown(rMEvt);
114 }
115
MouseMove(const MouseEvent & rMEvt)116 void ChartWindow::MouseMove( const MouseEvent& rMEvt )
117 {
118 if( m_pWindowController )
119 m_pWindowController->execute_MouseMove( rMEvt );
120 else
121 Window::MouseMove( rMEvt );
122 }
123
Tracking(const TrackingEvent & rTEvt)124 void ChartWindow::Tracking( const TrackingEvent& rTEvt )
125 {
126 if( !m_pWindowController )
127 Window::Tracking( rTEvt );
128 }
129
MouseButtonUp(const MouseEvent & rMEvt)130 void ChartWindow::MouseButtonUp( const MouseEvent& rMEvt )
131 {
132 if( m_pWindowController )
133 m_pWindowController->execute_MouseButtonUp( rMEvt );
134 else
135 Window::MouseButtonUp( rMEvt );
136 }
137
Resize()138 void ChartWindow::Resize()
139 {
140 if( m_pWindowController )
141 m_pWindowController->execute_Resize();
142 else
143 Window::Resize();
144 }
145
Activate()146 void ChartWindow::Activate()
147 {
148 if( !m_pWindowController )
149 Window::Activate();
150 }
Deactivate()151 void ChartWindow::Deactivate()
152 {
153 if( !m_pWindowController )
154 Window::Deactivate();
155 }
GetFocus()156 void ChartWindow::GetFocus()
157 {
158 if( !m_pWindowController )
159 Window::GetFocus();
160 }
LoseFocus()161 void ChartWindow::LoseFocus()
162 {
163 if( !m_pWindowController )
164 Window::LoseFocus();
165 }
166
Command(const CommandEvent & rCEvt)167 void ChartWindow::Command( const CommandEvent& rCEvt )
168 {
169 if( m_pWindowController )
170 m_pWindowController->execute_Command( rCEvt );
171 else
172 Window::Command( rCEvt );
173 }
174
KeyInput(const KeyEvent & rKEvt)175 void ChartWindow::KeyInput( const KeyEvent& rKEvt )
176 {
177 if( m_pWindowController )
178 {
179 if( !m_pWindowController->execute_KeyInput(rKEvt) )
180 Window::KeyInput(rKEvt);
181 }
182 else
183 Window::KeyInput( rKEvt );
184 }
185
CreateAccessible()186 uno::Reference< css::accessibility::XAccessible > ChartWindow::CreateAccessible()
187 {
188 if( m_pWindowController )
189 return m_pWindowController->CreateAccessible();
190 else
191 return Window::CreateAccessible();
192 }
193
DataChanged(const DataChangedEvent & rDCEvt)194 void ChartWindow::DataChanged( const DataChangedEvent& rDCEvt )
195 {
196 vcl::Window::DataChanged( rDCEvt );
197
198 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
199 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
200 {
201 adjustHighContrastMode();
202 }
203 }
204
RequestHelp(const HelpEvent & rHEvt)205 void ChartWindow::RequestHelp( const HelpEvent& rHEvt )
206 {
207 bool bHelpHandled = false;
208 if( ( rHEvt.GetMode() & HelpEventMode::QUICK ) &&
209 m_pWindowController )
210 {
211 // Point aLogicHitPos = PixelToLogic( rHEvt.GetMousePosPixel()); // old chart: GetPointerPosPixel()
212 Point aLogicHitPos = PixelToLogic( GetPointerPosPixel());
213 OUString aQuickHelpText;
214 awt::Rectangle aHelpRect;
215 bool bIsBalloonHelp( Help::IsBalloonHelpEnabled() );
216 bHelpHandled = m_pWindowController->requestQuickHelp( aLogicHitPos, bIsBalloonHelp, aQuickHelpText, aHelpRect );
217
218 if( bHelpHandled )
219 {
220 if( bIsBalloonHelp )
221 Help::ShowBalloon(
222 this, rHEvt.GetMousePosPixel(), lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText );
223 else
224 Help::ShowQuickHelp(
225 this, lcl_AWTRectToVCLRect( aHelpRect ), aQuickHelpText );
226 }
227 }
228
229 if( !bHelpHandled )
230 vcl::Window::RequestHelp( rHEvt );
231 }
232
LogicMouseButtonDown(const MouseEvent & rEvent)233 void ChartWindow::LogicMouseButtonDown(const MouseEvent& rEvent)
234 {
235 MouseButtonDown(rEvent);
236 }
237
LogicMouseButtonUp(const MouseEvent & rEvent)238 void ChartWindow::LogicMouseButtonUp(const MouseEvent& rEvent)
239 {
240 MouseButtonUp(rEvent);
241 }
242
LogicMouseMove(const MouseEvent & rEvent)243 void ChartWindow::LogicMouseMove(const MouseEvent& rEvent)
244 {
245 MouseMove(rEvent);
246 }
247
adjustHighContrastMode()248 void ChartWindow::adjustHighContrastMode()
249 {
250 static const DrawModeFlags nContrastMode =
251 DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill |
252 DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient;
253
254 bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
255 GetOutDev()->SetDrawMode( bUseContrast ? nContrastMode : DrawModeFlags::Default );
256 }
257
ForceInvalidate()258 void ChartWindow::ForceInvalidate()
259 {
260 vcl::Window::Invalidate();
261 }
Invalidate(InvalidateFlags nFlags)262 void ChartWindow::Invalidate( InvalidateFlags nFlags )
263 {
264 if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts"
265 return;
266 vcl::Window::Invalidate( nFlags );
267 }
Invalidate(const tools::Rectangle & rRect,InvalidateFlags nFlags)268 void ChartWindow::Invalidate( const tools::Rectangle& rRect, InvalidateFlags nFlags )
269 {
270 if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts"
271 return;
272 vcl::Window::Invalidate( rRect, nFlags );
273 }
Invalidate(const vcl::Region & rRegion,InvalidateFlags nFlags)274 void ChartWindow::Invalidate( const vcl::Region& rRegion, InvalidateFlags nFlags )
275 {
276 if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts"
277 return;
278 vcl::Window::Invalidate( rRegion, nFlags );
279 }
280
LogicInvalidate(const tools::Rectangle * pRectangle)281 void ChartWindow::LogicInvalidate(const tools::Rectangle* pRectangle)
282 {
283 SfxViewShell* pCurrentShell = SfxViewShell::Current();
284 if ( nullptr == pCurrentShell )
285 return;
286 OString sRectangle;
287 if (!pRectangle)
288 {
289 // we have to invalidate the whole chart area not the whole document
290 sRectangle = GetBoundingBox().toString();
291 }
292 else
293 {
294 tools::Rectangle aRectangle(*pRectangle);
295 // When dragging shapes the map mode is disabled.
296 if (IsMapModeEnabled())
297 {
298 if (GetMapMode().GetMapUnit() == MapUnit::Map100thMM)
299 aRectangle = OutputDevice::LogicToLogic(aRectangle, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip));
300 }
301 else
302 {
303 aRectangle = PixelToLogic(aRectangle, MapMode(MapUnit::MapTwip));
304 }
305
306 vcl::Window* pEditWin = GetParentEditWin();
307 if (pEditWin)
308 {
309 MapMode aCWMapMode = GetMapMode();
310 double fXScale( aCWMapMode.GetScaleX() );
311 double fYScale( aCWMapMode.GetScaleY() );
312
313 if (!IsMapModeEnabled())
314 {
315 aRectangle.SetLeft( aRectangle.Left() / fXScale );
316 aRectangle.SetRight( aRectangle.Right() / fXScale );
317 aRectangle.SetTop( aRectangle.Top() / fYScale );
318 aRectangle.SetBottom( aRectangle.Bottom() / fYScale );
319 }
320
321 Point aOffset = this->GetOffsetPixelFrom(*pEditWin);
322 aOffset.setX( aOffset.X() * (TWIPS_PER_PIXEL / fXScale) );
323 aOffset.setY( aOffset.Y() * (TWIPS_PER_PIXEL / fYScale) );
324
325 aRectangle = tools::Rectangle(aRectangle.TopLeft() + aOffset, aRectangle.GetSize());
326 }
327
328 sRectangle = aRectangle.toString();
329 }
330 SfxLokHelper::notifyInvalidation(pCurrentShell, sRectangle);
331 }
332
GetUITestFactory() const333 FactoryFunction ChartWindow::GetUITestFactory() const
334 {
335 return ChartWindowUIObject::create;
336 }
337
GetController()338 ChartController* ChartWindow::GetController()
339 {
340 return m_pWindowController;
341 }
342
GetParentEditWin()343 vcl::Window* ChartWindow::GetParentEditWin()
344 {
345 if (m_pViewShellWindow)
346 return m_pViewShellWindow.get();
347
348 // So, you are thinking, why do not invoke pCurrentShell->GetWindow() ?
349 // Because in Impress the parent edit win is not view shell window.
350 SfxViewShell* pCurrentShell = SfxViewShell::Current();
351 if( pCurrentShell )
352 {
353 SfxInPlaceClient* pIPClient = pCurrentShell->GetIPClient();
354 if (pIPClient)
355 {
356 vcl::Window* pRootWin = pIPClient->GetEditWin();
357 if(pRootWin && pRootWin->IsAncestorOf(*this))
358 {
359 m_pViewShellWindow = pRootWin;
360 return m_pViewShellWindow.get();
361 }
362 }
363 }
364 return nullptr;
365 }
366
GetBoundingBox()367 tools::Rectangle ChartWindow::GetBoundingBox()
368 {
369 tools::Rectangle aBBox;
370
371 vcl::Window* pRootWin = GetParentEditWin();
372 if (pRootWin)
373 {
374 // In all cases, the following code fragment
375 // returns the chart bounding box in twips.
376 MapMode aCWMapMode = GetMapMode();
377 double fXScale( aCWMapMode.GetScaleX() );
378 double fYScale( aCWMapMode.GetScaleY() );
379 Point aOffset = GetOffsetPixelFrom(*pRootWin);
380 aOffset.setX( aOffset.X() * (TWIPS_PER_PIXEL / fXScale) );
381 aOffset.setY( aOffset.Y() * (TWIPS_PER_PIXEL / fYScale) );
382 Size aSize = GetSizePixel();
383 aSize.setWidth( aSize.Width() * (TWIPS_PER_PIXEL / fXScale) );
384 aSize.setHeight( aSize.Height() * (TWIPS_PER_PIXEL / fYScale) );
385 aBBox = tools::Rectangle(aOffset, aSize);
386 }
387 return aBBox;
388 }
389
390 } //namespace chart
391
392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
393