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