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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sfx2/viewfrm.hxx>
21 #include <sfx2/dispatch.hxx>
22 #include <IDocumentChartDataProviderAccess.hxx>
23 #include <osl/diagnose.h>
25 #include <swmodule.hxx>
29 #include <chartins.hxx>
30 #include <tablemgr.hxx>
32 #include <unochart.hxx>
37 #include <anchoredobject.hxx>
39 #include <cppuhelper/bootstrap.hxx>
40 #include <comphelper/propertysequence.hxx>
41 #include <com/sun/star/awt/Point.hpp>
42 #include <com/sun/star/awt/Size.hpp>
43 #include <com/sun/star/awt/XWindow.hpp>
44 #include <svtools/dialogclosedlistener.hxx>
45 #include <com/sun/star/chart2/data/XDataProvider.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/lang/XInitialization.hpp>
48 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
49 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::uno
;
54 Point
SwGetChartDialogPos( const vcl::Window
*pParentWin
, const Size
& rDialogSize
, const tools::Rectangle
& rLogicChart
)
56 // positioning code according to spec; similar to Calc fuins2.cxx
59 OSL_ENSURE( pParentWin
, "Window not found" );
62 tools::Rectangle aObjPixel
= pParentWin
->LogicToPixel( rLogicChart
, pParentWin
->GetMapMode() );
63 tools::Rectangle
aObjAbs( pParentWin
->OutputToAbsoluteScreenPixel( aObjPixel
.TopLeft() ),
64 pParentWin
->OutputToAbsoluteScreenPixel( aObjPixel
.BottomRight() ) );
66 tools::Rectangle aDesktop
= pParentWin
->GetDesktopRectPixel();
67 Size aSpace
= pParentWin
->LogicToPixel(Size(8, 12), MapMode(MapUnit::MapAppFont
));
69 bool bCenterHor
= false;
71 if ( aDesktop
.Bottom() - aObjAbs
.Bottom() >= rDialogSize
.Height() + aSpace
.Height() )
73 // first preference: below the chart
74 aRet
.setY( aObjAbs
.Bottom() + aSpace
.Height() );
77 else if ( aObjAbs
.Top() - aDesktop
.Top() >= rDialogSize
.Height() + aSpace
.Height() )
79 // second preference: above the chart
80 aRet
.setY( aObjAbs
.Top() - rDialogSize
.Height() - aSpace
.Height() );
85 bool bFitLeft
= ( aObjAbs
.Left() - aDesktop
.Left() >= rDialogSize
.Width() + aSpace
.Width() );
86 bool bFitRight
= ( aDesktop
.Right() - aObjAbs
.Right() >= rDialogSize
.Width() + aSpace
.Width() );
88 if ( bFitLeft
|| bFitRight
)
90 if (SwView
* pView
= GetActiveView())
92 // if both fit, prefer right in RTL mode, left otherwise
93 bool bLayoutRTL
= pView
->GetWrtShell().IsTableRightToLeft();
94 bool bPutRight
= bFitRight
&& ( bLayoutRTL
|| !bFitLeft
);
96 aRet
.setX( aObjAbs
.Right() + aSpace
.Width() );
98 aRet
.setX( aObjAbs
.Left() - rDialogSize
.Width() - aSpace
.Width() );
102 aRet
.setY( aObjAbs
.Top() + ( aObjAbs
.GetHeight() - rDialogSize
.Height() ) / 2 );
106 // doesn't fit on any edge - put at the bottom of the screen
107 aRet
.setY( aDesktop
.Bottom() - rDialogSize
.Height() );
112 aRet
.setX( aObjAbs
.Left() + ( aObjAbs
.GetWidth() - rDialogSize
.Width() ) / 2 );
114 // limit to screen (centering might lead to invalid positions)
115 if ( aRet
.X() + rDialogSize
.Width() - 1 > aDesktop
.Right() )
116 aRet
.setX( aDesktop
.Right() - rDialogSize
.Width() + 1 );
117 if ( aRet
.X() < aDesktop
.Left() )
118 aRet
.setX( aDesktop
.Left() );
119 if ( aRet
.Y() + rDialogSize
.Height() - 1 > aDesktop
.Bottom() )
120 aRet
.setY( aDesktop
.Bottom() - rDialogSize
.Height() + 1 );
121 if ( aRet
.Y() < aDesktop
.Top() )
122 aRet
.setY( aDesktop
.Top() );
128 SwInsertChart::SwInsertChart( const Link
<css::ui::dialogs::DialogClosedEvent
*, void>& rLink
)
130 SwView
*pView
= ::GetActiveView();
134 // get range string of marked data
135 SwWrtShell
&rWrtShell
= pView
->GetWrtShell();
136 uno::Reference
< chart2::data::XDataProvider
> xDataProvider
;
137 uno::Reference
< frame::XModel
> xChartModel
;
138 OUString aRangeString
;
140 if( rWrtShell
.IsCursorInTable())
142 if (!rWrtShell
.IsTableMode())
144 // select whole table
145 rWrtShell
.GetView().GetViewFrame().GetDispatcher()->
146 Execute(FN_TABLE_SELECT_ALL
, SfxCallMode::SYNCHRON
);
148 if( ! rWrtShell
.IsTableComplexForChart())
150 SwFrameFormat
* pTableFormat
= rWrtShell
.GetTableFormat();
151 aRangeString
= pTableFormat
->GetName() + "." + rWrtShell
.GetBoxNms();
153 // get table data provider
154 xDataProvider
.set( pView
->GetDocShell()->getIDocumentChartDataProviderAccess().GetChartDataProvider( true ) );
158 SwFlyFrameFormat
*pFlyFrameFormat
= nullptr;
159 xChartModel
.set( SwTableFUNC( &rWrtShell
).InsertChart( xDataProvider
, xDataProvider
.is(), aRangeString
, &pFlyFrameFormat
));
162 //@todo get context from writer if that has one
163 uno::Reference
< uno::XComponentContext
> xContext(
164 ::cppu::defaultBootstrap_InitialComponentContext() );
165 if( !(xContext
.is() && xChartModel
.is() && xDataProvider
.is()))
168 uno::Reference
< lang::XMultiComponentFactory
> xMCF( xContext
->getServiceManager() );
172 uno::Reference
< ui::dialogs::XAsynchronousExecutableDialog
> xDialog(
173 xMCF
->createInstanceWithContext(
174 "com.sun.star.comp.chart2.WizardDialog", xContext
),
176 uno::Reference
< lang::XInitialization
> xInit( xDialog
, uno::UNO_QUERY
);
180 uno::Sequence
<uno::Any
> aSeq(comphelper::InitAnyPropertySequence(
182 {"ParentWindow", uno::Any(uno::Reference
< awt::XWindow
>())},
183 {"ChartModel", uno::Any(xChartModel
)}
185 xInit
->initialize( aSeq
);
187 // try to set the dialog's position so it doesn't hide the chart
188 uno::Reference
< beans::XPropertySet
> xDialogProps( xDialog
, uno::UNO_QUERY
);
189 if ( xDialogProps
.is() )
194 awt::Size aDialogAWTSize
;
195 if( xDialogProps
->getPropertyValue("Size")
198 Size
aDialogSize( aDialogAWTSize
.Width
, aDialogAWTSize
.Height
);
199 if ( !aDialogSize
.IsEmpty() )
201 //calculate and set new position
204 aSwRect
= pFlyFrameFormat
->GetAnchoredObj()->GetObjRectWithSpaces();
205 tools::Rectangle
aRect( aSwRect
.SVRect() );
206 Point aDialogPos
= SwGetChartDialogPos( &rWrtShell
.GetView().GetEditWin(), aDialogSize
, aRect
);
207 xDialogProps
->setPropertyValue("Position",
208 uno::Any( awt::Point(aDialogPos
.getX(),aDialogPos
.getY()) ) );
212 catch (const uno::Exception
&)
214 OSL_FAIL("Chart wizard couldn't be positioned automatically" );
218 rtl::Reference
<::svt::DialogClosedListener
> pListener
= new ::svt::DialogClosedListener();
219 pListener
->SetDialogClosedLink( rLink
);
221 xDialog
->startExecuteModal( pListener
);
225 uno::Reference
< lang::XComponent
> xComponent( xDialog
, uno::UNO_QUERY
);
227 xComponent
->dispose();
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */