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