1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sw.hxx" 24 25 #include <sfx2/viewfrm.hxx> 26 #include <vcl/msgbox.hxx> 27 #include <sfx2/dispatch.hxx> 28 #include <sfx2/basedlgs.hxx> 29 #include <IDocumentUndoRedo.hxx> 30 31 #include <sfx2/app.hxx> 32 #include <swtypes.hxx> 33 #include <swmodule.hxx> 34 #include <wrtsh.hxx> 35 #include <docsh.hxx> 36 #include <view.hxx> 37 #include <chartins.hxx> 38 #include <tablemgr.hxx> 39 #include <frmfmt.hxx> 40 #include <swtable.hxx> 41 #include <tblsel.hxx> 42 #include <unochart.hxx> 43 #include <autoedit.hxx> 44 #include <doc.hxx> 45 46 #include <edtwin.hxx> 47 48 #include <cmdid.h> 49 #include <chartins.hrc> 50 #include <anchoredobject.hxx> 51 52 #include <sot/clsids.hxx> 53 54 #include <cppuhelper/bootstrap.hxx> 55 #include <cppuhelper/component_context.hxx> 56 #include <comphelper/processfactory.hxx> 57 #include <com/sun/star/chart2/data/XDataProvider.hpp> 58 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 59 #include <com/sun/star/chart/ChartDataRowSource.hpp> 60 #include <com/sun/star/frame/XComponentLoader.hpp> 61 #include <com/sun/star/lang/XInitialization.hpp> 62 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 63 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> 64 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 65 66 using namespace ::com::sun::star; 67 using namespace ::com::sun::star::uno; 68 using ::rtl::OUString; 69 70 Point SwGetChartDialogPos( const Window *pParentWin, const Size& rDialogSize, const Rectangle& rLogicChart ) 71 { 72 // !! positioning code according to specs; similar to Calc fuins2.cxx 73 74 Point aRet; 75 76 DBG_ASSERT( pParentWin, "Window not found" ); 77 if (pParentWin) 78 { 79 Rectangle aObjPixel = pParentWin->LogicToPixel( rLogicChart, pParentWin->GetMapMode() ); 80 Rectangle aObjAbs( pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.TopLeft() ), 81 pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.BottomRight() ) ); 82 83 Rectangle aDesktop = pParentWin->GetDesktopRectPixel(); 84 Size aSpace = pParentWin->LogicToPixel( Size( 8, 12 ), MAP_APPFONT ); 85 86 sal_Bool bLayoutRTL = ::GetActiveView()->GetWrtShell().IsTableRightToLeft(); 87 bool bCenterHor = false; 88 89 if ( aDesktop.Bottom() - aObjAbs.Bottom() >= rDialogSize.Height() + aSpace.Height() ) 90 { 91 // first preference: below the chart 92 aRet.Y() = aObjAbs.Bottom() + aSpace.Height(); 93 bCenterHor = true; 94 } 95 else if ( aObjAbs.Top() - aDesktop.Top() >= rDialogSize.Height() + aSpace.Height() ) 96 { 97 // second preference: above the chart 98 aRet.Y() = aObjAbs.Top() - rDialogSize.Height() - aSpace.Height(); 99 bCenterHor = true; 100 } 101 else 102 { 103 bool bFitLeft = ( aObjAbs.Left() - aDesktop.Left() >= rDialogSize.Width() + aSpace.Width() ); 104 bool bFitRight = ( aDesktop.Right() - aObjAbs.Right() >= rDialogSize.Width() + aSpace.Width() ); 105 106 if ( bFitLeft || bFitRight ) 107 { 108 // if both fit, prefer right in RTL mode, left otherwise 109 bool bPutRight = bFitRight && ( bLayoutRTL || !bFitLeft ); 110 if ( bPutRight ) 111 aRet.X() = aObjAbs.Right() + aSpace.Width(); 112 else 113 aRet.X() = aObjAbs.Left() - rDialogSize.Width() - aSpace.Width(); 114 115 // center vertically 116 aRet.Y() = aObjAbs.Top() + ( aObjAbs.GetHeight() - rDialogSize.Height() ) / 2; 117 } 118 else 119 { 120 // doesn't fit on any edge - put at the bottom of the screen 121 aRet.Y() = aDesktop.Bottom() - rDialogSize.Height(); 122 bCenterHor = true; 123 } 124 } 125 if ( bCenterHor ) 126 aRet.X() = aObjAbs.Left() + ( aObjAbs.GetWidth() - rDialogSize.Width() ) / 2; 127 128 // limit to screen (centering might lead to invalid positions) 129 if ( aRet.X() + rDialogSize.Width() - 1 > aDesktop.Right() ) 130 aRet.X() = aDesktop.Right() - rDialogSize.Width() + 1; 131 if ( aRet.X() < aDesktop.Left() ) 132 aRet.X() = aDesktop.Left(); 133 if ( aRet.Y() + rDialogSize.Height() - 1 > aDesktop.Bottom() ) 134 aRet.Y() = aDesktop.Bottom() - rDialogSize.Height() + 1; 135 if ( aRet.Y() < aDesktop.Top() ) 136 aRet.Y() = aDesktop.Top(); 137 } 138 139 return aRet; 140 } 141 142 /*------------------------------------------------------------------------ 143 Description: 144 ------------------------------------------------------------------------*/ 145 146 void SwInsertChart(Window* pParent, SfxBindings* pBindings ) 147 { 148 (void) pParent; 149 (void) pBindings; 150 SwView *pView = ::GetActiveView(); 151 152 // get range string of marked data 153 SwWrtShell &rWrtShell = pView->GetWrtShell(); 154 uno::Reference< chart2::data::XDataProvider > xDataProvider; 155 uno::Reference< frame::XModel > xChartModel; 156 OUString aRangeString; 157 158 if( rWrtShell.IsCrsrInTbl()) 159 { 160 if (!rWrtShell.IsTableMode()) 161 { 162 // select whole table 163 rWrtShell.GetView().GetViewFrame()->GetDispatcher()-> 164 Execute(FN_TABLE_SELECT_ALL, SFX_CALLMODE_SYNCHRON); 165 } 166 if( ! rWrtShell.IsTblComplexForChart()) 167 { 168 SwFrmFmt* pTblFmt = rWrtShell.GetTableFmt(); 169 String aCurrentTblName = pTblFmt->GetName(); 170 // String aText( String::CreateFromAscii("<.>") ); // was used for UI 171 // aText.Insert( rWrtShell.GetBoxNms(), 2); 172 // aText.Insert( aCurrentTblName, 1 ); 173 aRangeString = aCurrentTblName; 174 aRangeString += OUString::valueOf( sal_Unicode('.') ); 175 aRangeString += rWrtShell.GetBoxNms(); 176 177 // get table data provider 178 xDataProvider.set( pView->GetDocShell()->getIDocumentChartDataProviderAccess()->GetChartDataProvider( true ) ); 179 } 180 } 181 182 SwFlyFrmFmt *pFlyFrmFmt = 0; 183 xChartModel.set( SwTableFUNC( &rWrtShell, sal_False ).InsertChart( xDataProvider, (sal_True == xDataProvider.is()), aRangeString, &pFlyFrmFmt )); 184 185 // open wizard 186 // TODO: get context from Writer if that has one 187 uno::Reference< uno::XComponentContext > xContext( 188 ::cppu::defaultBootstrap_InitialComponentContext() ); 189 if( xContext.is() && xChartModel.is() && xDataProvider.is()) 190 { 191 uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() ); 192 if(xMCF.is()) 193 { 194 uno::Reference< ui::dialogs::XExecutableDialog > xDialog( 195 xMCF->createInstanceWithContext( 196 C2U("com.sun.star.comp.chart2.WizardDialog") 197 , xContext), uno::UNO_QUERY); 198 uno::Reference< lang::XInitialization > xInit( xDialog, uno::UNO_QUERY ); 199 if( xInit.is() ) 200 { 201 uno::Reference< awt::XWindow > xDialogParentWindow(0); 202 // initialize dialog 203 uno::Sequence<uno::Any> aSeq(2); 204 uno::Any* pArray = aSeq.getArray(); 205 beans::PropertyValue aParam1; 206 aParam1.Name = C2U("ParentWindow"); 207 aParam1.Value <<= uno::makeAny(xDialogParentWindow); 208 beans::PropertyValue aParam2; 209 aParam2.Name = C2U("ChartModel"); 210 aParam2.Value <<= uno::makeAny(xChartModel); 211 pArray[0] <<= uno::makeAny(aParam1); 212 pArray[1] <<= uno::makeAny(aParam2); 213 xInit->initialize( aSeq ); 214 215 // try to set the dialog's position so it doesn't hide the chart 216 uno::Reference < beans::XPropertySet > xDialogProps( xDialog, uno::UNO_QUERY ); 217 if ( xDialogProps.is() ) 218 { 219 try 220 { 221 // get dialog size: 222 awt::Size aDialogAWTSize; 223 if( xDialogProps->getPropertyValue( ::rtl::OUString::createFromAscii("Size") ) 224 >>= aDialogAWTSize ) 225 { 226 Size aDialogSize( aDialogAWTSize.Width, aDialogAWTSize.Height ); 227 if ( aDialogSize.Width() > 0 && aDialogSize.Height() > 0 ) 228 { 229 // calculate and set new position 230 SwRect aSwRect; 231 if (pFlyFrmFmt) 232 aSwRect = pFlyFrmFmt->GetAnchoredObj()->GetObjRectWithSpaces(); 233 Rectangle aRect( aSwRect.SVRect() ); 234 Point aDialogPos = SwGetChartDialogPos( &rWrtShell.GetView().GetEditWin(), aDialogSize, aRect ); 235 xDialogProps->setPropertyValue( ::rtl::OUString::createFromAscii("Position"), 236 uno::makeAny( awt::Point(aDialogPos.getX(),aDialogPos.getY()) ) ); 237 } 238 } 239 } 240 catch( uno::Exception& ) 241 { 242 DBG_ERROR( "Chart wizard couldn't be positioned automatically\n" ); 243 } 244 } 245 246 sal_Int16 nDialogRet = xDialog->execute(); 247 if( nDialogRet == ui::dialogs::ExecutableDialogResults::CANCEL ) 248 { 249 rWrtShell.Undo(); 250 rWrtShell.GetIDocumentUndoRedo().ClearRedo(); 251 } 252 else 253 { 254 DBG_ASSERT( nDialogRet == ui::dialogs::ExecutableDialogResults::OK, 255 "dialog execution failed" ); 256 } 257 } 258 uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY ); 259 if( xComponent.is()) 260 xComponent->dispose(); 261 } 262 } 263 } 264 265 266 void __EXPORT AutoEdit::KeyInput( const KeyEvent& rEvt ) 267 { 268 sal_uInt16 nCode = rEvt.GetKeyCode().GetCode(); 269 if( nCode != KEY_SPACE ) 270 Edit::KeyInput( rEvt ); 271 } 272 273 /* vim: set noet sw=4 ts=4: */ 274