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