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 <vcl/msgbox.hxx>
22 #include <sfx2/dispatch.hxx>
23 #include <sfx2/basedlgs.hxx>
24 #include <IDocumentUndoRedo.hxx>
25 #include <IDocumentChartDataProviderAccess.hxx>
27 #include <sfx2/app.hxx>
28 #include <swtypes.hxx>
29 #include <swmodule.hxx>
33 #include <chartins.hxx>
34 #include <tablemgr.hxx>
36 #include <swtable.hxx>
38 #include <unochart.hxx>
44 #include <anchoredobject.hxx>
46 #include <comphelper/classids.hxx>
48 #include <cppuhelper/bootstrap.hxx>
49 #include <cppuhelper/component_context.hxx>
50 #include <comphelper/processfactory.hxx>
51 #include <com/sun/star/chart2/data/XDataProvider.hpp>
52 #include <com/sun/star/lang/XInitialization.hpp>
53 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
54 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
56 using namespace ::com::sun::star
;
57 using namespace ::com::sun::star::uno
;
59 Point
SwGetChartDialogPos( const vcl::Window
*pParentWin
, const Size
& rDialogSize
, const tools::Rectangle
& rLogicChart
)
61 // positioning code according to spec; similar to Calc fuins2.cxx
64 OSL_ENSURE( pParentWin
, "Window not found" );
67 tools::Rectangle aObjPixel
= pParentWin
->LogicToPixel( rLogicChart
, pParentWin
->GetMapMode() );
68 tools::Rectangle
aObjAbs( pParentWin
->OutputToAbsoluteScreenPixel( aObjPixel
.TopLeft() ),
69 pParentWin
->OutputToAbsoluteScreenPixel( aObjPixel
.BottomRight() ) );
71 tools::Rectangle aDesktop
= pParentWin
->GetDesktopRectPixel();
72 Size aSpace
= pParentWin
->LogicToPixel( Size( 8, 12 ), MapUnit::MapAppFont
);
74 bool bLayoutRTL
= ::GetActiveView()->GetWrtShell().IsTableRightToLeft();
75 bool bCenterHor
= false;
77 if ( aDesktop
.Bottom() - aObjAbs
.Bottom() >= rDialogSize
.Height() + aSpace
.Height() )
79 // first preference: below the chart
80 aRet
.Y() = aObjAbs
.Bottom() + aSpace
.Height();
83 else if ( aObjAbs
.Top() - aDesktop
.Top() >= rDialogSize
.Height() + aSpace
.Height() )
85 // second preference: above the chart
86 aRet
.Y() = aObjAbs
.Top() - rDialogSize
.Height() - aSpace
.Height();
91 bool bFitLeft
= ( aObjAbs
.Left() - aDesktop
.Left() >= rDialogSize
.Width() + aSpace
.Width() );
92 bool bFitRight
= ( aDesktop
.Right() - aObjAbs
.Right() >= rDialogSize
.Width() + aSpace
.Width() );
94 if ( bFitLeft
|| bFitRight
)
96 // if both fit, prefer right in RTL mode, left otherwise
97 bool bPutRight
= bFitRight
&& ( bLayoutRTL
|| !bFitLeft
);
99 aRet
.X() = aObjAbs
.Right() + aSpace
.Width();
101 aRet
.X() = aObjAbs
.Left() - rDialogSize
.Width() - aSpace
.Width();
104 aRet
.Y() = aObjAbs
.Top() + ( aObjAbs
.GetHeight() - rDialogSize
.Height() ) / 2;
108 // doesn't fit on any edge - put at the bottom of the screen
109 aRet
.Y() = aDesktop
.Bottom() - rDialogSize
.Height();
114 aRet
.X() = aObjAbs
.Left() + ( aObjAbs
.GetWidth() - rDialogSize
.Width() ) / 2;
116 // limit to screen (centering might lead to invalid positions)
117 if ( aRet
.X() + rDialogSize
.Width() - 1 > aDesktop
.Right() )
118 aRet
.X() = aDesktop
.Right() - rDialogSize
.Width() + 1;
119 if ( aRet
.X() < aDesktop
.Left() )
120 aRet
.X() = aDesktop
.Left();
121 if ( aRet
.Y() + rDialogSize
.Height() - 1 > aDesktop
.Bottom() )
122 aRet
.Y() = aDesktop
.Bottom() - rDialogSize
.Height() + 1;
123 if ( aRet
.Y() < aDesktop
.Top() )
124 aRet
.Y() = aDesktop
.Top();
130 void SwInsertChart(vcl::Window
* pParent
, SfxBindings
* pBindings
)
134 SwView
*pView
= ::GetActiveView();
136 // get range string of marked data
137 SwWrtShell
&rWrtShell
= pView
->GetWrtShell();
138 uno::Reference
< chart2::data::XDataProvider
> xDataProvider
;
139 uno::Reference
< frame::XModel
> xChartModel
;
140 OUString aRangeString
;
142 if( rWrtShell
.IsCursorInTable())
144 if (!rWrtShell
.IsTableMode())
146 // select whole table
147 rWrtShell
.GetView().GetViewFrame()->GetDispatcher()->
148 Execute(FN_TABLE_SELECT_ALL
, SfxCallMode::SYNCHRON
);
150 if( ! rWrtShell
.IsTableComplexForChart())
152 SwFrameFormat
* pTableFormat
= rWrtShell
.GetTableFormat();
153 aRangeString
= pTableFormat
->GetName() + "." + rWrtShell
.GetBoxNms();
155 // get table data provider
156 xDataProvider
.set( pView
->GetDocShell()->getIDocumentChartDataProviderAccess().GetChartDataProvider( true ) );
160 SwFlyFrameFormat
*pFlyFrameFormat
= nullptr;
161 xChartModel
.set( SwTableFUNC( &rWrtShell
).InsertChart( xDataProvider
, xDataProvider
.is(), aRangeString
, &pFlyFrameFormat
));
164 //@todo get context from writer if that has one
165 uno::Reference
< uno::XComponentContext
> xContext(
166 ::cppu::defaultBootstrap_InitialComponentContext() );
167 if( xContext
.is() && xChartModel
.is() && xDataProvider
.is())
169 uno::Reference
< lang::XMultiComponentFactory
> xMCF( xContext
->getServiceManager() );
172 uno::Reference
< ui::dialogs::XExecutableDialog
> xDialog(
173 xMCF
->createInstanceWithContext(
174 "com.sun.star.comp.chart2.WizardDialog", xContext
),
176 uno::Reference
< lang::XInitialization
> xInit( xDialog
, uno::UNO_QUERY
);
179 uno::Reference
< awt::XWindow
> xDialogParentWindow(nullptr);
181 uno::Sequence
<uno::Any
> aSeq(2);
182 uno::Any
* pArray
= aSeq
.getArray();
183 beans::PropertyValue aParam1
;
184 aParam1
.Name
= "ParentWindow";
185 aParam1
.Value
<<= xDialogParentWindow
;
186 beans::PropertyValue aParam2
;
187 aParam2
.Name
= "ChartModel";
188 aParam2
.Value
<<= xChartModel
;
189 pArray
[0] <<= aParam1
;
190 pArray
[1] <<= aParam2
;
191 xInit
->initialize( aSeq
);
193 // try to set the dialog's position so it doesn't hide the chart
194 uno::Reference
< beans::XPropertySet
> xDialogProps( xDialog
, uno::UNO_QUERY
);
195 if ( xDialogProps
.is() )
200 awt::Size aDialogAWTSize
;
201 if( xDialogProps
->getPropertyValue("Size")
204 Size
aDialogSize( aDialogAWTSize
.Width
, aDialogAWTSize
.Height
);
205 if ( aDialogSize
.Width() > 0 && aDialogSize
.Height() > 0 )
207 //calculate and set new position
210 aSwRect
= pFlyFrameFormat
->GetAnchoredObj()->GetObjRectWithSpaces();
211 tools::Rectangle
aRect( aSwRect
.SVRect() );
212 Point aDialogPos
= SwGetChartDialogPos( &rWrtShell
.GetView().GetEditWin(), aDialogSize
, aRect
);
213 xDialogProps
->setPropertyValue("Position",
214 uno::makeAny( awt::Point(aDialogPos
.getX(),aDialogPos
.getY()) ) );
218 catch (const uno::Exception
&)
220 OSL_FAIL("Chart wizard couldn't be positioned automatically" );
224 sal_Int16 nDialogRet
= xDialog
->execute();
225 if( nDialogRet
== ui::dialogs::ExecutableDialogResults::CANCEL
)
228 rWrtShell
.GetIDocumentUndoRedo().ClearRedo();
232 OSL_ENSURE( nDialogRet
== ui::dialogs::ExecutableDialogResults::OK
,
233 "dialog execution failed" );
236 uno::Reference
< lang::XComponent
> xComponent( xDialog
, uno::UNO_QUERY
);
238 xComponent
->dispose();
243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */