xref: /aoo41x/main/svx/source/table/svdotable.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #define ITEMID_BOX SDRATTR_TABLE_BORDER
32 #define ITEMID_BOXINFO SDRATTR_TABLE_BORDER_INNER
33 
34 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
35 #include <com/sun/star/container/XNamed.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/container/XIndexAccess.hpp>
38 
39 #include <vcl/canvastools.hxx>
40 #include <com/sun/star/style/XStyle.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <basegfx/polygon/b2dpolygontools.hxx>
43 #include <basegfx/polygon/b2dpolypolygon.hxx>
44 #include <basegfx/polygon/b2dpolygon.hxx>
45 #include <svl/style.hxx>
46 #include "editeng/editstat.hxx"
47 #include "editeng/outlobj.hxx"
48 #include "svx/svdview.hxx"
49 #include "svx/sdr/properties/textproperties.hxx"
50 #include "svx/svdotable.hxx"
51 #include "svx/svdhdl.hxx"
52 #include "viewcontactoftableobj.hxx"
53 #include "svx/svdoutl.hxx"
54 #include "svx/svddrag.hxx"
55 #include "svx/svdpagv.hxx"
56 #include "tablemodel.hxx"
57 #include "cell.hxx"
58 #include "svx/xflclit.hxx"
59 #include "tablelayouter.hxx"
60 #include "svx/svdetc.hxx"
61 #include "tablehandles.hxx"
62 #include "editeng/boxitem.hxx"
63 #include "svx/framelink.hxx"
64 #include "svx/sdr/table/tabledesign.hxx"
65 #include "svx/svdundo.hxx"
66 #include "svx/svdstr.hrc"
67 #include "svx/svdglob.hxx"
68 #include "editeng/writingmodeitem.hxx"
69 #include "editeng/frmdiritem.hxx"
70 #include "svx/xflhtit.hxx"
71 #include "svx/xflftrit.hxx"
72 #include "svx/xfltrit.hxx"
73 
74 // -----------------------------------------------------------------------------
75 
76 using ::rtl::OUString;
77 using ::com::sun::star::uno::Any;
78 using ::com::sun::star::uno::Reference;
79 using ::com::sun::star::uno::XInterface;
80 using ::com::sun::star::uno::UNO_QUERY;
81 using ::com::sun::star::uno::UNO_QUERY_THROW;
82 using ::com::sun::star::uno::Exception;
83 using ::com::sun::star::container::XIndexAccess;
84 using ::com::sun::star::style::XStyle;
85 using ::com::sun::star::table::XTableRows;
86 using ::com::sun::star::table::XTableColumns;
87 using ::com::sun::star::table::XTable;
88 using ::com::sun::star::beans::XPropertySet;
89 using ::com::sun::star::util::XModifyBroadcaster;
90 using sdr::properties::TextProperties;
91 using sdr::properties::BaseProperties;
92 using namespace ::com::sun::star::text;
93 using namespace ::com::sun::star::container;
94 using namespace ::com::sun::star::style;
95 
96 namespace sdr { namespace table {
97 
98 class TableProperties : public TextProperties
99 {
100 protected:
101 	// create a new itemset
102 	SfxItemSet& CreateObjectSpecificItemSet(SfxItemPool& rPool);
103 
104 public:
105 	// basic constructor
106 	TableProperties(SdrObject& rObj );
107 
108 	// constructor for copying, but using new object
109 	TableProperties(const TableProperties& rProps, SdrObject& rObj );
110 
111 	// destructor
112 	~TableProperties();
113 
114 	// Clone() operator, normally just calls the local copy constructor
115 	BaseProperties& Clone(SdrObject& rObj) const;
116 
117 	virtual void ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem);
118 };
119 
120 TableProperties::TableProperties(SdrObject& rObj)
121 : TextProperties(rObj)
122 {
123 }
124 
125 TableProperties::TableProperties(const TableProperties& rProps, SdrObject& rObj)
126 : TextProperties(rProps, rObj)
127 {
128 }
129 
130 TableProperties::~TableProperties()
131 {
132 }
133 
134 BaseProperties& TableProperties::Clone(SdrObject& rObj) const
135 {
136 	return *(new TableProperties(*this, rObj));
137 }
138 
139 void TableProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
140 {
141 	if( nWhich == SDRATTR_TEXTDIRECTION )
142 		AttributeProperties::ItemChange( nWhich, pNewItem );
143 	else
144 		TextProperties::ItemChange( nWhich, pNewItem );
145 }
146 
147 // create a new itemset
148 SfxItemSet& TableProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
149 {
150 	return *(new SfxItemSet(rPool,
151 
152 		// range from SdrAttrObj
153 		SDRATTR_START, SDRATTR_SHADOW_LAST,
154 		SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
155 		SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
156 
157 		// range for SdrTableObj
158 		SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST,
159 
160 		// range from SdrTextObj
161 		EE_ITEMS_START, EE_ITEMS_END,
162 
163 		// end
164 		0, 0));
165 }
166 
167 class TableObjectGeoData : public SdrTextObjGeoData
168 {
169 public:
170 	Rectangle	maLogicRect;
171 };
172 
173 //------------------------------------------------------------------------
174 // TableStyleSettings
175 //------------------------------------------------------------------------
176 
177 TableStyleSettings::TableStyleSettings()
178 : mbUseFirstRow(true)
179 , mbUseLastRow(false)
180 , mbUseFirstColumn(false)
181 , mbUseLastColumn(false)
182 , mbUseRowBanding(true)
183 , mbUseColumnBanding(false)
184 {
185 }
186 
187 TableStyleSettings::TableStyleSettings( const TableStyleSettings& rStyle )
188 {
189 	(*this) = rStyle;
190 }
191 
192 TableStyleSettings& TableStyleSettings::operator=(const TableStyleSettings& rStyle)
193 {
194 	mbUseFirstRow = rStyle.mbUseFirstRow;
195 	mbUseLastRow = rStyle.mbUseLastRow;
196 	mbUseFirstColumn = rStyle.mbUseFirstColumn;
197 	mbUseLastColumn = rStyle.mbUseLastColumn;
198 	mbUseRowBanding = rStyle.mbUseRowBanding;
199 	mbUseColumnBanding = rStyle.mbUseColumnBanding;
200 	return *this;
201 }
202 
203 bool TableStyleSettings::operator==( const TableStyleSettings& rStyle ) const
204 {
205 	return
206 		(mbUseFirstRow == rStyle.mbUseFirstRow) &&
207 		(mbUseLastRow == rStyle.mbUseLastRow) &&
208 		(mbUseFirstColumn == rStyle.mbUseFirstColumn) &&
209 		(mbUseLastColumn == rStyle.mbUseLastColumn) &&
210 		(mbUseRowBanding == rStyle.mbUseRowBanding) &&
211 		(mbUseColumnBanding == rStyle.mbUseColumnBanding);
212 }
213 
214 // -----------------------------------------------------------------------------
215 
216 class SdrTableObjImpl : public TableDesignUser, public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
217 {
218 public:
219 	CellRef	mxActiveCell;
220 	TableModelRef mxTable;
221 	SdrTableObj* mpTableObj;
222 	TableLayouter* mpLayouter;
223 	CellPos maEditPos;
224 	TableStyleSettings maTableStyle;
225 	Reference< XIndexAccess > mxTableStyle;
226 	bool mbModifyPending;
227 //	sal_Int32 mnSavedEditRowHeight;
228 
229 	void SetModel(SdrModel* pOldModel, SdrModel* pNewModel);
230 
231 	CellRef getCell( const CellPos& rPos ) const;
232 	void LayoutTable( Rectangle& rArea, bool bFitWidth, bool bFitHeight );
233 
234 	bool ApplyCellStyles();
235 	void UpdateCells( Rectangle& rArea );
236 
237 	SdrTableObjImpl();
238 	virtual ~SdrTableObjImpl();
239 
240 	void init( SdrTableObj* pTable, sal_Int32 nColumns, sal_Int32 nRows );
241 	void dispose();
242 
243 	sal_Int32 getColumnCount() const;
244 	sal_Int32 getRowCount() const;
245 
246 	void DragEdge( bool mbHorizontal, int nEdge, sal_Int32 nOffset );
247 
248 	const SfxPoolItem* GetCellItem( const CellPos& rPos, sal_uInt16 nWhich ) const;
249 //	void GetBorderLines( const CellPos& rPos, const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const;
250 
251 	void operator=( const SdrTableObjImpl& rSource );
252 
253     // XModifyListener
254     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
255 
256     // XEventListener
257     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
258 
259 	void update();
260 
261 	void connectTableStyle();
262 	void disconnectTableStyle();
263 	virtual bool isInUse();
264 
265 	bool UpdateWritingMode();
266 };
267 
268 // -----------------------------------------------------------------------------
269 
270 SdrTableObjImpl::SdrTableObjImpl()
271 : mpTableObj( 0 )
272 , mpLayouter( 0 )
273 {
274 }
275 
276 // -----------------------------------------------------------------------------
277 
278 SdrTableObjImpl::~SdrTableObjImpl()
279 {
280 }
281 
282 // -----------------------------------------------------------------------------
283 
284 void SdrTableObjImpl::init( SdrTableObj* pTable, sal_Int32 nColumns, sal_Int32 nRows )
285 {
286 	mpTableObj = pTable;
287 	mxTable = new TableModel( pTable );
288 	mxTable->init( nColumns, nRows );
289 	mpLayouter = new TableLayouter( mxTable );
290 	Reference< XModifyListener > xListener( static_cast< ::com::sun::star::util::XModifyListener* >(this) );
291 	mxTable->addModifyListener( xListener );
292 	UpdateWritingMode();
293 	LayoutTable( mpTableObj->aRect, true, true );
294 	mpTableObj->maLogicRect = mpTableObj->aRect;
295 }
296 
297 // -----------------------------------------------------------------------------
298 
299 void SdrTableObjImpl::operator=( const SdrTableObjImpl& rSource )
300 {
301 	if( mpLayouter )
302 	{
303 		delete mpLayouter;
304 		mpLayouter = 0;
305 	}
306 
307 	if( mxTable.is() )
308 	{
309 		Reference< XModifyListener > xListener( static_cast< ::com::sun::star::util::XModifyListener* >(this) );
310 		mxTable->removeModifyListener( xListener );
311 		mxTable->dispose();
312 		mxTable.clear();
313 	}
314 
315 	maTableStyle = rSource.maTableStyle;
316 
317 	mxTable = new TableModel( mpTableObj, rSource.mxTable );
318 	mpLayouter = new TableLayouter( mxTable );
319 	Reference< XModifyListener > xListener( static_cast< ::com::sun::star::util::XModifyListener* >(this) );
320 	mxTable->addModifyListener( xListener );
321 	mxTableStyle = rSource.mxTableStyle;
322 	UpdateWritingMode();
323 	ApplyCellStyles();
324 	mpTableObj->aRect = mpTableObj->maLogicRect;
325 	LayoutTable( mpTableObj->aRect, false, false );
326 }
327 
328 // -----------------------------------------------------------------------------
329 
330 void SdrTableObjImpl::SetModel(SdrModel* /*pOldModel*/, SdrModel* pNewModel)
331 {
332 	// try to find new table style
333 	disconnectTableStyle();
334 
335 	Reference< XIndexAccess > xNewTableStyle;
336 	if( mxTableStyle.is() ) try
337 	{
338 		const OUString sStyleName( Reference< XNamed >( mxTableStyle, UNO_QUERY_THROW )->getName() );
339 
340 		Reference< XStyleFamiliesSupplier > xSFS( pNewModel->getUnoModel(), UNO_QUERY_THROW );
341 		Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
342 		const rtl::OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
343 		Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
344 
345 		if( xTableFamilyAccess->hasByName( sStyleName ) )
346 		{
347 			// found table style with the same name
348 			xTableFamilyAccess->getByName( sStyleName ) >>= xNewTableStyle;
349 		}
350 		else
351 		{
352 			// copy or?
353 			Reference< XIndexAccess > xIndexAccess( xTableFamilyAccess, UNO_QUERY_THROW );
354 			xIndexAccess->getByIndex( 0 ) >>= xNewTableStyle;
355 		}
356 	}
357 	catch( Exception& )
358 	{
359 		DBG_ERROR("svx::SdrTableObjImpl::SetModel(), exception caught!");
360 	}
361 
362 	mxTableStyle = xNewTableStyle;
363 
364 	connectTableStyle();
365 	update();
366 }
367 
368 // -----------------------------------------------------------------------------
369 
370 bool SdrTableObjImpl::ApplyCellStyles()
371 {
372 	if( !mxTable.is() || !mxTable.is() || !mxTableStyle.is() )
373 		return false;
374 
375 	bool bChanges = false;
376 
377 	const sal_Int32 nColCount = getColumnCount();
378 	const sal_Int32 nRowCount = getRowCount();
379 
380 	const TableStyleSettings& rStyle = maTableStyle;
381 
382 	CellPos aPos;
383 	for( aPos.mnRow = 0; aPos.mnRow < nRowCount; ++aPos.mnRow )
384 	{
385 		const bool bFirstRow = (aPos.mnRow == 0) && rStyle.mbUseFirstRow;
386 		const bool bLastRow = (aPos.mnRow == nRowCount-1) && rStyle.mbUseLastRow;
387 
388 		for( aPos.mnCol = 0; aPos.mnCol < nColCount; ++aPos.mnCol )
389 		{
390 			Reference< XStyle > xStyle;
391 
392 			// first and last row win first, if used and available
393 			if( bFirstRow )
394 			{
395 				mxTableStyle->getByIndex(first_row_style) >>= xStyle;
396 			}
397 			else if( bLastRow )
398 			{
399 				mxTableStyle->getByIndex(last_row_style) >>= xStyle;
400 			}
401 
402 			if( !xStyle.is() )
403 			{
404 				// next come first and last column, if used and available
405 				if( rStyle.mbUseFirstColumn && (aPos.mnCol == 0)  )
406 				{
407 					mxTableStyle->getByIndex(first_column_style) >>= xStyle;
408 				}
409 				else if( rStyle.mbUseLastColumn && (aPos.mnCol == nColCount-1) )
410 				{
411 					mxTableStyle->getByIndex(last_column_style) >>= xStyle;
412 				}
413 			}
414 
415 			if( !xStyle.is() && rStyle.mbUseRowBanding )
416 			{
417 				if( (aPos.mnRow & 1) == 0 )
418 				{
419 					mxTableStyle->getByIndex(even_rows_style) >>= xStyle;
420 				}
421 				else
422 				{
423 					mxTableStyle->getByIndex(odd_rows_style) >>= xStyle;
424 				}
425 			}
426 
427 			if( !xStyle.is() && rStyle.mbUseColumnBanding )
428 			{
429 				if( (aPos.mnCol & 1) == 0 )
430 				{
431 					mxTableStyle->getByIndex(even_columns_style) >>= xStyle;
432 				}
433 				else
434 				{
435 					mxTableStyle->getByIndex(odd_columns_style) >>= xStyle;
436 				}
437 			}
438 
439 			if( !xStyle.is() )
440 			{
441 				// use default cell style if non found yet
442 				mxTableStyle->getByIndex(body_style) >>= xStyle;
443 			}
444 
445 
446 			if( xStyle.is() )
447 			{
448 				SfxUnoStyleSheet* pStyle = SfxUnoStyleSheet::getUnoStyleSheet(xStyle);
449 
450 				if( pStyle )
451 				{
452 					CellRef xCell( getCell( aPos ) );
453 					if( xCell.is() && ( xCell->GetStyleSheet() != pStyle ) )
454 					{
455 						bChanges = true;
456 						xCell->SetStyleSheet( pStyle, sal_True );
457 					}
458 				}
459 			}
460 		}
461 	}
462 
463 	return bChanges;
464 }
465 
466 // -----------------------------------------------------------------------------
467 
468 void SdrTableObjImpl::dispose()
469 {
470 	if( mxTable.is() )
471 		mxTable->dispose();
472 }
473 
474 // -----------------------------------------------------------------------------
475 
476 void SdrTableObjImpl::DragEdge( bool mbHorizontal, int nEdge, sal_Int32 nOffset )
477 {
478 	if( (nEdge > 0) && mxTable.is()) try
479 	{
480 		const OUString sSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) );
481 		nEdge--;
482 		if( mbHorizontal )
483 		{
484 			if( (nEdge >= 0) && (nEdge < getRowCount()) )
485 			{
486 				sal_Int32 nHeigth = mpLayouter->getRowHeight( nEdge );
487 				nHeigth += nOffset;
488 				Reference< XIndexAccess > xRows( mxTable->getRows(), UNO_QUERY_THROW );
489 				Reference< XPropertySet > xRowSet( xRows->getByIndex( nEdge ), UNO_QUERY_THROW );
490 				xRowSet->setPropertyValue( sSize, Any( nHeigth ) );
491 			}
492 		}
493 		else
494 		{
495 			if( (nEdge >= 0) && (nEdge < getColumnCount()) )
496 			{
497 				sal_Int32 nWidth = mpLayouter->getColumnWidth( nEdge );
498 				nWidth += nOffset;
499 
500 				Reference< XIndexAccess > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
501 				Reference< XPropertySet > xColSet( xCols->getByIndex( nEdge ), UNO_QUERY_THROW );
502 				xColSet->setPropertyValue( sSize, Any( nWidth ) );
503 
504 				if( nEdge > 0 && nEdge < mxTable->getColumnCount() )
505 				{
506 					const bool bRTL = mpLayouter->GetWritingMode() == WritingMode_RL_TB;
507 
508 					if( bRTL )
509 						nEdge--;
510 					else
511 						nEdge++;
512 
513 					if( (bRTL && (nEdge >= 0)) || (!bRTL && (nEdge < mxTable->getColumnCount())) )
514 					{
515 						nWidth = mpLayouter->getColumnWidth( nEdge );
516 						nWidth = std::max( (sal_Int32)(nWidth - nOffset), (sal_Int32)0 );
517 
518 						xColSet = Reference< XPropertySet >( xCols->getByIndex( nEdge ), UNO_QUERY_THROW );
519 						xColSet->setPropertyValue( sSize, Any( nWidth ) );
520 					}
521 				}
522 			}
523 		}
524 	}
525 	catch( Exception& )
526 	{
527 		DBG_ERROR( "svx::SdrTableObjImpl::DragEdge(), exception caught!" );
528 	}
529 }
530 
531 // -----------------------------------------------------------------------------
532 // XModifyListener
533 // -----------------------------------------------------------------------------
534 
535 void SAL_CALL SdrTableObjImpl::modified( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException)
536 {
537 	update();
538 }
539 
540 void SdrTableObjImpl::update()
541 {
542 	// source can be the table model itself or the assigned table template
543 	TableModelNotifyGuard aGuard( mxTable.get() );
544 	if( mpTableObj )
545 	{
546 		if( (maEditPos.mnRow >= getRowCount()) || (maEditPos.mnCol >= getColumnCount()) || (getCell( maEditPos ) != mxActiveCell) )
547 		{
548 			if(maEditPos.mnRow >= getRowCount())
549 				maEditPos.mnRow = getRowCount()-1;
550 
551 			if(maEditPos.mnCol >= getColumnCount())
552 				maEditPos.mnCol = getColumnCount()-1;
553 
554 			mpTableObj->setActiveCell( maEditPos );
555 		}
556 
557 		ApplyCellStyles();
558 
559 		mpTableObj->aRect = mpTableObj->maLogicRect;
560 		LayoutTable( mpTableObj->aRect, false, false );
561 
562 		mpTableObj->SetRectsDirty();
563 		mpTableObj->ActionChanged();
564 		mpTableObj->BroadcastObjectChange();
565 	}
566 }
567 
568 // -----------------------------------------------------------------------------
569 
570 void SdrTableObjImpl::connectTableStyle()
571 {
572 	if( mxTableStyle.is() )
573 	{
574 		Reference< XModifyBroadcaster > xBroadcaster( mxTableStyle, UNO_QUERY );
575 		if( xBroadcaster.is() )
576 		{
577 			Reference< XModifyListener > xListener( static_cast< ::com::sun::star::util::XModifyListener* >(this) );
578 			xBroadcaster->addModifyListener( xListener );
579 		}
580 	}
581 }
582 
583 // -----------------------------------------------------------------------------
584 
585 void SdrTableObjImpl::disconnectTableStyle()
586 {
587 	if( mxTableStyle.is() )
588 	{
589 		Reference< XModifyBroadcaster > xBroadcaster( mxTableStyle, UNO_QUERY );
590 		if( xBroadcaster.is() )
591 		{
592 			Reference< XModifyListener > xListener( static_cast< ::com::sun::star::util::XModifyListener* >(this) );
593 			xBroadcaster->removeModifyListener( xListener );
594 		}
595 	}
596 }
597 
598 // -----------------------------------------------------------------------------
599 
600 bool SdrTableObjImpl::isInUse()
601 {
602 	return mpTableObj && mpTableObj->IsInserted();
603 }
604 
605 // -----------------------------------------------------------------------------
606 // XEventListener
607 // -----------------------------------------------------------------------------
608 
609 void SAL_CALL SdrTableObjImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException)
610 {
611 	mxActiveCell.clear();
612 	mxTable.clear();
613 	if( mpLayouter )
614 	{
615 		delete mpLayouter;
616 		mpLayouter = 0;
617 	}
618 	mpTableObj = 0;
619 }
620 
621 // -----------------------------------------------------------------------------
622 
623 CellRef SdrTableObjImpl::getCell(  const CellPos& rPos  ) const
624 {
625 	CellRef xCell;
626 	if( mxTable.is() ) try
627 	{
628 		xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ).get() ) );
629 	}
630 	catch( Exception& )
631 	{
632 		DBG_ERROR( "svx::SdrTableObjImpl::getCell(), exception caught!" );
633 	}
634 	return xCell;
635 }
636 
637 // -----------------------------------------------------------------------------
638 
639 sal_Int32 SdrTableObjImpl::getColumnCount() const
640 {
641 	return mxTable.is() ? mxTable->getColumnCount() : 0;
642 }
643 
644 // -----------------------------------------------------------------------------
645 
646 sal_Int32 SdrTableObjImpl::getRowCount() const
647 {
648 	return mxTable.is() ? mxTable->getRowCount() : 0;
649 }
650 
651 // -----------------------------------------------------------------------------
652 
653 void SdrTableObjImpl::LayoutTable( Rectangle& rArea, bool bFitWidth, bool bFitHeight )
654 {
655 	if( mpLayouter && mpTableObj->GetModel() )
656 	{
657 		TableModelNotifyGuard aGuard( mxTable.get() );
658 		mpLayouter->LayoutTable( rArea, bFitWidth, bFitHeight );
659 	}
660 }
661 
662 // -----------------------------------------------------------------------------
663 
664 bool SdrTableObjImpl::UpdateWritingMode()
665 {
666 	if( mpTableObj && mpLayouter )
667 	{
668 		WritingMode eWritingMode = (WritingMode)static_cast< const SvxWritingModeItem& >( mpTableObj->GetObjectItem( SDRATTR_TEXTDIRECTION ) ).GetValue();
669 
670 		if( eWritingMode != WritingMode_TB_RL )
671 		{
672 			if( static_cast< const SvxFrameDirectionItem& >( mpTableObj->GetObjectItem( EE_PARA_WRITINGDIR ) ).GetValue() == FRMDIR_HORI_LEFT_TOP )
673 				eWritingMode = WritingMode_LR_TB;
674 			else
675 				eWritingMode = WritingMode_RL_TB;
676 		}
677 
678 		if( eWritingMode != mpLayouter->GetWritingMode() )
679 		{
680 			mpLayouter->SetWritingMode( eWritingMode );
681 			return true;
682 		}
683 	}
684 	return false;
685 }
686 
687 // -----------------------------------------------------------------------------
688 
689 void SdrTableObjImpl::UpdateCells( Rectangle& rArea )
690 {
691 	if( mpLayouter && mxTable.is() )
692 	{
693 		TableModelNotifyGuard aGuard( mxTable.get() );
694 		mpLayouter->updateCells( rArea );
695 		mxTable->setModified(sal_True);
696 	}
697 }
698 
699 // -----------------------------------------------------------------------------
700 
701 const SfxPoolItem* SdrTableObjImpl::GetCellItem( const CellPos& rPos, sal_uInt16 nWhich ) const
702 {
703 	CellRef xCell( getCell( rPos  ) );
704 	if( xCell.is() )
705 		return xCell->GetItemSet().GetItem( nWhich );
706 	else
707 		return 0;
708 }
709 
710 // -----------------------------------------------------------------------------
711 // BaseProperties section
712 // -----------------------------------------------------------------------------
713 
714 sdr::properties::BaseProperties* SdrTableObj::CreateObjectSpecificProperties()
715 {
716 	return new TableProperties(*this);
717 }
718 
719 // -----------------------------------------------------------------------------
720 // DrawContact section
721 // -----------------------------------------------------------------------------
722 
723 sdr::contact::ViewContact* SdrTableObj::CreateObjectSpecificViewContact()
724 {
725 	return new sdr::contact::ViewContactOfTableObj(*this);
726 }
727 
728 // --------------------------------------------------------------------
729 
730 TYPEINIT1(SdrTableObj,SdrTextObj);
731 
732 // --------------------------------------------------------------------
733 
734 SdrTableObj::SdrTableObj(SdrModel* _pModel)
735 {
736 	pModel = _pModel;
737 	init( 1, 1 );
738 }
739 
740 // --------------------------------------------------------------------
741 
742 SdrTableObj::SdrTableObj(SdrModel* _pModel, const ::Rectangle& rNewRect, sal_Int32 nColumns, sal_Int32 nRows)
743 : SdrTextObj( rNewRect )
744 , maLogicRect( rNewRect )
745 {
746 	pModel = _pModel;
747 
748 	if( nColumns <= 0 )
749 		nColumns = 1;
750 
751 	if( nRows <= 0 )
752 		nRows = 1;
753 
754 	init( nColumns, nRows );
755 }
756 
757 // --------------------------------------------------------------------
758 
759 void SdrTableObj::init( sal_Int32 nColumns, sal_Int32 nRows )
760 {
761 	bClosedObj = sal_True;
762 
763 	mpImpl = new SdrTableObjImpl;
764 	mpImpl->acquire();
765 	mpImpl->init( this, nColumns, nRows );
766 }
767 
768 // --------------------------------------------------------------------
769 
770 SdrTableObj::~SdrTableObj()
771 {
772 	mpImpl->dispose();
773 	mpImpl->release();
774 }
775 
776 // --------------------------------------------------------------------
777 // table stuff
778 // --------------------------------------------------------------------
779 
780 Reference< XTable > SdrTableObj::getTable() const
781 {
782 	return Reference< XTable >( mpImpl->mxTable.get() );
783 }
784 
785 // --------------------------------------------------------------------
786 
787 bool SdrTableObj::isValid( const CellPos& rPos ) const
788 {
789 	return (rPos.mnCol >= 0) && (rPos.mnCol < mpImpl->getColumnCount()) && (rPos.mnRow >= 0) && (rPos.mnRow < mpImpl->getRowCount());
790 }
791 
792 // --------------------------------------------------------------------
793 
794 CellPos SdrTableObj::getFirstCell() const
795 {
796 	return CellPos( 0,0 );
797 }
798 
799 // --------------------------------------------------------------------
800 
801 CellPos SdrTableObj::getLastCell() const
802 {
803 	CellPos aPos;
804 	if( mpImpl->mxTable.is() )
805 	{
806 		aPos.mnCol = mpImpl->getColumnCount()-1;
807 		aPos.mnRow = mpImpl->getRowCount()-1;
808 	}
809 	return aPos;
810 }
811 
812 // --------------------------------------------------------------------
813 
814 CellPos SdrTableObj::getLeftCell( const CellPos& rPos, bool bEdgeTravel ) const
815 {
816 	switch( GetWritingMode() )
817 	{
818 	default:
819 	case WritingMode_LR_TB:
820 		return getPreviousCell( rPos, bEdgeTravel );
821 	case WritingMode_RL_TB:
822 		return getNextCell( rPos, bEdgeTravel );
823 	case WritingMode_TB_RL:
824 		return getPreviousRow( rPos, bEdgeTravel );
825 	}
826 }
827 
828 // --------------------------------------------------------------------
829 
830 CellPos SdrTableObj::getRightCell( const CellPos& rPos, bool bEdgeTravel  ) const
831 {
832 	switch( GetWritingMode() )
833 	{
834 	default:
835 	case WritingMode_LR_TB:
836 		return getNextCell( rPos, bEdgeTravel );
837 	case WritingMode_RL_TB:
838 		return getPreviousCell( rPos, bEdgeTravel );
839 	case WritingMode_TB_RL:
840 		return getNextRow( rPos, bEdgeTravel );
841 	}
842 }
843 
844 // --------------------------------------------------------------------
845 
846 CellPos SdrTableObj::getUpCell( const CellPos& rPos, bool bEdgeTravel ) const
847 {
848 	switch( GetWritingMode() )
849 	{
850 	default:
851 	case WritingMode_LR_TB:
852 	case WritingMode_RL_TB:
853 		return getPreviousRow( rPos, bEdgeTravel );
854 	case WritingMode_TB_RL:
855 		return getPreviousCell( rPos, bEdgeTravel );
856 	}
857 }
858 
859 // --------------------------------------------------------------------
860 
861 CellPos SdrTableObj::getDownCell( const CellPos& rPos, bool bEdgeTravel ) const
862 {
863 	switch( GetWritingMode() )
864 	{
865 	default:
866 	case WritingMode_LR_TB:
867 	case WritingMode_RL_TB:
868 		return getNextRow( rPos, bEdgeTravel );
869 	case WritingMode_TB_RL:
870 		return getNextCell( rPos, bEdgeTravel );
871 	}
872 }
873 
874 // --------------------------------------------------------------------
875 
876 CellPos SdrTableObj::getPreviousCell( const CellPos& rPos, bool bEdgeTravel ) const
877 {
878 	CellPos aPos( rPos );
879 	if( mpImpl )
880 	{
881 		CellRef xCell( mpImpl->getCell( aPos ) );
882 		if( xCell.is() && xCell->isMerged() )
883 		{
884 			sal_Int32 nTemp = 0;
885 			findMergeOrigin( mpImpl->mxTable.get(), aPos.mnCol, aPos.mnRow, aPos.mnCol, nTemp );
886 		}
887 
888 		if( aPos.mnCol > 0 )
889 		{
890 			--aPos.mnCol;
891 		}
892 
893 		else if( bEdgeTravel && (aPos.mnRow > 0) )
894 		{
895 			aPos.mnCol = mpImpl->mxTable->getColumnCount()-1;
896 			--aPos.mnRow;
897 		}
898 	}
899 	return aPos;
900 }
901 
902 // --------------------------------------------------------------------
903 
904 CellPos SdrTableObj::getNextCell( const CellPos& rPos, bool bEdgeTravel ) const
905 {
906 	CellPos aPos( rPos );
907 	if( mpImpl )
908 	{
909 		CellRef xCell( mpImpl->getCell( aPos ) );
910 		if( xCell.is() )
911 		{
912 			if( xCell->isMerged() )
913 			{
914 				findMergeOrigin( mpImpl->mxTable, aPos.mnCol, aPos.mnRow, aPos.mnCol, aPos.mnRow );
915 
916 				xCell = mpImpl->getCell(aPos);
917 
918 				if( xCell.is() )
919 				{
920 					aPos.mnCol += xCell->getColumnSpan();
921 					aPos.mnRow = rPos.mnRow;
922 				}
923 			}
924 			else
925 			{
926 				aPos.mnCol += xCell->getColumnSpan();
927 			}
928 
929 			if( aPos.mnCol < mpImpl->mxTable->getColumnCount() )
930 				return aPos;
931 
932 			if( bEdgeTravel && ((aPos.mnRow + 1) < mpImpl->getRowCount()) )
933 			{
934 				aPos.mnCol = 0;
935 				aPos.mnRow += 1;
936 				return aPos;
937 			}
938 		}
939 	}
940 
941 	// last cell reached, no traveling possible
942 	return rPos;
943 }
944 
945 // --------------------------------------------------------------------
946 
947 CellPos SdrTableObj::getPreviousRow( const CellPos& rPos, bool bEdgeTravel ) const
948 {
949 	CellPos aPos( rPos );
950 	if( mpImpl )
951 	{
952 		CellRef xCell( mpImpl->getCell( aPos ) );
953 		if( xCell.is() )
954 		{
955 			if( xCell->isMerged() )
956 			{
957 				sal_Int32 nTemp = 0;
958 				findMergeOrigin( mpImpl->mxTable, aPos.mnCol, aPos.mnRow, nTemp, aPos.mnRow );
959 			}
960 		}
961 
962 		if( aPos.mnRow > 0 )
963 		{
964 			--aPos.mnRow;
965 		}
966 		else if( bEdgeTravel && (aPos.mnCol > 0) )
967 		{
968 			aPos.mnRow = mpImpl->mxTable->getRowCount()-1;
969 			--aPos.mnCol;
970 		}
971 	}
972 	return aPos;
973 }
974 
975 // --------------------------------------------------------------------
976 
977 CellPos SdrTableObj::getNextRow( const CellPos& rPos, bool bEdgeTravel ) const
978 {
979 	CellPos aPos( rPos );
980 
981 	if( mpImpl )
982 	{
983 		CellRef xCell( mpImpl->getCell( rPos ) );
984 		if( xCell.is() )
985 		{
986 			if( xCell->isMerged() )
987 			{
988 				findMergeOrigin( mpImpl->mxTable, aPos.mnCol, aPos.mnRow, aPos.mnCol, aPos.mnRow );
989 				xCell = mpImpl->getCell(aPos);
990 				aPos.mnCol = rPos.mnCol;
991 			}
992 
993 			if( xCell.is() )
994 				aPos.mnRow += xCell->getRowSpan();
995 
996 			if( aPos.mnRow < mpImpl->mxTable->getRowCount() )
997 				return aPos;
998 
999 			if( bEdgeTravel && (aPos.mnCol + 1) < mpImpl->mxTable->getColumnCount() )
1000 			{
1001 				aPos.mnRow = 0;
1002 				aPos.mnCol += 1;
1003 
1004 				while( aPos.mnCol < mpImpl->mxTable->getColumnCount() )
1005 				{
1006 					xCell = mpImpl->getCell( aPos );
1007 					if( xCell.is() && !xCell->isMerged() )
1008 						return aPos;
1009 					aPos.mnCol += 1;
1010 				}
1011 			}
1012 		}
1013 	}
1014 
1015 	// last position reached, no more traveling possible
1016 	return rPos;
1017 }
1018 
1019 // --------------------------------------------------------------------
1020 
1021 const TableStyleSettings& SdrTableObj::getTableStyleSettings() const
1022 {
1023 	if( mpImpl )
1024 	{
1025 		return mpImpl->maTableStyle;
1026 	}
1027 	else
1028 	{
1029 		static TableStyleSettings aTmp;
1030 		return aTmp;
1031 	}
1032 }
1033 
1034 // --------------------------------------------------------------------
1035 
1036 void SdrTableObj::setTableStyleSettings( const TableStyleSettings& rStyle )
1037 {
1038 	if( mpImpl )
1039 	{
1040 		mpImpl->maTableStyle = rStyle;
1041 		mpImpl->update();
1042 	}
1043 }
1044 
1045 // --------------------------------------------------------------------
1046 
1047 TableHitKind SdrTableObj::CheckTableHit( const Point& rPos, sal_Int32& rnX, sal_Int32& rnY, int nTol ) const
1048 {
1049 	if( !mpImpl || !mpImpl->mxTable.is() )
1050 		return SDRTABLEHIT_NONE;
1051 
1052 	rnX = 0;
1053 	rnY = 0;
1054 
1055 	const sal_Int32 nColCount = mpImpl->getColumnCount();
1056 	const sal_Int32 nRowCount = mpImpl->getRowCount();
1057 
1058 	sal_Int32 nX = rPos.X() + nTol - aRect.nLeft;
1059 	sal_Int32 nY = rPos.Y() + nTol - aRect.nTop;
1060 
1061 	if( (nX < 0) || (nX > (aRect.GetWidth() + nTol)) || (nY < 0) || (nY > (aRect.GetHeight() + nTol) ) )
1062 		return SDRTABLEHIT_NONE;
1063 
1064 	// get vertical edge number and check for a hit
1065 	const bool bRTL = GetWritingMode() == WritingMode_RL_TB;
1066 	bool bVrtHit = false;
1067 	if( nX >= 0 )
1068 	{
1069 		if( !bRTL )
1070 		{
1071 			while( rnX <= nColCount )
1072 			{
1073 				if( nX <= (2*nTol) )
1074 				{
1075 					bVrtHit = true;
1076 					break;
1077 				}
1078 
1079 				if( rnX == nColCount )
1080 					break;
1081 
1082 				nX -= mpImpl->mpLayouter->getColumnWidth( rnX );
1083 				if( nX < 0 )
1084 					break;
1085 				rnX++;
1086 			}
1087 		}
1088 		else
1089 		{
1090 			rnX = nColCount;
1091 			while( rnX >= 0 )
1092 			{
1093 				if( nX <= (2*nTol) )
1094 				{
1095 					bVrtHit = true;
1096 					break;
1097 				}
1098 
1099 				if( rnX == 0 )
1100 					break;
1101 
1102 				rnX--;
1103 				nX -= mpImpl->mpLayouter->getColumnWidth( rnX );
1104 				if( nX < 0 )
1105 					break;
1106 			}
1107 		}
1108 	}
1109 
1110 	// rnX is now the edge number left to the pointer, if it was hit bHrzHit is also true
1111 
1112 	// get vertical edge number and check for a hit
1113 	bool bHrzHit = false;
1114 	if( nY >= 0 )
1115 	{
1116 		while( rnY <= nRowCount )
1117 		{
1118 			if( nY <= (2*nTol) )
1119 			{
1120 				bHrzHit = true;
1121 				break;
1122 			}
1123 
1124 			if( rnY == nRowCount )
1125 				break;
1126 
1127 			nY -= mpImpl->mpLayouter->getRowHeight(rnY);
1128 			if( nY < 0 )
1129 				break;
1130 			rnY++;
1131 		}
1132 	}
1133 
1134 	// rnY is now the edge number above the pointer, if it was hit bVrtHit is also true
1135 
1136 	if( bVrtHit && mpImpl->mpLayouter->isEdgeVisible( rnX, rnY, false ) )
1137 		return SDRTABLEHIT_VERTICAL_BORDER;
1138 
1139 	if( bHrzHit && mpImpl->mpLayouter->isEdgeVisible( rnX, rnY, true ) )
1140 		return SDRTABLEHIT_HORIZONTAL_BORDER;
1141 
1142 	CellRef xCell( mpImpl->getCell( CellPos( rnX, rnY ) ) );
1143 	if( xCell.is() && xCell->isMerged() )
1144 		findMergeOrigin( mpImpl->mxTable.get(), rnX, rnY, rnX, rnY );
1145 
1146 	if( xCell.is() )
1147 	{
1148 		nX += mpImpl->mpLayouter->getColumnWidth( rnX );
1149 		if( nX < xCell->GetTextLeftDistance() )
1150 			return SDRTABLEHIT_CELL;
1151 	}
1152 
1153 	return SDRTABLEHIT_CELLTEXTAREA;
1154 }
1155 
1156 const SfxItemSet& SdrTableObj::GetActiveCellItemSet() const
1157 {
1158 	return getActiveCell()->GetItemSet();
1159 }
1160 
1161 // --------------------------------------------------------------------
1162 
1163 void SdrTableObj::InsertRows( sal_Int32 nIndex, sal_Int32 nCount /*= 1*/ )
1164 {
1165 	if( mpImpl->mxTable.is() ) try
1166 	{
1167 		Reference< XTableRows > xRows( mpImpl->mxTable->getRows(), UNO_QUERY_THROW );
1168 		xRows->insertByIndex( nIndex, nCount );
1169 	}
1170 	catch( Exception& )
1171 	{
1172 		DBG_ERROR("SdrTableObj::InsertRows(), exception caught!");
1173 	}
1174 }
1175 
1176 // --------------------------------------------------------------------
1177 
1178 void SdrTableObj::InsertColumns( sal_Int32 nIndex, sal_Int32 nCount /*= 1*/ )
1179 {
1180 	if( mpImpl->mxTable.is() ) try
1181 	{
1182 		Reference< XTableColumns > xColumns( mpImpl->mxTable->getColumns(), UNO_QUERY_THROW );
1183 		xColumns->insertByIndex( nIndex, nCount );
1184 	}
1185 	catch( Exception& )
1186 	{
1187 		DBG_ERROR("SdrTableObj::InsertColumns(), exception caught!");
1188 	}
1189 }
1190 
1191 // --------------------------------------------------------------------
1192 
1193 void SdrTableObj::DeleteRows( sal_Int32 nIndex, sal_Int32 nCount /*= 1*/ )
1194 {
1195 	if( mpImpl->mxTable.is() ) try
1196 	{
1197 		Reference< XTableRows > xRows( mpImpl->mxTable->getRows(), UNO_QUERY_THROW );
1198 		xRows->removeByIndex( nIndex, nCount );
1199 	}
1200 	catch( Exception& )
1201 	{
1202 		DBG_ERROR("SdrTableObj::DeleteRows(), exception caught!");
1203 	}
1204 }
1205 
1206 // --------------------------------------------------------------------
1207 
1208 void SdrTableObj::DeleteColumns( sal_Int32 nIndex, sal_Int32 nCount /*= 1*/ )
1209 {
1210 	if( mpImpl->mxTable.is() ) try
1211 	{
1212 		Reference< XTableColumns > xColumns( mpImpl->mxTable->getColumns(), UNO_QUERY_THROW );
1213 		xColumns->removeByIndex( nIndex, nCount );
1214 	}
1215 	catch( Exception& )
1216 	{
1217 		DBG_ERROR("SdrTableObj::DeleteColumns(), exception caught!");
1218 	}
1219 }
1220 
1221 // --------------------------------------------------------------------
1222 
1223 void SdrTableObj::setTableStyle( const Reference< XIndexAccess >& xTableStyle )
1224 {
1225 	if( mpImpl && (mpImpl->mxTableStyle != xTableStyle) )
1226 	{
1227 		mpImpl->disconnectTableStyle();
1228 		mpImpl->mxTableStyle = xTableStyle;
1229 		mpImpl->connectTableStyle();
1230 		mpImpl->update();
1231 	}
1232 }
1233 
1234 // --------------------------------------------------------------------
1235 
1236 const Reference< XIndexAccess >& SdrTableObj::getTableStyle() const
1237 {
1238 	if( mpImpl )
1239 	{
1240 		return mpImpl->mxTableStyle;
1241 	}
1242 	else
1243 	{
1244 		static Reference< XIndexAccess > aTmp;
1245 		return aTmp;
1246 	}
1247 }
1248 
1249 // --------------------------------------------------------------------
1250 // text stuff
1251 // --------------------------------------------------------------------
1252 
1253 /** returns the currently active text. */
1254 SdrText* SdrTableObj::getActiveText() const
1255 {
1256 	return dynamic_cast< SdrText* >( getActiveCell().get() );
1257 }
1258 
1259 // --------------------------------------------------------------------
1260 
1261 /** returns the nth available text. */
1262 SdrText* SdrTableObj::getText( sal_Int32 nIndex ) const
1263 {
1264 	if( mpImpl->mxTable.is() )
1265 	{
1266 		const sal_Int32 nColCount = mpImpl->getColumnCount();
1267 		if( nColCount )
1268 		{
1269 			CellPos aPos( nIndex % nColCount, nIndex / nColCount );
1270 
1271 			CellRef xCell( mpImpl->getCell( aPos ) );
1272 			return dynamic_cast< SdrText* >( xCell.get() );
1273 		}
1274 	}
1275 	return 0;
1276 }
1277 
1278 // --------------------------------------------------------------------
1279 
1280 /** returns the number of texts available for this object. */
1281 sal_Int32 SdrTableObj::getTextCount() const
1282 {
1283 	if( mpImpl->mxTable.is() )
1284 	{
1285 		const sal_Int32 nColCount = mpImpl->getColumnCount();
1286 		const sal_Int32 nRowCount = mpImpl->getRowCount();
1287 
1288 		return nColCount * nRowCount;
1289 	}
1290 	else
1291 	{
1292 		return 0;
1293 	}
1294 }
1295 
1296 // --------------------------------------------------------------------
1297 
1298 /** changes the current active text */
1299 void SdrTableObj::setActiveText( sal_Int32 nIndex )
1300 {
1301 	if( mpImpl && mpImpl->mxTable.is() )
1302 	{
1303 		const sal_Int32 nColCount = mpImpl->mxTable->getColumnCount();
1304 		if( nColCount )
1305 		{
1306 			CellPos aPos( nIndex % nColCount, nIndex / nColCount );
1307 			if( isValid( aPos ) )
1308 				setActiveCell( aPos );
1309 		}
1310 	}
1311 }
1312 
1313 // --------------------------------------------------------------------
1314 
1315 /** returns the index of the text that contains the given point or -1 */
1316 sal_Int32 SdrTableObj::CheckTextHit(const Point& rPnt) const
1317 {
1318 	if( mpImpl && mpImpl->mxTable.is() )
1319 	{
1320 		CellPos aPos;
1321 		if( CheckTableHit( rPnt, aPos.mnCol, aPos.mnRow, 0 ) == SDRTABLEHIT_CELLTEXTAREA )
1322 			return aPos.mnRow * mpImpl->mxTable->getColumnCount() + aPos.mnCol;
1323 	}
1324 
1325 	return 0;
1326 }
1327 
1328 // --------------------------------------------------------------------
1329 
1330 SdrOutliner* SdrTableObj::GetCellTextEditOutliner( const Cell& rCell ) const
1331 {
1332 	if( mpImpl && (mpImpl->getCell( mpImpl->maEditPos ).get() == &rCell) )
1333 		return pEdtOutl;
1334 	else
1335 		return 0;
1336 }
1337 
1338 
1339 // --------------------------------------------------------------------
1340 
1341 const TableLayouter& SdrTableObj::getTableLayouter() const
1342 {
1343 	OSL_ENSURE(mpImpl && mpImpl->mpLayouter, "getTableLayouter() error: no mpImpl or mpLayouter (!)");
1344 	return *(mpImpl->mpLayouter);
1345 }
1346 
1347 // --------------------------------------------------------------------
1348 
1349 void SdrTableObj::FitFrameToTextSize()
1350 {
1351 	// todo
1352 }
1353 
1354 // --------------------------------------------------------------------
1355 
1356 FASTBOOL SdrTableObj::IsAutoGrowHeight() const
1357 {
1358 	return sal_True;
1359 }
1360 
1361 // --------------------------------------------------------------------
1362 
1363 FASTBOOL SdrTableObj::IsAutoGrowWidth() const
1364 {
1365 	return sal_True;
1366 }
1367 
1368 // --------------------------------------------------------------------
1369 
1370 bool SdrTableObj::HasText() const
1371 {
1372 	return true;
1373 }
1374 
1375 // --------------------------------------------------------------------
1376 
1377 bool SdrTableObj::IsTextEditActive( const CellPos& rPos )
1378 {
1379 	return pEdtOutl && mpImpl && (rPos == mpImpl->maEditPos);
1380 }
1381 
1382 // --------------------------------------------------------------------
1383 
1384 void SdrTableObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
1385 {
1386 	if( (pEditStatus->GetStatusWord() & EE_STAT_TEXTHEIGHTCHANGED) && mpImpl && mpImpl->mpLayouter )
1387 	{
1388 		Rectangle aRect0( aRect );
1389 		aRect = maLogicRect;
1390 //		mpImpl->mpLayouter->setRowHeight( mpImpl->maEditPos.mnRow, mpImpl->mnSavedEditRowHeight );
1391 		mpImpl->LayoutTable( aRect, false, false );
1392 		SetRectsDirty();
1393 		ActionChanged();
1394 		BroadcastObjectChange();
1395 		if( aRect0 != aRect )
1396 			SendUserCall(SDRUSERCALL_RESIZE,aRect0);
1397 	}
1398 }
1399 
1400 // --------------------------------------------------------------------
1401 
1402 void SdrTableObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
1403 {
1404 	rInfo.bResizeFreeAllowed=sal_True;
1405 	rInfo.bResizePropAllowed=sal_True;
1406 	rInfo.bRotateFreeAllowed=sal_False;
1407 	rInfo.bRotate90Allowed  =sal_False;
1408 	rInfo.bMirrorFreeAllowed=sal_False;
1409 	rInfo.bMirror45Allowed  =sal_False;
1410 	rInfo.bMirror90Allowed  =sal_False;
1411 
1412 	// allow transparence
1413 	rInfo.bTransparenceAllowed = sal_True;
1414 
1415 	// gradient depends on fillstyle
1416 	XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue();
1417 	rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
1418 	rInfo.bShearAllowed     =sal_False;
1419 	rInfo.bEdgeRadiusAllowed=sal_False;
1420 	rInfo.bCanConvToPath    =sal_False;
1421 	rInfo.bCanConvToPoly    =sal_False;
1422 	rInfo.bCanConvToPathLineToArea=sal_False;
1423 	rInfo.bCanConvToPolyLineToArea=sal_False;
1424 	rInfo.bCanConvToContour = sal_False;
1425 }
1426 
1427 // --------------------------------------------------------------------
1428 
1429 sal_uInt16 SdrTableObj::GetObjIdentifier() const
1430 {
1431 	return static_cast<sal_uInt16>(OBJ_TABLE);
1432 }
1433 
1434 // --------------------------------------------------------------------
1435 
1436 void SdrTableObj::SetPage(SdrPage* pNewPage)
1437 {
1438 	SdrTextObj::SetPage(pNewPage);
1439 }
1440 
1441 // --------------------------------------------------------------------
1442 
1443 void SdrTableObj::SetModel(SdrModel* pNewModel)
1444 {
1445 	SdrModel* pOldModel = GetModel();
1446 	if( pNewModel != pOldModel )
1447 	{
1448 		SdrTextObj::SetModel(pNewModel);
1449 
1450 		if( mpImpl )
1451 		{
1452 			mpImpl->SetModel( pOldModel, pNewModel );
1453 
1454 			if( !maLogicRect.IsEmpty() )
1455 			{
1456 				aRect = maLogicRect;
1457 				mpImpl->LayoutTable( aRect, false, false );
1458 			}
1459 		}
1460 	}
1461 }
1462 
1463 // --------------------------------------------------------------------
1464 
1465 void SdrTableObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, Rectangle* pAnchorRect, sal_Bool bLineWidth ) const
1466 {
1467 	if( mpImpl )
1468 		TakeTextRect( mpImpl->maEditPos, rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth );
1469 }
1470 
1471 // --------------------------------------------------------------------
1472 
1473 void SdrTableObj::TakeTextRect( const CellPos& rPos, SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, Rectangle* pAnchorRect, sal_Bool /*bLineWidth*/ ) const
1474 {
1475 	if( !mpImpl )
1476 		return;
1477 
1478 	CellRef xCell( mpImpl->getCell( rPos ) );
1479 	if( !xCell.is() )
1480 		return;
1481 
1482 	Rectangle aAnkRect;
1483 	TakeTextAnchorRect( rPos, aAnkRect );
1484 
1485 	SdrTextVertAdjust eVAdj=xCell->GetTextVerticalAdjust();
1486 //	SdrTextHorzAdjust eHAdj=xCell->GetTextHorizontalAdjust();
1487 
1488 	sal_uIntPtr nStat0=rOutliner.GetControlWord();
1489 	Size aNullSize;
1490 	nStat0 |= EE_CNTRL_AUTOPAGESIZE;
1491 	rOutliner.SetControlWord(nStat0);
1492 	rOutliner.SetMinAutoPaperSize(aNullSize);
1493 	rOutliner.SetMaxAutoPaperSize(aAnkRect.GetSize());
1494 	rOutliner.SetPaperSize(aAnkRect.GetSize());
1495 
1496 	// #103516# New try with _BLOCK for hor and ver after completely
1497 	// supporting full width for vertical text.
1498 //	if( SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
1499 //	{
1500 		rOutliner.SetMinAutoPaperSize(Size(aAnkRect.GetWidth(), 0));
1501 //	}
1502 //	else if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
1503 //	{
1504 //		rOutliner.SetMinAutoPaperSize(Size(0, aAnkRect.GetHeight()));
1505 //	}
1506 
1507 	// ---
1508 
1509 	// set text at outliner, maybe from edit outliner
1510 	OutlinerParaObject* pPara= xCell->GetOutlinerParaObject();
1511 	if (pEdtOutl && !bNoEditText && mpImpl->mxActiveCell == xCell )
1512 		pPara=pEdtOutl->CreateParaObject();
1513 
1514 	if (pPara)
1515 	{
1516 		const bool bHitTest = pModel && (&pModel->GetHitTestOutliner() == &rOutliner);
1517 
1518 		const SdrTextObj* pTestObj = rOutliner.GetTextObj();
1519 		if( !pTestObj || !bHitTest || (pTestObj != this) || (pTestObj->GetOutlinerParaObject() != xCell->GetOutlinerParaObject()) )
1520 		{
1521 			if( bHitTest ) // #i33696# take back fix #i27510#
1522 				rOutliner.SetTextObj( this );
1523 
1524 			rOutliner.SetUpdateMode(sal_True);
1525 			rOutliner.SetText(*pPara);
1526 		}
1527 	}
1528 	else
1529 	{
1530 		rOutliner.SetTextObj( NULL );
1531 	}
1532 
1533 	if (pEdtOutl && !bNoEditText && pPara && mpImpl->mxActiveCell == xCell )
1534 		delete pPara;
1535 
1536 	rOutliner.SetUpdateMode(sal_True);
1537 	rOutliner.SetControlWord(nStat0);
1538 
1539 	Point aTextPos(aAnkRect.TopLeft());
1540 	Size aTextSiz(rOutliner.GetPaperSize());
1541 /*
1542 	if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
1543 	{
1544 		long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
1545 		if (eHAdj==SDRTEXTHORZADJUST_CENTER)
1546 			aTextPos.X()+=nFreeWdt/2;
1547 		if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
1548 			aTextPos.X()+=nFreeWdt;
1549 	}
1550 */
1551 	if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
1552 	{
1553 		long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
1554 		if (eVAdj==SDRTEXTVERTADJUST_CENTER)
1555 			aTextPos.Y()+=nFreeHgt/2;
1556 		if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
1557 			aTextPos.Y()+=nFreeHgt;
1558 	}
1559 
1560 	if (pAnchorRect)
1561 		*pAnchorRect=aAnkRect;
1562 
1563 	rTextRect=Rectangle(aTextPos,aTextSiz);
1564 }
1565 
1566 // --------------------------------------------------------------------
1567 
1568 const CellRef& SdrTableObj::getActiveCell() const
1569 {
1570 	if( mpImpl )
1571 	{
1572 		if( !mpImpl->mxActiveCell.is() )
1573 		{
1574 			CellPos aPos;
1575 			const_cast< SdrTableObj* >(this)->setActiveCell( aPos );
1576 		}
1577 		return mpImpl->mxActiveCell;
1578 	}
1579 	else
1580 	{
1581 		static CellRef xCell;
1582 		return xCell;
1583 	}
1584 }
1585 
1586 // --------------------------------------------------------------------
1587 
1588 sal_Int32 SdrTableObj::getRowCount() const
1589 {
1590 	return mpImpl ? mpImpl->getRowCount() : 0;
1591 }
1592 
1593 // --------------------------------------------------------------------
1594 
1595 sal_Int32 SdrTableObj::getColumnCount() const
1596 {
1597 	return mpImpl ? mpImpl->getColumnCount() : 0;
1598 }
1599 
1600 // --------------------------------------------------------------------
1601 
1602 void SdrTableObj::setActiveCell( const CellPos& rPos )
1603 {
1604 	if( mpImpl && mpImpl->mxTable.is() ) try
1605 	{
1606 		mpImpl->mxActiveCell.set( dynamic_cast< Cell* >( mpImpl->mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ).get() ) );
1607 		if( mpImpl->mxActiveCell.is() && mpImpl->mxActiveCell->isMerged() )
1608 		{
1609 			CellPos aOrigin;
1610 			findMergeOrigin( mpImpl->mxTable.get(), rPos.mnCol, rPos.mnRow, aOrigin.mnCol, aOrigin.mnRow );
1611 			mpImpl->mxActiveCell.set( dynamic_cast< Cell* >( mpImpl->mxTable->getCellByPosition( aOrigin.mnCol, aOrigin.mnRow ).get() ) );
1612 			mpImpl->maEditPos = aOrigin;
1613 		}
1614 		else
1615 		{
1616 			mpImpl->maEditPos = rPos;
1617 		}
1618 	}
1619 	catch( Exception& )
1620 	{
1621 		DBG_ERROR("SdrTableObj::setActiveCell(), exception caught!");
1622 	}
1623 }
1624 
1625 // --------------------------------------------------------------------
1626 
1627 void SdrTableObj::getActiveCellPos( CellPos& rPos ) const
1628 {
1629 	rPos = mpImpl->maEditPos;
1630 }
1631 
1632 // --------------------------------------------------------------------
1633 
1634 void SdrTableObj::getCellBounds( const CellPos& rPos, ::Rectangle& rCellRect )
1635 {
1636 	if( mpImpl )
1637 	{
1638 		CellRef xCell( mpImpl->getCell( rPos ) );
1639 		if( xCell.is() )
1640 			rCellRect = xCell->getCellRect();
1641 	}
1642 }
1643 
1644 // --------------------------------------------------------------------
1645 
1646 void SdrTableObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
1647 {
1648 	if( mpImpl )
1649 		TakeTextAnchorRect( mpImpl->maEditPos, rAnchorRect );
1650 }
1651 
1652 // --------------------------------------------------------------------
1653 
1654 void SdrTableObj::TakeTextAnchorRect( const CellPos& rPos, Rectangle& rAnchorRect ) const
1655 {
1656 	Rectangle aAnkRect(aRect);
1657 
1658 	if( mpImpl )
1659 	{
1660 		CellRef xCell( mpImpl->getCell( rPos ) );
1661 		if( xCell.is() )
1662 			xCell->TakeTextAnchorRect( aAnkRect );
1663 	}
1664 
1665 	ImpJustifyRect(aAnkRect);
1666 	rAnchorRect=aAnkRect;
1667 }
1668 
1669 // --------------------------------------------------------------------
1670 
1671 void SdrTableObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
1672 {
1673 	if( mpImpl )
1674 		TakeTextEditArea( mpImpl->maEditPos, pPaperMin, pPaperMax, pViewInit, pViewMin );
1675 }
1676 
1677 // --------------------------------------------------------------------
1678 
1679 void SdrTableObj::TakeTextEditArea( const CellPos& rPos, Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin ) const
1680 {
1681 	Size aPaperMin,aPaperMax;
1682 	Rectangle aViewInit;
1683 	TakeTextAnchorRect( rPos, aViewInit );
1684 
1685 	Size aAnkSiz(aViewInit.GetSize());
1686 	aAnkSiz.Width()--; aAnkSiz.Height()--; // weil GetSize() ein draufaddiert
1687 
1688 	Size aMaxSiz(aAnkSiz.Width(),1000000);
1689 	if (pModel!=NULL)
1690 	{
1691 		Size aTmpSiz(pModel->GetMaxObjSize());
1692 		if (aTmpSiz.Height()!=0)
1693 			aMaxSiz.Height()=aTmpSiz.Height();
1694 	}
1695 
1696 	CellRef xCell( mpImpl->getCell( rPos ) );
1697 	SdrTextVertAdjust eVAdj = xCell.is() ? xCell->GetTextVerticalAdjust() : SDRTEXTVERTADJUST_TOP;
1698 //	SdrTextHorzAdjust eHAdj = xCell.is() ? xCell->GetTextHorizontalAdjust() : SDRTEXTHORZADJUST_LEFT;
1699 
1700 	aPaperMax=aMaxSiz;
1701 
1702 //	if((SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) || (SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()))
1703 		aPaperMin.Width() = aAnkSiz.Width();
1704 
1705 	if (pViewMin!=NULL)
1706 	{
1707 		*pViewMin=aViewInit;
1708 /*
1709 		long nXFree=aAnkSiz.Width()-aPaperMin.Width();
1710 
1711 		if (eHAdj==SDRTEXTHORZADJUST_LEFT)
1712 		{
1713 			pViewMin->Right()-=nXFree;
1714 		}
1715 		else if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
1716 		{
1717 			pViewMin->Left()+=nXFree;
1718 		}
1719 		else
1720 		{
1721 			pViewMin->Left()+=nXFree/2;
1722 			pViewMin->Right()=pViewMin->Left()+aPaperMin.Width();
1723 		}
1724 */
1725 		long nYFree=aAnkSiz.Height()-aPaperMin.Height();
1726 
1727 		if (eVAdj==SDRTEXTVERTADJUST_TOP)
1728 		{
1729 			pViewMin->Bottom()-=nYFree;
1730 		}
1731 		else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
1732 		{
1733 			pViewMin->Top()+=nYFree;
1734 		}
1735 		else
1736 		{
1737 			pViewMin->Top()+=nYFree/2;
1738 			pViewMin->Bottom()=pViewMin->Top()+aPaperMin.Height();
1739 		}
1740 	}
1741 
1742 
1743 	if(IsVerticalWriting())
1744 		aPaperMin.Width() = 0;
1745 	else
1746 		aPaperMin.Height() = 0;
1747 
1748 	if (pPaperMin!=NULL) *pPaperMin=aPaperMin;
1749 	if (pPaperMax!=NULL) *pPaperMax=aPaperMax;
1750 	if (pViewInit!=NULL) *pViewInit=aViewInit;
1751 }
1752 
1753 // --------------------------------------------------------------------
1754 
1755 sal_uInt16 SdrTableObj::GetOutlinerViewAnchorMode() const
1756 {
1757 	EVAnchorMode eRet=ANCHOR_TOP_LEFT;
1758 	CellRef xCell( getActiveCell() );
1759 	if( xCell.is() )
1760 	{
1761 		SdrTextVertAdjust eV=xCell->GetTextVerticalAdjust();
1762 //		SdrTextHorzAdjust eH=xCell->GetTextHorizontalAdjust();
1763 
1764 //		if (eH==SDRTEXTHORZADJUST_LEFT)
1765 		{
1766 			if (eV==SDRTEXTVERTADJUST_TOP)
1767 			{
1768 				eRet=ANCHOR_TOP_LEFT;
1769 			}
1770 			else if (eV==SDRTEXTVERTADJUST_BOTTOM)
1771 			{
1772 				eRet=ANCHOR_BOTTOM_LEFT;
1773 			}
1774 			else
1775 			{
1776 				eRet=ANCHOR_VCENTER_LEFT;
1777 			}
1778 		}
1779 /*
1780 		else if (eH==SDRTEXTHORZADJUST_RIGHT)
1781 		{
1782 			if (eV==SDRTEXTVERTADJUST_TOP)
1783 			{
1784 				eRet=ANCHOR_TOP_RIGHT;
1785 			}
1786 			else if (eV==SDRTEXTVERTADJUST_BOTTOM)
1787 			{
1788 				eRet=ANCHOR_BOTTOM_RIGHT;
1789 			}
1790 			else
1791 			{
1792 				eRet=ANCHOR_VCENTER_RIGHT;
1793 			}
1794 		}
1795 		else
1796 		{
1797 			if (eV==SDRTEXTVERTADJUST_TOP)
1798 			{
1799 				eRet=ANCHOR_TOP_HCENTER;
1800 			}
1801 			else if (eV==SDRTEXTVERTADJUST_BOTTOM)
1802 			{
1803 				eRet=ANCHOR_BOTTOM_HCENTER;
1804 			}
1805 			else
1806 			{
1807 				eRet=ANCHOR_VCENTER_HCENTER;
1808 			}
1809 		}
1810 */
1811 	}
1812 	return (sal_uInt16)eRet;
1813 }
1814 
1815 // --------------------------------------------------------------------
1816 
1817 OutlinerParaObject* SdrTableObj::GetEditOutlinerParaObject() const
1818 {
1819 	return SdrTextObj::GetEditOutlinerParaObject();
1820 }
1821 
1822 // --------------------------------------------------------------------
1823 
1824 SdrOutliner* SdrTableObj::GetCellTextEditOutliner( const CellPos& rPos ) const
1825 {
1826 	if( pEdtOutl && mpImpl && (mpImpl->maEditPos == rPos) )
1827 		return pEdtOutl;
1828 	else
1829 		return 0;
1830 }
1831 
1832 // --------------------------------------------------------------------
1833 
1834 struct ImplTableShadowPaintInfo
1835 {
1836 	Color maShadowColor;
1837 	sal_uInt32 mnXDistance;
1838 	sal_uInt32 mnYDistance;
1839 	sal_uInt16 mnShadowTransparence;
1840 
1841 	ImplTableShadowPaintInfo( const SfxItemSet& rSet )
1842 	{
1843         const SdrShadowColorItem& rShadColItem = ((const SdrShadowColorItem&)(rSet.Get(SDRATTR_SHADOWCOLOR)));
1844         maShadowColor = rShadColItem.GetColorValue();
1845         mnShadowTransparence = ((const SdrShadowTransparenceItem&)(rSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue();
1846 
1847 		mnXDistance = ((SdrShadowXDistItem&)(rSet.Get(SDRATTR_SHADOWXDIST))).GetValue();
1848 		mnYDistance = ((SdrShadowYDistItem&)(rSet.Get(SDRATTR_SHADOWYDIST))).GetValue();
1849 	}
1850 };
1851 
1852 // --------------------------------------------------------------------
1853 
1854 void lcl_VertLineEnds( OutputDevice& rDev, const Point& rTop, const Point& rBottom,
1855         const Color& rColor, long nXOffs, long nWidth,
1856         const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine )
1857 {
1858     rDev.SetLineColor(rColor);              // PEN_NULL ???
1859     rDev.SetFillColor(rColor);
1860 
1861 	//	Position oben/unten muss unabhaengig von der Liniendicke sein,
1862 	//	damit der Winkel stimmt (oder X-Position auch anpassen)
1863 	long nTopPos = rTop.Y();
1864 	long nBotPos = rBottom.Y();
1865 
1866     long nTopLeft = rTop.X() + nXOffs;
1867     long nTopRight = nTopLeft + nWidth - 1;
1868 
1869     long nBotLeft = rBottom.X() + nXOffs;
1870     long nBotRight = nBotLeft + nWidth - 1;
1871 
1872 	//	oben abschliessen
1873 
1874     if ( rTopLine.Prim() )
1875 	{
1876         long nLineW = rTopLine.GetWidth();
1877         if (nLineW >= 2)
1878 		{
1879 			Point aTriangle[3];
1880 			aTriangle[0] = Point( nTopLeft, nTopPos );		// wie aPoints[0]
1881 			aTriangle[1] = Point( nTopRight, nTopPos );		// wie aPoints[1]
1882             aTriangle[2] = Point( rTop.X(), nTopPos - (nLineW - 1) / 2 );
1883 			Polygon aTriPoly( 3, aTriangle );
1884             rDev.DrawPolygon( aTriPoly );
1885 		}
1886 	}
1887 
1888 	//	unten abschliessen
1889 
1890     if ( rBottomLine.Prim() )
1891 	{
1892         long nLineW = rBottomLine.GetWidth();
1893         if (nLineW >= 2)
1894 		{
1895 			Point aTriangle[3];
1896 			aTriangle[0] = Point( nBotLeft, nBotPos );		// wie aPoints[3]
1897 			aTriangle[1] = Point( nBotRight, nBotPos );		// wie aPoints[2]
1898             aTriangle[2] = Point( rBottom.X(), nBotPos - (nLineW - 1) / 2 + nLineW - 1 );
1899 			Polygon aTriPoly( 3, aTriangle );
1900             rDev.DrawPolygon( aTriPoly );
1901 		}
1902 	}
1903 }
1904 
1905 void lcl_VertLine( OutputDevice& rDev, const Point& rTop, const Point& rBottom,
1906                     const svx::frame::Style& rLine,
1907                     const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine,
1908                     const Color* pForceColor )
1909 {
1910     if( rLine.Prim() )
1911     {
1912         svx::frame::DrawVerFrameBorderSlanted( rDev, rTop, rBottom, rLine, pForceColor );
1913 
1914         svx::frame::Style aScaled( rLine );
1915         aScaled.ScaleSelf( 1.0 / cos( svx::frame::GetVerDiagAngle( rTop, rBottom ) ) );
1916         if( pForceColor )
1917             aScaled.SetColor( *pForceColor );
1918 
1919         long nXOffs = (aScaled.GetWidth() - 1) / -2L;
1920 
1921         lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1922             nXOffs, aScaled.Prim(), rTopLine, rBottomLine );
1923 
1924         if( aScaled.Secn() )
1925             lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(),
1926                 nXOffs + aScaled.Prim() + aScaled.Dist(), aScaled.Secn(), rTopLine, rBottomLine );
1927     }
1928 }
1929 
1930 // --------------------------------------------------------------------
1931 
1932 void SdrTableObj::TakeObjNameSingul(XubString& rName) const
1933 {
1934 	rName = ImpGetResStr(STR_ObjNameSingulTable);
1935 
1936 	String aName( GetName() );
1937 	if(aName.Len())
1938 	{
1939 		rName += sal_Unicode(' ');
1940 		rName += sal_Unicode('\'');
1941 		rName += aName;
1942 		rName += sal_Unicode('\'');
1943 	}
1944 }
1945 
1946 // --------------------------------------------------------------------
1947 
1948 void SdrTableObj::TakeObjNamePlural(XubString& rName) const
1949 {
1950 	rName = ImpGetResStr(STR_ObjNamePluralTable);
1951 }
1952 
1953 // --------------------------------------------------------------------
1954 
1955 void SdrTableObj::operator=(const SdrObject& rObj)
1956 {
1957 	// call parent
1958 	SdrObject::operator=(rObj);
1959 
1960 	const SdrTableObj* pTableObj = dynamic_cast< const SdrTableObj* >( &rObj );
1961 	if (pTableObj!=NULL)
1962 	{
1963 		TableModelNotifyGuard aGuard( mpImpl ? mpImpl->mxTable.get() : 0 );
1964 
1965 		maLogicRect = pTableObj->maLogicRect;
1966 		aRect = pTableObj->aRect;
1967 		aGeo = pTableObj->aGeo;
1968 		eTextKind = pTableObj->eTextKind;
1969 		bTextFrame = pTableObj->bTextFrame;
1970 		aTextSize = pTableObj->aTextSize;
1971 		bTextSizeDirty = pTableObj->bTextSizeDirty;
1972 		bNoShear = pTableObj->bNoShear;
1973 		bNoRotate = pTableObj->bNoRotate;
1974 		bNoMirror = pTableObj->bNoMirror;
1975 		bDisableAutoWidthOnDragging = pTableObj->bDisableAutoWidthOnDragging;
1976 
1977 		if( pTableObj->mpImpl )
1978 			*mpImpl = *pTableObj->mpImpl;
1979 	}
1980 }
1981 
1982 // --------------------------------------------------------------------
1983 
1984 basegfx::B2DPolyPolygon SdrTableObj::TakeXorPoly() const
1985 {
1986 	return SdrTextObj::TakeXorPoly();
1987 }
1988 
1989 // --------------------------------------------------------------------
1990 
1991 basegfx::B2DPolyPolygon SdrTableObj::TakeContour() const
1992 {
1993 	return SdrTextObj::TakeContour();
1994 }
1995 
1996 // --------------------------------------------------------------------
1997 
1998 const Rectangle& SdrTableObj::GetSnapRect() const
1999 {
2000 	return aRect;
2001 }
2002 
2003 // --------------------------------------------------------------------
2004 
2005 void SdrTableObj::NbcSetSnapRect(const Rectangle& rRect)
2006 {
2007 	NbcSetLogicRect( rRect );
2008 }
2009 
2010 // --------------------------------------------------------------------
2011 
2012 const Rectangle& SdrTableObj::GetLogicRect() const
2013 {
2014 	return maLogicRect;
2015 }
2016 
2017 // --------------------------------------------------------------------
2018 
2019 void SdrTableObj::RecalcSnapRect()
2020 {
2021 }
2022 
2023 // --------------------------------------------------------------------
2024 
2025 sal_uInt32 SdrTableObj::GetSnapPointCount() const
2026 {
2027 	return SdrTextObj::GetSnapPointCount();
2028 }
2029 
2030 // --------------------------------------------------------------------
2031 
2032 
2033 Point SdrTableObj::GetSnapPoint(sal_uInt32 i) const
2034 {
2035 	return SdrTextObj::GetSnapPoint(i);
2036 }
2037 
2038 // --------------------------------------------------------------------
2039 
2040 sal_Bool SdrTableObj::BegTextEdit(SdrOutliner& rOutl)
2041 {
2042 	if( pEdtOutl != NULL )
2043 		return sal_False;
2044 
2045 	pEdtOutl=&rOutl;
2046 
2047 //	ForceOutlinerParaObject();
2048 
2049 	mbInEditMode = sal_True;
2050 
2051 	rOutl.Init( OUTLINERMODE_TEXTOBJECT );
2052 	rOutl.SetRefDevice( pModel->GetRefDevice() );
2053 
2054 // --
2055 		FASTBOOL bUpdMerk=rOutl.GetUpdateMode();
2056 		if (bUpdMerk) rOutl.SetUpdateMode(sal_False);
2057 		Size aPaperMin;
2058 		Size aPaperMax;
2059 		Rectangle aEditArea;
2060 		TakeTextEditArea(&aPaperMin,&aPaperMax,&aEditArea,NULL);
2061 
2062 		rOutl.SetMinAutoPaperSize(aPaperMin);
2063 		rOutl.SetMaxAutoPaperSize(aPaperMax);
2064 		rOutl.SetPaperSize(aPaperMax);
2065 
2066 		if (bUpdMerk) rOutl.SetUpdateMode(sal_True);
2067 //---
2068 
2069 	sal_uIntPtr nStat=rOutl.GetControlWord();
2070 //	nStat	&= ~EE_CNTRL_AUTOPAGESIZE;
2071 	nStat	|= EE_CNTRL_AUTOPAGESIZE;
2072 	nStat	&=~EE_CNTRL_STRETCHING;
2073 	rOutl.SetControlWord(nStat);
2074 
2075 	OutlinerParaObject* pPara = GetOutlinerParaObject();
2076 	if(pPara)
2077 		rOutl.SetText(*pPara);
2078 
2079 	rOutl.UpdateFields();
2080 	rOutl.ClearModifyFlag();
2081 
2082 //	mpImpl->mnSavedEditRowHeight = mpImpl->mpLayouter->getRowHeight( mpImpl->maEditPos.mnRow );
2083 
2084 	return sal_True;
2085 }
2086 
2087 // --------------------------------------------------------------------
2088 
2089 void SdrTableObj::EndTextEdit(SdrOutliner& rOutl)
2090 {
2091 	if(rOutl.IsModified())
2092 	{
2093 		if( GetModel() && GetModel()->IsUndoEnabled() )
2094 			GetModel()->AddUndo( GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*this) );
2095 
2096 		OutlinerParaObject* pNewText = 0;
2097 		Paragraph* p1stPara = rOutl.GetParagraph( 0 );
2098 		sal_uInt32 nParaAnz = rOutl.GetParagraphCount();
2099 
2100 		if(p1stPara)
2101 		{
2102 			if(nParaAnz == 1)
2103 			{
2104 				// if its only one paragraph, check if it is empty
2105 				XubString aStr(rOutl.GetText(p1stPara));
2106 
2107 				if(!aStr.Len())
2108 				{
2109 					// gotcha!
2110 					nParaAnz = 0;
2111 				}
2112 			}
2113 
2114 			// to remove the grey field background
2115 			rOutl.UpdateFields();
2116 
2117 			if(nParaAnz != 0)
2118 			{
2119 				// create new text object
2120 				pNewText = rOutl.CreateParaObject( 0, (sal_uInt16)nParaAnz );
2121 			}
2122 		}
2123 		SetOutlinerParaObject(pNewText);
2124 	}
2125 
2126 	pEdtOutl = 0;
2127 	rOutl.Clear();
2128 	sal_uInt32 nStat = rOutl.GetControlWord();
2129 	nStat &= ~EE_CNTRL_AUTOPAGESIZE;
2130 	rOutl.SetControlWord(nStat);
2131 
2132 	mbInEditMode = sal_False;
2133 }
2134 
2135 // --------------------------------------------------------------------
2136 
2137 OutlinerParaObject* SdrTableObj::GetOutlinerParaObject() const
2138 {
2139 	CellRef xCell( getActiveCell() );
2140 	if( xCell.is() )
2141 		return xCell->GetOutlinerParaObject();
2142 	else
2143 		return 0;
2144 }
2145 
2146 // --------------------------------------------------------------------
2147 
2148 void SdrTableObj::NbcSetOutlinerParaObject( OutlinerParaObject* pTextObject)
2149 {
2150 	CellRef xCell( getActiveCell() );
2151 	if( xCell.is() )
2152 	{
2153 		if( pModel )
2154 		{
2155 			// Update HitTestOutliner
2156 			const SdrTextObj* pTestObj = pModel->GetHitTestOutliner().GetTextObj();
2157 			if( pTestObj && pTestObj->GetOutlinerParaObject() == xCell->GetOutlinerParaObject() )
2158 				pModel->GetHitTestOutliner().SetTextObj( NULL );
2159 		}
2160 
2161 		xCell->SetOutlinerParaObject( pTextObject );
2162 
2163 		SetTextSizeDirty();
2164 		NbcAdjustTextFrameWidthAndHeight();
2165 //		ImpSetTextStyleSheetListeners();
2166 //		ImpCheckMasterCachable();
2167 	}
2168 }
2169 
2170 // --------------------------------------------------------------------
2171 
2172 void SdrTableObj::NbcSetLogicRect(const Rectangle& rRect)
2173 {
2174 	maLogicRect=rRect;
2175 	ImpJustifyRect(maLogicRect);
2176 	const bool bWidth = maLogicRect.getWidth() != aRect.getWidth();
2177 	const bool bHeight = maLogicRect.getHeight() != aRect.getHeight();
2178 	aRect=maLogicRect;
2179 	NbcAdjustTextFrameWidthAndHeight( !bHeight, !bWidth );
2180 	SetRectsDirty();
2181 }
2182 
2183 
2184 // --------------------------------------------------------------------
2185 
2186 void SdrTableObj::AdjustToMaxRect( const Rectangle& rMaxRect, bool /* bShrinkOnly = false */ )
2187 {
2188 	Rectangle aAdjustRect( rMaxRect );
2189 	aAdjustRect.setHeight( GetLogicRect().getHeight() );
2190 	SetLogicRect( aAdjustRect );
2191 }
2192 
2193 // --------------------------------------------------------------------
2194 
2195 void SdrTableObj::NbcMove(const Size& rSiz)
2196 {
2197 	MoveRect(maLogicRect,rSiz);
2198 	SdrTextObj::NbcMove( rSiz );
2199 	if( mpImpl )
2200 		mpImpl->UpdateCells( aRect );
2201 }
2202 
2203 // --------------------------------------------------------------------
2204 
2205 void SdrTableObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
2206 {
2207 	Rectangle aOldRect( maLogicRect );
2208 	ResizeRect(maLogicRect,rRef,xFact,yFact);
2209 
2210 	aRect = maLogicRect;
2211 	NbcAdjustTextFrameWidthAndHeight( maLogicRect.GetHeight() == aOldRect.GetHeight(), maLogicRect.GetWidth() == aOldRect.GetWidth() );
2212 	SetRectsDirty();
2213 }
2214 
2215 // --------------------------------------------------------------------
2216 
2217 FASTBOOL SdrTableObj::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt)
2218 {
2219 	Rectangle aNeuRect(maLogicRect);
2220 	FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt);
2221 	if (bRet)
2222 	{
2223 		Rectangle aBoundRect0;
2224 		if (pUserCall!=NULL)
2225 			aBoundRect0=GetLastBoundRect();
2226 		aRect=aNeuRect;
2227 		SetRectsDirty();
2228 		SetChanged();
2229 		BroadcastObjectChange();
2230 		SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
2231 	}
2232 	return bRet;
2233 }
2234 
2235 // --------------------------------------------------------------------
2236 
2237 FASTBOOL SdrTableObj::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHeight, FASTBOOL bWidth) const
2238 {
2239 	if((pModel == NULL) || rR.IsEmpty() || !mpImpl || !mpImpl->mxTable.is() )
2240 		return sal_False;
2241 
2242 	Rectangle aRectangle( rR );
2243 	mpImpl->LayoutTable( aRectangle, !bWidth, !bHeight );
2244 
2245 	if( aRectangle != rR )
2246 	{
2247 		rR = aRectangle;
2248 		return sal_True;
2249 	}
2250 	else
2251 	{
2252 		return sal_False;
2253 	}
2254 }
2255 
2256 // --------------------------------------------------------------------
2257 
2258 void SdrTableObj::NbcReformatText()
2259 {
2260 	NbcAdjustTextFrameWidthAndHeight();
2261 }
2262 
2263 // --------------------------------------------------------------------
2264 
2265 void SdrTableObj::ReformatText()
2266 {
2267 	Rectangle aBoundRect0;
2268 	if (pUserCall!=NULL)
2269 		aBoundRect0=GetLastBoundRect();
2270 	NbcReformatText();
2271 	SetChanged();
2272 	BroadcastObjectChange();
2273 	SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
2274 }
2275 
2276 // --------------------------------------------------------------------
2277 
2278 sal_Bool SdrTableObj::IsVerticalWriting() const
2279 {
2280 	const SvxWritingModeItem* pModeItem = dynamic_cast< const SvxWritingModeItem* >( &GetObjectItem( SDRATTR_TEXTDIRECTION ) );
2281 	return pModeItem && pModeItem->GetValue() == com::sun::star::text::WritingMode_TB_RL;
2282 }
2283 
2284 // --------------------------------------------------------------------
2285 
2286 void SdrTableObj::SetVerticalWriting(sal_Bool bVertical )
2287 {
2288 	if( bVertical != IsVerticalWriting() )
2289 	{
2290 		SvxWritingModeItem aModeItem( com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION );
2291 		SetObjectItem( aModeItem );
2292 	}
2293 }
2294 
2295 // --------------------------------------------------------------------
2296 
2297 WritingMode SdrTableObj::GetWritingMode() const
2298 {
2299 	WritingMode eMode = WritingMode_LR_TB;
2300 	if( mpImpl && mpImpl->mpLayouter )
2301 		eMode = mpImpl->mpLayouter->GetWritingMode();
2302 	return eMode;
2303 }
2304 
2305 // --------------------------------------------------------------------
2306 
2307 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
2308 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
2309 sal_Bool SdrTableObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon ) const
2310 {
2311 	return SdrTextObj::TRGetBaseGeometry( rMatrix, rPolyPolygon );
2312 }
2313 
2314 // --------------------------------------------------------------------
2315 
2316 // sets the base geometry of the object using infos contained in the homogen 3x3 matrix.
2317 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
2318 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
2319 void SdrTableObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon )
2320 {
2321 	SdrTextObj::TRSetBaseGeometry( rMatrix, rPolyPolygon );
2322 }
2323 
2324 // --------------------------------------------------------------------
2325 
2326 bool SdrTableObj::IsRealyEdited() const
2327 {
2328 	return pEdtOutl && pEdtOutl->IsModified();
2329 }
2330 
2331 // --------------------------------------------------------------------
2332 
2333 FASTBOOL SdrTableObj::IsFontwork() const
2334 {
2335 	return sal_False;
2336 }
2337 
2338 // --------------------------------------------------------------------
2339 
2340 sal_uInt32 SdrTableObj::GetHdlCount() const
2341 {
2342 	sal_uInt32 nCount = SdrTextObj::GetHdlCount();
2343 	const sal_Int32 nRowCount = mpImpl->getRowCount();
2344 	const sal_Int32 nColCount = mpImpl->getColumnCount();
2345 
2346 	if( nRowCount && nColCount )
2347 		nCount += nRowCount + nColCount + 2 + 1;
2348 
2349 	return nCount;
2350 }
2351 
2352 // --------------------------------------------------------------------
2353 
2354 void SdrTableObj::AddToHdlList(SdrHdlList& rHdlList) const
2355 {
2356 	const sal_Int32 nRowCount = mpImpl->getRowCount();
2357 	const sal_Int32 nColCount = mpImpl->getColumnCount();
2358 
2359 	// first add row handles
2360 	std::vector< TableEdgeHdl* > aRowEdges( nRowCount + 1 );
2361 
2362 	for( sal_Int32 nRow = 0; nRow <= nRowCount; nRow++ )
2363 	{
2364 		sal_Int32 nEdgeMin, nEdgeMax;
2365 		const sal_Int32 nEdge = mpImpl->mpLayouter->getHorizontalEdge( nRow, &nEdgeMin, &nEdgeMax );
2366 		nEdgeMin -= nEdge;
2367 		nEdgeMax -= nEdge;
2368 
2369 		Point aPoint( aRect.TopLeft() );
2370 		aPoint.Y() += nEdge;
2371 
2372 		TableEdgeHdl* pHdl= new TableEdgeHdl(aPoint,true,nEdgeMin,nEdgeMax,nColCount+1);
2373 		pHdl->SetPointNum( nRow );
2374 		rHdlList.AddHdl( pHdl );
2375 		aRowEdges[nRow] = pHdl;
2376 	}
2377 
2378 	// second add column handles
2379 	std::vector< TableEdgeHdl* > aColEdges( nColCount + 1 );
2380 
2381 	for( sal_Int32 nCol = 0; nCol <= nColCount; nCol++ )
2382 	{
2383 		sal_Int32 nEdgeMin, nEdgeMax;
2384 		const sal_Int32 nEdge = mpImpl->mpLayouter->getVerticalEdge( nCol, &nEdgeMin, &nEdgeMax );
2385 		nEdgeMin -= nEdge;
2386 		nEdgeMax -= nEdge;
2387 
2388 		Point aPoint( aRect.TopLeft() );
2389 		aPoint.X() += nEdge;
2390 
2391 		TableEdgeHdl* pHdl = new TableEdgeHdl(aPoint,false,nEdgeMin,nEdgeMax, nRowCount+1);
2392 		pHdl->SetPointNum( nCol );
2393 		rHdlList.AddHdl( pHdl );
2394 		aColEdges[nCol] = pHdl;
2395 	}
2396 
2397 	// now add visible edges to row and column handles
2398 	if( mpImpl && mpImpl->mpLayouter )
2399 	{
2400 		TableLayouter& rLayouter = *mpImpl->mpLayouter;
2401 
2402 		sal_Int32 nY = 0;
2403 
2404 		for( sal_Int32 nRow = 0; nRow <= nRowCount; ++nRow )
2405 		{
2406 			const sal_Int32 nRowHeight = (nRow == nRowCount) ? 0 : rLayouter.getRowHeight(nRow);
2407 			sal_Int32 nX = 0;
2408 
2409 			for( sal_Int32 nCol = 0; nCol <= nColCount; ++nCol )
2410 			{
2411 				const sal_Int32 nColWidth = (nCol == nColCount) ? 0 : rLayouter.getColumnWidth(nCol);
2412 
2413 				if( nRowHeight > 0 )
2414 				{
2415 					if( rLayouter.isEdgeVisible( nCol, nRow, false ) )
2416 						aColEdges[nCol]->SetEdge( nRow, nY, nY + nRowHeight, (rLayouter.getBorderLine( nCol, nRow, false ) == 0) ? Visible : Invisible);
2417 				}
2418 
2419 				if( nColWidth > 0 )
2420 				{
2421 					if( rLayouter.isEdgeVisible( nCol, nRow, true ) )
2422 						aRowEdges[nRow]->SetEdge( nCol, nX, nX + nColWidth, (rLayouter.getBorderLine( nCol, nRow, true ) == 0) ? Visible : Invisible);
2423 				}
2424 
2425 				nX += nColWidth;
2426 			}
2427 
2428 			nY += nRowHeight;
2429 		}
2430 	}
2431 
2432 	// add remaining handles
2433 	SdrHdl* pH=0;
2434 	rHdlList.AddHdl( pH = new TableBorderHdl( aRect ) ); pH->SetMoveOutside( true );
2435 	rHdlList.AddHdl( pH = new SdrHdl(aRect.TopLeft(),HDL_UPLFT) ); pH->SetMoveOutside( true );
2436 	rHdlList.AddHdl( pH = new SdrHdl(aRect.TopCenter(),HDL_UPPER) ); pH->SetMoveOutside( true );
2437 	rHdlList.AddHdl( pH = new SdrHdl(aRect.TopRight(),HDL_UPRGT) ); pH->SetMoveOutside( true );
2438 	rHdlList.AddHdl( pH = new SdrHdl(aRect.LeftCenter(),HDL_LEFT) ); pH->SetMoveOutside( true );
2439 	rHdlList.AddHdl( pH = new SdrHdl(aRect.RightCenter(),HDL_RIGHT) ); pH->SetMoveOutside( true );
2440 	rHdlList.AddHdl( pH = new SdrHdl(aRect.BottomLeft(),HDL_LWLFT) ); pH->SetMoveOutside( true );
2441 	rHdlList.AddHdl( pH = new SdrHdl(aRect.BottomCenter(),HDL_LOWER) ); pH->SetMoveOutside( true );
2442 	rHdlList.AddHdl( pH = new SdrHdl(aRect.BottomRight(),HDL_LWRGT) ); pH->SetMoveOutside( true );
2443 
2444 	sal_uIntPtr nHdlCount = rHdlList.GetHdlCount();
2445 	for( sal_uIntPtr nHdl = 0; nHdl < nHdlCount; nHdl++ )
2446 		rHdlList.GetHdl(nHdl)->SetObj((SdrObject*)this);
2447 }
2448 
2449 // --------------------------------------------------------------------
2450 
2451 SdrHdl* SdrTableObj::GetHdl(sal_uInt32 nHdlNum) const
2452 {
2453 	// #i73248#
2454 	// Warn the user that this is ineffective and show alternatives. Should not be used at all.
2455 	OSL_ENSURE(false, "SdrTableObj::GetHdl(): ineffective, use AddToHdlList instead (!)");
2456 
2457 	// to have an alternative, get single handle using the ineffective way
2458 	SdrHdl* pRetval = 0;
2459 	SdrHdlList aLocalList(0);
2460 	AddToHdlList(aLocalList);
2461 	const sal_uInt32 nHdlCount(aLocalList.GetHdlCount());
2462 
2463 	if(nHdlCount && nHdlNum < nHdlCount)
2464 	{
2465 		// remove and remember. The other created handles will be deleted again with the
2466 		// destruction of the local list
2467 		pRetval = aLocalList.RemoveHdl(nHdlNum);
2468 	}
2469 
2470 	return pRetval;
2471 }
2472 
2473 ////////////////////////////////////////////////////////////////////////////////////////////////////
2474 // Draging
2475 
2476 bool SdrTableObj::hasSpecialDrag() const
2477 {
2478 	return true;
2479 }
2480 
2481 bool SdrTableObj::beginSpecialDrag(SdrDragStat& rDrag) const
2482 {
2483 	const SdrHdl* pHdl = rDrag.GetHdl();
2484 	const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind());
2485 
2486     switch( eHdl )
2487 	{
2488 	    case HDL_UPLFT:
2489 	    case HDL_UPPER:
2490 	    case HDL_UPRGT:
2491 	    case HDL_LEFT:
2492 	    case HDL_RIGHT:
2493 	    case HDL_LWLFT:
2494 	    case HDL_LOWER:
2495 	    case HDL_LWRGT:
2496 	    case HDL_MOVE:
2497         {
2498 		    break;
2499         }
2500 
2501 	    case HDL_USER:
2502         {
2503 		    rDrag.SetEndDragChangesAttributes(false);
2504 		    rDrag.SetNoSnap(true);
2505 		    break;
2506         }
2507 
2508 	    default:
2509         {
2510 		    return false;
2511         }
2512 	}
2513 
2514 	return true;
2515 }
2516 
2517 bool SdrTableObj::applySpecialDrag(SdrDragStat& rDrag)
2518 {
2519 	bool bRet(true);
2520 	const SdrHdl* pHdl = rDrag.GetHdl();
2521 	const SdrHdlKind eHdl((pHdl == NULL) ? HDL_MOVE : pHdl->GetKind());
2522 
2523 	switch( eHdl )
2524 	{
2525 	    case HDL_UPLFT:
2526 	    case HDL_UPPER:
2527 	    case HDL_UPRGT:
2528 	    case HDL_LEFT:
2529 	    case HDL_RIGHT:
2530 	    case HDL_LWLFT:
2531 	    case HDL_LOWER:
2532 	    case HDL_LWRGT:
2533         {
2534     		const Rectangle aNewRectangle(ImpDragCalcRect(rDrag));
2535 
2536             if(aNewRectangle != aRect)
2537             {
2538    			    NbcSetLogicRect(aNewRectangle);
2539             }
2540 
2541 		    break;
2542         }
2543 
2544 	    case HDL_MOVE:
2545         {
2546    		    NbcMove( Size( rDrag.GetDX(), rDrag.GetDY() ) );
2547             break;
2548         }
2549 
2550 	    case HDL_USER:
2551 	    {
2552 		    rDrag.SetEndDragChangesAttributes(false);
2553 		    rDrag.SetNoSnap(true);
2554             const TableEdgeHdl* pEdgeHdl = dynamic_cast< const TableEdgeHdl* >( pHdl );
2555 
2556             if( pEdgeHdl )
2557 		    {
2558 			    if( GetModel() && IsInserted() )
2559                 {
2560                     rDrag.SetEndDragChangesAttributes(true);
2561                 }
2562 
2563 			    mpImpl->DragEdge( pEdgeHdl->IsHorizontalEdge(), pEdgeHdl->GetPointNum(), pEdgeHdl->GetValidDragOffset( rDrag ) );
2564 		    }
2565 		    break;
2566 	    }
2567 
2568 	    default:
2569 	    {
2570 		    bRet = false;
2571         }
2572 	}
2573 
2574 	return bRet;
2575 }
2576 
2577 String SdrTableObj::getSpecialDragComment(const SdrDragStat& rDrag) const
2578 {
2579 	return SdrTextObj::getSpecialDragComment( rDrag );
2580 }
2581 
2582 basegfx::B2DPolyPolygon SdrTableObj::getSpecialDragPoly(const SdrDragStat& rDrag) const
2583 {
2584 	basegfx::B2DPolyPolygon aRetval;
2585 	const SdrHdl* pHdl = rDrag.GetHdl();
2586 
2587     if( pHdl && (HDL_USER == pHdl->GetKind()) )
2588     {
2589 		const TableEdgeHdl* pEdgeHdl = dynamic_cast< const TableEdgeHdl* >( pHdl );
2590 
2591         if( pEdgeHdl )
2592         {
2593 			aRetval = pEdgeHdl->getSpecialDragPoly( rDrag );
2594         }
2595     }
2596 
2597     return aRetval;
2598 }
2599 
2600 ////////////////////////////////////////////////////////////////////////////////////////////////////
2601 // Create
2602 // --------------------------------------------------------------------
2603 
2604 FASTBOOL SdrTableObj::BegCreate(SdrDragStat& rStat)
2605 {
2606 	rStat.SetOrtho4Possible();
2607     Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
2608 	aRect1.Justify();
2609 	rStat.SetActionRect(aRect1);
2610 	aRect = aRect1;
2611 	return sal_True;
2612 }
2613 
2614 // --------------------------------------------------------------------
2615 
2616 FASTBOOL SdrTableObj::MovCreate(SdrDragStat& rStat)
2617 {
2618 	Rectangle aRect1;
2619 	rStat.TakeCreateRect(aRect1);
2620 	ImpJustifyRect(aRect1);
2621 	rStat.SetActionRect(aRect1);
2622 	aRect=aRect1; // fuer ObjName
2623 	SetBoundRectDirty();
2624 	bSnapRectDirty=sal_True;
2625 	return sal_True;
2626 }
2627 
2628 // --------------------------------------------------------------------
2629 
2630 FASTBOOL SdrTableObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
2631 {
2632 	rStat.TakeCreateRect(aRect);
2633 	ImpJustifyRect(aRect);
2634 	return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
2635 }
2636 
2637 void SdrTableObj::BrkCreate(SdrDragStat& /*rStat*/)
2638 {
2639 }
2640 
2641 // --------------------------------------------------------------------
2642 
2643 FASTBOOL SdrTableObj::BckCreate(SdrDragStat& /*rStat*/)
2644 {
2645 	return sal_True;
2646 }
2647 
2648 // --------------------------------------------------------------------
2649 
2650 basegfx::B2DPolyPolygon SdrTableObj::TakeCreatePoly(const SdrDragStat& rDrag) const
2651 {
2652 	Rectangle aRect1;
2653 	rDrag.TakeCreateRect(aRect1);
2654 	aRect1.Justify();
2655 
2656 	basegfx::B2DPolyPolygon aRetval;
2657 	const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom());
2658 	aRetval.append(basegfx::tools::createPolygonFromRect(aRange));
2659 	return aRetval;
2660 }
2661 
2662 // --------------------------------------------------------------------
2663 
2664 Pointer SdrTableObj::GetCreatePointer() const
2665 {
2666 	return Pointer(POINTER_CROSS);
2667 }
2668 
2669 // --------------------------------------------------------------------
2670 
2671 void SdrTableObj::createCell( CellRef& xNewCell )
2672 {
2673     xNewCell = Cell::create( *this, 0 );
2674 }
2675 
2676 // --------------------------------------------------------------------
2677 
2678 SdrObjGeoData *SdrTableObj::NewGeoData() const
2679 {
2680 	return new TableObjectGeoData;
2681 }
2682 
2683 // --------------------------------------------------------------------
2684 
2685 void SdrTableObj::SaveGeoData(SdrObjGeoData& rGeo) const
2686 {
2687 	DBG_ASSERT( dynamic_cast< TableObjectGeoData* >( &rGeo ), "svx::SdrTableObj::SaveGeoData(), illegal geo data!" );
2688 	SdrTextObj::SaveGeoData (rGeo);
2689 
2690 	((TableObjectGeoData &) rGeo).maLogicRect = maLogicRect;
2691 }
2692 
2693 // --------------------------------------------------------------------
2694 
2695 void SdrTableObj::RestGeoData(const SdrObjGeoData& rGeo)
2696 {
2697 	DBG_ASSERT( dynamic_cast< const TableObjectGeoData* >( &rGeo ), "svx::SdrTableObj::SaveGeoData(), illegal geo data!" );
2698 
2699 	maLogicRect = ((TableObjectGeoData &) rGeo).maLogicRect;
2700 
2701 	SdrTextObj::RestGeoData (rGeo);
2702 
2703 	if( mpImpl )
2704 		mpImpl->LayoutTable( aRect, false, false );
2705 	ActionChanged();
2706 }
2707 
2708 // --------------------------------------------------------------------
2709 
2710 SdrTableObj* SdrTableObj::CloneRange( const CellPos& rStart, const CellPos& rEnd )
2711 {
2712 	const sal_Int32 nColumns = rEnd.mnCol - rStart.mnCol + 1;
2713 	const sal_Int32 nRows = rEnd.mnRow - rStart.mnRow + 1;
2714 
2715 	SdrTableObj* pNewTableObj = new SdrTableObj( GetModel(), GetCurrentBoundRect(), nColumns, nRows);
2716 	pNewTableObj->setTableStyleSettings( getTableStyleSettings() );
2717 	pNewTableObj->setTableStyle( getTableStyle() );
2718 
2719 	Reference< XTable > xTable( getTable() );
2720 	Reference< XTable > xNewTable( pNewTableObj->getTable() );
2721 
2722 	if( !xTable.is() || !xNewTable.is() )
2723 	{
2724 		delete pNewTableObj;
2725 		return 0;
2726 	}
2727 
2728 	// copy cells
2729 	for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
2730 	{
2731 		for( sal_Int32 nCol = 0; nCol < nColumns; ++nCol ) try
2732 		{
2733 			CellRef xTargetCell( dynamic_cast< Cell* >( xNewTable->getCellByPosition( nCol, nRow ).get() ) );
2734 			if( xTargetCell.is() )
2735 				xTargetCell->cloneFrom( dynamic_cast< Cell* >( xTable->getCellByPosition( rStart.mnCol + nCol, rStart.mnRow + nRow ).get() ) );
2736 		}
2737 		catch( Exception& )
2738 		{
2739 			DBG_ERROR( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2740 		}
2741 	}
2742 
2743 	// copy row heights
2744 	Reference< XTableRows > xNewRows( xNewTable->getRows(), UNO_QUERY_THROW );
2745 	const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM( "Height" ) );
2746 	for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
2747 	{
2748 		Reference< XPropertySet > xNewSet( xNewRows->getByIndex( nRow ), UNO_QUERY_THROW );
2749 		xNewSet->setPropertyValue( sHeight, Any( mpImpl->mpLayouter->getRowHeight( rStart.mnRow + nRow ) ) );
2750 	}
2751 
2752 	// copy column widths
2753 	Reference< XTableColumns > xNewColumns( xNewTable->getColumns(), UNO_QUERY_THROW );
2754 	const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM( "Width" ) );
2755 	for( sal_Int32 nCol = 0; nCol < nColumns; ++nCol )
2756 	{
2757 		Reference< XPropertySet > xNewSet( xNewColumns->getByIndex( nCol ), UNO_QUERY_THROW );
2758 		xNewSet->setPropertyValue( sWidth, Any( mpImpl->mpLayouter->getColumnWidth( rStart.mnCol + nCol ) ) );
2759 	}
2760 
2761 	pNewTableObj->NbcReformatText();
2762 	pNewTableObj->SetLogicRect( pNewTableObj->GetCurrentBoundRect() );
2763 
2764 	return pNewTableObj;
2765 }
2766 
2767 // --------------------------------------------------------------------
2768 
2769 void SdrTableObj::DistributeColumns( sal_Int32 nFirstColumn, sal_Int32 nLastColumn )
2770 {
2771 	if( mpImpl && mpImpl->mpLayouter )
2772 	{
2773 		TableModelNotifyGuard aGuard( mpImpl->mxTable.get() );
2774 		mpImpl->mpLayouter->DistributeColumns( aRect, nFirstColumn, nLastColumn );
2775 	}
2776 }
2777 
2778 // --------------------------------------------------------------------
2779 
2780 void SdrTableObj::DistributeRows( sal_Int32 nFirstRow, sal_Int32 nLastRow )
2781 {
2782 	if( mpImpl && mpImpl->mpLayouter )
2783 	{
2784 		TableModelNotifyGuard aGuard( mpImpl->mxTable.get() );
2785 		mpImpl->mpLayouter->DistributeRows( aRect, nFirstRow, nLastRow );
2786 	}
2787 }
2788 
2789 // --------------------------------------------------------------------
2790 
2791 void SdrTableObj::SetChanged()
2792 {
2793 	if( mpImpl )
2794 	{
2795 		if( mpImpl->UpdateWritingMode() )
2796 			mpImpl->LayoutTable( aRect, false, false );
2797 	}
2798 
2799 	::SdrTextObj::SetChanged();
2800 }
2801 
2802 // --------------------------------------------------------------------
2803 
2804 void SdrTableObj::uno_lock()
2805 {
2806 	if( mpImpl && mpImpl->mxTable.is() )
2807 		mpImpl->mxTable->lockBroadcasts();
2808 }
2809 
2810 // --------------------------------------------------------------------
2811 
2812 void SdrTableObj::uno_unlock()
2813 {
2814 	if( mpImpl && mpImpl->mxTable.is() )
2815 		mpImpl->mxTable->unlockBroadcasts();
2816 }
2817 
2818 // --------------------------------------------------------------------
2819 
2820 
2821 
2822 } }
2823