fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleSpreadsheet.cxx
blobe46e6df7444e13dd925b09ebc534296690fc9a87
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "AccessibleSpreadsheet.hxx"
21 #include "AccessibilityHints.hxx"
22 #include "AccessibleCell.hxx"
23 #include "AccessibleDocument.hxx"
24 #include "tabvwsh.hxx"
25 #include "document.hxx"
26 #include "hints.hxx"
27 #include "scmod.hxx"
28 #include "markdata.hxx"
29 #include <gridwin.hxx>
31 #include <unotools/accessiblestatesethelper.hxx>
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
35 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
36 #include <comphelper/servicehelper.hxx>
37 #include <tools/gen.hxx>
38 #include <svtools/colorcfg.hxx>
39 #include <vcl/svapp.hxx>
40 #include "scresid.hxx"
41 #include "sc.hrc"
43 #include <algorithm>
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::accessibility;
48 bool CompMinCol(const std::pair<sal_uInt16,sal_uInt16> & pc1,const std::pair<sal_uInt16,sal_uInt16> &pc2)
50 return pc1.first < pc2.first;
53 ScMyAddress ScAccessibleSpreadsheet::CalcScAddressFromRangeList(ScRangeList *pMarkedRanges,sal_Int32 nSelectedChildIndex)
55 if (pMarkedRanges->size() <= 1)
57 ScRange* pRange = pMarkedRanges->front();
58 if (pRange)
60 // MT IA2: Not used.
61 // const int nRowNum = pRange->aEnd.Row() - pRange->aStart.Row() + 1;
62 const int nColNum = pRange->aEnd.Col() - pRange->aStart.Col() + 1;
63 const int nCurCol = nSelectedChildIndex % nColNum;
64 const int nCurRow = (nSelectedChildIndex - nCurCol)/nColNum;
65 return ScMyAddress(static_cast<SCCOL>(pRange->aStart.Col() + nCurCol), pRange->aStart.Row() + nCurRow, maActiveCell.Tab());
68 else
70 sal_Int32 nMinRow = MAXROW;
71 sal_Int32 nMaxRow = 0;
72 m_vecTempRange.clear();
73 size_t nSize = pMarkedRanges->size();
74 for (size_t i = 0; i < nSize; ++i)
76 ScRange* pRange = (*pMarkedRanges)[i];
77 if (pRange->aStart.Tab() != pRange->aEnd.Tab())
79 if ((maActiveCell.Tab() >= pRange->aStart.Tab()) ||
80 maActiveCell.Tab() <= pRange->aEnd.Tab())
82 m_vecTempRange.push_back(pRange);
83 nMinRow = std::min(pRange->aStart.Row(),nMinRow);
84 nMaxRow = std::max(pRange->aEnd.Row(),nMaxRow);
86 else
87 SAL_WARN("sc", "Range of wrong table");
89 else if(pRange->aStart.Tab() == maActiveCell.Tab())
91 m_vecTempRange.push_back(pRange);
92 nMinRow = std::min(pRange->aStart.Row(),nMinRow);
93 nMaxRow = std::max(pRange->aEnd.Row(),nMaxRow);
95 else
96 SAL_WARN("sc", "Range of wrong table");
98 int nCurrentIndex = 0 ;
99 for(sal_Int32 row = nMinRow ; row <= nMaxRow ; ++row)
101 m_vecTempCol.clear();
103 VEC_RANGE::const_iterator vi = m_vecTempRange.begin();
104 for (; vi < m_vecTempRange.end(); ++vi)
106 ScRange *p = *vi;
107 if ( row >= p->aStart.Row() && row <= p->aEnd.Row())
109 m_vecTempCol.push_back(std::make_pair(p->aStart.Col(),p->aEnd.Col()));
113 std::sort(m_vecTempCol.begin(),m_vecTempCol.end(),CompMinCol);
115 VEC_COL::const_iterator vic = m_vecTempCol.begin();
116 for(; vic != m_vecTempCol.end(); ++vic)
118 const PAIR_COL &pariCol = *vic;
119 sal_uInt16 nCol = pariCol.second - pariCol.first + 1;
120 if (nCol + nCurrentIndex > nSelectedChildIndex)
122 return ScMyAddress(static_cast<SCCOL>(pariCol.first + nSelectedChildIndex - nCurrentIndex), row, maActiveCell.Tab());
124 nCurrentIndex += nCol;
129 return ScMyAddress(0,0,maActiveCell.Tab());
132 bool ScAccessibleSpreadsheet::CalcScRangeDifferenceMax(ScRange *pSrc,ScRange *pDest,int nMax,VEC_MYADDR &vecRet,int &nSize)
134 //Src Must be :Src > Dest
135 if (pDest->In(*pSrc))
136 {//Here is Src In Dest,Src <= Dest
137 return false;
139 if (!pDest->Intersects(*pSrc))
141 int nCellCount = sal_uInt32(pDest->aEnd.Col() - pDest->aStart.Col() + 1)
142 * sal_uInt32(pDest->aEnd.Row() - pDest->aStart.Row() + 1)
143 * sal_uInt32(pDest->aEnd.Tab() - pDest->aStart.Tab() + 1);
144 if (nCellCount + nSize > nMax)
146 return true;
148 else if(nCellCount > 0)
150 nCellCount +=nSize;
151 for (sal_Int32 row = pDest->aStart.Row(); row <= pDest->aEnd.Row();++row)
153 for (sal_uInt16 col = pDest->aStart.Col(); col <= pDest->aEnd.Col();++col)
155 vecRet.push_back(ScMyAddress(col,row,pDest->aStart.Tab()));
159 return false;
161 sal_Int32 nMinRow = pSrc->aStart.Row();
162 sal_Int32 nMaxRow = pSrc->aEnd.Row();
163 for (; nMinRow <= nMaxRow ; ++nMinRow,--nMaxRow)
165 for (sal_uInt16 col = pSrc->aStart.Col(); col <= pSrc->aEnd.Col();++col)
167 if (nSize > nMax)
169 return true;
171 ScMyAddress cell(col,nMinRow,pSrc->aStart.Tab());
172 if(!pDest->In(cell))
173 {//In Src ,Not In Dest
174 vecRet.push_back(cell);
175 ++nSize;
178 if (nMinRow != nMaxRow)
180 for (sal_uInt16 col = pSrc->aStart.Col(); col <= pSrc->aEnd.Col();++col)
182 if (nSize > nMax)
184 return true;
186 ScMyAddress cell(col,nMaxRow,pSrc->aStart.Tab());
187 if(!pDest->In(cell))
188 {//In Src ,Not In Dest
189 vecRet.push_back(cell);
190 ++nSize;
195 return false;
198 //In Src , Not in Dest
199 bool ScAccessibleSpreadsheet::CalcScRangeListDifferenceMax(ScRangeList *pSrc,ScRangeList *pDest,int nMax,VEC_MYADDR &vecRet)
201 if (pSrc == NULL || pDest == NULL)
203 return false;
205 int nSize =0;
206 if (pDest->GetCellCount() == 0)//if the Dest Rang List is empty
208 if (pSrc->GetCellCount() > sal_uInt32(nMax))//if the Src Cell count is greater then nMax
210 return true;
212 //now the cell count is less then nMax
213 vecRet.reserve(10);
214 size_t nSrcSize = pSrc->size();
215 for (size_t i = 0; i < nSrcSize; ++i)
217 ScRange* pRange = (*pSrc)[i];
218 for (sal_Int32 row = pRange->aStart.Row(); row <= pRange->aEnd.Row();++row)
220 for (sal_uInt16 col = pRange->aStart.Col(); col <= pRange->aEnd.Col();++col)
222 vecRet.push_back(ScMyAddress(col,row,pRange->aStart.Tab()));
226 return false;
228 //the Dest Rang List is not empty
229 vecRet.reserve(10);
230 size_t nSizeSrc = pSrc->size();
231 for (size_t i = 0; i < nSizeSrc; ++i)
233 ScRange* pRange = (*pSrc)[i];
234 size_t nSizeDest = pDest->size();
235 for (size_t j = 0; j < nSizeDest; ++j)
237 ScRange* pRangeDest = (*pDest)[j];
238 if (CalcScRangeDifferenceMax(pRange,pRangeDest,nMax,vecRet,nSize))
240 return true;
244 return false;
247 //===== internal ============================================================
249 // FIXME: really unclear why we have an ScAccessibleTableBase with
250 // only this single sub-class
251 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
252 ScAccessibleDocument* pAccDoc,
253 ScTabViewShell* pViewShell,
254 SCTAB nTab,
255 ScSplitPos eSplitPos)
257 ScAccessibleTableBase (pAccDoc, GetDocument(pViewShell),
258 ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))),
259 mbIsSpreadsheet( true ),
260 m_bFormulaMode( false ),
261 m_bFormulaLastMode( false ),
262 m_nMinX(0),m_nMaxX(0),m_nMinY(0),m_nMaxY(0)
264 ConstructScAccessibleSpreadsheet( pAccDoc, pViewShell, nTab, eSplitPos );
267 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
268 ScAccessibleSpreadsheet& rParent, const ScRange& rRange ) :
269 ScAccessibleTableBase( rParent.mpAccDoc, rParent.mpDoc, rRange),
270 mbIsSpreadsheet( false )
272 ConstructScAccessibleSpreadsheet( rParent.mpAccDoc, rParent.mpViewShell, rParent.mnTab, rParent.meSplitPos );
275 ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet()
277 delete mpMarkedRanges;
278 if (mpViewShell)
279 mpViewShell->RemoveAccessibilityObject(*this);
282 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
283 ScAccessibleDocument* pAccDoc,
284 ScTabViewShell* pViewShell,
285 SCTAB nTab,
286 ScSplitPos eSplitPos)
288 mpViewShell = pViewShell;
289 mpMarkedRanges = 0;
290 mpSortedMarkedCells = 0;
291 mpAccDoc = pAccDoc;
292 mpAccCell.clear();
293 meSplitPos = eSplitPos;
294 mnTab = nTab;
295 mbHasSelection = false;
296 mbDelIns = false;
297 mbIsFocusSend = false;
298 maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos));
299 if (mpViewShell)
301 mpViewShell->AddAccessibilityObject(*this);
303 const ScViewData& rViewData = mpViewShell->GetViewData();
304 const ScMarkData& rMarkData = rViewData.GetMarkData();
305 maActiveCell = rViewData.GetCurPos();
306 mbHasSelection = rMarkData.GetTableSelect(maActiveCell.Tab()) &&
307 (rMarkData.IsMarked() || rMarkData.IsMultiMarked());
308 mpAccCell = GetAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
309 ScDocument* pScDoc= GetDocument(mpViewShell);
310 if (pScDoc)
312 pScDoc->GetName( maActiveCell.Tab(), m_strOldTabName );
317 void SAL_CALL ScAccessibleSpreadsheet::disposing()
319 SolarMutexGuard aGuard;
320 if (mpViewShell)
322 mpViewShell->RemoveAccessibilityObject(*this);
323 mpViewShell = NULL;
325 mpAccCell.clear();
327 ScAccessibleTableBase::disposing();
330 void ScAccessibleSpreadsheet::CompleteSelectionChanged(bool bNewState)
332 if (IsFormulaMode())
334 return ;
336 if (mpMarkedRanges)
337 DELETEZ(mpMarkedRanges);
338 mbHasSelection = bNewState;
340 AccessibleEventObject aEvent;
341 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
342 if (bNewState)
343 aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED);
344 else
345 aEvent.OldValue = uno::makeAny(AccessibleStateType::SELECTED);
346 aEvent.Source = uno::Reference< XAccessibleContext >(this);
348 CommitChange(aEvent);
351 void ScAccessibleSpreadsheet::LostFocus()
353 AccessibleEventObject aEvent;
354 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
355 aEvent.Source = uno::Reference< XAccessibleContext >(this);
356 aEvent.OldValue <<= uno::Reference<XAccessible>(mpAccCell.get());
358 CommitChange(aEvent);
360 CommitFocusLost();
363 void ScAccessibleSpreadsheet::GotFocus()
365 CommitFocusGained();
366 AccessibleEventObject aEvent;
367 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
368 aEvent.Source = uno::Reference< XAccessibleContext >(this);
369 uno::Reference< XAccessible > xNew;
370 if (IsFormulaMode())
372 if (!m_pAccFormulaCell.is() || !m_bFormulaLastMode)
374 ScAddress aFormulaAddr;
375 if(!GetFormulaCurrentFocusCell(aFormulaAddr))
377 return;
379 m_pAccFormulaCell = GetAccessibleCellAt(aFormulaAddr.Row(),aFormulaAddr.Col());
381 xNew = m_pAccFormulaCell.get();
383 else
385 if(mpAccCell->GetCellAddress() == maActiveCell)
387 xNew = mpAccCell.get();
389 else
391 CommitFocusCell(maActiveCell);
392 return ;
395 aEvent.NewValue <<= xNew;
397 CommitChange(aEvent);
400 void ScAccessibleSpreadsheet::BoundingBoxChanged()
402 AccessibleEventObject aEvent;
403 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
404 aEvent.Source = uno::Reference< XAccessibleContext >(this);
406 CommitChange(aEvent);
409 void ScAccessibleSpreadsheet::VisAreaChanged()
411 AccessibleEventObject aEvent;
412 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
413 aEvent.Source = uno::Reference< XAccessibleContext >(this);
415 CommitChange(aEvent);
418 //===== SfxListener =====================================================
420 void ScAccessibleSpreadsheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
422 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
423 if (pSimpleHint)
425 if (pSimpleHint->GetId() == SC_HINT_ACC_CURSORCHANGED)
427 if (mpViewShell)
429 ScViewData& rViewData = mpViewShell->GetViewData();
431 m_bFormulaMode = rViewData.IsRefMode() || SC_MOD()->IsFormulaMode();
432 if ( m_bFormulaMode )
434 NotifyRefMode();
435 m_bFormulaLastMode = true;
436 return;
438 if (m_bFormulaLastMode)
439 {//Last Notify Mode Is Formula Mode.
440 m_vecFormulaLastMyAddr.clear();
441 RemoveFormulaSelection(true);
442 m_pAccFormulaCell.clear();
443 //Remove All Selection
445 m_bFormulaLastMode = m_bFormulaMode;
447 AccessibleEventObject aEvent;
448 aEvent.Source = uno::Reference< XAccessible >(this);
449 ScAddress aNewCell = rViewData.GetCurPos();
450 if(aNewCell.Tab() != maActiveCell.Tab())
452 aEvent.EventId = AccessibleEventId::PAGE_CHANGED;
453 ScAccessibleDocument *pAccDoc =
454 static_cast<ScAccessibleDocument*>(getAccessibleParent().get());
455 if(pAccDoc)
457 pAccDoc->CommitChange(aEvent);
460 bool bNewPosCell = (aNewCell != maActiveCell) || mpViewShell->GetForceFocusOnCurCell(); // #i123629#
461 bool bNewPosCellFocus=false;
462 if ( bNewPosCell && IsFocused() && aNewCell.Tab() == maActiveCell.Tab() )
463 {//single Focus
464 bNewPosCellFocus=true;
466 ScMarkData &refScMarkData = rViewData.GetMarkData();
467 // MT IA2: Not used
468 // int nSelCount = refScMarkData.GetSelectCount();
469 bool bIsMark =refScMarkData.IsMarked();
470 bool bIsMultMark = refScMarkData.IsMultiMarked();
471 bool bNewMarked = refScMarkData.GetTableSelect(aNewCell.Tab()) && ( bIsMark || bIsMultMark );
472 // sal_Bool bNewCellSelected = isAccessibleSelected(aNewCell.Row(), aNewCell.Col());
473 sal_uInt16 nTab = rViewData.GetTabNo();
474 ScRange aMarkRange;
475 refScMarkData.GetMarkArea(aMarkRange);
476 aEvent.OldValue <<= ::com::sun::star::uno::Any();
477 //Mark All
478 if ( !bNewPosCellFocus &&
479 (bNewMarked || bIsMark || bIsMultMark ) &&
480 aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
482 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
483 aEvent.NewValue <<= ::com::sun::star::uno::Any();
484 CommitChange(aEvent);
485 return ;
487 if (!mpMarkedRanges)
489 mpMarkedRanges = new ScRangeList();
491 refScMarkData.FillRangeListWithMarks(mpMarkedRanges, true);
493 //For Whole Col Row
494 bool bWholeRow = ::labs(aMarkRange.aStart.Row() - aMarkRange.aEnd.Row()) == MAXROW ;
495 bool bWholeCol = ::abs(aMarkRange.aStart.Col() - aMarkRange.aEnd.Col()) == MAXCOL ;
496 if ((bNewMarked || bIsMark || bIsMultMark ) && (bWholeCol || bWholeRow))
498 if ( aMarkRange != m_aLastWithInMarkRange )
500 RemoveSelection(refScMarkData);
501 if(bNewPosCell)
503 CommitFocusCell(aNewCell);
505 bool bLastIsWholeColRow =
506 (::labs(m_aLastWithInMarkRange.aStart.Row() - m_aLastWithInMarkRange.aEnd.Row()) == MAXROW && bWholeRow) ||
507 (::abs(m_aLastWithInMarkRange.aStart.Col() - m_aLastWithInMarkRange.aEnd.Col()) == MAXCOL && bWholeCol);
508 bool bSelSmaller=
509 bLastIsWholeColRow &&
510 !aMarkRange.In(m_aLastWithInMarkRange) &&
511 aMarkRange.Intersects(m_aLastWithInMarkRange);
512 if( !bSelSmaller )
514 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
515 aEvent.NewValue <<= ::com::sun::star::uno::Any();
516 CommitChange(aEvent);
518 m_aLastWithInMarkRange = aMarkRange;
520 return ;
522 m_aLastWithInMarkRange = aMarkRange;
523 int nNewMarkCount = mpMarkedRanges->GetCellCount();
524 bool bSendSingle= (0 == nNewMarkCount) && bNewPosCell;
525 if (bSendSingle)
527 RemoveSelection(refScMarkData);
528 if(bNewPosCellFocus)
530 CommitFocusCell(aNewCell);
532 uno::Reference< XAccessible > xChild ;
533 if (bNewPosCellFocus)
535 xChild = mpAccCell.get();
537 else
539 mpAccCell = GetAccessibleCellAt(aNewCell.Row(),aNewCell.Col());
540 xChild = mpAccCell.get();
542 maActiveCell = aNewCell;
543 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
544 aEvent.NewValue <<= xChild;
545 aEvent.OldValue <<= uno::Reference< XAccessible >();
546 CommitChange(aEvent);
548 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
549 aEvent.NewValue <<= xChild;
550 CommitChange(aEvent);
551 OSL_ASSERT(m_mapSelectionSend.count(aNewCell) == 0 );
552 m_mapSelectionSend.insert(MAP_ADDR_XACC::value_type(aNewCell,xChild));
555 else
557 ScRange aDelRange;
558 bool bIsDel = rViewData.GetDelMark( aDelRange );
559 if ( (!bIsDel || (bIsDel && aMarkRange != aDelRange)) &&
560 bNewMarked &&
561 nNewMarkCount > 0 &&
562 !IsSameMarkCell() )
564 RemoveSelection(refScMarkData);
565 if(bNewPosCellFocus)
567 CommitFocusCell(aNewCell);
569 VEC_MYADDR vecNew;
570 if(CalcScRangeListDifferenceMax(mpMarkedRanges,&m_LastMarkedRanges,10,vecNew))
572 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
573 aEvent.NewValue <<= ::com::sun::star::uno::Any();
574 CommitChange(aEvent);
576 else
578 VEC_MYADDR::iterator viAddr = vecNew.begin();
579 for(; viAddr < vecNew.end() ; ++viAddr )
581 uno::Reference< XAccessible > xChild = getAccessibleCellAt(viAddr->Row(),viAddr->Col());
582 if (!(bNewPosCellFocus && *viAddr == aNewCell) )
584 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
585 aEvent.NewValue <<= xChild;
586 CommitChange(aEvent);
588 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
589 aEvent.NewValue <<= xChild;
590 CommitChange(aEvent);
591 m_mapSelectionSend.insert(MAP_ADDR_XACC::value_type(*viAddr,xChild));
596 if (bNewPosCellFocus && maActiveCell != aNewCell)
598 CommitFocusCell(aNewCell);
600 m_LastMarkedRanges = *mpMarkedRanges;
603 else if (pSimpleHint->GetId() == SC_HINT_DATACHANGED)
605 if (!mbDelIns)
606 CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
607 else
608 mbDelIns = false;
609 ScViewData& rViewData = mpViewShell->GetViewData();
610 ScAddress aNewCell = rViewData.GetCurPos();
611 if( maActiveCell == aNewCell)
613 ScDocument* pScDoc= GetDocument(mpViewShell);
614 if (pScDoc)
616 OUString valStr(pScDoc->GetString(aNewCell.Col(),aNewCell.Row(),aNewCell.Tab()));
617 if(m_strCurCellValue != valStr)
619 AccessibleEventObject aEvent;
620 aEvent.EventId = AccessibleEventId::VALUE_CHANGED;
621 mpAccCell->CommitChange(aEvent);
622 m_strCurCellValue=valStr;
624 OUString tabName;
625 pScDoc->GetName( maActiveCell.Tab(), tabName );
626 if( m_strOldTabName != tabName )
628 AccessibleEventObject aEvent;
629 aEvent.EventId = AccessibleEventId::NAME_CHANGED;
630 OUString sOldName(ScResId(STR_ACC_TABLE_NAME));
631 sOldName = sOldName.replaceFirst("%1", m_strOldTabName);
632 aEvent.OldValue <<= sOldName;
633 OUString sNewName(ScResId(STR_ACC_TABLE_NAME));
634 sOldName = sNewName.replaceFirst("%1", tabName);
635 aEvent.NewValue <<= sNewName;
636 CommitChange( aEvent );
637 m_strOldTabName = tabName;
642 // commented out, because to use a ModelChangeEvent is not the right way
643 // at the moment there is no way, but the Java/Gnome Api should be extended sometime
644 /* if (mpViewShell)
646 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
648 Rectangle aNewPos(aNewVisCells);
650 if (aNewVisCells.IsOver(maVisCells))
651 aNewPos.Union(maVisCells);
652 else
653 CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE);
655 maVisCells = aNewVisCells;
657 CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE);
661 else if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
663 const ScUpdateRefHint& rRef = static_cast<const ScUpdateRefHint&>(rHint);
664 if (rRef.GetMode() == URM_INSDEL && rRef.GetDz() == 0) //test whether table is inserted or deleted
666 if (((rRef.GetRange().aStart.Col() == maRange.aStart.Col()) &&
667 (rRef.GetRange().aEnd.Col() == maRange.aEnd.Col())) ||
668 ((rRef.GetRange().aStart.Row() == maRange.aStart.Row()) &&
669 (rRef.GetRange().aEnd.Row() == maRange.aEnd.Row())))
671 // ignore next SC_HINT_DATACHANGED notification
672 mbDelIns = true;
674 sal_Int16 nId(0);
675 SCsCOL nX(rRef.GetDx());
676 SCsROW nY(rRef.GetDy());
677 ScRange aRange(rRef.GetRange());
678 if ((nX < 0) || (nY < 0))
680 OSL_ENSURE(!((nX < 0) && (nY < 0)), "should not be possible to remove row and column at the same time");
681 nId = AccessibleTableModelChangeType::DELETE;
682 if (nX < 0)
684 nX = -nX;
685 nY = aRange.aEnd.Row() - aRange.aStart.Row();
687 else
689 nY = -nY;
690 nX = aRange.aEnd.Col() - aRange.aStart.Col();
693 else if ((nX > 0) || (nY > 0))
695 OSL_ENSURE(!((nX > 0) && (nY > 0)), "should not be possible to add row and column at the same time");
696 nId = AccessibleTableModelChangeType::INSERT;
697 if (nX < 0)
698 nY = aRange.aEnd.Row() - aRange.aStart.Row();
699 else
700 nX = aRange.aEnd.Col() - aRange.aStart.Col();
702 else
704 OSL_FAIL("is it a deletion or a insertion?");
707 CommitTableModelChange(rRef.GetRange().aStart.Row(),
708 rRef.GetRange().aStart.Col(),
709 rRef.GetRange().aStart.Row() + nY,
710 rRef.GetRange().aStart.Col() + nX, nId);
712 AccessibleEventObject aEvent;
713 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
714 aEvent.Source = uno::Reference< XAccessibleContext >(this);
715 aEvent.NewValue <<= uno::Reference<XAccessible>(mpAccCell.get());
717 CommitChange(aEvent);
722 ScAccessibleTableBase::Notify(rBC, rHint);
725 void ScAccessibleSpreadsheet::RemoveSelection(ScMarkData &refScMarkData)
727 AccessibleEventObject aEvent;
728 aEvent.Source = uno::Reference< XAccessible >(this);
729 aEvent.OldValue <<= ::com::sun::star::uno::Any();
730 MAP_ADDR_XACC::iterator miRemove = m_mapSelectionSend.begin();
731 for(; miRemove != m_mapSelectionSend.end() ;)
733 if (refScMarkData.IsCellMarked(miRemove->first.Col(),miRemove->first.Row(),true) ||
734 refScMarkData.IsCellMarked(miRemove->first.Col(),miRemove->first.Row(),false) )
736 ++miRemove;
737 continue;
739 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
740 aEvent.NewValue <<= miRemove->second;
741 CommitChange(aEvent);
742 MAP_ADDR_XACC::iterator miNext = miRemove;
743 ++miNext;
744 m_mapSelectionSend.erase(miRemove);
745 miRemove = miNext;
748 void ScAccessibleSpreadsheet::CommitFocusCell(const ScAddress &aNewCell)
750 OSL_ASSERT(!IsFormulaMode());
751 if(IsFormulaMode())
753 return ;
755 AccessibleEventObject aEvent;
756 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
757 aEvent.Source = uno::Reference< XAccessible >(this);
758 aEvent.OldValue <<= uno::Reference<XAccessible>(mpAccCell.get());
759 mpAccCell.clear();
760 mpAccCell = GetAccessibleCellAt(aNewCell.Row(), aNewCell.Col());
761 aEvent.NewValue <<= uno::Reference<XAccessible>(mpAccCell.get());
762 maActiveCell = aNewCell;
763 ScDocument* pScDoc= GetDocument(mpViewShell);
764 if (pScDoc)
766 m_strCurCellValue = pScDoc->GetString(maActiveCell.Col(),maActiveCell.Row(),maActiveCell.Tab());
768 CommitChange(aEvent);
771 bool ScAccessibleSpreadsheet::IsSameMarkCell()
773 return m_LastMarkedRanges == *mpMarkedRanges;
776 //===== XAccessibleTable ================================================
778 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleRowHeaders( )
779 throw (uno::RuntimeException, std::exception)
781 SolarMutexGuard aGuard;
782 IsObjectValid();
783 uno::Reference< XAccessibleTable > xAccessibleTable;
784 if( mpDoc && mbIsSpreadsheet )
786 if( const ScRange* pRowRange = mpDoc->GetRepeatRowRange( mnTab ) )
788 SCROW nStart = pRowRange->aStart.Row();
789 SCROW nEnd = pRowRange->aEnd.Row();
790 if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXROW) )
791 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart, mnTab, MAXCOL, nEnd, mnTab ) ) );
794 return xAccessibleTable;
797 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleColumnHeaders( )
798 throw (uno::RuntimeException, std::exception)
800 SolarMutexGuard aGuard;
801 IsObjectValid();
802 uno::Reference< XAccessibleTable > xAccessibleTable;
803 if( mpDoc && mbIsSpreadsheet )
805 if( const ScRange* pColRange = mpDoc->GetRepeatColRange( mnTab ) )
807 SCCOL nStart = pColRange->aStart.Col();
808 SCCOL nEnd = pColRange->aEnd.Col();
809 if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXCOL) )
810 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart, 0, mnTab, nEnd, MAXROW, mnTab ) ) );
813 return xAccessibleTable;
816 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleRows( )
817 throw (uno::RuntimeException, std::exception)
819 SolarMutexGuard aGuard;
820 IsObjectValid();
821 uno::Sequence<sal_Int32> aSequence;
822 if (IsFormulaMode())
824 return aSequence;
826 if (mpViewShell)
828 aSequence.realloc(maRange.aEnd.Row() - maRange.aStart.Row() + 1);
829 const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
830 sal_Int32* pSequence = aSequence.getArray();
831 sal_Int32 nCount(0);
832 for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i)
834 if (rMarkdata.IsRowMarked(i))
836 pSequence[nCount] = i;
837 ++nCount;
840 aSequence.realloc(nCount);
842 else
843 aSequence.realloc(0);
844 return aSequence;
847 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
848 throw (uno::RuntimeException, std::exception)
850 SolarMutexGuard aGuard;
851 IsObjectValid();
852 uno::Sequence<sal_Int32> aSequence;
853 if (IsFormulaMode())
855 return aSequence;
857 if (mpViewShell)
859 aSequence.realloc(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
860 const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
861 sal_Int32* pSequence = aSequence.getArray();
862 sal_Int32 nCount(0);
863 for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i)
865 if (rMarkdata.IsColumnMarked(i))
867 pSequence[nCount] = i;
868 ++nCount;
871 aSequence.realloc(nCount);
873 else
874 aSequence.realloc(0);
875 return aSequence;
878 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow )
879 throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception)
881 SolarMutexGuard aGuard;
882 IsObjectValid();
883 if (IsFormulaMode())
885 return sal_False;
888 if ((nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
889 throw lang::IndexOutOfBoundsException();
891 bool bResult(false);
892 if (mpViewShell)
894 const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
895 bResult = rMarkdata.IsRowMarked((SCROW)nRow);
897 return bResult;
900 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn )
901 throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception)
903 SolarMutexGuard aGuard;
904 IsObjectValid();
906 if (IsFormulaMode())
908 return sal_False;
910 if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0))
911 throw lang::IndexOutOfBoundsException();
913 bool bResult(false);
914 if (mpViewShell)
916 const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
917 bResult = rMarkdata.IsColumnMarked((SCCOL)nColumn);
919 return bResult;
922 rtl::Reference<ScAccessibleCell> ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow, sal_Int32 nColumn)
924 if (IsFormulaMode())
926 ScAddress aCellAddress(static_cast<SCCOL>(nColumn), nRow, mpViewShell->GetViewData().GetTabNo());
927 if ((aCellAddress == m_aFormulaActiveCell) && m_pAccFormulaCell.is())
929 return m_pAccFormulaCell;
931 else
932 return ScAccessibleCell::create(this, mpViewShell, aCellAddress, GetAccessibleIndexFormula(nRow, nColumn), meSplitPos, mpAccDoc);
934 else
936 ScAddress aCellAddress(static_cast<SCCOL>(maRange.aStart.Col() + nColumn),
937 static_cast<SCROW>(maRange.aStart.Row() + nRow), maRange.aStart.Tab());
938 if ((aCellAddress == maActiveCell) && mpAccCell.is())
940 return mpAccCell;
942 else
943 return ScAccessibleCell::create(this, mpViewShell, aCellAddress, getAccessibleIndex(nRow, nColumn), meSplitPos, mpAccDoc);
947 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
948 throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception)
950 SolarMutexGuard aGuard;
951 IsObjectValid();
952 if (!IsFormulaMode())
954 if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
955 nRow < 0 ||
956 nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
957 nColumn < 0)
958 throw lang::IndexOutOfBoundsException();
960 rtl::Reference<ScAccessibleCell> pAccessibleCell = GetAccessibleCellAt(nRow, nColumn);
961 return pAccessibleCell.get();
964 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
965 throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception)
967 SolarMutexGuard aGuard;
968 IsObjectValid();
970 if (IsFormulaMode())
972 ScAddress addr(static_cast<SCCOL>(nColumn), nRow, 0);
973 return IsScAddrFormulaSel(addr);
975 if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
976 (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
977 throw lang::IndexOutOfBoundsException();
979 bool bResult(false);
980 if (mpViewShell)
982 const ScMarkData& rMarkdata = mpViewShell->GetViewData().GetMarkData();
983 bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow));
985 return bResult;
988 //===== XAccessibleComponent ============================================
990 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleAtPoint(const awt::Point& rPoint)
991 throw (uno::RuntimeException, std::exception)
993 uno::Reference< XAccessible > xAccessible;
994 if (containsPoint(rPoint))
996 SolarMutexGuard aGuard;
997 IsObjectValid();
998 if (mpViewShell)
1000 SCsCOL nX;
1001 SCsROW nY;
1002 mpViewShell->GetViewData().GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY);
1003 try {
1004 xAccessible = getAccessibleCellAt(nY, nX);
1006 catch(const ::com::sun::star::lang::IndexOutOfBoundsException &)
1008 return NULL;
1012 return xAccessible;
1015 void SAL_CALL ScAccessibleSpreadsheet::grabFocus( )
1016 throw (uno::RuntimeException, std::exception)
1018 if (getAccessibleParent().is())
1020 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1021 if (xAccessibleComponent.is())
1022 xAccessibleComponent->grabFocus();
1026 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getForeground( )
1027 throw (uno::RuntimeException, std::exception)
1029 return COL_BLACK;
1032 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground( )
1033 throw (uno::RuntimeException, std::exception)
1035 SolarMutexGuard aGuard;
1036 IsObjectValid();
1037 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
1040 //===== XAccessibleContext ==============================================
1042 uno::Reference<XAccessibleRelationSet> SAL_CALL ScAccessibleSpreadsheet::getAccessibleRelationSet()
1043 throw (::com::sun::star::uno::RuntimeException, std::exception)
1045 utl::AccessibleRelationSetHelper* pRelationSet = NULL;
1046 if(mpAccDoc)
1047 pRelationSet = mpAccDoc->GetRelationSet(NULL);
1048 if (!pRelationSet)
1049 pRelationSet = new utl::AccessibleRelationSetHelper();
1050 return pRelationSet;
1053 uno::Reference<XAccessibleStateSet> SAL_CALL
1054 ScAccessibleSpreadsheet::getAccessibleStateSet()
1055 throw (uno::RuntimeException, std::exception)
1057 SolarMutexGuard aGuard;
1058 uno::Reference<XAccessibleStateSet> xParentStates;
1059 if (getAccessibleParent().is())
1061 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1062 xParentStates = xParentContext->getAccessibleStateSet();
1064 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1065 if (IsDefunc(xParentStates))
1066 pStateSet->AddState(AccessibleStateType::DEFUNC);
1067 else
1069 pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS);
1070 if (IsEditable(xParentStates))
1071 pStateSet->AddState(AccessibleStateType::EDITABLE);
1072 pStateSet->AddState(AccessibleStateType::ENABLED);
1073 pStateSet->AddState(AccessibleStateType::FOCUSABLE);
1074 if (IsFocused())
1075 pStateSet->AddState(AccessibleStateType::FOCUSED);
1076 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
1077 pStateSet->AddState(AccessibleStateType::OPAQUE);
1078 pStateSet->AddState(AccessibleStateType::SELECTABLE);
1079 if (IsCompleteSheetSelected())
1080 pStateSet->AddState(AccessibleStateType::SELECTED);
1081 if (isShowing())
1082 pStateSet->AddState(AccessibleStateType::SHOWING);
1083 if (isVisible())
1084 pStateSet->AddState(AccessibleStateType::VISIBLE);
1086 return pStateSet;
1089 ///===== XAccessibleSelection ===========================================
1091 void SAL_CALL ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex )
1092 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1094 SolarMutexGuard aGuard;
1095 IsObjectValid();
1096 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
1097 throw lang::IndexOutOfBoundsException();
1099 if (mpViewShell)
1101 sal_Int32 nCol(getAccessibleColumn(nChildIndex));
1102 sal_Int32 nRow(getAccessibleRow(nChildIndex));
1104 SelectCell(nRow, nCol, false);
1108 void SAL_CALL
1109 ScAccessibleSpreadsheet::clearAccessibleSelection( )
1110 throw (uno::RuntimeException, std::exception)
1112 SolarMutexGuard aGuard;
1113 IsObjectValid();
1114 if (mpViewShell)
1116 if (!IsFormulaMode())
1117 mpViewShell->Unmark();
1121 void SAL_CALL ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
1122 throw (uno::RuntimeException, std::exception)
1124 SolarMutexGuard aGuard;
1125 IsObjectValid();
1126 if (mpViewShell)
1128 if (IsFormulaMode())
1130 ScViewData& rViewData = mpViewShell->GetViewData();
1131 mpViewShell->InitRefMode( 0, 0, rViewData.GetTabNo(), SC_REFTYPE_REF );
1132 rViewData.SetRefStart(0, 0, rViewData.GetTabNo());
1133 rViewData.SetRefEnd(MAXCOL, MAXROW, rViewData.GetTabNo());
1134 mpViewShell->UpdateRef(MAXCOL, MAXROW, rViewData.GetTabNo());
1136 else
1137 mpViewShell->SelectAll();
1141 sal_Int32 SAL_CALL
1142 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
1143 throw (uno::RuntimeException, std::exception)
1145 SolarMutexGuard aGuard;
1146 IsObjectValid();
1147 sal_Int32 nResult(0);
1148 if (mpViewShell)
1150 if (IsFormulaMode())
1152 nResult = GetRowAll() * GetColAll() ;
1154 else
1156 if (!mpMarkedRanges)
1158 mpMarkedRanges = new ScRangeList();
1159 ScMarkData aMarkData(mpViewShell->GetViewData().GetMarkData());
1160 aMarkData.FillRangeListWithMarks(mpMarkedRanges, false);
1162 // is possible, because there shouldn't be overlapped ranges in it
1163 if (mpMarkedRanges)
1164 nResult = mpMarkedRanges->GetCellCount();
1167 return nResult;
1170 uno::Reference<XAccessible > SAL_CALL
1171 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1172 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1174 SolarMutexGuard aGuard;
1175 IsObjectValid();
1176 uno::Reference < XAccessible > xAccessible;
1177 if (IsFormulaMode())
1179 if(CheckChildIndex(nSelectedChildIndex))
1181 ScAddress addr = GetChildIndexAddress(nSelectedChildIndex);
1182 xAccessible = getAccessibleCellAt(addr.Row(), addr.Col());
1184 return xAccessible;
1186 if (mpViewShell)
1188 if (!mpMarkedRanges)
1190 mpMarkedRanges = new ScRangeList();
1191 mpViewShell->GetViewData().GetMarkData().FillRangeListWithMarks(mpMarkedRanges, false);
1193 if (mpMarkedRanges)
1195 if ((nSelectedChildIndex < 0) ||
1196 (mpMarkedRanges->GetCellCount() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
1198 throw lang::IndexOutOfBoundsException();
1200 ScMyAddress addr = CalcScAddressFromRangeList(mpMarkedRanges,nSelectedChildIndex);
1201 if( m_mapSelectionSend.find(addr) != m_mapSelectionSend.end() )
1202 xAccessible = m_mapSelectionSend[addr];
1203 else
1204 xAccessible = getAccessibleCellAt(addr.Row(), addr.Col());
1207 return xAccessible;
1210 void SAL_CALL ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex )
1211 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1213 SolarMutexGuard aGuard;
1214 IsObjectValid();
1216 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
1217 throw lang::IndexOutOfBoundsException();
1219 if (mpViewShell)
1221 sal_Int32 nCol(getAccessibleColumn(nChildIndex));
1222 sal_Int32 nRow(getAccessibleRow(nChildIndex));
1224 if (IsFormulaMode())
1226 if(IsScAddrFormulaSel(
1227 ScAddress(static_cast<SCCOL>(nCol), nRow,mpViewShell->GetViewData().GetTabNo()))
1230 SelectCell(nRow, nCol, true);
1232 return ;
1234 if (mpViewShell->GetViewData().GetMarkData().IsCellMarked(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)))
1235 SelectCell(nRow, nCol, true);
1239 void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow, sal_Int32 nCol, bool bDeselect)
1241 if (IsFormulaMode())
1243 if (bDeselect)
1244 {//??
1245 return;
1247 else
1249 ScViewData& rViewData = mpViewShell->GetViewData();
1251 mpViewShell->InitRefMode( static_cast<SCCOL>(nCol), nRow, rViewData.GetTabNo(), SC_REFTYPE_REF );
1252 mpViewShell->UpdateRef(static_cast<SCCOL>(nCol), nRow, rViewData.GetTabNo());
1254 return ;
1256 mpViewShell->SetTabNo( maRange.aStart.Tab() );
1258 mpViewShell->DoneBlockMode( true ); // continue selecting
1259 mpViewShell->InitBlockMode( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), maRange.aStart.Tab(), bDeselect, false, false );
1261 mpViewShell->SelectionChanged();
1265 void ScAccessibleSpreadsheet::CreateSortedMarkedCells()
1267 mpSortedMarkedCells = new std::vector<ScMyAddress>();
1268 mpSortedMarkedCells->reserve(mpMarkedRanges->GetCellCount());
1269 for ( size_t i = 0, ListSize = mpMarkedRanges->size(); i < ListSize; ++i )
1271 ScRange* pRange = (*mpMarkedRanges)[i];
1272 if (pRange->aStart.Tab() != pRange->aEnd.Tab())
1274 if ((maActiveCell.Tab() >= pRange->aStart.Tab()) ||
1275 maActiveCell.Tab() <= pRange->aEnd.Tab())
1277 ScRange aRange(*pRange);
1278 aRange.aStart.SetTab(maActiveCell.Tab());
1279 aRange.aEnd.SetTab(maActiveCell.Tab());
1280 AddMarkedRange(aRange);
1282 else
1284 OSL_FAIL("Range of wrong table");
1287 else if(pRange->aStart.Tab() == maActiveCell.Tab())
1288 AddMarkedRange(*pRange);
1289 else
1291 OSL_FAIL("Range of wrong table");
1294 std::sort(mpSortedMarkedCells->begin(), mpSortedMarkedCells->end());
1297 void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange& rRange)
1299 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
1301 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1303 ScMyAddress aCell(nCol, nRow, maActiveCell.Tab());
1304 mpSortedMarkedCells->push_back(aCell);
1309 //===== XServiceInfo ====================================================
1311 OUString SAL_CALL ScAccessibleSpreadsheet::getImplementationName()
1312 throw (uno::RuntimeException, std::exception)
1314 return OUString("ScAccessibleSpreadsheet");
1317 uno::Sequence< OUString> SAL_CALL
1318 ScAccessibleSpreadsheet::getSupportedServiceNames()
1319 throw (uno::RuntimeException, std::exception)
1321 uno::Sequence< OUString > aSequence = ScAccessibleTableBase::getSupportedServiceNames();
1322 sal_Int32 nOldSize(aSequence.getLength());
1323 aSequence.realloc(nOldSize + 1);
1325 aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheet";
1327 return aSequence;
1330 //===== XTypeProvider =======================================================
1332 uno::Sequence<sal_Int8> SAL_CALL
1333 ScAccessibleSpreadsheet::getImplementationId()
1334 throw (uno::RuntimeException, std::exception)
1336 return css::uno::Sequence<sal_Int8>();
1339 ///===== XAccessibleEventBroadcaster =====================================
1341 void SAL_CALL ScAccessibleSpreadsheet::addAccessibleEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
1342 throw (uno::RuntimeException, std::exception)
1344 SolarMutexGuard aGuard;
1345 IsObjectValid();
1346 ScAccessibleTableBase::addAccessibleEventListener(xListener);
1350 //==== internal =========================================================
1352 Rectangle ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
1353 throw (uno::RuntimeException, std::exception)
1355 Rectangle aRect;
1356 if (mpViewShell)
1358 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1359 if (pWindow)
1360 aRect = pWindow->GetWindowExtentsRelative(NULL);
1362 return aRect;
1365 Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const
1366 throw (uno::RuntimeException, std::exception)
1368 Rectangle aRect;
1369 if (mpViewShell)
1371 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1372 if (pWindow)
1373 //#101986#; extends to the same window, because the parent is the document and it has the same window
1374 aRect = pWindow->GetWindowExtentsRelative(pWindow);
1376 return aRect;
1379 bool ScAccessibleSpreadsheet::IsDefunc(
1380 const uno::Reference<XAccessibleStateSet>& rxParentStates)
1382 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
1383 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1386 bool ScAccessibleSpreadsheet::IsEditable(
1387 const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
1389 if (IsFormulaMode())
1391 return false;
1393 bool bProtected(false);
1394 if (mpDoc && mpDoc->IsTabProtected(maRange.aStart.Tab()))
1395 bProtected = true;
1396 return !bProtected;
1399 bool ScAccessibleSpreadsheet::IsFocused()
1401 bool bFocused(false);
1402 if (mpViewShell)
1404 if (mpViewShell->GetViewData().GetActivePart() == meSplitPos)
1405 bFocused = mpViewShell->GetActiveWin()->HasFocus();
1407 return bFocused;
1410 bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
1412 if (IsFormulaMode())
1414 return false;
1417 bool bResult(false);
1418 if(mpViewShell)
1420 //#103800#; use a copy of MarkData
1421 ScMarkData aMarkData(mpViewShell->GetViewData().GetMarkData());
1422 aMarkData.MarkToMulti();
1423 if (aMarkData.IsAllMarked(maRange))
1424 bResult = true;
1426 return bResult;
1429 ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell)
1431 ScDocument* pDoc = NULL;
1432 if (pViewShell)
1433 pDoc = pViewShell->GetViewData().GetDocument();
1434 return pDoc;
1437 Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
1439 Rectangle aVisArea;
1440 if (pViewShell)
1442 vcl::Window* pWindow = pViewShell->GetWindowByPos(eSplitPos);
1443 if (pWindow)
1445 aVisArea.SetPos(pViewShell->GetViewData().GetPixPos(eSplitPos));
1446 aVisArea.SetSize(pWindow->GetSizePixel());
1449 return aVisArea;
1452 Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea)
1454 if (mpViewShell)
1456 SCsCOL nStartX, nEndX;
1457 SCsROW nStartY, nEndY;
1459 mpViewShell->GetViewData().GetPosFromPixel( 1, 1, meSplitPos, nStartX, nStartY);
1460 mpViewShell->GetViewData().GetPosFromPixel( rVisArea.GetWidth(), rVisArea.GetHeight(), meSplitPos, nEndX, nEndY);
1462 return Rectangle(nStartX, nStartY, nEndX, nEndY);
1464 else
1465 return Rectangle();
1468 sal_Bool SAL_CALL ScAccessibleSpreadsheet::selectRow( sal_Int32 row )
1469 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1471 SolarMutexGuard g;
1473 if (IsFormulaMode())
1475 return sal_False;
1478 mpViewShell->SetTabNo( maRange.aStart.Tab() );
1479 mpViewShell->DoneBlockMode( true ); // continue selecting
1480 mpViewShell->InitBlockMode( 0, row, maRange.aStart.Tab(), false, false, true );
1481 mpViewShell->MarkCursor( MAXCOL, row, maRange.aStart.Tab(), false, true );
1482 mpViewShell->SelectionChanged();
1483 return sal_True;
1486 sal_Bool SAL_CALL ScAccessibleSpreadsheet::selectColumn( sal_Int32 column )
1487 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1489 SolarMutexGuard g;
1491 if (IsFormulaMode())
1493 return sal_False;
1496 mpViewShell->SetTabNo( maRange.aStart.Tab() );
1497 mpViewShell->DoneBlockMode( true ); // continue selecting
1498 mpViewShell->InitBlockMode( static_cast<SCCOL>(column), 0, maRange.aStart.Tab(), false, true, false );
1499 mpViewShell->MarkCursor( static_cast<SCCOL>(column), MAXROW, maRange.aStart.Tab(), true, false );
1500 mpViewShell->SelectionChanged();
1501 return sal_True;
1504 sal_Bool SAL_CALL ScAccessibleSpreadsheet::unselectRow( sal_Int32 row )
1505 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1507 SolarMutexGuard g;
1509 if (IsFormulaMode())
1511 return sal_False;
1514 mpViewShell->SetTabNo( maRange.aStart.Tab() );
1515 mpViewShell->DoneBlockMode( true ); // continue selecting
1516 mpViewShell->InitBlockMode( 0, row, maRange.aStart.Tab(), false, false, true, true );
1517 mpViewShell->MarkCursor( MAXCOL, row, maRange.aStart.Tab(), false, true );
1518 mpViewShell->SelectionChanged();
1519 mpViewShell->DoneBlockMode( true );
1520 return sal_True;
1523 sal_Bool SAL_CALL ScAccessibleSpreadsheet::unselectColumn( sal_Int32 column )
1524 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1526 SolarMutexGuard g;
1528 if (IsFormulaMode())
1530 return sal_False;
1533 mpViewShell->SetTabNo( maRange.aStart.Tab() );
1534 mpViewShell->DoneBlockMode( true ); // continue selecting
1535 mpViewShell->InitBlockMode( static_cast<SCCOL>(column), 0, maRange.aStart.Tab(), false, true, false, true );
1536 mpViewShell->MarkCursor( static_cast<SCCOL>(column), MAXROW, maRange.aStart.Tab(), true, false );
1537 mpViewShell->SelectionChanged();
1538 mpViewShell->DoneBlockMode( true );
1539 return sal_True;
1542 void ScAccessibleSpreadsheet::FireFirstCellFocus()
1544 if (IsFormulaMode())
1546 return ;
1548 if (mbIsFocusSend)
1550 return ;
1552 mbIsFocusSend = true;
1553 AccessibleEventObject aEvent;
1554 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1555 aEvent.Source = uno::Reference< XAccessible >(this);
1556 aEvent.NewValue <<= getAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
1557 CommitChange(aEvent);
1560 void ScAccessibleSpreadsheet::NotifyRefMode()
1562 ScViewData& rViewData = mpViewShell->GetViewData();
1563 if (!rViewData.IsRefMode())
1564 // Not in reference mode. Bail out.
1565 return;
1567 sal_uInt16 nRefStartX = rViewData.GetRefStartX();
1568 sal_Int32 nRefStartY = rViewData.GetRefStartY();
1569 sal_uInt16 nRefEndX = rViewData.GetRefEndX();
1570 sal_Int32 nRefEndY = rViewData.GetRefEndY();
1571 ScAddress aFormulaAddr;
1572 if(!GetFormulaCurrentFocusCell(aFormulaAddr))
1574 return ;
1576 if (m_aFormulaActiveCell != aFormulaAddr)
1577 {//New Focus
1578 m_nMinX =std::min(nRefStartX,nRefEndX);
1579 m_nMaxX =std::max(nRefStartX,nRefEndX);
1580 m_nMinY = std::min(nRefStartY,nRefEndY);
1581 m_nMaxY = std::max(nRefStartY,nRefEndY);
1582 RemoveFormulaSelection();
1583 AccessibleEventObject aEvent;
1584 aEvent.Source = uno::Reference< XAccessible >(this);
1585 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1586 aEvent.Source = uno::Reference< XAccessible >(this);
1587 aEvent.OldValue <<= uno::Reference<XAccessible>(m_pAccFormulaCell.get());
1588 m_pAccFormulaCell = GetAccessibleCellAt(aFormulaAddr.Row(), aFormulaAddr.Col());
1589 uno::Reference< XAccessible > xNew = m_pAccFormulaCell.get();
1590 aEvent.NewValue <<= xNew;
1591 CommitChange(aEvent);
1592 if (nRefStartX == nRefEndX && nRefStartY == nRefEndY)
1593 {//Selection Single
1594 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1595 aEvent.NewValue <<= xNew;
1596 CommitChange(aEvent);
1597 m_mapFormulaSelectionSend.insert(MAP_ADDR_XACC::value_type(aFormulaAddr,xNew));
1598 m_vecFormulaLastMyAddr.clear();
1599 m_vecFormulaLastMyAddr.push_back(aFormulaAddr);
1601 else
1603 VEC_MYADDR vecCurSel;
1604 int nCurSize = (m_nMaxX - m_nMinX +1)*(m_nMaxY - m_nMinY +1) ;
1605 vecCurSel.reserve(nCurSize);
1606 for (sal_uInt16 x = m_nMinX ; x <= m_nMaxX ; ++x)
1608 for (sal_Int32 y = m_nMinY ; y <= m_nMaxY ; ++y)
1610 ScMyAddress aAddr(x,y,0);
1611 vecCurSel.push_back(aAddr);
1614 std::sort(vecCurSel.begin(), vecCurSel.end());
1615 VEC_MYADDR vecNew;
1616 std::set_difference(vecCurSel.begin(),vecCurSel.end(),
1617 m_vecFormulaLastMyAddr.begin(),m_vecFormulaLastMyAddr.end(),
1618 std::back_insert_iterator<VEC_MYADDR>(vecNew));
1619 int nNewSize = vecNew.size();
1620 if ( nNewSize > 10 )
1622 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1623 aEvent.NewValue <<= ::com::sun::star::uno::Any();
1624 CommitChange(aEvent);
1626 else
1628 VEC_MYADDR::iterator viAddr = vecNew.begin();
1629 for(; viAddr != vecNew.end() ; ++viAddr )
1631 uno::Reference< XAccessible > xChild;
1632 if (*viAddr == aFormulaAddr)
1634 xChild = m_pAccFormulaCell.get();
1636 else
1638 xChild = getAccessibleCellAt(viAddr->Row(),viAddr->Col());
1639 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS;
1640 aEvent.NewValue <<= xChild;
1641 CommitChange(aEvent);
1643 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1644 aEvent.NewValue <<= xChild;
1645 CommitChange(aEvent);
1646 m_mapFormulaSelectionSend.insert(MAP_ADDR_XACC::value_type(*viAddr,xChild));
1649 m_vecFormulaLastMyAddr.swap(vecCurSel);
1652 m_aFormulaActiveCell = aFormulaAddr;
1655 void ScAccessibleSpreadsheet::RemoveFormulaSelection(bool bRemoveAll )
1657 AccessibleEventObject aEvent;
1658 aEvent.Source = uno::Reference< XAccessible >(this);
1659 aEvent.OldValue <<= ::com::sun::star::uno::Any();
1660 MAP_ADDR_XACC::iterator miRemove = m_mapFormulaSelectionSend.begin();
1661 for(; miRemove != m_mapFormulaSelectionSend.end() ;)
1663 if( !bRemoveAll && IsScAddrFormulaSel(miRemove->first) )
1665 ++miRemove;
1666 continue;
1668 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1669 aEvent.NewValue <<= miRemove->second;
1670 CommitChange(aEvent);
1671 MAP_ADDR_XACC::iterator miNext = miRemove;
1672 ++miNext;
1673 m_mapFormulaSelectionSend.erase(miRemove);
1674 miRemove = miNext;
1678 bool ScAccessibleSpreadsheet::IsScAddrFormulaSel(const ScAddress &addr) const
1680 if( addr.Col() >= m_nMinX && addr.Col() <= m_nMaxX &&
1681 addr.Row() >= m_nMinY && addr.Row() <= m_nMaxY &&
1682 addr.Tab() == mpViewShell->GetViewData().GetTabNo() )
1684 return true;
1686 return false;
1689 bool ScAccessibleSpreadsheet::CheckChildIndex(sal_Int32 nIndex) const
1691 sal_Int32 nMaxIndex = (m_nMaxX - m_nMinX +1)*(m_nMaxY - m_nMinY +1) -1 ;
1692 return nIndex <= nMaxIndex && nIndex >= 0 ;
1695 ScAddress ScAccessibleSpreadsheet::GetChildIndexAddress(sal_Int32 nIndex) const
1697 sal_Int32 nRowAll = GetRowAll();
1698 sal_uInt16 nColAll = GetColAll();
1699 if (nIndex < 0 || nIndex >= nRowAll * nColAll )
1701 return ScAddress();
1703 return ScAddress(
1704 static_cast<SCCOL>((nIndex - nIndex % nRowAll) / nRowAll + + m_nMinX),
1705 nIndex % nRowAll + m_nMinY,
1706 mpViewShell->GetViewData().GetTabNo()
1710 sal_Int32 ScAccessibleSpreadsheet::GetAccessibleIndexFormula( sal_Int32 nRow, sal_Int32 nColumn )
1712 sal_uInt16 nColRelative = sal_uInt16(nColumn) - GetColAll();
1713 sal_Int32 nRowRelative = nRow - GetRowAll();
1714 if (nRow < 0 || nColumn < 0 || nRowRelative >= GetRowAll() || nColRelative >= GetColAll() )
1716 return -1;
1718 return GetRowAll() * nRowRelative + nColRelative;
1721 bool ScAccessibleSpreadsheet::IsFormulaMode()
1723 ScViewData& rViewData = mpViewShell->GetViewData();
1724 m_bFormulaMode = rViewData.IsRefMode() || SC_MOD()->IsFormulaMode();
1725 return m_bFormulaMode ;
1728 bool ScAccessibleSpreadsheet::GetFormulaCurrentFocusCell(ScAddress &addr)
1730 ScViewData& rViewData = mpViewShell->GetViewData();
1731 sal_uInt16 nRefX=0;
1732 sal_Int32 nRefY=0;
1733 if(m_bFormulaLastMode)
1735 nRefX=rViewData.GetRefEndX();
1736 nRefY=rViewData.GetRefEndY();
1738 else
1740 nRefX=rViewData.GetRefStartX();
1741 nRefY=rViewData.GetRefStartY();
1743 if( /* Always true: nRefX >= 0 && */ nRefX <= MAXCOL && nRefY >= 0 && nRefY <= MAXROW)
1745 addr = ScAddress(nRefX,nRefY,rViewData.GetTabNo());
1746 return true;
1748 return false;
1751 uno::Reference < XAccessible > ScAccessibleSpreadsheet::GetActiveCell()
1753 if( m_mapSelectionSend.find( maActiveCell ) != m_mapSelectionSend.end() )
1754 return m_mapSelectionSend[maActiveCell];
1755 else
1756 return getAccessibleCellAt(maActiveCell.Row(), maActiveCell .Col());
1759 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */