1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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"
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();
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());
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
);
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
);
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
)
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
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
)
148 else if(nCellCount
> 0)
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()));
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
)
171 ScMyAddress
cell(col
,nMinRow
,pSrc
->aStart
.Tab());
173 {//In Src ,Not In Dest
174 vecRet
.push_back(cell
);
178 if (nMinRow
!= nMaxRow
)
180 for (sal_uInt16 col
= pSrc
->aStart
.Col(); col
<= pSrc
->aEnd
.Col();++col
)
186 ScMyAddress
cell(col
,nMaxRow
,pSrc
->aStart
.Tab());
188 {//In Src ,Not In Dest
189 vecRet
.push_back(cell
);
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
)
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
212 //now the cell count is less then nMax
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()));
228 //the Dest Rang List is not empty
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
))
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
,
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
;
279 mpViewShell
->RemoveAccessibilityObject(*this);
282 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
283 ScAccessibleDocument
* pAccDoc
,
284 ScTabViewShell
* pViewShell
,
286 ScSplitPos eSplitPos
)
288 mpViewShell
= pViewShell
;
290 mpSortedMarkedCells
= 0;
293 meSplitPos
= eSplitPos
;
295 mbHasSelection
= false;
297 mbIsFocusSend
= false;
298 maVisCells
= GetVisCells(GetVisArea(mpViewShell
, meSplitPos
));
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
);
312 pScDoc
->GetName( maActiveCell
.Tab(), m_strOldTabName
);
317 void SAL_CALL
ScAccessibleSpreadsheet::disposing()
319 SolarMutexGuard aGuard
;
322 mpViewShell
->RemoveAccessibilityObject(*this);
327 ScAccessibleTableBase::disposing();
330 void ScAccessibleSpreadsheet::CompleteSelectionChanged(bool bNewState
)
337 DELETEZ(mpMarkedRanges
);
338 mbHasSelection
= bNewState
;
340 AccessibleEventObject aEvent
;
341 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
343 aEvent
.NewValue
= uno::makeAny(AccessibleStateType::SELECTED
);
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
);
363 void ScAccessibleSpreadsheet::GotFocus()
366 AccessibleEventObject aEvent
;
367 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
368 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
369 uno::Reference
< XAccessible
> xNew
;
372 if (!m_pAccFormulaCell
.is() || !m_bFormulaLastMode
)
374 ScAddress aFormulaAddr
;
375 if(!GetFormulaCurrentFocusCell(aFormulaAddr
))
379 m_pAccFormulaCell
= GetAccessibleCellAt(aFormulaAddr
.Row(),aFormulaAddr
.Col());
381 xNew
= m_pAccFormulaCell
.get();
385 if(mpAccCell
->GetCellAddress() == maActiveCell
)
387 xNew
= mpAccCell
.get();
391 CommitFocusCell(maActiveCell
);
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
);
425 if (pSimpleHint
->GetId() == SC_HINT_ACC_CURSORCHANGED
)
429 ScViewData
& rViewData
= mpViewShell
->GetViewData();
431 m_bFormulaMode
= rViewData
.IsRefMode() || SC_MOD()->IsFormulaMode();
432 if ( m_bFormulaMode
)
435 m_bFormulaLastMode
= true;
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());
457 pAccDoc
->CommitChange(aEvent
);
460 bool bNewPosCell
= (aNewCell
!= maActiveCell
) || mpViewShell
->GetForceFocusOnCurCell(); // #i123629#
461 bool bNewPosCellFocus
=false;
462 if ( bNewPosCell
&& IsFocused() && aNewCell
.Tab() == maActiveCell
.Tab() )
464 bNewPosCellFocus
=true;
466 ScMarkData
&refScMarkData
= rViewData
.GetMarkData();
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();
475 refScMarkData
.GetMarkArea(aMarkRange
);
476 aEvent
.OldValue
<<= ::com::sun::star::uno::Any();
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
);
489 mpMarkedRanges
= new ScRangeList();
491 refScMarkData
.FillRangeListWithMarks(mpMarkedRanges
, true);
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
);
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
);
509 bLastIsWholeColRow
&&
510 !aMarkRange
.In(m_aLastWithInMarkRange
) &&
511 aMarkRange
.Intersects(m_aLastWithInMarkRange
);
514 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_WITHIN
;
515 aEvent
.NewValue
<<= ::com::sun::star::uno::Any();
516 CommitChange(aEvent
);
518 m_aLastWithInMarkRange
= aMarkRange
;
522 m_aLastWithInMarkRange
= aMarkRange
;
523 int nNewMarkCount
= mpMarkedRanges
->GetCellCount();
524 bool bSendSingle
= (0 == nNewMarkCount
) && bNewPosCell
;
527 RemoveSelection(refScMarkData
);
530 CommitFocusCell(aNewCell
);
532 uno::Reference
< XAccessible
> xChild
;
533 if (bNewPosCellFocus
)
535 xChild
= mpAccCell
.get();
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
));
558 bool bIsDel
= rViewData
.GetDelMark( aDelRange
);
559 if ( (!bIsDel
|| (bIsDel
&& aMarkRange
!= aDelRange
)) &&
564 RemoveSelection(refScMarkData
);
567 CommitFocusCell(aNewCell
);
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
);
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
)
606 CommitTableModelChange(maRange
.aStart
.Row(), maRange
.aStart
.Col(), maRange
.aEnd
.Row(), maRange
.aEnd
.Col(), AccessibleTableModelChangeType::UPDATE
);
609 ScViewData
& rViewData
= mpViewShell
->GetViewData();
610 ScAddress aNewCell
= rViewData
.GetCurPos();
611 if( maActiveCell
== aNewCell
)
613 ScDocument
* pScDoc
= GetDocument(mpViewShell
);
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
;
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
646 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
648 Rectangle aNewPos(aNewVisCells);
650 if (aNewVisCells.IsOver(maVisCells))
651 aNewPos.Union(maVisCells);
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
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
;
685 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
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
;
698 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
700 nX
= aRange
.aEnd
.Col() - aRange
.aStart
.Col();
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) )
739 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_REMOVE
;
740 aEvent
.NewValue
<<= miRemove
->second
;
741 CommitChange(aEvent
);
742 MAP_ADDR_XACC::iterator miNext
= miRemove
;
744 m_mapSelectionSend
.erase(miRemove
);
748 void ScAccessibleSpreadsheet::CommitFocusCell(const ScAddress
&aNewCell
)
750 OSL_ASSERT(!IsFormulaMode());
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());
760 mpAccCell
= GetAccessibleCellAt(aNewCell
.Row(), aNewCell
.Col());
761 aEvent
.NewValue
<<= uno::Reference
<XAccessible
>(mpAccCell
.get());
762 maActiveCell
= aNewCell
;
763 ScDocument
* pScDoc
= GetDocument(mpViewShell
);
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
;
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
;
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
;
821 uno::Sequence
<sal_Int32
> aSequence
;
828 aSequence
.realloc(maRange
.aEnd
.Row() - maRange
.aStart
.Row() + 1);
829 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData().GetMarkData();
830 sal_Int32
* pSequence
= aSequence
.getArray();
832 for (SCROW i
= maRange
.aStart
.Row(); i
<= maRange
.aEnd
.Row(); ++i
)
834 if (rMarkdata
.IsRowMarked(i
))
836 pSequence
[nCount
] = i
;
840 aSequence
.realloc(nCount
);
843 aSequence
.realloc(0);
847 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
848 throw (uno::RuntimeException
, std::exception
)
850 SolarMutexGuard aGuard
;
852 uno::Sequence
<sal_Int32
> aSequence
;
859 aSequence
.realloc(maRange
.aEnd
.Col() - maRange
.aStart
.Col() + 1);
860 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData().GetMarkData();
861 sal_Int32
* pSequence
= aSequence
.getArray();
863 for (SCCOL i
= maRange
.aStart
.Col(); i
<= maRange
.aEnd
.Col(); ++i
)
865 if (rMarkdata
.IsColumnMarked(i
))
867 pSequence
[nCount
] = i
;
871 aSequence
.realloc(nCount
);
874 aSequence
.realloc(0);
878 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow
)
879 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
, std::exception
)
881 SolarMutexGuard aGuard
;
888 if ((nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row())) || (nRow
< 0))
889 throw lang::IndexOutOfBoundsException();
894 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData().GetMarkData();
895 bResult
= rMarkdata
.IsRowMarked((SCROW
)nRow
);
900 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn
)
901 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
, std::exception
)
903 SolarMutexGuard aGuard
;
910 if ((nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col())) || (nColumn
< 0))
911 throw lang::IndexOutOfBoundsException();
916 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData().GetMarkData();
917 bResult
= rMarkdata
.IsColumnMarked((SCCOL
)nColumn
);
922 rtl::Reference
<ScAccessibleCell
> ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow
, sal_Int32 nColumn
)
926 ScAddress
aCellAddress(static_cast<SCCOL
>(nColumn
), nRow
, mpViewShell
->GetViewData().GetTabNo());
927 if ((aCellAddress
== m_aFormulaActiveCell
) && m_pAccFormulaCell
.is())
929 return m_pAccFormulaCell
;
932 return ScAccessibleCell::create(this, mpViewShell
, aCellAddress
, GetAccessibleIndexFormula(nRow
, nColumn
), meSplitPos
, mpAccDoc
);
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())
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
;
952 if (!IsFormulaMode())
954 if (nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row()) ||
956 nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col()) ||
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
;
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();
982 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData().GetMarkData();
983 bResult
= rMarkdata
.IsCellMarked(static_cast<SCCOL
>(nColumn
), static_cast<SCROW
>(nRow
));
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
;
1002 mpViewShell
->GetViewData().GetPosFromPixel( rPoint
.X
, rPoint
.Y
, meSplitPos
, nX
, nY
);
1004 xAccessible
= getAccessibleCellAt(nY
, nX
);
1006 catch(const ::com::sun::star::lang::IndexOutOfBoundsException
&)
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
)
1032 sal_Int32 SAL_CALL
ScAccessibleSpreadsheet::getBackground( )
1033 throw (uno::RuntimeException
, std::exception
)
1035 SolarMutexGuard aGuard
;
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
;
1047 pRelationSet
= mpAccDoc
->GetRelationSet(NULL
);
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
);
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
);
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
);
1082 pStateSet
->AddState(AccessibleStateType::SHOWING
);
1084 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
1089 ///===== XAccessibleSelection ===========================================
1091 void SAL_CALL
ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex
)
1092 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1094 SolarMutexGuard aGuard
;
1096 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
1097 throw lang::IndexOutOfBoundsException();
1101 sal_Int32
nCol(getAccessibleColumn(nChildIndex
));
1102 sal_Int32
nRow(getAccessibleRow(nChildIndex
));
1104 SelectCell(nRow
, nCol
, false);
1109 ScAccessibleSpreadsheet::clearAccessibleSelection( )
1110 throw (uno::RuntimeException
, std::exception
)
1112 SolarMutexGuard aGuard
;
1116 if (!IsFormulaMode())
1117 mpViewShell
->Unmark();
1121 void SAL_CALL
ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
1122 throw (uno::RuntimeException
, std::exception
)
1124 SolarMutexGuard aGuard
;
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());
1137 mpViewShell
->SelectAll();
1142 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
1143 throw (uno::RuntimeException
, std::exception
)
1145 SolarMutexGuard aGuard
;
1147 sal_Int32
nResult(0);
1150 if (IsFormulaMode())
1152 nResult
= GetRowAll() * GetColAll() ;
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
1164 nResult
= mpMarkedRanges
->GetCellCount();
1170 uno::Reference
<XAccessible
> SAL_CALL
1171 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
1172 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1174 SolarMutexGuard aGuard
;
1176 uno::Reference
< XAccessible
> xAccessible
;
1177 if (IsFormulaMode())
1179 if(CheckChildIndex(nSelectedChildIndex
))
1181 ScAddress addr
= GetChildIndexAddress(nSelectedChildIndex
);
1182 xAccessible
= getAccessibleCellAt(addr
.Row(), addr
.Col());
1188 if (!mpMarkedRanges
)
1190 mpMarkedRanges
= new ScRangeList();
1191 mpViewShell
->GetViewData().GetMarkData().FillRangeListWithMarks(mpMarkedRanges
, false);
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
];
1204 xAccessible
= getAccessibleCellAt(addr
.Row(), addr
.Col());
1210 void SAL_CALL
ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex
)
1211 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1213 SolarMutexGuard aGuard
;
1216 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
1217 throw lang::IndexOutOfBoundsException();
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);
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())
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());
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);
1284 OSL_FAIL("Range of wrong table");
1287 else if(pRange->aStart.Tab() == maActiveCell.Tab())
1288 AddMarkedRange(*pRange);
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";
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
;
1346 ScAccessibleTableBase::addAccessibleEventListener(xListener
);
1350 //==== internal =========================================================
1352 Rectangle
ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
1353 throw (uno::RuntimeException
, std::exception
)
1358 vcl::Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
1360 aRect
= pWindow
->GetWindowExtentsRelative(NULL
);
1365 Rectangle
ScAccessibleSpreadsheet::GetBoundingBox() const
1366 throw (uno::RuntimeException
, std::exception
)
1371 vcl::Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
1373 //#101986#; extends to the same window, because the parent is the document and it has the same window
1374 aRect
= pWindow
->GetWindowExtentsRelative(pWindow
);
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())
1393 bool bProtected(false);
1394 if (mpDoc
&& mpDoc
->IsTabProtected(maRange
.aStart
.Tab()))
1399 bool ScAccessibleSpreadsheet::IsFocused()
1401 bool bFocused(false);
1404 if (mpViewShell
->GetViewData().GetActivePart() == meSplitPos
)
1405 bFocused
= mpViewShell
->GetActiveWin()->HasFocus();
1410 bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
1412 if (IsFormulaMode())
1417 bool bResult(false);
1420 //#103800#; use a copy of MarkData
1421 ScMarkData
aMarkData(mpViewShell
->GetViewData().GetMarkData());
1422 aMarkData
.MarkToMulti();
1423 if (aMarkData
.IsAllMarked(maRange
))
1429 ScDocument
* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell
* pViewShell
)
1431 ScDocument
* pDoc
= NULL
;
1433 pDoc
= pViewShell
->GetViewData().GetDocument();
1437 Rectangle
ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell
* pViewShell
, ScSplitPos eSplitPos
)
1442 vcl::Window
* pWindow
= pViewShell
->GetWindowByPos(eSplitPos
);
1445 aVisArea
.SetPos(pViewShell
->GetViewData().GetPixPos(eSplitPos
));
1446 aVisArea
.SetSize(pWindow
->GetSizePixel());
1452 Rectangle
ScAccessibleSpreadsheet::GetVisCells(const Rectangle
& rVisArea
)
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
);
1468 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::selectRow( sal_Int32 row
)
1469 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1473 if (IsFormulaMode())
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();
1486 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::selectColumn( sal_Int32 column
)
1487 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1491 if (IsFormulaMode())
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();
1504 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::unselectRow( sal_Int32 row
)
1505 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1509 if (IsFormulaMode())
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 );
1523 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::unselectColumn( sal_Int32 column
)
1524 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
1528 if (IsFormulaMode())
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 );
1542 void ScAccessibleSpreadsheet::FireFirstCellFocus()
1544 if (IsFormulaMode())
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.
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
))
1576 if (m_aFormulaActiveCell
!= aFormulaAddr
)
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
)
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
);
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());
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
);
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();
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
) )
1668 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED_REMOVE
;
1669 aEvent
.NewValue
<<= miRemove
->second
;
1670 CommitChange(aEvent
);
1671 MAP_ADDR_XACC::iterator miNext
= miRemove
;
1673 m_mapFormulaSelectionSend
.erase(miRemove
);
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() )
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
)
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() )
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();
1733 if(m_bFormulaLastMode
)
1735 nRefX
=rViewData
.GetRefEndX();
1736 nRefY
=rViewData
.GetRefEndY();
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());
1751 uno::Reference
< XAccessible
> ScAccessibleSpreadsheet::GetActiveCell()
1753 if( m_mapSelectionSend
.find( maActiveCell
) != m_mapSelectionSend
.end() )
1754 return m_mapSelectionSend
[maActiveCell
];
1756 return getAccessibleCellAt(maActiveCell
.Row(), maActiveCell
.Col());
1759 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */