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 <vcl/help.hxx>
21 #include <vcl/svapp.hxx>
23 #include "tabview.hxx"
24 #include "document.hxx"
27 #include "gridwin.hxx"
28 #include "globstr.hrc"
30 #include "dociter.hxx"
32 extern sal_uInt16 nScFillModeMouseModifier
; // global.cxx
34 // STATIC DATA -----------------------------------------------------------
36 //==================================================================
39 // --- Referenz-Eingabe / Fill-Cursor
42 void ScTabView::HideTip()
46 Help::HideTip( nTipVisible
);
51 void ScTabView::ShowRefTip()
53 sal_Bool bDone
= false;
54 if ( aViewData
.GetRefType() == SC_REFTYPE_REF
&& Help::IsQuickHelpEnabled() )
56 SCCOL nStartX
= aViewData
.GetRefStartX();
57 SCROW nStartY
= aViewData
.GetRefStartY();
58 SCCOL nEndX
= aViewData
.GetRefEndX();
59 SCROW nEndY
= aViewData
.GetRefEndY();
60 if ( nEndX
!= nStartX
|| nEndY
!= nStartY
) // nicht fuer einzelne Zelle
62 sal_Bool bLeft
= ( nEndX
< nStartX
);
63 sal_Bool bTop
= ( nEndY
< nStartY
);
64 PutInOrder( nStartX
, nEndX
);
65 PutInOrder( nStartY
, nEndY
);
66 SCCOL nCols
= nEndX
+1-nStartX
;
67 SCROW nRows
= nEndY
+1-nStartY
;
69 String aHelp
= ScGlobal::GetRscString( STR_QUICKHELP_REF
);
70 aHelp
.SearchAndReplace( rtl::OUString("%1"),
71 String::CreateFromInt32(nRows
) );
72 aHelp
.SearchAndReplace( rtl::OUString("%2"),
73 String::CreateFromInt32(nCols
) );
75 ScSplitPos eWhich
= aViewData
.GetActivePart();
76 Window
* pWin
= pGridWin
[eWhich
];
79 Point aStart
= aViewData
.GetScrPos( nStartX
, nStartY
, eWhich
);
80 Point aEnd
= aViewData
.GetScrPos( nEndX
+1, nEndY
+1, eWhich
);
82 Point
aPos( bLeft
? aStart
.X() : ( aEnd
.X() + 3 ),
83 bTop
? aStart
.Y() : ( aEnd
.Y() + 3 ) );
84 sal_uInt16 nFlags
= ( bLeft
? QUICKHELP_RIGHT
: QUICKHELP_LEFT
) |
85 ( bTop
? QUICKHELP_BOTTOM
: QUICKHELP_TOP
);
87 // nicht ueber die editierte Formel
88 if ( !bTop
&& aViewData
.HasEditView( eWhich
) &&
89 nEndY
+1 == aViewData
.GetEditViewRow() )
91 // dann an der oberen Kante der editierten Zelle ausrichten
92 aPos
.Y() -= 2; // die 3 von oben
93 nFlags
= ( nFlags
& ~QUICKHELP_TOP
) | QUICKHELP_BOTTOM
;
96 Rectangle
aRect( pWin
->OutputToScreenPixel( aPos
), Size(1,1) );
98 //! Test, ob geaendert ??
101 nTipVisible
= Help::ShowTip( pWin
, aRect
, aHelp
, nFlags
);
111 void ScTabView::StopRefMode()
113 if (aViewData
.IsRefMode())
115 aViewData
.SetRefMode( false, SC_REFTYPE_NONE
);
118 UpdateShrinkOverlay();
120 if ( aViewData
.GetTabNo() >= aViewData
.GetRefStartZ() &&
121 aViewData
.GetTabNo() <= aViewData
.GetRefEndZ() )
123 ScDocument
* pDoc
= aViewData
.GetDocument();
124 SCCOL nStartX
= aViewData
.GetRefStartX();
125 SCROW nStartY
= aViewData
.GetRefStartY();
126 SCCOL nEndX
= aViewData
.GetRefEndX();
127 SCROW nEndY
= aViewData
.GetRefEndY();
128 if ( nStartX
== nEndX
&& nStartY
== nEndY
)
129 pDoc
->ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, aViewData
.GetTabNo() );
131 PaintArea( nStartX
,nStartY
,nEndX
,nEndY
, SC_UPDATE_MARKS
);
135 pSelEngine
->SetAddMode( false ); //! sollte das nicht bei Reset passieren?
137 ScSplitPos eOld
= pSelEngine
->GetWhich();
138 ScSplitPos eNew
= aViewData
.GetActivePart();
141 pSelEngine
->SetWindow( pGridWin
[ eNew
] );
142 pSelEngine
->SetWhich( eNew
);
143 pSelEngine
->SetVisibleArea( Rectangle(Point(),
144 pGridWin
[eNew
]->GetOutputSizePixel()) );
145 pGridWin
[eOld
]->MoveMouseStatus(*pGridWin
[eNew
]);
149 // AlignToCursor(SC_FOLLOW_NONE): Only switch active part.
150 // This must also be done if no RefMode was active (for RangeFinder dragging),
151 // but if RefMode was set, AlignToCursor must be after SelectionEngine reset,
152 // so the SelectionEngine SetWindow call from AlignToCursor doesn't capture
153 // the mouse again when called from Tracking/MouseButtonUp (#94562#).
154 AlignToCursor( aViewData
.GetCurX(), aViewData
.GetCurY(), SC_FOLLOW_NONE
);
157 void ScTabView::DoneRefMode( bool bContinue
)
159 ScDocument
* pDoc
= aViewData
.GetDocument();
160 if ( aViewData
.GetRefType() == SC_REFTYPE_REF
&& bContinue
)
161 SC_MOD()->AddRefEntry();
163 sal_Bool bWasRef
= aViewData
.IsRefMode();
164 aViewData
.SetRefMode( false, SC_REFTYPE_NONE
);
167 UpdateShrinkOverlay();
170 if ( bWasRef
&& aViewData
.GetTabNo() >= aViewData
.GetRefStartZ() &&
171 aViewData
.GetTabNo() <= aViewData
.GetRefEndZ() )
173 SCCOL nStartX
= aViewData
.GetRefStartX();
174 SCROW nStartY
= aViewData
.GetRefStartY();
175 SCCOL nEndX
= aViewData
.GetRefEndX();
176 SCROW nEndY
= aViewData
.GetRefEndY();
177 if ( nStartX
== nEndX
&& nStartY
== nEndY
)
178 pDoc
->ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, aViewData
.GetTabNo() );
180 PaintArea( nStartX
,nStartY
,nEndX
,nEndY
, SC_UPDATE_MARKS
);
184 void ScTabView::UpdateRef( SCCOL nCurX
, SCROW nCurY
, SCTAB nCurZ
)
186 ScDocument
* pDoc
= aViewData
.GetDocument();
188 if (!aViewData
.IsRefMode())
190 // Das kommt vor, wenn bei einem Referenz-Dialog als erstes mit Control in die
191 // die Tabelle geklickt wird. Dann die neue Referenz an den alten Inhalt anhaengen:
193 ScModule
* pScMod
= SC_MOD();
194 if (pScMod
->IsFormulaMode())
195 pScMod
->AddRefEntry();
197 InitRefMode( nCurX
, nCurY
, nCurZ
, SC_REFTYPE_REF
);
200 if ( nCurX
!= aViewData
.GetRefEndX() || nCurY
!= aViewData
.GetRefEndY() ||
201 nCurZ
!= aViewData
.GetRefEndZ() )
203 ScMarkData
& rMark
= aViewData
.GetMarkData();
204 SCTAB nTab
= aViewData
.GetTabNo();
206 SCCOL nStartX
= aViewData
.GetRefStartX();
207 SCROW nStartY
= aViewData
.GetRefStartY();
208 SCCOL nEndX
= aViewData
.GetRefEndX();
209 SCROW nEndY
= aViewData
.GetRefEndY();
210 if ( nStartX
== nEndX
&& nStartY
== nEndY
)
211 pDoc
->ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
212 ScUpdateRect
aRect( nStartX
, nStartY
, nEndX
, nEndY
);
214 aViewData
.SetRefEnd( nCurX
, nCurY
, nCurZ
);
216 nStartX
= aViewData
.GetRefStartX();
217 nStartY
= aViewData
.GetRefStartY();
218 nEndX
= aViewData
.GetRefEndX();
219 nEndY
= aViewData
.GetRefEndY();
220 if ( nStartX
== nEndX
&& nStartY
== nEndY
)
221 pDoc
->ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
222 aRect
.SetNew( nStartX
, nStartY
, nEndX
, nEndY
);
224 ScRefType eType
= aViewData
.GetRefType();
225 if ( eType
== SC_REFTYPE_REF
)
228 aViewData
.GetRefStartX(), aViewData
.GetRefStartY(), aViewData
.GetRefStartZ(),
229 aViewData
.GetRefEndX(), aViewData
.GetRefEndY(), aViewData
.GetRefEndZ() );
230 SC_MOD()->SetReference( aRef
, pDoc
, &rMark
);
233 else if ( eType
== SC_REFTYPE_EMBED_LT
|| eType
== SC_REFTYPE_EMBED_RB
)
235 PutInOrder(nStartX
,nEndX
);
236 PutInOrder(nStartY
,nEndY
);
237 pDoc
->SetEmbedded( ScRange(nStartX
,nStartY
,nTab
, nEndX
,nEndY
,nTab
) );
238 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
239 pDocSh
->UpdateOle( &aViewData
, sal_True
);
240 pDocSh
->SetDocumentModified();
247 if (aRect
.GetDiff( nPaintStartX
, nPaintStartY
, nPaintEndX
, nPaintEndY
))
248 PaintArea( nPaintStartX
, nPaintStartY
, nPaintEndX
, nPaintEndY
, SC_UPDATE_MARKS
);
251 // Tip-Hilfe fuer Auto-Fill
253 if ( aViewData
.GetRefType() == SC_REFTYPE_FILL
&& Help::IsQuickHelpEnabled() )
257 aViewData
.GetSimpleArea( aMarkRange
);
258 SCCOL nEndX
= aViewData
.GetRefEndX();
259 SCROW nEndY
= aViewData
.GetRefEndY();
261 if ( aViewData
.GetFillMode() == SC_FILL_MATRIX
&& !(nScFillModeMouseModifier
& KEY_MOD1
) )
263 aHelpStr
= ScGlobal::GetRscString( STR_TIP_RESIZEMATRIX
);
264 SCCOL nCols
= nEndX
+ 1 - aViewData
.GetRefStartX(); // Reihenfolge ist richtig
265 SCROW nRows
= nEndY
+ 1 - aViewData
.GetRefStartY();
266 aHelpStr
.SearchAndReplace( rtl::OUString("%1"),
267 String::CreateFromInt32(nRows
) );
268 aHelpStr
.SearchAndReplace( rtl::OUString("%2"),
269 String::CreateFromInt32(nCols
) );
271 else if ( aViewData
.GetDelMark( aDelRange
) )
272 aHelpStr
= ScGlobal::GetRscString( STR_QUICKHELP_DELETE
);
273 else if ( nEndX
!= aMarkRange
.aEnd
.Col() || nEndY
!= aMarkRange
.aEnd
.Row() )
274 aHelpStr
= pDoc
->GetAutoFillPreview( aMarkRange
, nEndX
, nEndY
);
276 // je nach Richtung die obere oder untere Ecke:
277 SCCOL nAddX
= ( nEndX
>= aMarkRange
.aEnd
.Col() ) ? 1 : 0;
278 SCROW nAddY
= ( nEndY
>= aMarkRange
.aEnd
.Row() ) ? 1 : 0;
279 Point aPos
= aViewData
.GetScrPos( nEndX
+nAddX
, nEndY
+nAddY
, aViewData
.GetActivePart() );
282 Window
* pWin
= GetActiveWin();
284 aPos
= pWin
->OutputToScreenPixel( aPos
);
285 Rectangle
aRect( aPos
, aPos
);
286 sal_uInt16 nAlign
= QUICKHELP_LEFT
|QUICKHELP_TOP
;
287 Help::ShowQuickHelp(pWin
, aRect
, aHelpStr
, nAlign
);
291 void ScTabView::InitRefMode( SCCOL nCurX
, SCROW nCurY
, SCTAB nCurZ
, ScRefType eType
, bool bPaint
)
293 ScDocument
* pDoc
= aViewData
.GetDocument();
294 ScMarkData
& rMark
= aViewData
.GetMarkData();
295 if (!aViewData
.IsRefMode())
297 aViewData
.SetRefMode( sal_True
, eType
);
298 aViewData
.SetRefStart( nCurX
, nCurY
, nCurZ
);
299 aViewData
.SetRefEnd( nCurX
, nCurY
, nCurZ
);
301 if (nCurZ
== aViewData
.GetTabNo() && bPaint
)
303 SCCOL nStartX
= nCurX
;
304 SCROW nStartY
= nCurY
;
307 pDoc
->ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, aViewData
.GetTabNo() );
309 //! nur Markierung ueber Inhalte zeichnen!
310 PaintArea( nStartX
,nStartY
,nEndX
,nEndY
, SC_UPDATE_MARKS
);
312 // SetReference ohne Merge-Anpassung
313 ScRange
aRef( nCurX
,nCurY
,nCurZ
, nCurX
,nCurY
,nCurZ
);
314 SC_MOD()->SetReference( aRef
, pDoc
, &rMark
);
319 void ScTabView::SetScrollBar( ScrollBar
& rScroll
, long nRangeMax
, long nVisible
, long nPos
, bool bLayoutRTL
)
322 nVisible
= 1; // #i59893# don't use visible size 0
324 rScroll
.SetRange( Range( 0, nRangeMax
) );
325 rScroll
.SetVisibleSize( nVisible
);
326 rScroll
.SetThumbPos( nPos
);
328 rScroll
.EnableRTL( bLayoutRTL
);
331 long ScTabView::GetScrollBarPos( ScrollBar
& rScroll
)
333 return rScroll
.GetThumbPos();
336 // UpdateScrollBars - sichtbaren Bereich und Scrollweite der Scrollbars einstellen
338 static long lcl_UpdateBar( ScrollBar
& rScroll
, SCCOLROW nSize
) // Size = (komplette) Zellen
343 nOldPos
= rScroll
.GetThumbPos();
344 rScroll
.SetPageSize( static_cast<long>(nSize
) );
345 nNewPos
= rScroll
.GetThumbPos();
347 rScroll
.SetPageSize( 1 ); // immer moeglich !
350 return nNewPos
- nOldPos
;
353 static long lcl_GetScrollRange( SCCOLROW nDocEnd
, SCCOLROW nPos
, SCCOLROW nVis
, SCCOLROW nMax
, SCCOLROW nStart
)
355 // get the end (positive) of a scroll bar range that always starts at 0
358 ++nMax
; // for partially visible cells
359 SCCOLROW nEnd
= Max(nDocEnd
, (SCCOLROW
)(nPos
+nVis
)) + nVis
;
363 return ( nEnd
- nStart
); // for range starting at 0
366 void ScTabView::UpdateScrollBars()
369 sal_Bool bTop
= ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
);
370 sal_Bool bRight
= ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
);
371 ScDocument
* pDoc
= aViewData
.GetDocument();
372 SCTAB nTab
= aViewData
.GetTabNo();
373 bool bLayoutRTL
= pDoc
->IsLayoutRTL( nTab
);
376 pDoc
->GetTableArea( nTab
, nUsedX
, nUsedY
); //! cachen !!!!!!!!!!!!!!!
385 if (aViewData
.GetHSplitMode()==SC_SPLIT_FIX
)
386 nStartX
= aViewData
.GetFixPosX();
387 if (aViewData
.GetVSplitMode()==SC_SPLIT_FIX
)
388 nStartY
= aViewData
.GetFixPosY();
390 nVisXL
= aViewData
.VisibleCellsX( SC_SPLIT_LEFT
);
391 long nMaxXL
= lcl_GetScrollRange( nUsedX
, aViewData
.GetPosX(SC_SPLIT_LEFT
), nVisXL
, MAXCOL
, 0 );
392 SetScrollBar( aHScrollLeft
, nMaxXL
, nVisXL
, aViewData
.GetPosX( SC_SPLIT_LEFT
), bLayoutRTL
);
394 nVisYB
= aViewData
.VisibleCellsY( SC_SPLIT_BOTTOM
);
395 long nMaxYB
= lcl_GetScrollRange( nUsedY
, aViewData
.GetPosY(SC_SPLIT_BOTTOM
), nVisYB
, MAXROW
, nStartY
);
396 SetScrollBar( aVScrollBottom
, nMaxYB
, nVisYB
, aViewData
.GetPosY( SC_SPLIT_BOTTOM
) - nStartY
, bLayoutRTL
);
400 nVisXR
= aViewData
.VisibleCellsX( SC_SPLIT_RIGHT
);
401 long nMaxXR
= lcl_GetScrollRange( nUsedX
, aViewData
.GetPosX(SC_SPLIT_RIGHT
), nVisXR
, MAXCOL
, nStartX
);
402 SetScrollBar( aHScrollRight
, nMaxXR
, nVisXR
, aViewData
.GetPosX( SC_SPLIT_RIGHT
) - nStartX
, bLayoutRTL
);
407 nVisYT
= aViewData
.VisibleCellsY( SC_SPLIT_TOP
);
408 long nMaxYT
= lcl_GetScrollRange( nUsedY
, aViewData
.GetPosY(SC_SPLIT_TOP
), nVisYT
, MAXROW
, 0 );
409 SetScrollBar( aVScrollTop
, nMaxYT
, nVisYT
, aViewData
.GetPosY( SC_SPLIT_TOP
), bLayoutRTL
);
414 nDiff
= lcl_UpdateBar( aHScrollLeft
, nVisXL
);
415 if (nDiff
) ScrollX( nDiff
, SC_SPLIT_LEFT
);
418 nDiff
= lcl_UpdateBar( aHScrollRight
, nVisXR
);
419 if (nDiff
) ScrollX( nDiff
, SC_SPLIT_RIGHT
);
422 nDiff
= lcl_UpdateBar( aVScrollBottom
, nVisYB
);
423 if (nDiff
) ScrollY( nDiff
, SC_SPLIT_BOTTOM
);
426 nDiff
= lcl_UpdateBar( aVScrollTop
, nVisYT
);
427 if (nDiff
) ScrollY( nDiff
, SC_SPLIT_TOP
);
430 // set visible area for online spelling
432 if ( aViewData
.IsActive() )
434 ScSplitPos eActive
= aViewData
.GetActivePart();
435 ScHSplitPos eHWhich
= WhichH( eActive
);
436 ScVSplitPos eVWhich
= WhichV( eActive
);
437 SCCOL nPosX
= aViewData
.GetPosX(eHWhich
);
438 SCROW nPosY
= aViewData
.GetPosY(eVWhich
);
439 SCCOL nEndX
= nPosX
+ ( ( eHWhich
== SC_SPLIT_LEFT
) ? nVisXL
: nVisXR
);
440 SCROW nEndY
= nPosY
+ ( ( eVWhich
== SC_SPLIT_TOP
) ? nVisYT
: nVisYB
);
441 if ( nEndX
> MAXCOL
) nEndX
= MAXCOL
;
442 if ( nEndY
> MAXROW
) nEndY
= MAXROW
;
443 ScRange
aVisible( nPosX
, nPosY
, nTab
, nEndX
, nEndY
, nTab
);
444 if ( pDoc
->SetVisibleSpellRange( aVisible
) )
445 SC_MOD()->AnythingChanged(); // if visible area has changed
449 #ifndef HDR_SLIDERSIZE
450 #define HDR_SLIDERSIZE 2
453 void ScTabView::InvertHorizontal( ScVSplitPos eWhich
, long nDragPos
)
455 for (sal_uInt16 i
=0; i
<4; i
++)
456 if (WhichV((ScSplitPos
)i
)==eWhich
)
458 ScGridWindow
* pWin
= pGridWin
[i
];
461 Rectangle
aRect( 0,nDragPos
, pWin
->GetOutputSizePixel().Width()-1,nDragPos
+HDR_SLIDERSIZE
-1 );
463 pWin
->DoInvertRect( aRect
); // Pixel
468 void ScTabView::InvertVertical( ScHSplitPos eWhich
, long nDragPos
)
470 for (sal_uInt16 i
=0; i
<4; i
++)
471 if (WhichH((ScSplitPos
)i
)==eWhich
)
473 ScGridWindow
* pWin
= pGridWin
[i
];
476 Rectangle
aRect( nDragPos
,0, nDragPos
+HDR_SLIDERSIZE
-1,pWin
->GetOutputSizePixel().Height()-1 );
478 pWin
->DoInvertRect( aRect
); // Pixel
483 //==================================================================
485 void ScTabView::InterpretVisible()
487 // make sure all visible cells are interpreted,
488 // so the next paint will not execute a macro function
490 ScDocument
* pDoc
= aViewData
.GetDocument();
491 if ( !pDoc
->GetAutoCalc() )
494 SCTAB nTab
= aViewData
.GetTabNo();
495 for (sal_uInt16 i
=0; i
<4; i
++)
497 // rely on gridwin pointers to find used panes
498 // no IsVisible test in case the whole view is not yet shown
502 ScHSplitPos eHWhich
= WhichH( ScSplitPos(i
) );
503 ScVSplitPos eVWhich
= WhichV( ScSplitPos(i
) );
505 SCCOL nX1
= aViewData
.GetPosX( eHWhich
);
506 SCROW nY1
= aViewData
.GetPosY( eVWhich
);
507 SCCOL nX2
= nX1
+ aViewData
.VisibleCellsX( eHWhich
);
508 SCROW nY2
= nY1
+ aViewData
.VisibleCellsY( eVWhich
);
510 if (nX2
> MAXCOL
) nX2
= MAXCOL
;
511 if (nY2
> MAXROW
) nY2
= MAXROW
;
513 ScCellIterator
aIter( pDoc
, nX1
, nY1
, nTab
, nX2
, nY2
, nTab
);
514 ScBaseCell
* pCell
= aIter
.GetFirst();
517 if ( pCell
->GetCellType() == CELLTYPE_FORMULA
&& ((ScFormulaCell
*)pCell
)->GetDirty() )
518 ((ScFormulaCell
*)pCell
)->Interpret();
520 pCell
= aIter
.GetNext();
525 // #i65047# repaint during the above loop may have set the bNeedsRepaint flag
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */