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