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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <svx/sdr/table/tablecontroller.hxx>
28 #include <tablemodel.hxx>
29 
30 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
31 #include <com/sun/star/container/XIndexAccess.hpp>
32 
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/table/XMergeableCellRange.hpp>
35 #include <com/sun/star/table/XMergeableCell.hpp>
36 
37 #include <sal/config.h>
38 
39 #include <vcl/svapp.hxx>
40 #include <svl/whiter.hxx>
41 
42 #include <sfx2/request.hxx>
43 
44 #include <editeng/scripttypeitem.hxx>
45 #include <svx/svdotable.hxx>
46 #include <svx/sdr/overlay/overlayobjectcell.hxx>
47 #include <svx/sdr/overlay/overlaymanager.hxx>
48 #include <svx/svxids.hrc>
49 #include <editeng/outlobj.hxx>
50 #include <svx/svdoutl.hxx>
51 #include <svx/svdpagv.hxx>
52 #include <svx/svdetc.hxx>
53 #include <editeng/editobj.hxx>
54 #include "editeng/editstat.hxx"
55 #include "editeng/unolingu.hxx"
56 #include "svx/sdrpagewindow.hxx"
57 #include <svx/selectioncontroller.hxx>
58 #include <svx/svdmodel.hxx>
59 #include "svx/sdrpaintwindow.hxx"
60 #include <svx/svxdlg.hxx>
61 #include <editeng/boxitem.hxx>
62 #include "cell.hxx"
63 #include <editeng/borderline.hxx>
64 #include <editeng/colritem.hxx>
65 #include "editeng/bolnitem.hxx"
66 #include "svx/svdstr.hrc"
67 #include "svx/svdglob.hxx"
68 #include "svx/svdpage.hxx"
69 #include "tableundo.hxx"
70 #include "tablelayouter.hxx"
71 
72 using ::rtl::OUString;
73 using namespace ::sdr::table;
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::table;
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::container;
79 using namespace ::com::sun::star::text;
80 using namespace ::com::sun::star::style;
81 
82 namespace sdr { namespace table {
83 
84 // --------------------------------------------------------------------
85 // class SvxTableControllerModifyListener
86 // --------------------------------------------------------------------
87 
88 class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
89 {
90 public:
SvxTableControllerModifyListener(SvxTableController * pController)91 	SvxTableControllerModifyListener( SvxTableController* pController )
92 		: mpController( pController ) {}
93 
94 	// XModifyListener
95     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
96 
97     // XEventListener
98     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
99 
100 	SvxTableController* mpController;
101 };
102 
103 // --------------------------------------------------------------------
104 // XModifyListener
105 // --------------------------------------------------------------------
106 
modified(const::com::sun::star::lang::EventObject &)107 void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException)
108 {
109 	if( mpController )
110 		mpController->onTableModified();
111 }
112 
113 // --------------------------------------------------------------------
114 // XEventListener
115 // --------------------------------------------------------------------
116 
disposing(const::com::sun::star::lang::EventObject &)117 void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException)
118 {
119 	mpController = 0;
120 }
121 
122 // --------------------------------------------------------------------
123 // class SvxTableController
124 // --------------------------------------------------------------------
125 
CreateTableController(SdrObjEditView * pView,const SdrObject * pObj,const rtl::Reference<sdr::SelectionController> & xRefController)126 rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
127 {
128 	return SvxTableController::create( pView, pObj, xRefController );
129 }
130 
131 // --------------------------------------------------------------------
132 
create(SdrObjEditView * pView,const SdrObject * pObj,const rtl::Reference<sdr::SelectionController> & xRefController)133 rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
134 {
135 	if( xRefController.is() )
136 	{
137 		SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
138 		if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView)  )
139 			return xRefController;
140 	}
141 	return new SvxTableController( pView, pObj );
142 }
143 
144 // --------------------------------------------------------------------
145 
SvxTableController(SdrObjEditView * pView,const SdrObject * pObj)146 SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
147 : mbCellSelectionMode(false)
148 , mbLeftButtonDown(false)
149 , mpSelectionOverlay(0)
150 , mpView( dynamic_cast< SdrView* >( pView ) )
151 , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
152 , mpModel( 0 )
153 , mnUpdateEvent( 0 )
154 {
155 	if( pObj )
156 		mpModel = pObj->GetModel();
157 
158 	if( mxTableObj.is() )
159 	{
160 		static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
161 		maCursorLastPos = maCursorFirstPos;
162 
163 		Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
164 		if( xTable.is() )
165 		{
166 			mxModifyListener = new SvxTableControllerModifyListener( this );
167 			xTable->addModifyListener( mxModifyListener );
168 
169 			mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
170 		}
171 	}
172 }
173 
174 // --------------------------------------------------------------------
175 
~SvxTableController()176 SvxTableController::~SvxTableController()
177 {
178 	if( mnUpdateEvent )
179 	{
180 		Application::RemoveUserEvent( mnUpdateEvent );
181 	}
182 
183 	if( mxModifyListener.is() && mxTableObj.get() )
184 	{
185 		Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
186 		if( xTable.is() )
187 		{
188 			xTable->removeModifyListener( mxModifyListener );
189 			mxModifyListener.clear();
190 		}
191 	}
192 }
193 
194 // --------------------------------------------------------------------
195 
196 const sal_uInt16 ACTION_NONE = 0;
197 const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
198 const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
199 const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
200 const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
201 const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
202 const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
203 const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
204 const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
205 const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
206 const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
207 const sal_uInt16 ACTION_EDIT_CELL = 11;
208 const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
209 const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
210 const sal_uInt16 ACTION_START_SELECTION = 14;
211 const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
212 const sal_uInt16 ACTION_TAB = 18;
213 
onKeyInput(const KeyEvent & rKEvt,Window * pWindow)214 bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, Window* pWindow )
215 {
216 	if( !checkTableObject() )
217 		return false;
218 
219 	// check if we are read only
220 	if( mpModel && mpModel->IsReadOnly())
221 	{
222 		switch( rKEvt.GetKeyCode().GetCode() )
223 		{
224 		case awt::Key::DOWN:
225 		case awt::Key::UP:
226 		case awt::Key::LEFT:
227 		case awt::Key::RIGHT:
228 		case awt::Key::TAB:
229 		case awt::Key::HOME:
230 		case awt::Key::END:
231 		case awt::Key::NUM2:
232 		case awt::Key::NUM4:
233 		case awt::Key::NUM6:
234 		case awt::Key::NUM8:
235 		case awt::Key::ESCAPE:
236 		case awt::Key::F2:
237 			break;
238 		default:
239 			// tell the view we eat the event, no further processing needed
240 			return true;
241 		}
242 	}
243 
244 	sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
245 
246 	return executeAction( nAction, ( rKEvt.GetKeyCode().IsShift() ) ? sal_True : sal_False, pWindow );
247 }
248 
249 // --------------------------------------------------------------------
250 // ::com::sun::star::awt::XMouseClickHandler:
251 // --------------------------------------------------------------------
252 
onMouseButtonDown(const MouseEvent & rMEvt,Window * pWindow)253 bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, Window* pWindow )
254 {
255 	if( !pWindow || !checkTableObject() )
256 		return false;
257 
258 	SdrViewEvent aVEvt;
259 	if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SDRMOUSEBUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
260 		return false;
261 
262 	TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
263 
264 	mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
265 
266 	if( eHit == SDRTABLEHIT_CELL )
267 	{
268 		StartSelection( maMouseDownPos );
269 		return true;
270 	}
271 
272 	if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
273 		return true; // right click will become context menu
274 
275 	// for cell selektion with the mouse remember our first hit
276 	if( mbLeftButtonDown )
277 	{
278 		RemoveSelection();
279 
280 		Point aPnt(rMEvt.GetPosPixel());
281 		if (pWindow!=NULL)
282 			aPnt=pWindow->PixelToLogic(aPnt);
283 
284 		SdrHdl* pHdl = mpView->PickHandle(aPnt);
285 
286 		if( pHdl )
287 		{
288 			mbLeftButtonDown = false;
289 		}
290 		else
291 		{
292 			::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
293 
294 			if( !pWindow || !pTableObj || eHit  == SDRTABLEHIT_NONE)
295 			{
296 				mbLeftButtonDown = false;
297 			}
298 		}
299 	}
300 
301 	return false;
302 }
303 
304 // --------------------------------------------------------------------
305 
onMouseButtonUp(const MouseEvent & rMEvt,Window *)306 bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, Window* /*pWin*/)
307 {
308 	if( !checkTableObject() )
309 		return false;
310 
311 	mbLeftButtonDown = false;
312 
313 	if( rMEvt.GetClicks() == 2 )
314 		return true;
315 
316 	return false;
317 }
318 
319 // --------------------------------------------------------------------
320 
onMouseMove(const MouseEvent & rMEvt,Window * pWindow)321 bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, Window* pWindow )
322 {
323 	if( !checkTableObject() )
324 		return false;
325 
326 	if( rMEvt.IsLeft() )
327 	{
328 		int i = 0;
329 		i++;
330 	}
331 
332 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
333 	CellPos aPos;
334 	if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
335 	{
336 		if(aPos != maMouseDownPos)
337 		{
338 			if( mbCellSelectionMode )
339 			{
340 				setSelectedCells( maMouseDownPos, aPos );
341 				return true;
342 			}
343 			else
344 			{
345 				StartSelection( maMouseDownPos );
346 			}
347 		}
348 		else if( mbCellSelectionMode )
349 		{
350 			UpdateSelection( aPos );
351 			return true;
352 		}
353 	}
354     return false;
355 }
356 
357 // --------------------------------------------------------------------
358 
onSelectionHasChanged()359 void SvxTableController::onSelectionHasChanged()
360 {
361 	bool bSelected = false;
362 
363 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
364 	if( pTableObj && pTableObj->IsTextEditActive() )
365 	{
366 		pTableObj->getActiveCellPos( maCursorFirstPos );
367 		maCursorLastPos = maCursorFirstPos;
368 		mbCellSelectionMode = false;
369 	}
370 	else
371 	{
372 		const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
373 		if( rMarkList.GetMarkCount() == 1 )
374 			bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
375 	}
376 
377 	if( bSelected )
378 	{
379 		updateSelectionOverlay();
380 	}
381 	else
382 	{
383 		destroySelectionOverlay();
384 	}
385 }
386 
387 // --------------------------------------------------------------------
388 
GetState(SfxItemSet & rSet)389 void SvxTableController::GetState( SfxItemSet& rSet )
390 {
391 	if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
392 		return;
393 
394 	SfxItemSet* pSet = 0;
395 
396 	bool bVertDone = false;
397 
398     // Iterate over all requested items in the set.
399 	SfxWhichIter aIter( rSet );
400 	sal_uInt16 nWhich = aIter.FirstWhich();
401 	while (nWhich)
402 	{
403 		switch (nWhich)
404 		{
405 			case SID_TABLE_VERT_BOTTOM:
406 			case SID_TABLE_VERT_CENTER:
407 			case SID_TABLE_VERT_NONE:
408 				{
409 					if( !mxTable.is() || !mxTableObj->GetModel() )
410 					{
411 						rSet.DisableItem(nWhich);
412 					}
413 					else if(!bVertDone)
414 					{
415 						if( !pSet )
416 						{
417 							pSet = new SfxItemSet( mxTableObj->GetModel()->GetItemPool() );
418 							MergeAttrFromSelectedCells(*pSet, sal_False);
419 						}
420 
421 						SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
422 
423 						if( pSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SFX_ITEM_DONTCARE )
424 							eAdj = ((SdrTextVertAdjustItem&)(pSet->Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
425 
426 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
427 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
428 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
429 						bVertDone = true;
430 					}
431 					break;
432 				}
433 			case SID_TABLE_DELETE_ROW:
434 				if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
435 					rSet.DisableItem(SID_TABLE_DELETE_ROW);
436 				break;
437 			case SID_TABLE_DELETE_COL:
438 				if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
439 					rSet.DisableItem(SID_TABLE_DELETE_COL);
440 				break;
441 			case SID_TABLE_MERGE_CELLS:
442 				if( !mxTable.is() || !hasSelectedCells() )
443 					rSet.DisableItem(SID_TABLE_MERGE_CELLS);
444 				break;
445 			case SID_TABLE_SPLIT_CELLS:
446 				if( !hasSelectedCells() || !mxTable.is() )
447 					rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
448 				break;
449 
450 			case SID_OPTIMIZE_TABLE:
451 			case SID_TABLE_DISTRIBUTE_COLUMNS:
452 			case SID_TABLE_DISTRIBUTE_ROWS:
453 			{
454 				bool bDistributeColumns = false;
455 				bool bDistributeRows = false;
456 				if( mxTable.is() )
457 				{
458 					CellPos aStart, aEnd;
459 					getSelectedCells( aStart, aEnd );
460 
461 					bDistributeColumns = aStart.mnCol != aEnd.mnCol;
462 					bDistributeRows = aStart.mnRow != aEnd.mnRow;
463 				}
464 				if( !bDistributeColumns && !bDistributeRows )
465 					rSet.DisableItem(SID_OPTIMIZE_TABLE);
466 				if( !bDistributeColumns )
467 					rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
468 				if( !bDistributeRows )
469 					rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
470 				break;
471 			}
472 
473 			case SID_AUTOFORMAT:
474 			case SID_TABLE_SORT_DIALOG:
475 			case SID_TABLE_AUTOSUM:
476 //				if( !mxTable.is() )
477 //					rSet.DisableItem( nWhich );
478 				break;
479 			default:
480 				break;
481         }
482 		nWhich = aIter.NextWhich();
483 	}
484 	if( pSet )
485 		delete pSet;
486 }
487 
488 // --------------------------------------------------------------------
489 
onInsert(sal_uInt16 nSId,const SfxItemSet * pArgs)490 void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
491 {
492 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
493 	if( !pTableObj )
494 		return;
495 
496 	if( mxTable.is() ) try
497 	{
498 		//
499 		bool bInsertAfter = true;
500 		sal_uInt16 nCount = 0;
501     	if( pArgs )
502     	{
503     	    const SfxPoolItem* pItem = 0;
504     	    pArgs->GetItemState(nSId, sal_False, &pItem);
505 			if (pItem)
506 			{
507 				nCount = ((const SfxInt16Item* )pItem)->GetValue();
508 				if(SFX_ITEM_SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, sal_True, &pItem))
509 					bInsertAfter = ((const SfxBoolItem* )pItem)->GetValue();
510 			}
511     	}
512 
513 		CellPos aStart, aEnd;
514 		if( hasSelectedCells() )
515 		{
516 			getSelectedCells( aStart, aEnd );
517 		}
518 		else
519 		{
520 		    if( bInsertAfter )
521 		    {
522 			    aStart.mnCol = mxTable->getColumnCount() - 1;
523 			    aStart.mnRow = mxTable->getRowCount() - 1;
524 			    aEnd = aStart;
525 		    }
526 		}
527 
528 		if( pTableObj->IsTextEditActive() )
529 			mpView->SdrEndTextEdit(sal_True);
530 
531 		RemoveSelection();
532 
533 		const OUString sSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) );
534 
535 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
536 
537 		switch( nSId )
538 		{
539 		case SID_TABLE_INSERT_COL:
540 		{
541 			TableModelNotifyGuard aGuard( mxTable.get() );
542 
543 			if( bUndo )
544 			{
545 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
546 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
547 			}
548 
549 			Reference< XTableColumns > xCols( mxTable->getColumns() );
550 			const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
551 			const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
552 			xCols->insertByIndex( nNewStartColumn, nNewColumns );
553 
554 			for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
555 			{
556 				Reference< XPropertySet >( xCols->getByIndex( aEnd.mnCol + nOffset + 1 ), UNO_QUERY_THROW )->
557 					setPropertyValue( sSize,
558 						Reference< XPropertySet >( xCols->getByIndex( aStart.mnCol + nOffset ), UNO_QUERY_THROW )->
559 							getPropertyValue( sSize ) );
560 			}
561 
562 			if( bUndo )
563 				mpModel->EndUndo();
564 
565 			aStart.mnCol = nNewStartColumn;
566 			aStart.mnRow = 0;
567 			aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
568 			aEnd.mnRow = mxTable->getRowCount() - 1;
569 			break;
570 		}
571 
572 		case SID_TABLE_INSERT_ROW:
573 		{
574 			TableModelNotifyGuard aGuard( mxTable.get() );
575 
576 			if( bUndo )
577 			{
578 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
579 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
580 			}
581 
582 			Reference< XTableRows > xRows( mxTable->getRows() );
583 			const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
584 			const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
585 			xRows->insertByIndex( nNewRowStart, nNewRows );
586 
587 			for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
588 			{
589 				Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
590 					setPropertyValue( sSize,
591 						Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
592 							getPropertyValue( sSize ) );
593 			}
594 
595 			if( bUndo )
596 				mpModel->EndUndo();
597 
598 			aStart.mnCol = 0;
599 			aStart.mnRow = nNewRowStart;
600 			aEnd.mnCol = mxTable->getColumnCount() - 1;
601 			aEnd.mnRow = aStart.mnRow + nNewRows - 1;
602 			break;
603 		}
604 		}
605 
606 		StartSelection( aStart );
607 		UpdateSelection( aEnd );
608 	}
609 	catch( Exception& e )
610 	{
611 		(void)e;
612 		DBG_ERROR("svx::SvxTableController::onInsert(), exception caught!");
613 	}
614 }
615 
616 // --------------------------------------------------------------------
617 
onDelete(sal_uInt16 nSId)618 void SvxTableController::onDelete( sal_uInt16 nSId )
619 {
620 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
621 	if( !pTableObj )
622 		return;
623 
624 	if( mxTable.is() && hasSelectedCells() )
625 	{
626 		CellPos aStart, aEnd;
627 		getSelectedCells( aStart, aEnd );
628 
629 		if( pTableObj->IsTextEditActive() )
630 			mpView->SdrEndTextEdit(sal_True);
631 
632 		RemoveSelection();
633 
634 		bool bDeleteTable = false;
635 		switch( nSId )
636 		{
637 		case SID_TABLE_DELETE_COL:
638 		{
639 			const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
640 			if( nRemovedColumns == mxTable->getColumnCount() )
641 			{
642 				bDeleteTable = true;
643 			}
644 			else
645 			{
646 				Reference< XTableColumns > xCols( mxTable->getColumns() );
647 				xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
648 			}
649 			break;
650 		}
651 
652 		case SID_TABLE_DELETE_ROW:
653 		{
654 			const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
655 			if( nRemovedRows == mxTable->getRowCount() )
656 			{
657 				bDeleteTable = true;
658 			}
659 			else
660 			{
661 				Reference< XTableRows > xRows( mxTable->getRows() );
662 				xRows->removeByIndex( aStart.mnRow, nRemovedRows );
663 			}
664 			break;
665 		}
666 		}
667 
668 		if( bDeleteTable )
669 			mpView->DeleteMarkedObj();
670 		else
671 			UpdateTableShape();
672 	}
673 }
674 
675 // --------------------------------------------------------------------
676 
onSelect(sal_uInt16 nSId)677 void SvxTableController::onSelect( sal_uInt16 nSId )
678 {
679 	if( mxTable.is() )
680 	{
681 		const sal_Int32 nRowCount = mxTable->getRowCount();
682 		const sal_Int32 nColCount = mxTable->getColumnCount();
683 		if( nRowCount && nColCount )
684 		{
685 			CellPos aStart, aEnd;
686 			getSelectedCells( aStart, aEnd );
687 
688 			switch( nSId )
689 			{
690 			case SID_TABLE_SELECT_ALL:
691 				aEnd.mnCol = 0; aEnd.mnRow = 0;
692 				aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
693 				break;
694 			case SID_TABLE_SELECT_COL:
695 				aEnd.mnRow = nRowCount - 1;
696 				aStart.mnRow = 0;
697 				break;
698 			case SID_TABLE_SELECT_ROW:
699 				aEnd.mnCol = nColCount - 1;
700 				aStart.mnCol = 0;
701 				break;
702 			}
703 
704 			StartSelection( aEnd );
705 			gotoCell( aStart, true, 0 );
706 		}
707 	}
708 }
709 
710 // --------------------------------------------------------------------
onFormatTable(SfxRequest & rReq)711 void SvxTableController::onFormatTable( SfxRequest& rReq )
712 {
713 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
714 	if( !pTableObj )
715 		return;
716 
717 	const SfxItemSet* pArgs = rReq.GetArgs();
718 
719 	if( !pArgs && pTableObj->GetModel() )
720 	{
721 		SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
722 		MergeAttrFromSelectedCells(aNewAttr, sal_False);
723 
724 		// merge drawing layer text distance items into SvxBoxItem used by the dialog
725 		SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
726 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLeftDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LEFTDIST))).GetValue()), BOX_LINE_LEFT );
727 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
728 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
729 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
730 		aNewAttr.Put( aBoxItem );
731 
732 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
733 		std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
734 		if( pDlg.get() && pDlg->Execute() )
735 		{
736 			SfxItemSet aNewSet( *(pDlg->GetOutputItemSet ()) );
737 
738 			SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
739 
740 			if( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) != aBoxItem.GetDistance( BOX_LINE_LEFT ) )
741 				aNewSet.Put(SdrTextLeftDistItem( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) ) );
742 
743 			if( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) != aBoxItem.GetDistance( BOX_LINE_RIGHT ) )
744 				aNewSet.Put(SdrTextRightDistItem( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) ) );
745 
746 			if( aNewBoxItem.GetDistance( BOX_LINE_TOP ) != aBoxItem.GetDistance( BOX_LINE_TOP ) )
747 				aNewSet.Put(SdrTextUpperDistItem( aNewBoxItem.GetDistance( BOX_LINE_TOP ) ) );
748 
749 			if( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) != aBoxItem.GetDistance( BOX_LINE_BOTTOM ) )
750 				aNewSet.Put(SdrTextLowerDistItem( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) ) );
751 
752 			SetAttrToSelectedCells(aNewSet, sal_False);
753 		}
754 		UpdateTableShape();
755 	}
756 }
757 
758 // --------------------------------------------------------------------
759 
Execute(SfxRequest & rReq)760 void SvxTableController::Execute( SfxRequest& rReq )
761 {
762 	const sal_uInt16 nSId = rReq.GetSlot();
763 	switch( nSId )
764 	{
765 	case SID_TABLE_INSERT_ROW:
766 	case SID_TABLE_INSERT_COL:
767 		onInsert( nSId, rReq.GetArgs() );
768 		break;
769 	case SID_TABLE_DELETE_ROW:
770 	case SID_TABLE_DELETE_COL:
771 		onDelete( nSId );
772 		break;
773 	case SID_TABLE_SELECT_ALL:
774 	case SID_TABLE_SELECT_COL:
775 	case SID_TABLE_SELECT_ROW:
776 		onSelect( nSId );
777 		break;
778 	case SID_FORMAT_TABLE_DLG:
779 		onFormatTable( rReq );
780 		break;
781 
782 	case SID_FRAME_LINESTYLE:
783 	case SID_FRAME_LINECOLOR:
784 	case SID_ATTR_BORDER:
785 		{
786 			const SfxItemSet* pArgs = rReq.GetArgs();
787 			if( pArgs )
788 				ApplyBorderAttr( *pArgs );
789 		}
790 		break;
791 
792 	case SID_ATTR_FILL_STYLE:
793 		{
794 			const SfxItemSet* pArgs = rReq.GetArgs();
795 			if( pArgs )
796 				SetAttributes( *pArgs, false );
797 		}
798 		break;
799 
800 	case SID_TABLE_MERGE_CELLS:
801 		MergeMarkedCells();
802 		break;
803 
804 	case SID_TABLE_SPLIT_CELLS:
805 		SplitMarkedCells();
806 		break;
807 
808 	case SID_TABLE_DISTRIBUTE_COLUMNS:
809 		DistributeColumns();
810 		break;
811 
812 	case SID_TABLE_DISTRIBUTE_ROWS:
813 		DistributeRows();
814 		break;
815 
816 	case SID_TABLE_VERT_BOTTOM:
817 	case SID_TABLE_VERT_CENTER:
818 	case SID_TABLE_VERT_NONE:
819 		SetVertical( nSId );
820 		break;
821 
822 	case SID_AUTOFORMAT:
823 	case SID_TABLE_SORT_DIALOG:
824 	case SID_TABLE_AUTOSUM:
825 	default:
826 		break;
827 
828 	case SID_TABLE_STYLE:
829 		SetTableStyle( rReq.GetArgs() );
830 		break;
831 
832 	case SID_TABLE_STYLE_SETTINGS:
833 		SetTableStyleSettings( rReq.GetArgs() );
834 		break;
835 	}
836 }
837 
SetTableStyle(const SfxItemSet * pArgs)838 void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
839 {
840 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
841 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
842 
843 	if( !pTableObj || !pModel || !pArgs || (SFX_ITEM_SET != pArgs->GetItemState(SID_TABLE_STYLE, sal_False)) )
844 		return;
845 
846 	const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
847 	if( pArg && mxTable.is() ) try
848 	{
849 		Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
850 		Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
851 		const OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
852 		Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
853 
854 		if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
855 		{
856 			// found table style with the same name
857 			Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
858 
859 			const bool bUndo = pModel->IsUndoEnabled();
860 
861 			if( bUndo )
862 			{
863 				pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
864 				pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
865 			}
866 
867 			pTableObj->setTableStyle( xNewTableStyle );
868 
869 			const sal_Int32 nRowCount = mxTable->getRowCount();
870 			const sal_Int32 nColCount = mxTable->getColumnCount();
871 			for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
872 			{
873 				for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
874 				{
875 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
876 					if( xCell.is() )
877 					{
878                         SfxItemSet aSet( xCell->GetItemSet() );
879                         bool bChanges = false;
880 	                    const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
881 
882 	                    for ( sal_uInt16 nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
883 	                    {
884 		                    if( (rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON) && (aSet.GetItemState( nWhich ) == SFX_ITEM_ON) )
885 		                    {
886 			                    aSet.ClearItem( nWhich );
887 			                    bChanges = true;
888 			                }
889 	                    }
890 
891 	                    if( bChanges )
892 	                    {
893 						    if( bUndo )
894 							    xCell->AddUndo();
895 
896 							xCell->SetMergedItemSetAndBroadcast( aSet, sal_True );
897 	                    }
898                     }
899 				}
900 				catch( Exception& e )
901 				{
902 					(void)e;
903 					DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
904 				}
905 			}
906 
907 			if( bUndo )
908 				pModel->EndUndo();
909 		}
910 	}
911 	catch( Exception& e )
912 	{
913 		(void)e;
914 		DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
915 	}
916 }
917 
SetTableStyleSettings(const SfxItemSet * pArgs)918 void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
919 {
920 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
921 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
922 
923 	if( !pTableObj || !pModel )
924 		return;
925 
926 	TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
927 
928 	const SfxPoolItem *pPoolItem=NULL;
929 
930 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, sal_False,&pPoolItem)) )
931 		aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
932 
933 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, sal_False,&pPoolItem)) )
934 		aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
935 
936 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, sal_False,&pPoolItem)) )
937 		aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
938 
939 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, sal_False,&pPoolItem)) )
940 		aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
941 
942 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, sal_False,&pPoolItem)) )
943 		aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
944 
945 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, sal_False,&pPoolItem)) )
946 		aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
947 
948 	if( aSettings == pTableObj->getTableStyleSettings() )
949 		return;
950 
951 	const bool bUndo = pModel->IsUndoEnabled();
952 
953 	if( bUndo )
954 	{
955 		pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
956 		pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
957 	}
958 
959 	pTableObj->setTableStyleSettings( aSettings );
960 
961 	if( bUndo )
962 		pModel->EndUndo();
963 }
964 
SetVertical(sal_uInt16 nSId)965 void SvxTableController::SetVertical( sal_uInt16 nSId )
966 {
967 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
968 	if( mxTable.is() && pTableObj )
969 	{
970 		TableModelNotifyGuard aGuard( mxTable.get() );
971 
972 		CellPos aStart, aEnd;
973 		getSelectedCells( aStart, aEnd );
974 
975 		SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
976 
977 		switch( nSId )
978 		{
979 			case SID_TABLE_VERT_BOTTOM:
980 				eAdj = SDRTEXTVERTADJUST_BOTTOM;
981 				break;
982 			case SID_TABLE_VERT_CENTER:
983 				eAdj = SDRTEXTVERTADJUST_CENTER;
984 				break;
985 			//case SID_TABLE_VERT_NONE:
986 			default:
987 				break;
988 		}
989 
990 		SdrTextVertAdjustItem aItem( eAdj );
991 
992 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
993 		{
994 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
995 			{
996 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
997 				if( xCell.is() )
998 					xCell->SetMergedItem(aItem);
999 			}
1000 		}
1001 
1002 		UpdateTableShape();
1003 	}
1004 }
1005 
MergeMarkedCells()1006 void SvxTableController::MergeMarkedCells()
1007 {
1008 	CellPos aStart, aEnd;
1009 	getSelectedCells( aStart, aEnd );
1010 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1011 	if( pTableObj )
1012 	{
1013 	    if( pTableObj->IsTextEditActive() )
1014 		    mpView->SdrEndTextEdit(sal_True);
1015 
1016         TableModelNotifyGuard aGuard( mxTable.get() );
1017 		MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
1018 	}
1019 }
1020 
SplitMarkedCells()1021 void SvxTableController::SplitMarkedCells()
1022 {
1023 	if( mxTable.is() )
1024 	{
1025 		CellPos aStart, aEnd;
1026 		getSelectedCells( aStart, aEnd );
1027 
1028 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1029 		std::auto_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
1030 		if( xDlg.get() && xDlg->Execute() )
1031 		{
1032 			const sal_Int32 nCount = xDlg->GetCount() - 1;
1033 			if( nCount < 1 )
1034 				return;
1035 
1036 			getSelectedCells( aStart, aEnd );
1037 
1038 			Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
1039 
1040 			const sal_Int32 nRowCount = mxTable->getRowCount();
1041 			const sal_Int32 nColCount = mxTable->getColumnCount();
1042 
1043 
1044 			SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1045 			if( pTableObj )
1046 			{
1047         	    if( pTableObj->IsTextEditActive() )
1048 		            mpView->SdrEndTextEdit(sal_True);
1049 
1050                 TableModelNotifyGuard aGuard( mxTable.get() );
1051 
1052 				const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1053 				if( bUndo )
1054 				{
1055 					mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
1056 					mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1057 				}
1058 
1059 				if( xDlg->IsHorizontal() )
1060 				{
1061 					xRange->split( 0, nCount );
1062 				}
1063 				else
1064 				{
1065 					xRange->split( nCount, 0 );
1066 				}
1067 
1068 				if( bUndo )
1069 					mpModel->EndUndo();
1070 			}
1071 			aEnd.mnRow += mxTable->getRowCount() - nRowCount;
1072 			aEnd.mnCol += mxTable->getColumnCount() - nColCount;
1073 
1074 			setSelectedCells( aStart, aEnd );
1075 		}
1076 	}
1077 }
1078 
DistributeColumns()1079 void SvxTableController::DistributeColumns()
1080 {
1081 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1082 	if( pTableObj )
1083 	{
1084 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1085 		if( bUndo )
1086 		{
1087 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
1088 			mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1089 		}
1090 
1091 		CellPos aStart, aEnd;
1092 		getSelectedCells( aStart, aEnd );
1093 		pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
1094 
1095 		if( bUndo )
1096 			mpModel->EndUndo();
1097 	}
1098 }
1099 
DistributeRows()1100 void SvxTableController::DistributeRows()
1101 {
1102 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1103 	if( pTableObj )
1104 	{
1105 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1106 		if( bUndo )
1107 		{
1108 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
1109 			mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1110 		}
1111 
1112 		CellPos aStart, aEnd;
1113 		getSelectedCells( aStart, aEnd );
1114 		pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
1115 
1116 		if( bUndo )
1117 			mpModel->EndUndo();
1118 	}
1119 }
1120 
DeleteMarked()1121 bool SvxTableController::DeleteMarked()
1122 {
1123 	if( mbCellSelectionMode )
1124 	{
1125 		if( mxTable.is() )
1126 		{
1127 			CellPos aStart, aEnd;
1128 			getSelectedCells( aStart, aEnd );
1129 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1130 			{
1131 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1132 				{
1133 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1134 					if( xCell.is() )
1135 						xCell->SetOutlinerParaObject( 0 );
1136 				}
1137 			}
1138 
1139 			UpdateTableShape();
1140 			return true;
1141 		}
1142 	}
1143 
1144 	return false;
1145 }
1146 
GetStyleSheet(SfxStyleSheet * & rpStyleSheet) const1147 bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
1148 {
1149 	if( hasSelectedCells() )
1150 	{
1151 		rpStyleSheet = 0;
1152 
1153 		if( mxTable.is() )
1154 		{
1155 			SfxStyleSheet* pRet=0;
1156 			bool b1st=true;
1157 
1158 			CellPos aStart, aEnd;
1159 			const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1160 
1161 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1162 			{
1163 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1164 				{
1165 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1166 					if( xCell.is() )
1167 					{
1168 						SfxStyleSheet* pSS=xCell->GetStyleSheet();
1169 						if(b1st)
1170 						{
1171 							pRet=pSS;
1172 						}
1173 						else if(pRet != pSS)
1174 						{
1175 							return true;
1176 						}
1177 						b1st=false;
1178 					}
1179 				}
1180 			}
1181 			rpStyleSheet = pRet;
1182 			return true;
1183 		}
1184 	}
1185 	return false;
1186 }
1187 
SetStyleSheet(SfxStyleSheet * pStyleSheet,bool bDontRemoveHardAttr)1188 bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
1189 {
1190 	if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
1191 	{
1192 		if( mxTable.is() )
1193 		{
1194 			CellPos aStart, aEnd;
1195 			getSelectedCells( aStart, aEnd );
1196 
1197 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1198 			{
1199 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1200 				{
1201 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1202 					if( xCell.is() )
1203 						xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1204 				}
1205 			}
1206 
1207 			UpdateTableShape();
1208 			return true;
1209 		}
1210 	}
1211 	return false;
1212 }
1213 
1214 // --------------------------------------------------------------------
1215 // internals
1216 // --------------------------------------------------------------------
1217 
checkTableObject()1218 bool SvxTableController::checkTableObject()
1219 {
1220 	return mxTableObj.is();
1221 }
1222 
1223 // --------------------------------------------------------------------
1224 
getKeyboardAction(const KeyEvent & rKEvt,Window *)1225 sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, Window* /*pWindow*/ )
1226 {
1227 	const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
1228 	const bool bMod2 = rKEvt.GetKeyCode().IsMod2() != 0; // Alt
1229 
1230 	const bool bTextEdit = mpView->IsTextEdit();
1231 
1232 	sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
1233 
1234 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1235 	if( !pTableObj )
1236 		return nAction;
1237 
1238 	// handle special keys
1239 	const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
1240 	switch( nCode )
1241 	{
1242 	case awt::Key::ESCAPE:			// handle escape
1243 	{
1244 		if( bTextEdit )
1245 		{
1246 			// escape during text edit ends text edit
1247 			nAction = ACTION_STOP_TEXT_EDIT;
1248 		}
1249 		if( mbCellSelectionMode )
1250 		{
1251 			// escape with selected cells removes selection
1252 			nAction = ACTION_REMOVE_SELECTION;
1253 		}
1254 		break;
1255 	}
1256 	case awt::Key::RETURN:		// handle return
1257 	{
1258 		if( !bMod1 && !bMod2 && !bTextEdit )
1259 		{
1260 			// when not already editing, return starts text edit
1261 			setSelectionStart( pTableObj->getFirstCell() );
1262 			nAction = ACTION_EDIT_CELL;
1263 		}
1264 		break;
1265 	}
1266 	case awt::Key::F2:			// f2 toggles text edit
1267 	{
1268 		if( bMod1 || bMod2 )	// f2 with modifiers is handled by the view
1269 		{
1270 		}
1271 		else if( bTextEdit )
1272 		{
1273 			// f2 during text edit stops text edit
1274 			nAction = ACTION_STOP_TEXT_EDIT;
1275 		}
1276 		else if( mbCellSelectionMode )
1277 		{
1278 			// f2 with selected cells removes selection
1279 			nAction = ACTION_REMOVE_SELECTION;
1280 		}
1281 		else
1282 		{
1283 			// f2 with no selection and no text edit starts text edit
1284 			setSelectionStart( pTableObj->getFirstCell() );
1285 			nAction = ACTION_EDIT_CELL;
1286 		}
1287 		break;
1288 	}
1289 	case awt::Key::HOME:
1290 	case awt::Key::NUM7:
1291 	{
1292 		if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
1293 		{
1294 			if( bMod1 && !bMod2 )
1295 			{
1296 				// strg + home jumps to first cell
1297 				nAction = ACTION_GOTO_FIRST_CELL;
1298 			}
1299 			else if( !bMod1 && bMod2 )
1300 			{
1301 				// alt + home jumps to first column
1302 				nAction = ACTION_GOTO_FIRST_COLUMN;
1303 			}
1304 		}
1305 		break;
1306 	}
1307 	case awt::Key::END:
1308 	case awt::Key::NUM1:
1309 	{
1310 		if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
1311 		{
1312 			if( bMod1 && !bMod2 )
1313 			{
1314 				// strg + end jumps to last cell
1315 				nAction = ACTION_GOTO_LAST_CELL;
1316 			}
1317 			else if( !bMod1 && bMod2 )
1318 			{
1319 				// alt + home jumps to last column
1320 				nAction = ACTION_GOTO_LAST_COLUMN;
1321 			}
1322 		}
1323 		break;
1324 	}
1325 
1326 	case awt::Key::TAB:
1327 	{
1328 		if( bTextEdit || mbCellSelectionMode )
1329 			nAction = ACTION_TAB;
1330 		break;
1331 	}
1332 
1333 	case awt::Key::UP:
1334 	case awt::Key::NUM8:
1335 	case awt::Key::DOWN:
1336 	case awt::Key::NUM2:
1337 	case awt::Key::LEFT:
1338 	case awt::Key::NUM4:
1339 	case awt::Key::RIGHT:
1340 	case awt::Key::NUM6:
1341 	{
1342 		bool bTextMove = false;
1343 
1344 		if( !bMod1 && bMod2 )
1345 		{
1346 			if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
1347 			{
1348 				nAction = ACTION_GOTO_LEFT_CELL;
1349 			}
1350 			else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
1351 			{
1352 				nAction = ACTION_GOTO_RIGHT_CELL;
1353 			}
1354 			break;
1355 		}
1356 
1357 		if( !bTextMove )
1358 		{
1359 			OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1360 			if( pOLV )
1361 			{
1362 				RemoveSelection();
1363 				// during text edit, check if we navigate out of the cell
1364 				ESelection aOldSelection = pOLV->GetSelection();
1365 				pOLV->PostKeyEvent(rKEvt);
1366 				bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
1367 				if( !bTextMove )
1368 				{
1369 					nAction = ACTION_NONE;
1370 				}
1371 			}
1372 		}
1373 
1374 		if( mbCellSelectionMode || bTextMove )
1375 		{
1376 			// no text edit, navigate in cells if selection active
1377 			switch( nCode )
1378 			{
1379 			case awt::Key::LEFT:
1380 			case awt::Key::NUM4:
1381 				nAction = ACTION_GOTO_LEFT_CELL;
1382 				break;
1383 			case awt::Key::RIGHT:
1384 			case awt::Key::NUM6:
1385 				nAction = ACTION_GOTO_RIGHT_CELL;
1386 				break;
1387 			case awt::Key::DOWN:
1388 			case awt::Key::NUM2:
1389 				nAction = ACTION_GOTO_DOWN_CELL;
1390 				break;
1391 			case awt::Key::UP:
1392 			case awt::Key::NUM8:
1393 				nAction = ACTION_GOTO_UP_CELL;
1394 				break;
1395 			}
1396 		}
1397 		break;
1398 	}
1399 	case awt::Key::PAGEUP:
1400 		if( bMod2 )
1401 			nAction = ACTION_GOTO_FIRST_ROW;
1402 		break;
1403 
1404 	case awt::Key::PAGEDOWN:
1405 		if( bMod2 )
1406 			nAction = ACTION_GOTO_LAST_ROW;
1407 		break;
1408 	}
1409 	return nAction;
1410 }
1411 
executeAction(sal_uInt16 nAction,bool bSelect,Window * pWindow)1412 bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, Window* pWindow )
1413 {
1414 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1415 	if( !pTableObj )
1416 		return false;
1417 
1418 	switch( nAction )
1419 	{
1420 	case ACTION_GOTO_FIRST_CELL:
1421 	{
1422 		gotoCell( pTableObj->getFirstCell(), bSelect, pWindow, nAction );
1423 		break;
1424 	}
1425 
1426 	case ACTION_GOTO_LEFT_CELL:
1427 	{
1428 		gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
1429 		break;
1430 	}
1431 
1432 	case ACTION_GOTO_RIGHT_CELL:
1433 	{
1434 		gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
1435 		break;
1436 	}
1437 
1438 	case ACTION_GOTO_LAST_CELL:
1439 	{
1440 		gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
1441 		break;
1442 	}
1443 
1444 	case ACTION_GOTO_FIRST_COLUMN:
1445 	{
1446 		CellPos aPos( pTableObj->getFirstCell().mnCol, getSelectionEnd().mnRow );
1447 		gotoCell( aPos, bSelect, pWindow, nAction );
1448 		break;
1449 	}
1450 
1451 	case ACTION_GOTO_LAST_COLUMN:
1452 	{
1453 		CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
1454 		gotoCell( aPos, bSelect, pWindow, nAction );
1455 		break;
1456 	}
1457 
1458 	case ACTION_GOTO_FIRST_ROW:
1459 	{
1460 		CellPos aPos( getSelectionEnd().mnCol, pTableObj->getFirstCell().mnRow );
1461 		gotoCell( aPos, bSelect, pWindow, nAction );
1462 		break;
1463 	}
1464 
1465 	case ACTION_GOTO_UP_CELL:
1466 	{
1467 		gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1468 		break;
1469 	}
1470 
1471 	case ACTION_GOTO_DOWN_CELL:
1472 	{
1473 		gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1474 		break;
1475 	}
1476 
1477 	case ACTION_GOTO_LAST_ROW:
1478 	{
1479 		CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
1480 		gotoCell( aPos, bSelect, pWindow, nAction );
1481 		break;
1482 	}
1483 
1484 	case ACTION_EDIT_CELL:
1485 		EditCell( getSelectionStart(), pWindow, 0, nAction );
1486 		break;
1487 
1488 	case ACTION_STOP_TEXT_EDIT:
1489 		StopTextEdit();
1490 		break;
1491 
1492 	case ACTION_REMOVE_SELECTION:
1493 		RemoveSelection();
1494 		break;
1495 
1496 	case ACTION_START_SELECTION:
1497 		StartSelection( getSelectionStart() );
1498 		break;
1499 
1500 	case ACTION_TAB:
1501 	{
1502 		if( bSelect )
1503 			gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
1504 		else
1505         {
1506             CellPos aSelectionEnd( getSelectionEnd() );
1507             CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
1508             if( aSelectionEnd == aNextCell )
1509             {
1510                 onInsert( SID_TABLE_INSERT_ROW, 0 );
1511                 aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
1512             }
1513 			gotoCell( aNextCell, false, pWindow, nAction );
1514         }
1515 		break;
1516 	}
1517 	}
1518 
1519 	return nAction != ACTION_HANDLED_BY_VIEW;
1520 }
1521 
1522 // --------------------------------------------------------------------
1523 
gotoCell(const CellPos & rPos,bool bSelect,Window * pWindow,sal_uInt16 nAction)1524 void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, Window* pWindow, sal_uInt16 nAction )
1525 {
1526 	if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
1527 		mpView->SdrEndTextEdit(sal_True);
1528 
1529 	if( bSelect )
1530 	{
1531 		maCursorLastPos = rPos;
1532 		if( mxTableObj.is() )
1533 			static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
1534 
1535 		if( !mbCellSelectionMode )
1536 		{
1537 			setSelectedCells( maCursorFirstPos, rPos );
1538 		}
1539 		else
1540 		{
1541 			UpdateSelection( rPos );
1542 		}
1543 	}
1544 	else
1545 	{
1546 		RemoveSelection();
1547 		EditCell( rPos, pWindow, 0, nAction );
1548 	}
1549 }
1550 
1551 // --------------------------------------------------------------------
1552 
getSelectionStart()1553 const CellPos& SvxTableController::getSelectionStart()
1554 {
1555 	checkCell( maCursorFirstPos );
1556 	return maCursorFirstPos;
1557 }
1558 
1559 // --------------------------------------------------------------------
1560 
setSelectionStart(const CellPos & rPos)1561 void SvxTableController::setSelectionStart( const CellPos& rPos )
1562 {
1563 	maCursorFirstPos = rPos;
1564 }
1565 
1566 // --------------------------------------------------------------------
1567 
getSelectionEnd()1568 const CellPos& SvxTableController::getSelectionEnd()
1569 {
1570 	checkCell( maCursorLastPos );
1571 	return maCursorLastPos;
1572 }
1573 
1574 // --------------------------------------------------------------------
1575 
getSelectionCursor()1576 Reference< XCellCursor > SvxTableController::getSelectionCursor()
1577 {
1578 	Reference< XCellCursor > xCursor;
1579 
1580 	if( mxTable.is() )
1581 	{
1582 		if( hasSelectedCells() )
1583 		{
1584 			CellPos aStart, aEnd;
1585 			getSelectedCells( aStart, aEnd );
1586 			xCursor = mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) );
1587 		}
1588 		else
1589 		{
1590 			xCursor = mxTable->createCursor();
1591 		}
1592 	}
1593 
1594 	return xCursor;
1595 }
1596 
MergeRange(sal_Int32 nFirstCol,sal_Int32 nFirstRow,sal_Int32 nLastCol,sal_Int32 nLastRow)1597 void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
1598 {
1599 	if( mxTable.is() ) try
1600 	{
1601 		Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
1602 		if( xRange->isMergeable() )
1603 		{
1604 			const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1605 			if( bUndo )
1606 			{
1607 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
1608 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
1609 			}
1610 
1611 			xRange->merge();
1612 
1613 			if( bUndo )
1614 				mpModel->EndUndo();
1615 		}
1616 	}
1617 	catch( Exception& )
1618 	{
1619 		DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
1620 	}
1621 }
1622 
1623 
1624 
1625 // --------------------------------------------------------------------
1626 
checkCell(CellPos & rPos)1627 void SvxTableController::checkCell( CellPos& rPos )
1628 {
1629 	if( mxTable.is() ) try
1630 	{
1631 		if( rPos.mnCol >= mxTable->getColumnCount() )
1632 			rPos.mnCol = mxTable->getColumnCount()-1;
1633 
1634 		if( rPos.mnRow >= mxTable->getRowCount() )
1635 			rPos.mnRow = mxTable->getRowCount()-1;
1636 	}
1637 	catch( Exception& e )
1638 	{
1639 		(void)e;
1640 		DBG_ERROR("sdr::table::SvxTableController::checkCell(), exception caught!" );
1641 	}
1642 }
1643 
1644 // --------------------------------------------------------------------
1645 
findMergeOrigin(CellPos & rPos)1646 void SvxTableController::findMergeOrigin( CellPos& rPos )
1647 {
1648 	if( mxTable.is() ) try
1649 	{
1650 		Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
1651 		if( xCell.is() && xCell->isMerged() )
1652 		{
1653 			::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
1654 		}
1655 	}
1656 	catch( Exception& e )
1657 	{
1658 		(void)e;
1659 		DBG_ERROR("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
1660 	}
1661 }
1662 
1663 // --------------------------------------------------------------------
1664 
EditCell(const CellPos & rPos,::Window * pWindow,const awt::MouseEvent * pMouseEvent,sal_uInt16 nAction)1665 void SvxTableController::EditCell( const CellPos& rPos, ::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
1666 {
1667 	SdrPageView* pPV = mpView->GetSdrPageView();
1668 
1669 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1670 	if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
1671 	{
1672 		bool bEmptyOutliner = false;
1673 
1674 		if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1675 		{
1676 			::Outliner* pOutl = mpView->GetTextEditOutliner();
1677 			sal_uIntPtr nParaAnz = pOutl->GetParagraphCount();
1678 			Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1679 
1680 			if(nParaAnz==1 && p1stPara)
1681 			{
1682 				// Bei nur einem Pararaph
1683 				if (pOutl->GetText(p1stPara).Len() == 0)
1684 				{
1685 					bEmptyOutliner = true;
1686 				}
1687 			}
1688 		}
1689 
1690 		CellPos aPos( rPos );
1691 		findMergeOrigin( aPos );
1692 
1693 		if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
1694 		{
1695 			if( pTableObj->IsTextEditActive() )
1696 				mpView->SdrEndTextEdit(sal_True);
1697 
1698 			pTableObj->setActiveCell( aPos );
1699 
1700 			// create new outliner, owner will be the SdrObjEditView
1701 			SdrOutliner* pOutl = SdrMakeOutliner( OUTLINERMODE_OUTLINEOBJECT, mpModel );
1702 			if( pTableObj->IsVerticalWriting() )
1703 				pOutl->SetVertical( sal_True );
1704 
1705 			if(mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, sal_True, pOutl))
1706 			{
1707 				maCursorLastPos = maCursorFirstPos = rPos;
1708 
1709 				OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1710 
1711 				bool bNoSel = true;
1712 
1713 				if( pMouseEvent )
1714 				{
1715 					::MouseEvent aMEvt( *pMouseEvent );
1716 
1717 					SdrViewEvent aVEvt;
1718 					SdrHitKind eHit = mpView->PickAnything(aMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
1719 
1720 					if (eHit == SDRHIT_TEXTEDIT)
1721 					{
1722 						// Text getroffen
1723 						pOLV->MouseButtonDown(aMEvt);
1724 						pOLV->MouseMove(aMEvt);
1725 						pOLV->MouseButtonUp(aMEvt);
1726 //						pOLV->MouseButtonDown(aMEvt);
1727 						bNoSel = false;
1728 					}
1729 					else
1730 					{
1731 						nAction = ACTION_GOTO_LEFT_CELL;
1732 					}
1733 				}
1734 
1735 				if( bNoSel )
1736 				{
1737 					// Move cursor to end of text
1738 					ESelection aNewSelection;
1739 
1740 					const WritingMode eMode = pTableObj->GetWritingMode();
1741 					if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
1742 					{
1743 						const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
1744 											 ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
1745 
1746 						if( bLast )
1747 							aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1748 					}
1749 					pOLV->SetSelection(aNewSelection);
1750 				}
1751 			}
1752 		}
1753 	}
1754 }
1755 
1756 // --------------------------------------------------------------------
1757 
StopTextEdit()1758 bool SvxTableController::StopTextEdit()
1759 {
1760 	if(mpView->IsTextEdit())
1761 	{
1762 		mpView->SdrEndTextEdit();
1763 		mpView->SetCurrentObj(OBJ_TABLE);
1764 		mpView->SetEditMode(SDREDITMODE_EDIT);
1765 		return true;
1766 	}
1767 	else
1768 	{
1769 		return false;
1770 	}
1771 }
1772 
1773 // --------------------------------------------------------------------
1774 
DeleteTable()1775 void SvxTableController::DeleteTable()
1776 {
1777 	//
1778 }
1779 
1780 // --------------------------------------------------------------------
1781 
getSelectedCells(CellPos & rFirst,CellPos & rLast)1782 void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
1783 {
1784 	if( mbCellSelectionMode )
1785 	{
1786 		checkCell( maCursorFirstPos );
1787 		checkCell( maCursorLastPos );
1788 
1789 		rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1790 		rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1791 		rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1792 		rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1793 
1794 		bool bExt = false;
1795 		if( mxTable.is() ) do
1796 		{
1797 			bExt = false;
1798 			for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
1799 			{
1800 				for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
1801 				{
1802 					Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
1803 					if( !xCell.is() )
1804 						continue;
1805 
1806 					if( xCell->isMerged() )
1807 					{
1808 						CellPos aPos( nCol, nRow );
1809 						findMergeOrigin( aPos );
1810 						if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
1811 						{
1812 							rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
1813 							rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
1814 							bExt = true;
1815 						}
1816 					}
1817 					else
1818 					{
1819 						if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
1820 						{
1821 							rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
1822 							rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
1823 							bExt = true;
1824 						}
1825 					}
1826 				}
1827 			}
1828 		}
1829 		while(bExt);
1830 	}
1831 	else if( mpView && mpView->IsTextEdit() )
1832 	{
1833 		rFirst = getSelectionStart();
1834 		findMergeOrigin( rFirst );
1835 		rLast = rFirst;
1836 
1837 		if( mxTable.is() )
1838 		{
1839 			Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
1840 			if( xCell.is() )
1841 			{
1842 				rLast.mnCol += xCell->getColumnSpan() - 1;
1843 				rLast.mnRow += xCell->getRowSpan() - 1;
1844 			}
1845 		}
1846 	}
1847 	else
1848 	{
1849 		rFirst.mnCol = 0;
1850 		rFirst.mnRow = 0;
1851 		if( mxTable.is() )
1852 		{
1853 			rLast.mnRow = mxTable->getRowCount()-1;
1854 			rLast.mnCol = mxTable->getColumnCount()-1;
1855 		}
1856 		else
1857 		{
1858 			rLast.mnRow = 0;
1859 			rLast.mnCol = 0;
1860 		}
1861 	}
1862 }
1863 
1864 // --------------------------------------------------------------------
1865 
StartSelection(const CellPos & rPos)1866 void SvxTableController::StartSelection( const CellPos& rPos )
1867 {
1868 	StopTextEdit();
1869 	mbCellSelectionMode = true;
1870 	maCursorLastPos = maCursorFirstPos = rPos;
1871 	mpView->MarkListHasChanged();
1872 }
1873 
1874 // --------------------------------------------------------------------
1875 
setSelectedCells(const CellPos & rStart,const CellPos & rEnd)1876 void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
1877 {
1878 	StopTextEdit();
1879 	mbCellSelectionMode = true;
1880 	maCursorFirstPos = rStart;
1881 	UpdateSelection( rEnd );
1882 }
1883 
1884 // --------------------------------------------------------------------
1885 
UpdateSelection(const CellPos & rPos)1886 void SvxTableController::UpdateSelection( const CellPos& rPos )
1887 {
1888 	maCursorLastPos = rPos;
1889 	mpView->MarkListHasChanged();
1890 }
1891 
1892 // --------------------------------------------------------------------
1893 
clearSelection()1894 void SvxTableController::clearSelection()
1895 {
1896 	RemoveSelection();
1897 }
1898 
1899 // --------------------------------------------------------------------
1900 
selectAll()1901 void SvxTableController::selectAll()
1902 {
1903 	if( mxTable.is() )
1904 	{
1905 		CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
1906 		if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
1907 		{
1908 			setSelectedCells( aPos1, aPos2 );
1909 		}
1910 	}
1911 }
1912 
1913 // --------------------------------------------------------------------
1914 
RemoveSelection()1915 void SvxTableController::RemoveSelection()
1916 {
1917 	if( mbCellSelectionMode )
1918 	{
1919 		mbCellSelectionMode = false;
1920 		mpView->MarkListHasChanged();
1921 	}
1922 }
1923 
1924 // --------------------------------------------------------------------
1925 
onTableModified()1926 void SvxTableController::onTableModified()
1927 {
1928 	if( mnUpdateEvent == 0 )
1929 		mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
1930 }
1931 // --------------------------------------------------------------------
1932 
updateSelectionOverlay()1933 void SvxTableController::updateSelectionOverlay()
1934 {
1935 	destroySelectionOverlay();
1936 	if( mbCellSelectionMode )
1937 	{
1938 		::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1939 		if( pTableObj )
1940 		{
1941 			sdr::overlay::OverlayObjectCell::RangeVector aRanges;
1942 
1943 			Rectangle aRect;
1944 			CellPos aStart,aEnd;
1945 			getSelectedCells( aStart, aEnd );
1946 			pTableObj->getCellBounds( aStart, aRect );
1947 
1948 			basegfx::B2DRange a2DRange( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1949 			a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1950 
1951 			findMergeOrigin( aEnd );
1952 			pTableObj->getCellBounds( aEnd, aRect );
1953 			a2DRange.expand( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1954 			a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1955 			aRanges.push_back( a2DRange );
1956 
1957 			::Color aHighlight( COL_BLUE );
1958 			OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
1959 			if( pOutDev )
1960 				aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
1961 
1962 			const sal_uInt32 nCount = mpView->PaintWindowCount();
1963 			for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
1964 			{
1965 				SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
1966 				if( pPaintWindow )
1967 				{
1968 					::sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
1969 					if( pOverlayManager )
1970 					{
1971 						// sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
1972 						sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
1973 
1974 						sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
1975 
1976 						pOverlayManager->add(*pOverlay);
1977 						mpSelectionOverlay = new ::sdr::overlay::OverlayObjectList;
1978 						mpSelectionOverlay->append(*pOverlay);
1979 					}
1980 				}
1981 			}
1982 		}
1983 	}
1984 }
1985 
1986 // --------------------------------------------------------------------
1987 
destroySelectionOverlay()1988 void SvxTableController::destroySelectionOverlay()
1989 {
1990 	if( mpSelectionOverlay )
1991 	{
1992 		delete mpSelectionOverlay;
1993 		mpSelectionOverlay = 0;
1994 	}
1995 }
1996 
1997 // --------------------------------------------------------------------
1998 
MergeAttrFromSelectedCells(SfxItemSet & rAttr,bool bOnlyHardAttr) const1999 void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
2000 {
2001 	if( mxTable.is() )
2002 	{
2003 		CellPos aStart, aEnd;
2004 		const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
2005 
2006 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2007 		{
2008 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2009 			{
2010 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2011 				if( xCell.is() && !xCell->isMerged() )
2012 				{
2013 					const SfxItemSet& rSet = xCell->GetItemSet();
2014 					SfxWhichIter aIter(rSet);
2015 					sal_uInt16 nWhich(aIter.FirstWhich());
2016 					while(nWhich)
2017 					{
2018 						if(!bOnlyHardAttr)
2019 						{
2020 							if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
2021 								rAttr.InvalidateItem(nWhich);
2022 							else
2023 								rAttr.MergeValue(rSet.Get(nWhich), sal_True);
2024 						}
2025 						else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
2026 						{
2027 							const SfxPoolItem& rItem = rSet.Get(nWhich);
2028 							rAttr.MergeValue(rItem, sal_True);
2029 						}
2030 
2031 						nWhich = aIter.NextWhich();
2032 					}
2033 				}
2034 			}
2035 		}
2036 	}
2037 
2038 	if( mpView->IsTextEdit() )
2039 	{
2040 	}
2041 }
2042 
2043 // --------------------------------------------------------------------
2044 
2045 const sal_uInt16 CELL_BEFORE = 0x0001;
2046 const sal_uInt16 CELL_LEFT   = 0x0002;
2047 const sal_uInt16 CELL_RIGHT  = 0x0004;
2048 const sal_uInt16 CELL_AFTER  = 0x0008;
2049 
2050 const sal_uInt16 CELL_UPPER  = 0x0010;
2051 const sal_uInt16 CELL_TOP    = 0x0020;
2052 const sal_uInt16 CELL_BOTTOM = 0x0040;
2053 const sal_uInt16 CELL_LOWER  = 0x0080;
2054 
2055 // --------------------------------------------------------------------
2056 
ImplSetLinePreserveColor(SvxBoxItem & rNewFrame,const SvxBorderLine * pNew,sal_uInt16 nLine)2057 static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, sal_uInt16 nLine )
2058 {
2059 	if( pNew )
2060 	{
2061 		const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
2062 		if( pOld )
2063 		{
2064 			SvxBorderLine aNewLine( *pNew );
2065 			aNewLine.SetColor( pOld->GetColor() );
2066 			rNewFrame.SetLine( &aNewLine, nLine );
2067 			return;
2068 		}
2069 	}
2070 	rNewFrame.SetLine( pNew, nLine );
2071 }
2072 
2073 // --------------------------------------------------------------------
2074 
ImplApplyBoxItem(sal_uInt16 nCellFlags,const SvxBoxItem * pBoxItem,const SvxBoxInfoItem * pBoxInfoItem,SvxBoxItem & rNewFrame)2075 static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
2076 {
2077 	if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2078 	{
2079 		// current cell is outside the selection
2080 
2081 		if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2082 		{
2083 			if( nCellFlags & CELL_UPPER )
2084 			{
2085 				if( pBoxInfoItem->IsValid(VALID_TOP) )
2086 					rNewFrame.SetLine(0, BOX_LINE_BOTTOM );
2087 			}
2088 			else if( nCellFlags & CELL_LOWER )
2089 			{
2090 				if( pBoxInfoItem->IsValid(VALID_BOTTOM) )
2091 					rNewFrame.SetLine( 0, BOX_LINE_TOP );
2092 			}
2093 		}
2094 		else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2095 		{
2096 			if( nCellFlags & CELL_BEFORE )
2097 			{
2098 				if( pBoxInfoItem->IsValid(VALID_LEFT) )
2099 					rNewFrame.SetLine( 0, BOX_LINE_RIGHT );
2100 			}
2101 			else if( nCellFlags & CELL_AFTER )
2102 			{
2103 				if( pBoxInfoItem->IsValid(VALID_RIGHT) )
2104 					rNewFrame.SetLine( 0, BOX_LINE_LEFT );
2105 			}
2106 		}
2107 	}
2108 	else
2109 	{
2110 		// current cell is inside the selection
2111 
2112 		if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
2113 			rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), BOX_LINE_LEFT );
2114 
2115 		if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
2116 			rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), BOX_LINE_RIGHT );
2117 
2118 		if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
2119 			rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), BOX_LINE_TOP );
2120 
2121 		if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
2122 			rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), BOX_LINE_BOTTOM );
2123 
2124 		// apply distance to borders
2125 		if( pBoxInfoItem->IsValid( VALID_DISTANCE ) )
2126 			for( sal_uInt16 nLine = 0; nLine < 4; ++nLine )
2127 				rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
2128 	}
2129 }
2130 
2131 // --------------------------------------------------------------------
2132 
ImplSetLineColor(SvxBoxItem & rNewFrame,sal_uInt16 nLine,const Color & rColor)2133 static void ImplSetLineColor( SvxBoxItem& rNewFrame, sal_uInt16 nLine, const Color& rColor )
2134 {
2135 	const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
2136 	if( pSourceLine )
2137 	{
2138 		SvxBorderLine aLine( *pSourceLine );
2139 		aLine.SetColor( rColor );
2140 		rNewFrame.SetLine( &aLine, nLine );
2141 	}
2142 }
2143 
2144 // --------------------------------------------------------------------
2145 
ImplApplyLineColorItem(sal_uInt16 nCellFlags,const SvxColorItem * pLineColorItem,SvxBoxItem & rNewFrame)2146 static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
2147 {
2148 	const Color aColor( pLineColorItem->GetValue() );
2149 
2150 	if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
2151 		ImplSetLineColor( rNewFrame, BOX_LINE_BOTTOM, aColor );
2152 
2153 	if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
2154 		ImplSetLineColor( rNewFrame, BOX_LINE_TOP, aColor );
2155 
2156 	if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
2157 		ImplSetLineColor( rNewFrame, BOX_LINE_RIGHT, aColor );
2158 
2159 	if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
2160 		ImplSetLineColor( rNewFrame, BOX_LINE_LEFT, aColor );
2161 }
2162 
2163 // --------------------------------------------------------------------
2164 
ImplApplyBorderLineItem(sal_uInt16 nCellFlags,const SvxBorderLine * pBorderLineItem,SvxBoxItem & rNewFrame)2165 static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
2166 {
2167 	if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2168 	{
2169 		if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2170 		{
2171 			if( nCellFlags & CELL_UPPER )
2172 			{
2173 				if( rNewFrame.GetBottom() )
2174 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2175 			}
2176 			else if( nCellFlags & CELL_LOWER )
2177 			{
2178 				if( rNewFrame.GetTop() )
2179 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2180 			}
2181 		}
2182 		else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2183 		{
2184 			if( nCellFlags & CELL_BEFORE )
2185 			{
2186 				if( rNewFrame.GetRight() )
2187 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2188 			}
2189 			else if( nCellFlags & CELL_AFTER )
2190 			{
2191 				if( rNewFrame.GetLeft() )
2192 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2193 			}
2194 		}
2195 	}
2196 	else
2197 	{
2198 		if( rNewFrame.GetBottom() )
2199 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2200 		if( rNewFrame.GetTop() )
2201 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2202 		if( rNewFrame.GetRight() )
2203 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2204 		if( rNewFrame.GetLeft() )
2205 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2206 	}
2207 }
2208 
2209 // --------------------------------------------------------------------
2210 
ApplyBorderAttr(const SfxItemSet & rAttr)2211 void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
2212 {
2213 	if( mxTable.is() )
2214 	{
2215 		const sal_Int32 nRowCount = mxTable->getRowCount();
2216 		const sal_Int32 nColCount = mxTable->getColumnCount();
2217 		if( nRowCount && nColCount )
2218 		{
2219 			const SvxBoxItem* pBoxItem = 0;
2220 			if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, sal_False) )
2221 				pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
2222 
2223 			const SvxBoxInfoItem* pBoxInfoItem = 0;
2224 			if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, sal_False) )
2225 				pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
2226 
2227 			const SvxColorItem* pLineColorItem = 0;
2228 			if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, sal_False) )
2229 				pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
2230 
2231 			const SvxBorderLine* pBorderLineItem = 0;
2232 			if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, sal_False) )
2233 				pBorderLineItem = ((const SvxLineItem&)rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
2234 
2235 			if( pBoxInfoItem && !pBoxItem )
2236 			{
2237 				const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
2238 				pBoxItem = &gaEmptyBoxItem;
2239 			}
2240 			else if( pBoxItem && !pBoxInfoItem )
2241 			{
2242 				const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
2243 				pBoxInfoItem = &gaEmptyBoxInfoItem;
2244 			}
2245 
2246 			CellPos aStart, aEnd;
2247 			getSelectedCells( aStart, aEnd );
2248 
2249 			const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2250 			const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2251 
2252 			for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2253 			{
2254 				sal_uInt16 nRowFlags = 0;
2255 				nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2256 				nRowFlags |= (nRow == aEnd.mnRow)   ? CELL_BOTTOM : 0;
2257 				nRowFlags |= (nRow < aStart.mnRow)  ? CELL_UPPER : 0;
2258 				nRowFlags |= (nRow > aEnd.mnRow)    ? CELL_LOWER : 0;
2259 
2260 				for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2261 				{
2262 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2263 					if( !xCell.is() )
2264 						continue;
2265 
2266 					const SfxItemSet& rSet = xCell->GetItemSet();
2267 					const SvxBoxItem* pOldOuter = (const SvxBoxItem*)	  &rSet.Get( SDRATTR_TABLE_BORDER );
2268 
2269 					SvxBoxItem aNewFrame( *pOldOuter );
2270 
2271 					sal_uInt16 nCellFlags = nRowFlags;
2272 					nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2273 					nCellFlags |= (nCol == aEnd.mnCol)   ? CELL_RIGHT : 0;
2274 					nCellFlags |= (nCol < aStart.mnCol)  ? CELL_BEFORE : 0;
2275 					nCellFlags |= (nCol > aEnd.mnCol)    ? CELL_AFTER : 0;
2276 
2277 					if( pBoxItem && pBoxInfoItem )
2278 						ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
2279 
2280 					if( pLineColorItem )
2281 						ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
2282 
2283 					if( pBorderLineItem )
2284 						ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
2285 
2286 					if (aNewFrame != *pOldOuter)
2287 					{
2288 						SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
2289 						aAttr.Put(aNewFrame);
2290 						xCell->SetMergedItemSetAndBroadcast( aAttr, false );
2291 					}
2292 				}
2293 			}
2294 		}
2295 	}
2296 }
2297 
2298 // --------------------------------------------------------------------
2299 
UpdateTableShape()2300 void SvxTableController::UpdateTableShape()
2301 {
2302 	SdrObject* pTableObj = mxTableObj.get();
2303 	if( pTableObj )
2304 	{
2305 		pTableObj->ActionChanged();
2306 		pTableObj->BroadcastObjectChange();
2307 	}
2308 	updateSelectionOverlay();
2309 }
2310 
2311 
2312 // --------------------------------------------------------------------
2313 
SetAttrToSelectedCells(const SfxItemSet & rAttr,bool bReplaceAll)2314 void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
2315 {
2316 	if( mxTable.is() )
2317 	{
2318 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2319 
2320 		if( bUndo )
2321 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2322 
2323 		CellPos aStart, aEnd;
2324 		getSelectedCells( aStart, aEnd );
2325 
2326 		SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
2327 		aAttr.Put(rAttr, sal_True);
2328 
2329 		const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2330 
2331 		if( bFrame )
2332 		{
2333 			aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2334 			aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2335 		}
2336 
2337 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2338 		{
2339 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2340 			{
2341 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2342 				if( xCell.is() )
2343 				{
2344 					if( bUndo )
2345 						xCell->AddUndo();
2346 					xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2347 				}
2348 			}
2349 		}
2350 
2351 		if( bFrame )
2352 		{
2353 			ApplyBorderAttr( rAttr );
2354 		}
2355 
2356 		UpdateTableShape();
2357 
2358 		if( bUndo )
2359 			mpModel->EndUndo();
2360 
2361 	}
2362 }
2363 
2364 // --------------------------------------------------------------------
2365 
GetAttributes(SfxItemSet & rTargetSet,bool bOnlyHardAttr) const2366 bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2367 {
2368 	if( mxTableObj.is() && hasSelectedCells() )
2369 	{
2370 		MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
2371 
2372 		if( mpView->IsTextEdit() )
2373 		{
2374 			if( mxTableObj->GetOutlinerParaObject() )
2375 				rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
2376 
2377 			OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
2378 			if(pTextEditOutlinerView)
2379 			{
2380 				// FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
2381 				rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), sal_False);
2382 				rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ), sal_False );
2383 			}
2384 		}
2385 
2386 		return true;
2387 	}
2388 	else
2389 	{
2390 		return false;
2391 	}
2392 }
2393 
2394 // --------------------------------------------------------------------
2395 
SetAttributes(const SfxItemSet & rSet,bool bReplaceAll)2396 bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2397 {
2398 	if( mbCellSelectionMode || mpView->IsTextEdit()  )
2399 	{
2400 		SetAttrToSelectedCells( rSet, bReplaceAll );
2401 		return true;
2402 	}
2403 	return false;
2404 }
2405 
2406 // --------------------------------------------------------------------
2407 
GetMarkedObjModel(SdrPage * pNewPage)2408 bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
2409 {
2410 	if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
2411 	{
2412 		::sdr::table::SdrTableObj& rTableObj = *static_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2413 
2414 		CellPos aStart, aEnd;
2415 		getSelectedCells( aStart, aEnd );
2416 
2417 		SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
2418 
2419 		pNewTableObj->SetPage( pNewPage );
2420 		pNewTableObj->SetModel( pNewPage->GetModel() );
2421 
2422 		SdrInsertReason aReason(SDRREASON_VIEWCALL);
2423 		pNewPage->InsertObject(pNewTableObj,CONTAINER_APPEND,&aReason);
2424 
2425 		return true;
2426 	}
2427 	catch( Exception& )
2428 	{
2429 		DBG_ERROR( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2430 	}
2431 	return false;
2432 }
2433 
2434 // --------------------------------------------------------------------
2435 
PasteObjModel(const SdrModel & rModel)2436 bool SvxTableController::PasteObjModel( const SdrModel& rModel )
2437 {
2438 	if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
2439 	{
2440 		const SdrPage* pPastePage = rModel.GetPage(0);
2441 		if( pPastePage && pPastePage->GetObjCount() == 1 )
2442 		{
2443 			SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
2444 			if( pPasteTableObj )
2445 			{
2446 				return PasteObject( pPasteTableObj );
2447 			}
2448 		}
2449 	}
2450 
2451 	return false;
2452 }
2453 
2454 // --------------------------------------------------------------------
2455 
PasteObject(SdrTableObj * pPasteTableObj)2456 bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
2457 {
2458 	if( !pPasteTableObj )
2459 		return false;
2460 
2461 	Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
2462 	if( !xPasteTable.is() )
2463 		return false;
2464 
2465 	if( !mxTable.is() )
2466 		return false;
2467 
2468 	sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
2469 	sal_Int32 nPasteRows = xPasteTable->getRowCount();
2470 
2471 	CellPos aStart, aEnd;
2472 	getSelectedCells( aStart, aEnd );
2473 
2474 	if( mpView->IsTextEdit() )
2475 		mpView->SdrEndTextEdit(sal_True);
2476 
2477 	sal_Int32 nColumns = mxTable->getColumnCount();
2478 	sal_Int32 nRows = mxTable->getRowCount();
2479 
2480 	const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
2481 	if( nMissing > 0 )
2482 	{
2483 		Reference< XTableRows > xRows( mxTable->getRows() );
2484 		xRows->insertByIndex( nRows, nMissing );
2485 		nRows = mxTable->getRowCount();
2486 	}
2487 
2488 	nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
2489 	nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
2490 
2491 	// copy cell contents
2492 	for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
2493 	{
2494 		for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
2495 		{
2496 			CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
2497 			if( xTargetCell.is() && !xTargetCell->isMerged() )
2498 			{
2499 				xTargetCell->AddUndo();
2500 				xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
2501 				nCol += xTargetCell->getColumnSpan() - 1;
2502 			}
2503 		}
2504 	}
2505 
2506 	UpdateTableShape();
2507 
2508 	return true;
2509 }
2510 
TakeFormatPaintBrush(boost::shared_ptr<SfxItemSet> &)2511 bool SvxTableController::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& /*rFormatSet*/  )
2512 {
2513     // SdrView::TakeFormatPaintBrush() is enough
2514     return false;
2515 }
2516 
ApplyFormatPaintBrush(SfxItemSet & rFormatSet,bool bNoCharacterFormats,bool bNoParagraphFormats)2517 bool SvxTableController::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2518 {
2519 	if( mbCellSelectionMode )
2520 	{
2521     	SdrTextObj* pTableObj = dynamic_cast<SdrTextObj*>( mxTableObj.get() );
2522     	if( !pTableObj )
2523     	    return false;
2524 
2525 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2526 
2527 		if( bUndo )
2528 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2529 
2530 		CellPos aStart, aEnd;
2531 		getSelectedCells( aStart, aEnd );
2532 
2533 		SfxItemSet aAttr(*rFormatSet.GetPool(), rFormatSet.GetRanges());
2534 		aAttr.Put(rFormatSet, sal_True);
2535 
2536 		const bool bFrame = (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2537 
2538 		if( bFrame )
2539 		{
2540 			aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2541 			aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2542 		}
2543 
2544         const sal_uInt16* pRanges = rFormatSet.GetRanges();
2545         bool bTextOnly = true;
2546 
2547         while( *pRanges )
2548         {
2549             if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
2550             {
2551                 bTextOnly = true;
2552                 break;
2553             }
2554             pRanges += 2;
2555         }
2556 
2557         const bool bReplaceAll = false;
2558 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2559 		{
2560 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2561 			{
2562 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2563 				if( xCell.is() )
2564 				{
2565 					if( bUndo )
2566 						xCell->AddUndo();
2567 				    if( !bTextOnly )
2568 					    xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2569 
2570                     SdrText* pText = static_cast< SdrText* >( xCell.get() );
2571                     mpView->ApplyFormatPaintBrushToText( rFormatSet, *pTableObj, pText, bNoCharacterFormats, bNoParagraphFormats );
2572 				}
2573 			}
2574 		}
2575 
2576 		if( bFrame )
2577 		{
2578 			ApplyBorderAttr( rFormatSet );
2579 		}
2580 
2581 		UpdateTableShape();
2582 
2583 		if( bUndo )
2584 			mpModel->EndUndo();
2585 
2586 	    return true;
2587 
2588 	}
2589     return false;
2590 }
2591 
2592 
2593 // --------------------------------------------------------------------
2594 
IMPL_LINK(SvxTableController,UpdateHdl,void *,EMPTYARG)2595 IMPL_LINK( SvxTableController, UpdateHdl, void *, EMPTYARG )
2596 {
2597 	mnUpdateEvent = 0;
2598 
2599 	if( mbCellSelectionMode )
2600 	{
2601 		CellPos aStart( maCursorFirstPos );
2602 		CellPos aEnd( maCursorLastPos );
2603 		checkCell(aStart);
2604 		checkCell(aEnd);
2605 		if( aStart != maCursorFirstPos  || aEnd != maCursorLastPos )
2606 		{
2607 			setSelectedCells( aStart, aEnd );
2608 		}
2609 	}
2610 	updateSelectionOverlay();
2611 
2612 	return 0;
2613 }
2614 
selectRow(sal_Int32 row)2615 sal_Bool SvxTableController::selectRow( sal_Int32 row )
2616 {
2617 	if( !mxTable.is() )
2618 		return sal_False;
2619 	CellPos aStart( 0, row ), aEnd( mxTable->getColumnCount() - 1, row );
2620 	StartSelection( aEnd );
2621 	gotoCell( aStart, true, 0 );
2622 	return sal_True;
2623 }
selectColumn(sal_Int32 column)2624 sal_Bool SvxTableController::selectColumn( sal_Int32 column )
2625 {
2626 	if( !mxTable.is() )
2627 		return sal_False;
2628 	CellPos aStart( column, 0 ), aEnd( column, mxTable->getRowCount() - 1 );
2629 	StartSelection( aEnd );
2630 	gotoCell( aStart, true, 0 );
2631 	return sal_True;
2632 }
deselectRow(sal_Int32 row)2633 sal_Bool SvxTableController::deselectRow( sal_Int32 row )
2634 {
2635 	if( !mxTable.is() )
2636 		return sal_False;
2637 	CellPos aStart( 0, row ), aEnd( mxTable->getColumnCount() - 1, row );
2638 	StartSelection( aEnd );
2639 	gotoCell( aStart, false, 0 );
2640 	return sal_True;
2641 }
deselectColumn(sal_Int32 column)2642 sal_Bool SvxTableController::deselectColumn( sal_Int32 column )
2643 {
2644 	if( !mxTable.is() )
2645 		return sal_False;
2646 	CellPos aStart( column, 0 ), aEnd( column, mxTable->getRowCount() - 1 );
2647 	StartSelection( aEnd );
2648 	gotoCell( aStart, false, 0 );
2649 	return sal_True;
2650 }
isRowSelected(sal_Int32 nRow)2651 sal_Bool SvxTableController::isRowSelected( sal_Int32 nRow )
2652 {
2653 	if( hasSelectedCells() )
2654 	{
2655 		CellPos aFirstPos, aLastPos;
2656 		getSelectedCells( aFirstPos, aLastPos );
2657 		if( (aFirstPos.mnCol == 0) && (nRow >= aFirstPos.mnRow && nRow <= aLastPos.mnRow) && (mxTable->getColumnCount() - 1 == aLastPos.mnCol) )
2658 			return sal_True;
2659 	}
2660 	return sal_False;
2661 }
isColumnSelected(sal_Int32 nColumn)2662 sal_Bool SvxTableController::isColumnSelected( sal_Int32 nColumn )
2663 {
2664 	if( hasSelectedCells() )
2665 	{
2666 		CellPos aFirstPos, aLastPos;
2667 		getSelectedCells( aFirstPos, aLastPos );
2668 		if( (aFirstPos.mnRow == 0) && (nColumn >= aFirstPos.mnCol && nColumn <= aLastPos.mnCol) && (mxTable->getRowCount() - 1 == aLastPos.mnRow) )
2669 			return sal_True;
2670 	}
2671 	return sal_False;
2672 }
2673 
isRowHeader()2674 sal_Bool SvxTableController::isRowHeader()
2675 {
2676 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2677 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
2678 
2679 	if( !pTableObj || !pModel )
2680 		return sal_False;
2681 
2682 	TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
2683 
2684 	return aSettings.mbUseFirstRow;
2685 }
2686 
isColumnHeader()2687 sal_Bool SvxTableController::isColumnHeader()
2688 {
2689 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2690 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
2691 
2692 	if( !pTableObj || !pModel )
2693 		return sal_False;
2694 
2695 	TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
2696 
2697 	return aSettings.mbUseFirstColumn;
2698 }
2699 } }
2700