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/svapp.hxx>
22 #include <scitems.hxx>
23 #include <sfx2/viewfrm.hxx>
24 #include <sfx2/bindings.hxx>
25 #include <vcl/help.hxx>
26 #include <vcl/settings.hxx>
28 #include <tabview.hxx>
29 #include <tabvwsh.hxx>
30 #include <document.hxx>
31 #include <gridwin.hxx>
32 #include <olinewin.hxx>
33 #include <olinetab.hxx>
34 #include <tabsplit.hxx>
35 #include <colrowba.hxx>
36 #include <tabcont.hxx>
39 #include <viewutil.hxx>
40 #include <globstr.hrc>
41 #include <drawview.hxx>
43 #include <viewuno.hxx>
44 #include <AccessibilityHints.hxx>
45 #include <appoptio.hxx>
48 #include <comphelper/lok.hxx>
49 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
50 #include <sfx2/lokhelper.hxx>
52 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
56 #include <basegfx/utils/zoomtools.hxx>
58 #define SPLIT_MARGIN 30
59 #define SPLIT_HANDLE_SIZE 5
60 #define WIDTH_MARGIN 5
62 #define SC_ICONSIZE 36
64 #define SC_SCROLLBAR_MIN 30
65 #define SC_TABBAR_MIN 6
67 using namespace ::com::sun::star
;
71 ScCornerButton::ScCornerButton( vcl::Window
* pParent
, ScViewData
* pData
, bool bAdditional
) :
72 Window( pParent
, WinBits( 0 ) ),
79 ScCornerButton::~ScCornerButton()
83 void ScCornerButton::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
85 const StyleSettings
& rStyleSettings
= rRenderContext
.GetSettings().GetStyleSettings();
86 SetBackground(rStyleSettings
.GetFaceColor());
88 Size
aSize(GetOutputSizePixel());
89 long nPosX
= aSize
.Width() - 1;
90 long nPosY
= aSize
.Height() - 1;
92 Window::Paint(rRenderContext
, rRect
);
94 bool bLayoutRTL
= pViewData
->GetDocument()->IsLayoutRTL( pViewData
->GetTabNo() );
95 long nDarkX
= bLayoutRTL
? 0 : nPosX
;
99 // match the shaded look of column/row headers
101 Color
aFace(rStyleSettings
.GetFaceColor());
102 Color
aWhite(COL_WHITE
);
103 Color
aCenter(aFace
);
104 aCenter
.Merge(aWhite
, 0xd0); // lighten up a bit
105 Color
aOuter(aFace
);
106 aOuter
.Merge(aWhite
, 0xa0); // lighten up more
108 long nCenterX
= (aSize
.Width() / 2) - 1;
109 long nCenterY
= (aSize
.Height() / 2) - 1;
111 rRenderContext
.SetLineColor();
112 rRenderContext
.SetFillColor(aCenter
);
113 rRenderContext
.DrawRect(tools::Rectangle(nCenterX
, nCenterY
, nCenterX
, nPosY
));
114 rRenderContext
.DrawRect(tools::Rectangle(nCenterX
, nCenterY
, nDarkX
, nCenterY
));
115 rRenderContext
.SetFillColor(aOuter
);
116 rRenderContext
.DrawRect(tools::Rectangle(0, 0, nPosX
, nCenterY
- 1));
118 rRenderContext
.DrawRect(tools::Rectangle(nCenterX
+ 1, nCenterY
, nPosX
, nPosY
));
120 rRenderContext
.DrawRect(tools::Rectangle(0, nCenterY
, nCenterX
- 1, nPosY
));
123 // both buttons have the same look now - only dark right/bottom lines
124 rRenderContext
.SetLineColor(rStyleSettings
.GetDarkShadowColor());
125 rRenderContext
.DrawLine(Point(0, nPosY
), Point(nPosX
, nPosY
));
126 rRenderContext
.DrawLine(Point(nDarkX
, 0), Point(nDarkX
, nPosY
));
129 void ScCornerButton::StateChanged( StateChangedType nType
)
131 Window::StateChanged( nType
);
133 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
134 SetBackground( rStyleSettings
.GetFaceColor() );
138 void ScCornerButton::DataChanged( const DataChangedEvent
& rDCEvt
)
140 Window::DataChanged( rDCEvt
);
142 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
143 SetBackground( rStyleSettings
.GetFaceColor() );
147 void ScCornerButton::Resize()
152 void ScCornerButton::MouseButtonDown( const MouseEvent
& rMEvt
)
154 ScModule
* pScMod
= SC_MOD();
155 bool bDisable
= pScMod
->IsFormulaMode() || pScMod
->IsModalMode();
158 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
159 pViewSh
->SetActive(); // Appear and SetViewFrame
160 pViewSh
->ActiveGrabFocus();
162 bool bControl
= rMEvt
.IsMod1();
163 pViewSh
->SelectAll( bControl
);
169 bool lcl_HasColOutline( const ScViewData
& rViewData
)
171 const ScOutlineTable
* pTable
= rViewData
.GetDocument()->GetOutlineTable(rViewData
.GetTabNo());
174 const ScOutlineArray
& rArray
= pTable
->GetColArray();
175 if ( rArray
.GetDepth() > 0 )
181 bool lcl_HasRowOutline( const ScViewData
& rViewData
)
183 const ScOutlineTable
* pTable
= rViewData
.GetDocument()->GetOutlineTable(rViewData
.GetTabNo());
186 const ScOutlineArray
& rArray
= pTable
->GetRowArray();
187 if ( rArray
.GetDepth() > 0 )
193 } // anonymous namespace
195 ScTabView::ScTabView( vcl::Window
* pParent
, ScDocShell
& rDocSh
, ScTabViewShell
* pViewShell
) :
196 pFrameWin( pParent
),
197 aViewData( &rDocSh
, pViewShell
),
198 pSelEngine( nullptr ),
199 aFunctionSet( &aViewData
),
200 pHdrSelEng( nullptr ),
201 aHdrFunc( &aViewData
),
202 pDrawView( nullptr ),
203 aVScrollTop( VclPtr
<ScrollBar
>::Create( pFrameWin
, WinBits( WB_VSCROLL
| WB_DRAG
) ) ),
204 aVScrollBottom( VclPtr
<ScrollBar
>::Create( pFrameWin
, WinBits( WB_VSCROLL
| WB_DRAG
) ) ),
205 aHScrollLeft( VclPtr
<ScrollBar
>::Create( pFrameWin
, WinBits( WB_HSCROLL
| WB_DRAG
) ) ),
206 aHScrollRight( VclPtr
<ScrollBar
>::Create( pFrameWin
, WinBits( WB_HSCROLL
| WB_DRAG
) ) ),
207 aCornerButton( VclPtr
<ScCornerButton
>::Create( pFrameWin
, &aViewData
, false ) ),
208 aTopButton( VclPtr
<ScCornerButton
>::Create( pFrameWin
, &aViewData
, true ) ),
209 aScrollBarBox( VclPtr
<ScrollBarBox
>::Create( pFrameWin
, WB_SIZEABLE
) ),
211 pPageBreakData( nullptr ),
212 pBrushDocument( nullptr ),
213 pDrawBrushSet( nullptr ),
214 pTimerWindow( nullptr ),
215 aExtraEditViewManager( pViewShell
, pGridWin
),
217 nTipAlign( QuickHelpFlags::NONE
),
221 nBlockStartXOrig( 0 ),
224 nBlockStartYOrig( 0 ),
230 mfPendingTabBarWidth( -1.0 ),
231 mnLOKStartHeaderRow( std::numeric_limits
<SCROW
>::min() ),
232 mnLOKEndHeaderRow( std::numeric_limits
<SCROW
>::min() ),
233 mnLOKStartHeaderCol( std::numeric_limits
<SCCOL
>::min() ),
234 mnLOKEndHeaderCol( std::numeric_limits
<SCCOL
>::min() ),
236 bInUpdateHeader( false ),
237 bInActivatePart( false ),
238 bInZoomUpdate( false ),
239 bMoveIsShift( false ),
240 bDrawSelMode( false ),
241 bLockPaintBrush( false ),
246 mbInlineWithScrollbar( false )
251 void ScTabView::InitScrollBar( ScrollBar
& rScrollBar
, long nMaxVal
)
253 rScrollBar
.SetRange( Range( 0, nMaxVal
) );
254 rScrollBar
.SetLineSize( 1 );
255 rScrollBar
.SetPageSize( 1 ); // is queried separately
256 rScrollBar
.SetVisibleSize( 10 ); // is reset by Resize
258 rScrollBar
.SetScrollHdl( LINK(this, ScTabView
, ScrollHdl
) );
259 rScrollBar
.SetEndScrollHdl( LINK(this, ScTabView
, EndScrollHdl
) );
261 rScrollBar
.EnableRTL( aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() ) );
266 void ScTabView::SetTimer( ScGridWindow
* pWin
, const MouseEvent
& rMEvt
)
270 aScrollTimer
.Start();
273 void ScTabView::ResetTimer()
276 pTimerWindow
= nullptr;
279 IMPL_LINK_NOARG(ScTabView
, TimerHdl
, Timer
*, void)
282 pTimerWindow
->MouseMove( aTimerMEvt
);
285 // --- Resize ---------------------------------------------------------------------
287 static void lcl_SetPosSize( vcl::Window
& rWindow
, const Point
& rPos
, const Size
& rSize
,
288 long nTotalWidth
, bool bLayoutRTL
)
290 Point aNewPos
= rPos
;
293 aNewPos
.X() = nTotalWidth
- rPos
.X() - rSize
.Width();
294 if ( aNewPos
== rWindow
.GetPosPixel() && rSize
.Width() != rWindow
.GetSizePixel().Width() )
296 // Document windows are manually painted right-to-left, so they need to
297 // be repainted if the size changes.
298 rWindow
.Invalidate();
301 rWindow
.SetPosSizePixel( aNewPos
, rSize
);
304 void ScTabView::DoResize( const Point
& rOffset
, const Size
& rSize
, bool bInner
)
308 bool bHasHint
= HasHintWindow();
312 bool bLayoutRTL
= aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() );
313 long nTotalWidth
= rSize
.Width();
315 nTotalWidth
+= 2*rOffset
.X();
317 bool bVScroll
= aViewData
.IsVScrollMode();
318 bool bHScroll
= aViewData
.IsHScrollMode();
319 bool bTabControl
= aViewData
.IsTabMode();
320 bool bHeaders
= aViewData
.IsHeaderMode();
321 bool bOutlMode
= aViewData
.IsOutlineMode();
322 bool bHOutline
= bOutlMode
&& lcl_HasColOutline(aViewData
);
323 bool bVOutline
= bOutlMode
&& lcl_HasRowOutline(aViewData
);
325 if ( aViewData
.GetDocShell()->IsPreview() )
326 bHScroll
= bVScroll
= bTabControl
= bHeaders
= bHOutline
= bVOutline
= false;
335 long nPosX
= rOffset
.X();
336 long nPosY
= rOffset
.Y();
337 long nSizeX
= rSize
.Width();
338 long nSizeY
= rSize
.Height();
340 bMinimized
= ( nSizeX
<=SC_ICONSIZE
|| nSizeY
<=SC_ICONSIZE
);
344 float fScaleFactor
= pFrameWin
->GetDPIScaleFactor();
346 long nSplitSizeX
= SPLIT_HANDLE_SIZE
* fScaleFactor
;
347 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
349 long nSplitSizeY
= SPLIT_HANDLE_SIZE
* fScaleFactor
;
350 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
353 aBorderPos
= rOffset
;
356 const StyleSettings
& rStyleSettings
= pFrameWin
->GetSettings().GetStyleSettings();
359 Size aFontSize
= rStyleSettings
.GetTabFont().GetFontSize();
360 MapMode
aPtMapMode(MapUnit::MapPoint
);
361 aFontSize
= pFrameWin
->LogicToPixel(aFontSize
, aPtMapMode
);
362 sal_Int32 nTabWidth
= aFontSize
.Height() + WIDTH_MARGIN
;
364 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
366 if ( aViewData
.GetHSplitPos() > nSizeX
- SPLIT_MARGIN
)
368 aViewData
.SetHSplitMode( SC_SPLIT_NONE
);
369 if ( WhichH( aViewData
.GetActivePart() ) == SC_SPLIT_RIGHT
)
370 ActivatePart( SC_SPLIT_BOTTOMLEFT
);
374 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
376 if ( aViewData
.GetVSplitPos() > nSizeY
- SPLIT_MARGIN
)
378 aViewData
.SetVSplitMode( SC_SPLIT_NONE
);
379 if ( WhichV( aViewData
.GetActivePart() ) == SC_SPLIT_TOP
)
380 ActivatePart( SC_SPLIT_BOTTOMLEFT
);
387 if (bHScroll
|| bVScroll
) // Scrollbars horizontal or vertical
389 long nScrollBarSize
= rStyleSettings
.GetScrollBarSize();
392 nBarX
= nScrollBarSize
;
399 if (!mbInlineWithScrollbar
)
400 nBarY
+= nScrollBarSize
;
405 // window at the bottom right
406 lcl_SetPosSize( *aScrollBarBox
.get(), Point( nPosX
+nSizeX
, nPosY
+nSizeY
), Size( nBarX
, nBarY
),
407 nTotalWidth
, bLayoutRTL
);
409 if (bHScroll
) // Scrollbars horizontal
411 long nSizeLt
= 0; // left scroll bar
412 long nSizeRt
= 0; // right scroll bar
413 long nSizeSp
= 0; // splitter
415 switch (aViewData
.GetHSplitMode())
418 nSizeSp
= nSplitSizeX
;
419 nSizeLt
= nSizeX
- nSizeSp
; // Covert the corner
421 case SC_SPLIT_NORMAL
:
422 nSizeSp
= nSplitSizeX
;
423 nSizeLt
= aViewData
.GetHSplitPos();
430 nSizeRt
= nSizeX
- nSizeLt
- nSizeSp
;
436 // pending relative tab bar width from extended document options
437 if( mfPendingTabBarWidth
>= 0.0 )
439 SetRelTabBarWidth( mfPendingTabBarWidth
);
440 mfPendingTabBarWidth
= -1.0;
443 if (mbInlineWithScrollbar
)
445 nTabSize
= pTabControl
->GetSizePixel().Width();
447 if ( aViewData
.GetHSplitMode() != SC_SPLIT_FIX
) // left Scrollbar
449 if (nTabSize
> nSizeLt
-SC_SCROLLBAR_MIN
)
450 nTabSize
= nSizeLt
-SC_SCROLLBAR_MIN
;
451 if (nTabSize
< SC_TABBAR_MIN
)
452 nTabSize
= SC_TABBAR_MIN
;
455 else // right Scrollbar
457 if (nTabSize
> nSizeRt
-SC_SCROLLBAR_MIN
)
458 nTabSize
= nSizeRt
-SC_SCROLLBAR_MIN
;
459 if (nTabSize
< SC_TABBAR_MIN
)
460 nTabSize
= SC_TABBAR_MIN
;
466 if (mbInlineWithScrollbar
)
468 Point
aTabPoint(nPosX
, nPosY
+ nSizeY
);
469 Size
aTabSize(nTabSize
, nBarY
);
470 lcl_SetPosSize(*pTabControl
.get(), aTabPoint
, aTabSize
, nTotalWidth
, bLayoutRTL
);
471 pTabControl
->SetSheetLayoutRTL(bLayoutRTL
);
473 Point
aHScrollLeftPoint(nPosX
+ nTabSize
, nPosY
+ nSizeY
);
474 Size
aHScrollLeftSize(nSizeLt
, nBarY
);
475 lcl_SetPosSize(*aHScrollLeft
.get(), aHScrollLeftPoint
, aHScrollLeftSize
, nTotalWidth
, bLayoutRTL
);
477 Point
aHSplitterPoint(nPosX
+ nTabSize
+ nSizeLt
, nPosY
+ nSizeY
);
478 Size
aHSplitterSize(nSizeSp
, nBarY
);
479 lcl_SetPosSize(*pHSplitter
.get(), aHSplitterPoint
, aHSplitterSize
, nTotalWidth
, bLayoutRTL
);
481 Point
aHScrollRightPoint(nPosX
+ nTabSize
+ nSizeLt
+ nSizeSp
, nPosY
+ nSizeY
);
482 Size
aHScrollRightSize(nSizeRt
, nBarY
);
483 lcl_SetPosSize(*aHScrollRight
.get(), aHScrollRightPoint
, aHScrollRightSize
, nTotalWidth
, bLayoutRTL
);
487 Point
aTabPoint(nPosX
, nPosY
+ nSizeY
+ nScrollBarSize
);
488 Size
aTabSize(nSizeX
, nTabWidth
);
489 lcl_SetPosSize(*pTabControl
.get(), aTabPoint
, aTabSize
, nTotalWidth
, bLayoutRTL
);
490 pTabControl
->SetSheetLayoutRTL(bLayoutRTL
);
492 Point
aHScrollLeftPoint(nPosX
, nPosY
+ nSizeY
);
493 Size
aHScrollLeftSize(nSizeLt
, nScrollBarSize
);
494 lcl_SetPosSize(*aHScrollLeft
.get(), aHScrollLeftPoint
, aHScrollLeftSize
, nTotalWidth
, bLayoutRTL
);
496 Point
aHSplitterPoint(nPosX
+ nSizeLt
, nPosY
+ nSizeY
);
497 Size
aHSplitterSize(nSizeSp
, nScrollBarSize
);
498 lcl_SetPosSize(*pHSplitter
.get(), aHSplitterPoint
, aHSplitterSize
, nTotalWidth
, bLayoutRTL
);
500 Point
aHScrollRightPoint(nPosX
+ nSizeLt
+ nSizeSp
, nPosY
+ nSizeY
);
501 Size
aHScrollRightSize(nSizeRt
, nScrollBarSize
);
502 lcl_SetPosSize(*aHScrollRight
.get(), aHScrollRightPoint
, aHScrollRightSize
, nTotalWidth
, bLayoutRTL
);
504 // SetDragRectPixel is done below
509 long nSizeUp
= 0; // upper scroll bar
510 long nSizeSp
= 0; // splitter
511 long nSizeDn
; // lower scroll bar
513 switch (aViewData
.GetVSplitMode())
517 nSizeSp
= nSplitSizeY
;
519 case SC_SPLIT_NORMAL
:
520 nSizeUp
= aViewData
.GetVSplitPos();
521 nSizeSp
= nSplitSizeY
;
528 nSizeDn
= nSizeY
- nSizeUp
- nSizeSp
;
530 lcl_SetPosSize( *aVScrollTop
.get(), Point(nPosX
+ nSizeX
, nPosY
),
531 Size(nBarX
, nSizeUp
), nTotalWidth
, bLayoutRTL
);
532 lcl_SetPosSize( *pVSplitter
, Point( nPosX
+ nSizeX
, nPosY
+nSizeUp
),
533 Size( nBarX
, nSizeSp
), nTotalWidth
, bLayoutRTL
);
534 lcl_SetPosSize( *aVScrollBottom
.get(), Point(nPosX
+ nSizeX
,
535 nPosY
+ nSizeUp
+ nSizeSp
),
536 Size(nBarX
, nSizeDn
), nTotalWidth
, bLayoutRTL
);
538 // SetDragRectPixel is done below
542 // SetDragRectPixel also without Scrollbars etc., when already split
543 if ( bHScroll
|| aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
544 pHSplitter
->SetDragRectPixel(
545 tools::Rectangle( nPosX
, nPosY
, nPosX
+nSizeX
, nPosY
+nSizeY
), pFrameWin
);
546 if ( bVScroll
|| aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
547 pVSplitter
->SetDragRectPixel(
548 tools::Rectangle( nPosX
, nPosY
, nPosX
+nSizeX
, nPosY
+nSizeY
), pFrameWin
);
550 if (bTabControl
&& ! bHScroll
)
552 nBarY
= aHScrollLeft
->GetSizePixel().Height();
553 nBarX
= aVScrollBottom
->GetSizePixel().Width();
555 long nSize1
= nSizeX
;
557 long nTabSize
= nSize1
;
558 if (nTabSize
< 0) nTabSize
= 0;
560 lcl_SetPosSize( *pTabControl
.get(), Point(nPosX
, nPosY
+nSizeY
-nBarY
),
561 Size(nTabSize
, nBarY
), nTotalWidth
, bLayoutRTL
);
563 lcl_SetPosSize( *aScrollBarBox
.get(), Point( nPosX
+nSizeX
, nPosY
+nSizeY
), Size( nBarX
, nBarY
),
564 nTotalWidth
, bLayoutRTL
);
568 Size aVScrSize
= aVScrollBottom
->GetSizePixel();
569 aVScrSize
.Height() -= nBarY
;
570 aVScrollBottom
->SetSizePixel( aVScrSize
);
578 if (bVOutline
&& pRowOutline
[SC_SPLIT_BOTTOM
])
580 nOutlineX
= pRowOutline
[SC_SPLIT_BOTTOM
]->GetDepthSize();
584 if (bHOutline
&& pColOutline
[SC_SPLIT_LEFT
])
586 nOutlineY
= pColOutline
[SC_SPLIT_LEFT
]->GetDepthSize();
591 if (bHeaders
) // column/row header
593 nBarX
= pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width();
594 nBarY
= pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height();
605 long nLeftSize
= nSizeX
;
608 long nBottomSize
= nSizeY
;
609 long nSplitPosX
= nPosX
;
610 long nSplitPosY
= nPosY
;
612 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
614 long nSplitHeight
= rSize
.Height();
615 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
617 // Do not allow freeze splitter to overlap scroll bar/tab bar
619 nSplitHeight
-= aHScrollLeft
->GetSizePixel().Height();
620 else if ( bTabControl
&& pTabControl
)
621 nSplitHeight
-= pTabControl
->GetSizePixel().Height();
623 nSplitPosX
= aViewData
.GetHSplitPos();
624 lcl_SetPosSize( *pHSplitter
,
625 Point(nSplitPosX
, nOutPosY
),
626 Size( nSplitSizeX
, nSplitHeight
- nTabWidth
), nTotalWidth
, bLayoutRTL
);
627 nLeftSize
= nSplitPosX
- nPosX
;
628 nSplitPosX
+= nSplitSizeX
;
629 nRightSize
= nSizeX
- nLeftSize
- nSplitSizeX
;
631 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
633 long nSplitWidth
= rSize
.Width();
634 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
&& bVScroll
)
635 nSplitWidth
-= aVScrollBottom
->GetSizePixel().Width();
636 nSplitPosY
= aViewData
.GetVSplitPos();
637 lcl_SetPosSize( *pVSplitter
,
638 Point( nOutPosX
, nSplitPosY
), Size( nSplitWidth
, nSplitSizeY
), nTotalWidth
, bLayoutRTL
);
639 nTopSize
= nSplitPosY
- nPosY
;
640 nSplitPosY
+= nSplitSizeY
;
641 nBottomSize
= nSizeY
- nTopSize
- nSplitSizeY
;
644 // ShowHide for pColOutline / pRowOutline happens in UpdateShow
646 if (bHOutline
) // Outline-Controls
648 if (pColOutline
[SC_SPLIT_LEFT
])
650 pColOutline
[SC_SPLIT_LEFT
]->SetHeaderSize( nBarX
);
651 lcl_SetPosSize( *pColOutline
[SC_SPLIT_LEFT
],
652 Point(nPosX
-nBarX
,nOutPosY
), Size(nLeftSize
+nBarX
,nOutlineY
), nTotalWidth
, bLayoutRTL
);
654 if (pColOutline
[SC_SPLIT_RIGHT
])
656 pColOutline
[SC_SPLIT_RIGHT
]->SetHeaderSize( 0 ); // always call to update RTL flag
657 lcl_SetPosSize( *pColOutline
[SC_SPLIT_RIGHT
],
658 Point(nSplitPosX
,nOutPosY
), Size(nRightSize
,nOutlineY
), nTotalWidth
, bLayoutRTL
);
665 if (pRowOutline
[SC_SPLIT_TOP
] && pRowOutline
[SC_SPLIT_BOTTOM
])
667 pRowOutline
[SC_SPLIT_TOP
]->SetHeaderSize( nBarY
);
668 lcl_SetPosSize( *pRowOutline
[SC_SPLIT_TOP
],
669 Point(nOutPosX
,nPosY
-nBarY
), Size(nOutlineX
,nTopSize
+nBarY
), nTotalWidth
, bLayoutRTL
);
670 pRowOutline
[SC_SPLIT_BOTTOM
]->SetHeaderSize( 0 );
671 lcl_SetPosSize( *pRowOutline
[SC_SPLIT_BOTTOM
],
672 Point(nOutPosX
,nSplitPosY
), Size(nOutlineX
,nBottomSize
), nTotalWidth
, bLayoutRTL
);
675 else if (pRowOutline
[SC_SPLIT_BOTTOM
])
677 pRowOutline
[SC_SPLIT_BOTTOM
]->SetHeaderSize( nBarY
);
678 lcl_SetPosSize( *pRowOutline
[SC_SPLIT_BOTTOM
],
679 Point(nOutPosX
,nSplitPosY
-nBarY
), Size(nOutlineX
,nBottomSize
+nBarY
), nTotalWidth
, bLayoutRTL
);
682 if (bHOutline
&& bVOutline
)
684 lcl_SetPosSize( *aTopButton
.get(), Point(nOutPosX
,nOutPosY
), Size(nOutlineX
,nOutlineY
), nTotalWidth
, bLayoutRTL
);
690 if (bHeaders
) // column/row header
692 lcl_SetPosSize( *pColBar
[SC_SPLIT_LEFT
],
693 Point(nPosX
,nPosY
-nBarY
), Size(nLeftSize
,nBarY
), nTotalWidth
, bLayoutRTL
);
694 if (pColBar
[SC_SPLIT_RIGHT
])
695 lcl_SetPosSize( *pColBar
[SC_SPLIT_RIGHT
],
696 Point(nSplitPosX
,nPosY
-nBarY
), Size(nRightSize
,nBarY
), nTotalWidth
, bLayoutRTL
);
698 if (pRowBar
[SC_SPLIT_TOP
])
699 lcl_SetPosSize( *pRowBar
[SC_SPLIT_TOP
],
700 Point(nPosX
-nBarX
,nPosY
), Size(nBarX
,nTopSize
), nTotalWidth
, bLayoutRTL
);
701 lcl_SetPosSize( *pRowBar
[SC_SPLIT_BOTTOM
],
702 Point(nPosX
-nBarX
,nSplitPosY
), Size(nBarX
,nBottomSize
), nTotalWidth
, bLayoutRTL
);
704 lcl_SetPosSize( *aCornerButton
.get(), Point(nPosX
-nBarX
,nPosY
-nBarY
), Size(nBarX
,nBarY
), nTotalWidth
, bLayoutRTL
);
705 aCornerButton
->Show();
706 pColBar
[SC_SPLIT_LEFT
]->Show();
707 pRowBar
[SC_SPLIT_BOTTOM
]->Show();
711 aCornerButton
->Hide();
712 pColBar
[SC_SPLIT_LEFT
]->Hide(); // always here
713 pRowBar
[SC_SPLIT_BOTTOM
]->Hide();
720 long nInnerPosX
= bLayoutRTL
? ( nTotalWidth
- nPosX
- nLeftSize
) : nPosX
;
721 pGridWin
[SC_SPLIT_BOTTOMLEFT
]->SetPosPixel( Point(nInnerPosX
,nSplitPosY
) );
725 lcl_SetPosSize( *pGridWin
[SC_SPLIT_BOTTOMLEFT
],
726 Point(nPosX
,nSplitPosY
), Size(nLeftSize
,nBottomSize
), nTotalWidth
, bLayoutRTL
);
727 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
728 lcl_SetPosSize( *pGridWin
[SC_SPLIT_BOTTOMRIGHT
],
729 Point(nSplitPosX
,nSplitPosY
), Size(nRightSize
,nBottomSize
), nTotalWidth
, bLayoutRTL
);
730 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
731 lcl_SetPosSize( *pGridWin
[SC_SPLIT_TOPLEFT
],
732 Point(nPosX
,nPosY
), Size(nLeftSize
,nTopSize
), nTotalWidth
, bLayoutRTL
);
733 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
&& aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
734 lcl_SetPosSize( *pGridWin
[SC_SPLIT_TOPRIGHT
],
735 Point(nSplitPosX
,nPosY
), Size(nRightSize
,nTopSize
), nTotalWidth
, bLayoutRTL
);
738 // update scroll bars
740 if (!bInUpdateHeader
)
742 UpdateScrollBars(); // don't reset scroll bars when scrolling
745 InterpretVisible(); // have everything calculated before painting
749 TestHintWindow(); // reposition
751 UpdateVarZoom(); // update variable zoom types (after resizing GridWindows)
753 if (aViewData
.GetViewShell()->HasAccessibilityObjects())
754 aViewData
.GetViewShell()->BroadcastAccessibility(SfxHint(SfxHintId::ScAccWindowResized
));
757 void ScTabView::UpdateVarZoom()
759 // update variable zoom types
761 SvxZoomType eZoomType
= GetZoomType();
762 if ( eZoomType
!= SvxZoomType::PERCENT
&& !bInZoomUpdate
)
764 bInZoomUpdate
= true;
765 const Fraction
& rOldX
= GetViewData().GetZoomX();
766 const Fraction
& rOldY
= GetViewData().GetZoomY();
767 long nOldPercent
= long(rOldY
* 100);
768 sal_uInt16 nNewZoom
= CalcZoom( eZoomType
, (sal_uInt16
)nOldPercent
);
769 Fraction
aNew( nNewZoom
, 100 );
771 if ( aNew
!= rOldX
|| aNew
!= rOldY
)
773 SetZoom( aNew
, aNew
, false ); // always separately per sheet
777 aViewData
.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM
);
778 aViewData
.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER
);
780 bInZoomUpdate
= false;
784 void ScTabView::UpdateFixPos()
786 bool bResize
= false;
787 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
788 if (aViewData
.UpdateFixX())
790 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
791 if (aViewData
.UpdateFixY())
797 void ScTabView::RepeatResize( bool bUpdateFix
)
801 ScSplitMode eHSplit
= aViewData
.GetHSplitMode();
802 ScSplitMode eVSplit
= aViewData
.GetVSplitMode();
804 // #i46796# UpdateFixX / UpdateFixY uses GetGridOffset, which requires the
805 // outline windows to be available. So UpdateShow has to be called before
806 // (also called from DoResize).
807 if ( eHSplit
== SC_SPLIT_FIX
|| eVSplit
== SC_SPLIT_FIX
)
810 if ( eHSplit
== SC_SPLIT_FIX
)
811 aViewData
.UpdateFixX();
812 if ( eVSplit
== SC_SPLIT_FIX
)
813 aViewData
.UpdateFixY();
816 DoResize( aBorderPos
, aFrameSize
);
818 //! border must be reset ???
821 void ScTabView::GetBorderSize( SvBorder
& rBorder
, const Size
& /* rSize */ )
823 bool bScrollBars
= aViewData
.IsVScrollMode();
824 bool bHeaders
= aViewData
.IsHeaderMode();
825 bool bOutlMode
= aViewData
.IsOutlineMode();
826 bool bHOutline
= bOutlMode
&& lcl_HasColOutline(aViewData
);
827 bool bVOutline
= bOutlMode
&& lcl_HasRowOutline(aViewData
);
828 bool bLayoutRTL
= aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() );
830 rBorder
= SvBorder();
832 if (bScrollBars
) // Scrollbars horizontal or vertical
834 rBorder
.Right() += aVScrollBottom
->GetSizePixel().Width();
835 rBorder
.Bottom() += aHScrollLeft
->GetSizePixel().Height();
839 if (bVOutline
&& pRowOutline
[SC_SPLIT_BOTTOM
])
840 rBorder
.Left() += pRowOutline
[SC_SPLIT_BOTTOM
]->GetDepthSize();
841 if (bHOutline
&& pColOutline
[SC_SPLIT_LEFT
])
842 rBorder
.Top() += pColOutline
[SC_SPLIT_LEFT
]->GetDepthSize();
844 if (bHeaders
) // column/row headers
846 rBorder
.Left() += pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width();
847 rBorder
.Top() += pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height();
851 ::std::swap( rBorder
.Left(), rBorder
.Right() );
854 IMPL_LINK_NOARG(ScTabView
, TabBarResize
, TabBar
*, void)
856 if (aViewData
.IsHScrollMode())
858 const long nOverlap
= 0; // ScrollBar::GetWindowOverlapPixel();
859 long nSize
= pTabControl
->GetSplitSize();
861 if (aViewData
.GetHSplitMode() != SC_SPLIT_FIX
)
863 long nMax
= pHSplitter
->GetPosPixel().X();
864 if( pTabControl
->IsEffectiveRTL() )
865 nMax
= pFrameWin
->GetSizePixel().Width() - nMax
;
867 if (nSize
>nMax
) nSize
= nMax
;
870 if ( nSize
!= pTabControl
->GetSizePixel().Width() )
872 pTabControl
->SetSizePixel( Size( nSize
+nOverlap
,
873 pTabControl
->GetSizePixel().Height() ) );
879 void ScTabView::SetTabBarWidth( long nNewWidth
)
881 Size aSize
= pTabControl
->GetSizePixel();
883 if ( aSize
.Width() != nNewWidth
)
885 aSize
.Width() = nNewWidth
;
886 pTabControl
->SetSizePixel( aSize
);
890 void ScTabView::SetRelTabBarWidth( double fRelTabBarWidth
)
892 if( (0.0 <= fRelTabBarWidth
) && (fRelTabBarWidth
<= 1.0) )
893 if( long nFrameWidth
= pFrameWin
->GetSizePixel().Width() )
894 SetTabBarWidth( static_cast< long >( fRelTabBarWidth
* nFrameWidth
+ 0.5 ) );
897 void ScTabView::SetPendingRelTabBarWidth( double fRelTabBarWidth
)
899 mfPendingTabBarWidth
= fRelTabBarWidth
;
900 SetRelTabBarWidth( fRelTabBarWidth
);
903 long ScTabView::GetTabBarWidth() const
905 return pTabControl
->GetSizePixel().Width();
908 double ScTabView::GetRelTabBarWidth()
913 ScGridWindow
* ScTabView::GetActiveWin()
915 ScSplitPos ePos
= aViewData
.GetActivePart();
916 OSL_ENSURE(pGridWin
[ePos
],"no active window");
917 return pGridWin
[ePos
];
920 void ScTabView::SetActivePointer( const Pointer
& rPointer
)
922 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
924 pWin
->SetPointer( rPointer
);
927 void ScTabView::ActiveGrabFocus()
929 ScSplitPos ePos
= aViewData
.GetActivePart();
931 pGridWin
[ePos
]->GrabFocus();
934 ScSplitPos
ScTabView::FindWindow( const vcl::Window
* pWindow
) const
936 ScSplitPos eVal
= SC_SPLIT_BOTTOMLEFT
; // Default
937 for (sal_uInt16 i
=0; i
<4; i
++)
938 if ( pGridWin
[i
] == pWindow
)
939 eVal
= (ScSplitPos
) i
;
944 Point
ScTabView::GetGridOffset() const
948 // size as in DoResize
950 bool bHeaders
= aViewData
.IsHeaderMode();
951 bool bOutlMode
= aViewData
.IsOutlineMode();
952 bool bHOutline
= bOutlMode
&& lcl_HasColOutline(aViewData
);
953 bool bVOutline
= bOutlMode
&& lcl_HasRowOutline(aViewData
);
956 if (bVOutline
&& pRowOutline
[SC_SPLIT_BOTTOM
])
957 aPos
.X() += pRowOutline
[SC_SPLIT_BOTTOM
]->GetDepthSize();
958 if (bHOutline
&& pColOutline
[SC_SPLIT_LEFT
])
959 aPos
.Y() += pColOutline
[SC_SPLIT_LEFT
]->GetDepthSize();
961 if (bHeaders
) // column/row headers
963 if (pRowBar
[SC_SPLIT_BOTTOM
])
964 aPos
.X() += pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width();
965 if (pColBar
[SC_SPLIT_LEFT
])
966 aPos
.Y() += pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height();
972 // --- Scroll-Bars --------------------------------------------------------
974 bool ScTabView::ScrollCommand( const CommandEvent
& rCEvt
, ScSplitPos ePos
)
979 const CommandWheelData
* pData
= rCEvt
.GetWheelData();
980 if (pData
&& pData
->GetMode() == CommandWheelMode::ZOOM
)
982 if ( !aViewData
.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() )
984 // for ole inplace editing, the scale is defined by the visarea and client size
985 // and can't be changed directly
987 const Fraction
& rOldY
= aViewData
.GetZoomY();
988 long nOld
= (long)( rOldY
* 100 );
990 if ( pData
->GetDelta() < 0 )
991 nNew
= std::max( (long) MINZOOM
, basegfx::zoomtools::zoomOut( nOld
));
993 nNew
= std::min( (long) MAXZOOM
, basegfx::zoomtools::zoomIn( nOld
));
996 // scroll wheel doesn't set the AppOptions default
998 bool bSyncZoom
= SC_MOD()->GetAppOptions().GetSynchronizeZoom();
999 SetZoomType( SvxZoomType::PERCENT
, bSyncZoom
);
1000 Fraction
aFract( nNew
, 100 );
1001 SetZoom( aFract
, aFract
, bSyncZoom
);
1005 aViewData
.GetBindings().Invalidate( SID_ATTR_ZOOM
);
1006 aViewData
.GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER
);
1014 ScHSplitPos eHPos
= WhichH(ePos
);
1015 ScVSplitPos eVPos
= WhichV(ePos
);
1016 ScrollBar
* pHScroll
= ( eHPos
== SC_SPLIT_LEFT
) ? aHScrollLeft
.get() : aHScrollRight
.get();
1017 ScrollBar
* pVScroll
= ( eVPos
== SC_SPLIT_TOP
) ? aVScrollTop
.get() : aVScrollBottom
.get();
1018 if ( pGridWin
[ePos
] )
1019 bDone
= pGridWin
[ePos
]->HandleScrollCommand( rCEvt
, pHScroll
, pVScroll
);
1024 IMPL_LINK_NOARG(ScTabView
, EndScrollHdl
, ScrollBar
*, void)
1033 IMPL_LINK( ScTabView
, ScrollHdl
, ScrollBar
*, pScroll
, void )
1035 bool bHoriz
= ( pScroll
== aHScrollLeft
.get() || pScroll
== aHScrollRight
.get() );
1038 nViewPos
= aViewData
.GetPosX( (pScroll
== aHScrollLeft
.get()) ?
1039 SC_SPLIT_LEFT
: SC_SPLIT_RIGHT
);
1041 nViewPos
= aViewData
.GetPosY( (pScroll
== aVScrollTop
.get()) ?
1042 SC_SPLIT_TOP
: SC_SPLIT_BOTTOM
);
1044 bool bLayoutRTL
= aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() );
1046 ScrollType eType
= pScroll
->GetType();
1047 if ( eType
== ScrollType::Drag
)
1052 nPrevDragPos
= nViewPos
;
1055 // show scroll position
1056 // (only QuickHelp, there is no entry for it in the status bar)
1058 if (Help::IsQuickHelpEnabled())
1060 Size aSize
= pScroll
->GetSizePixel();
1062 /* Convert scrollbar mouse position to screen position. If RTL
1063 mode of scrollbar differs from RTL mode of its parent, then the
1064 direct call to Window::OutputToNormalizedScreenPixel() will
1065 give unusable results, because calculation of screen position
1066 is based on parent orientation and expects equal orientation of
1067 the child position. Need to mirror mouse position before. */
1068 Point aMousePos
= pScroll
->GetPointerPosPixel();
1069 if( pScroll
->IsRTLEnabled() != pScroll
->GetParent()->IsRTLEnabled() )
1070 aMousePos
.X() = aSize
.Width() - aMousePos
.X() - 1;
1071 aMousePos
= pScroll
->OutputToNormalizedScreenPixel( aMousePos
);
1073 // convert top-left position of scrollbar to screen position
1074 Point aPos
= pScroll
->OutputToNormalizedScreenPixel( Point() );
1076 // get scrollbar scroll position for help text (row number/column name)
1077 long nScrollMin
= 0; // simulate RangeMin
1078 if ( aViewData
.GetHSplitMode()==SC_SPLIT_FIX
&& pScroll
== aHScrollRight
.get() )
1079 nScrollMin
= aViewData
.GetFixPosX();
1080 if ( aViewData
.GetVSplitMode()==SC_SPLIT_FIX
&& pScroll
== aVScrollBottom
.get() )
1081 nScrollMin
= aViewData
.GetFixPosY();
1082 long nScrollPos
= GetScrollBarPos( *pScroll
) + nScrollMin
;
1085 tools::Rectangle aRect
;
1086 QuickHelpFlags nAlign
;
1089 aHelpStr
= ScGlobal::GetRscString(STR_COLUMN
) +
1090 " " + ScColToAlpha((SCCOL
) nScrollPos
);
1092 aRect
.Left() = aMousePos
.X();
1093 aRect
.Top() = aPos
.Y() - 4;
1094 nAlign
= QuickHelpFlags::Bottom
|QuickHelpFlags::Center
;
1098 aHelpStr
= ScGlobal::GetRscString(STR_ROW
) +
1099 " " + OUString::number(nScrollPos
+ 1);
1101 // show quicktext always inside sheet area
1102 aRect
.Left() = bLayoutRTL
? (aPos
.X() + aSize
.Width() + 8) : (aPos
.X() - 8);
1103 aRect
.Top() = aMousePos
.Y();
1104 nAlign
= (bLayoutRTL
? QuickHelpFlags::Left
: QuickHelpFlags::Right
) | QuickHelpFlags::VCenter
;
1106 aRect
.Right() = aRect
.Left();
1107 aRect
.Bottom() = aRect
.Top();
1109 Help::ShowQuickHelp(pScroll
->GetParent(), aRect
, aHelpStr
, nAlign
);
1113 long nDelta
= pScroll
->GetDelta();
1116 case ScrollType::LineUp
:
1119 case ScrollType::LineDown
:
1122 case ScrollType::PageUp
:
1123 if ( pScroll
== aHScrollLeft
.get() ) nDelta
= -(long) aViewData
.PrevCellsX( SC_SPLIT_LEFT
);
1124 if ( pScroll
== aHScrollRight
.get() ) nDelta
= -(long) aViewData
.PrevCellsX( SC_SPLIT_RIGHT
);
1125 if ( pScroll
== aVScrollTop
.get() ) nDelta
= -(long) aViewData
.PrevCellsY( SC_SPLIT_TOP
);
1126 if ( pScroll
== aVScrollBottom
.get() ) nDelta
= -(long) aViewData
.PrevCellsY( SC_SPLIT_BOTTOM
);
1127 if (nDelta
==0) nDelta
=-1;
1129 case ScrollType::PageDown
:
1130 if ( pScroll
== aHScrollLeft
.get() ) nDelta
= aViewData
.VisibleCellsX( SC_SPLIT_LEFT
);
1131 if ( pScroll
== aHScrollRight
.get() ) nDelta
= aViewData
.VisibleCellsX( SC_SPLIT_RIGHT
);
1132 if ( pScroll
== aVScrollTop
.get() ) nDelta
= aViewData
.VisibleCellsY( SC_SPLIT_TOP
);
1133 if ( pScroll
== aVScrollBottom
.get() ) nDelta
= aViewData
.VisibleCellsY( SC_SPLIT_BOTTOM
);
1134 if (nDelta
==0) nDelta
=1;
1136 case ScrollType::Drag
:
1138 // only scroll in the correct direction, do not jitter around hidden ranges
1139 long nScrollMin
= 0; // simulate RangeMin
1140 if ( aViewData
.GetHSplitMode()==SC_SPLIT_FIX
&& pScroll
== aHScrollRight
.get() )
1141 nScrollMin
= aViewData
.GetFixPosX();
1142 if ( aViewData
.GetVSplitMode()==SC_SPLIT_FIX
&& pScroll
== aVScrollBottom
.get() )
1143 nScrollMin
= aViewData
.GetFixPosY();
1145 long nScrollPos
= GetScrollBarPos( *pScroll
) + nScrollMin
;
1146 nDelta
= nScrollPos
- nViewPos
;
1147 if ( nScrollPos
> nPrevDragPos
)
1149 if (nDelta
<0) nDelta
=0;
1151 else if ( nScrollPos
< nPrevDragPos
)
1153 if (nDelta
>0) nDelta
=0;
1157 nPrevDragPos
= nScrollPos
;
1162 // added to avoid warnings
1168 bool bUpdate
= ( eType
!= ScrollType::Drag
); // don't alter the ranges while dragging
1170 ScrollX( nDelta
, (pScroll
== aHScrollLeft
.get()) ? SC_SPLIT_LEFT
: SC_SPLIT_RIGHT
, bUpdate
);
1172 ScrollY( nDelta
, (pScroll
== aVScrollTop
.get()) ? SC_SPLIT_TOP
: SC_SPLIT_BOTTOM
, bUpdate
);
1176 void ScTabView::ScrollX( long nDeltaX
, ScHSplitPos eWhich
, bool bUpdBars
)
1178 SCCOL nOldX
= aViewData
.GetPosX(eWhich
);
1179 SCCOL nNewX
= nOldX
+ static_cast<SCCOL
>(nDeltaX
);
1185 if ( nNewX
> MAXCOL
)
1187 nDeltaX
-= nNewX
- MAXCOL
;
1191 SCCOL nDir
= ( nDeltaX
> 0 ) ? 1 : -1;
1192 ScDocument
* pDoc
= aViewData
.GetDocument();
1193 SCTAB nTab
= aViewData
.GetTabNo();
1194 while ( pDoc
->ColHidden(nNewX
, nTab
) &&
1195 nNewX
+nDir
>= 0 && nNewX
+nDir
<= MAXCOL
)
1196 nNewX
= sal::static_int_cast
<SCCOL
>( nNewX
+ nDir
);
1200 if (aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
1202 if (eWhich
== SC_SPLIT_LEFT
)
1203 nNewX
= nOldX
; // always keep the left part
1206 SCCOL nFixX
= aViewData
.GetFixPosX();
1216 if ( nNewX
>= 0 && nNewX
<= MAXCOL
&& nDeltaX
)
1218 SCCOL nTrackX
= std::max( nOldX
, nNewX
);
1220 // with VCL Update() affects all windows at the moment, that is why
1221 // calling Update after scrolling of the GridWindow would possibly
1222 // already have painted the column/row bar with updated position. -
1223 // Therefore call Update once before on column/row bar
1224 if (pColBar
[eWhich
])
1225 pColBar
[eWhich
]->Update();
1227 long nOldPos
= aViewData
.GetScrPos( nTrackX
, 0, eWhich
).X();
1228 aViewData
.SetPosX( eWhich
, nNewX
);
1229 long nDiff
= aViewData
.GetScrPos( nTrackX
, 0, eWhich
).X() - nOldPos
;
1231 if ( eWhich
==SC_SPLIT_LEFT
)
1233 pGridWin
[SC_SPLIT_BOTTOMLEFT
]->ScrollPixel( nDiff
, 0 );
1234 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
1235 pGridWin
[SC_SPLIT_TOPLEFT
]->ScrollPixel( nDiff
, 0 );
1239 pGridWin
[SC_SPLIT_BOTTOMRIGHT
]->ScrollPixel( nDiff
, 0 );
1240 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
1241 pGridWin
[SC_SPLIT_TOPRIGHT
]->ScrollPixel( nDiff
, 0 );
1243 if (pColBar
[eWhich
]) { pColBar
[eWhich
]->Scroll( nDiff
,0 ); pColBar
[eWhich
]->Update(); }
1244 if (pColOutline
[eWhich
]) pColOutline
[eWhich
]->ScrollPixel( nDiff
);
1249 if (nDeltaX
==1 || nDeltaX
==-1)
1250 pGridWin
[aViewData
.GetActivePart()]->Update();
1254 SetNewVisArea(); // MapMode must already be set
1259 void ScTabView::ScrollY( long nDeltaY
, ScVSplitPos eWhich
, bool bUpdBars
)
1261 SCROW nOldY
= aViewData
.GetPosY(eWhich
);
1262 SCROW nNewY
= nOldY
+ static_cast<SCROW
>(nDeltaY
);
1268 if ( nNewY
> MAXROW
)
1270 nDeltaY
-= nNewY
- MAXROW
;
1274 SCROW nDir
= ( nDeltaY
> 0 ) ? 1 : -1;
1275 ScDocument
* pDoc
= aViewData
.GetDocument();
1276 SCTAB nTab
= aViewData
.GetTabNo();
1277 while ( pDoc
->RowHidden(nNewY
, nTab
) &&
1278 nNewY
+nDir
>= 0 && nNewY
+nDir
<= MAXROW
)
1283 if (aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1285 if (eWhich
== SC_SPLIT_TOP
)
1286 nNewY
= nOldY
; // always keep the upper part
1289 SCROW nFixY
= aViewData
.GetFixPosY();
1299 if ( nNewY
>= 0 && nNewY
<= MAXROW
&& nDeltaY
)
1301 SCROW nTrackY
= std::max( nOldY
, nNewY
);
1303 // adjust row headers before the actual scrolling, so it does not get painted twice
1304 // PosY may then also not be set yet, pass on new value
1305 SCROW nUNew
= nNewY
;
1306 UpdateHeaderWidth( &eWhich
, &nUNew
); // adjust row headers
1308 if (pRowBar
[eWhich
])
1309 pRowBar
[eWhich
]->Update();
1311 long nOldPos
= aViewData
.GetScrPos( 0, nTrackY
, eWhich
).Y();
1312 aViewData
.SetPosY( eWhich
, nNewY
);
1313 long nDiff
= aViewData
.GetScrPos( 0, nTrackY
, eWhich
).Y() - nOldPos
;
1315 if ( eWhich
==SC_SPLIT_TOP
)
1317 pGridWin
[SC_SPLIT_TOPLEFT
]->ScrollPixel( 0, nDiff
);
1318 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
1319 pGridWin
[SC_SPLIT_TOPRIGHT
]->ScrollPixel( 0, nDiff
);
1323 pGridWin
[SC_SPLIT_BOTTOMLEFT
]->ScrollPixel( 0, nDiff
);
1324 if ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
)
1325 pGridWin
[SC_SPLIT_BOTTOMRIGHT
]->ScrollPixel( 0, nDiff
);
1327 if (pRowBar
[eWhich
]) { pRowBar
[eWhich
]->Scroll( 0,nDiff
); pRowBar
[eWhich
]->Update(); }
1328 if (pRowOutline
[eWhich
]) pRowOutline
[eWhich
]->ScrollPixel( nDiff
);
1333 if (nDeltaY
==1 || nDeltaY
==-1)
1334 pGridWin
[aViewData
.GetActivePart()]->Update();
1338 SetNewVisArea(); // MapMode must already be set
1343 void ScTabView::ScrollLines( long nDeltaX
, long nDeltaY
)
1345 ScSplitPos eWhich
= aViewData
.GetActivePart();
1347 ScrollX(nDeltaX
,WhichH(eWhich
));
1349 ScrollY(nDeltaY
,WhichV(eWhich
));
1355 SCROW
lcl_LastVisible( const ScViewData
& rViewData
)
1357 // If many rows are hidden at end of the document (what kind of idiot does that?),
1358 // then there should not be a switch to wide row headers because of this
1359 //! as a member to the document???
1360 ScDocument
* pDoc
= rViewData
.GetDocument();
1361 SCTAB nTab
= rViewData
.GetTabNo();
1363 SCROW nVis
= MAXROW
;
1364 while ( nVis
> 0 && pDoc
->GetRowHeight( nVis
, nTab
) == 0 )
1369 } // anonymous namespace
1371 void ScTabView::UpdateHeaderWidth( const ScVSplitPos
* pWhich
, const SCROW
* pPosY
)
1373 if ( !pRowBar
[SC_SPLIT_BOTTOM
] || MAXROW
< 10000 )
1376 SCROW nEndPos
= MAXROW
;
1377 if ( !aViewData
.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() )
1379 // for OLE Inplace always MAXROW
1381 if ( pWhich
&& *pWhich
== SC_SPLIT_BOTTOM
&& pPosY
)
1384 nEndPos
= aViewData
.GetPosY( SC_SPLIT_BOTTOM
);
1385 nEndPos
+= aViewData
.CellsAtY( nEndPos
, 1, SC_SPLIT_BOTTOM
); // VisibleCellsY
1386 if (nEndPos
> MAXROW
)
1387 nEndPos
= lcl_LastVisible( aViewData
);
1389 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
1392 if ( pWhich
&& *pWhich
== SC_SPLIT_TOP
&& pPosY
)
1395 nTopEnd
= aViewData
.GetPosY( SC_SPLIT_TOP
);
1396 nTopEnd
+= aViewData
.CellsAtY( nTopEnd
, 1, SC_SPLIT_TOP
);// VisibleCellsY
1397 if (nTopEnd
> MAXROW
)
1398 nTopEnd
= lcl_LastVisible( aViewData
);
1400 if ( nTopEnd
> nEndPos
)
1405 long nSmall
= pRowBar
[SC_SPLIT_BOTTOM
]->GetSmallWidth();
1406 long nBig
= pRowBar
[SC_SPLIT_BOTTOM
]->GetBigWidth();
1407 long nDiff
= nBig
- nSmall
;
1411 else if (nEndPos
<1) // avoid extra step at 0 (when only one row is visible)
1413 long nWidth
= nBig
- ( 10000 - nEndPos
) * nDiff
/ 10000;
1415 if ( nWidth
!= pRowBar
[SC_SPLIT_BOTTOM
]->GetWidth() && !bInUpdateHeader
)
1417 bInUpdateHeader
= true;
1419 pRowBar
[SC_SPLIT_BOTTOM
]->SetWidth( nWidth
);
1420 if (pRowBar
[SC_SPLIT_TOP
])
1421 pRowBar
[SC_SPLIT_TOP
]->SetWidth( nWidth
);
1425 // on VCL there are endless updates (each Update is valid for all windows)
1426 //aCornerButton->Update(); // otherwise this never gets an Update
1428 bInUpdateHeader
= false;
1432 inline void ShowHide( vcl::Window
* pWin
, bool bShow
)
1434 OSL_ENSURE(pWin
|| !bShow
, "window is not present");
1439 void ScTabView::UpdateShow()
1441 bool bHScrollMode
= aViewData
.IsHScrollMode();
1442 bool bVScrollMode
= aViewData
.IsVScrollMode();
1443 bool bTabMode
= aViewData
.IsTabMode();
1444 bool bOutlMode
= aViewData
.IsOutlineMode();
1445 bool bHOutline
= bOutlMode
&& lcl_HasColOutline(aViewData
);
1446 bool bVOutline
= bOutlMode
&& lcl_HasRowOutline(aViewData
);
1447 bool bHeader
= aViewData
.IsHeaderMode();
1449 bool bShowH
= ( aViewData
.GetHSplitMode() != SC_SPLIT_NONE
);
1450 bool bShowV
= ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
);
1452 if ( aViewData
.GetDocShell()->IsPreview() )
1453 bHScrollMode
= bVScrollMode
= bTabMode
= bHeader
= bHOutline
= bVOutline
= false;
1457 if (bShowH
&& !pGridWin
[SC_SPLIT_BOTTOMRIGHT
])
1459 pGridWin
[SC_SPLIT_BOTTOMRIGHT
] = VclPtr
<ScGridWindow
>::Create( pFrameWin
, &aViewData
, SC_SPLIT_BOTTOMRIGHT
);
1460 DoAddWin( pGridWin
[SC_SPLIT_BOTTOMRIGHT
] );
1462 if (bShowV
&& !pGridWin
[SC_SPLIT_TOPLEFT
])
1464 pGridWin
[SC_SPLIT_TOPLEFT
] = VclPtr
<ScGridWindow
>::Create( pFrameWin
, &aViewData
, SC_SPLIT_TOPLEFT
);
1465 DoAddWin( pGridWin
[SC_SPLIT_TOPLEFT
] );
1467 if (bShowH
&& bShowV
&& !pGridWin
[SC_SPLIT_TOPRIGHT
])
1469 pGridWin
[SC_SPLIT_TOPRIGHT
] = VclPtr
<ScGridWindow
>::Create( pFrameWin
, &aViewData
, SC_SPLIT_TOPRIGHT
);
1470 DoAddWin( pGridWin
[SC_SPLIT_TOPRIGHT
] );
1473 if (bHOutline
&& !pColOutline
[SC_SPLIT_LEFT
])
1474 pColOutline
[SC_SPLIT_LEFT
] = VclPtr
<ScOutlineWindow
>::Create( pFrameWin
, SC_OUTLINE_HOR
, &aViewData
, SC_SPLIT_BOTTOMLEFT
);
1475 if (bShowH
&& bHOutline
&& !pColOutline
[SC_SPLIT_RIGHT
])
1476 pColOutline
[SC_SPLIT_RIGHT
] = VclPtr
<ScOutlineWindow
>::Create( pFrameWin
, SC_OUTLINE_HOR
, &aViewData
, SC_SPLIT_BOTTOMRIGHT
);
1478 if (bVOutline
&& !pRowOutline
[SC_SPLIT_BOTTOM
])
1479 pRowOutline
[SC_SPLIT_BOTTOM
] = VclPtr
<ScOutlineWindow
>::Create( pFrameWin
, SC_OUTLINE_VER
, &aViewData
, SC_SPLIT_BOTTOMLEFT
);
1480 if (bShowV
&& bVOutline
&& !pRowOutline
[SC_SPLIT_TOP
])
1481 pRowOutline
[SC_SPLIT_TOP
] = VclPtr
<ScOutlineWindow
>::Create( pFrameWin
, SC_OUTLINE_VER
, &aViewData
, SC_SPLIT_TOPLEFT
);
1483 if (bShowH
&& bHeader
&& !pColBar
[SC_SPLIT_RIGHT
])
1484 pColBar
[SC_SPLIT_RIGHT
] = VclPtr
<ScColBar
>::Create( pFrameWin
, SC_SPLIT_RIGHT
,
1485 &aHdrFunc
, pHdrSelEng
, this );
1486 if (bShowV
&& bHeader
&& !pRowBar
[SC_SPLIT_TOP
])
1487 pRowBar
[SC_SPLIT_TOP
] = VclPtr
<ScRowBar
>::Create( pFrameWin
, SC_SPLIT_TOP
,
1488 &aHdrFunc
, pHdrSelEng
, this );
1492 ShowHide( aHScrollLeft
.get(), bHScrollMode
);
1493 ShowHide( aHScrollRight
.get(), bShowH
&& bHScrollMode
);
1494 ShowHide( aVScrollBottom
.get(), bVScrollMode
);
1495 ShowHide( aVScrollTop
.get(), bShowV
&& bVScrollMode
);
1496 ShowHide( aScrollBarBox
.get(), bVScrollMode
|| bHScrollMode
);
1498 ShowHide( pHSplitter
, bHScrollMode
|| bShowH
); // always generated
1499 ShowHide( pVSplitter
, bVScrollMode
|| bShowV
);
1500 ShowHide( pTabControl
, bTabMode
);
1502 // from here dynamically generated
1504 ShowHide( pGridWin
[SC_SPLIT_BOTTOMRIGHT
], bShowH
);
1505 ShowHide( pGridWin
[SC_SPLIT_TOPLEFT
], bShowV
);
1506 ShowHide( pGridWin
[SC_SPLIT_TOPRIGHT
], bShowH
&& bShowV
);
1508 ShowHide( pColOutline
[SC_SPLIT_LEFT
], bHOutline
);
1509 ShowHide( pColOutline
[SC_SPLIT_RIGHT
], bShowH
&& bHOutline
);
1511 ShowHide( pRowOutline
[SC_SPLIT_BOTTOM
], bVOutline
);
1512 ShowHide( pRowOutline
[SC_SPLIT_TOP
], bShowV
&& bVOutline
);
1514 ShowHide( pColBar
[SC_SPLIT_RIGHT
], bShowH
&& bHeader
);
1515 ShowHide( pRowBar
[SC_SPLIT_TOP
], bShowV
&& bHeader
);
1517 //! register new Gridwindows
1520 bool ScTabView::UpdateVisibleRange()
1522 bool bChanged
= false;
1523 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
1525 if (!pWin
|| !pWin
->IsVisible())
1528 if (pWin
->UpdateVisibleRange())
1535 // --- Splitter --------------------------------------------------------
1537 IMPL_LINK( ScTabView
, SplitHdl
, Splitter
*, pSplitter
, void )
1539 if ( pSplitter
== pHSplitter
)
1540 DoHSplit( pHSplitter
->GetSplitPosPixel() );
1542 DoVSplit( pVSplitter
->GetSplitPosPixel() );
1544 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
|| aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1545 FreezeSplitters( true );
1547 DoResize( aBorderPos
, aFrameSize
);
1550 void ScTabView::DoHSplit(long nSplitPos
)
1552 // nSplitPos is the real pixel position on the frame window,
1553 // mirroring for RTL has to be done here.
1555 bool bLayoutRTL
= aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() );
1557 nSplitPos
= pFrameWin
->GetOutputSizePixel().Width() - nSplitPos
- 1;
1564 nMinPos
= SPLIT_MARGIN
;
1565 if ( pRowBar
[SC_SPLIT_BOTTOM
] && pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width() >= nMinPos
)
1566 nMinPos
= pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width() + 1;
1567 nMaxPos
= aFrameSize
.Width() - SPLIT_MARGIN
;
1569 ScSplitMode aOldMode
= aViewData
.GetHSplitMode();
1570 ScSplitMode aNewMode
= SC_SPLIT_NORMAL
;
1572 aViewData
.SetHSplitPos( nSplitPos
);
1573 if ( nSplitPos
< nMinPos
|| nSplitPos
> nMaxPos
)
1574 aNewMode
= SC_SPLIT_NONE
;
1576 aViewData
.SetHSplitMode( aNewMode
);
1578 if ( aNewMode
!= aOldMode
)
1580 UpdateShow(); // before ActivatePart !!
1582 if ( aNewMode
== SC_SPLIT_NONE
)
1584 if (aViewData
.GetActivePart() == SC_SPLIT_TOPRIGHT
)
1585 ActivatePart( SC_SPLIT_TOPLEFT
);
1586 if (aViewData
.GetActivePart() == SC_SPLIT_BOTTOMRIGHT
)
1587 ActivatePart( SC_SPLIT_BOTTOMLEFT
);
1591 nOldDelta
= aViewData
.GetPosX( SC_SPLIT_LEFT
);
1592 long nLeftWidth
= nSplitPos
- pRowBar
[SC_SPLIT_BOTTOM
]->GetSizePixel().Width();
1593 if ( nLeftWidth
< 0 ) nLeftWidth
= 0;
1594 nNewDelta
= nOldDelta
+ aViewData
.CellsAtX( nOldDelta
, 1, SC_SPLIT_LEFT
,
1595 (sal_uInt16
) nLeftWidth
);
1596 if ( nNewDelta
> MAXCOL
)
1598 aViewData
.SetPosX( SC_SPLIT_RIGHT
, nNewDelta
);
1599 if ( nNewDelta
> aViewData
.GetCurX() )
1600 ActivatePart( (WhichV(aViewData
.GetActivePart()) == SC_SPLIT_BOTTOM
) ?
1601 SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_TOPLEFT
);
1603 ActivatePart( (WhichV(aViewData
.GetActivePart()) == SC_SPLIT_BOTTOM
) ?
1604 SC_SPLIT_BOTTOMRIGHT
: SC_SPLIT_TOPRIGHT
);
1607 // Form Layer needs to know the visible part of all windows
1608 // that is why MapMode must already be correct here
1609 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
1611 pWin
->SetMapMode( pWin
->GetDrawMapMode() );
1621 void ScTabView::DoVSplit(long nSplitPos
)
1628 nMinPos
= SPLIT_MARGIN
;
1629 if ( pColBar
[SC_SPLIT_LEFT
] && pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height() >= nMinPos
)
1630 nMinPos
= pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height() + 1;
1631 nMaxPos
= aFrameSize
.Height() - SPLIT_MARGIN
;
1633 ScSplitMode aOldMode
= aViewData
.GetVSplitMode();
1634 ScSplitMode aNewMode
= SC_SPLIT_NORMAL
;
1636 aViewData
.SetVSplitPos( nSplitPos
);
1637 if ( nSplitPos
< nMinPos
|| nSplitPos
> nMaxPos
)
1638 aNewMode
= SC_SPLIT_NONE
;
1640 aViewData
.SetVSplitMode( aNewMode
);
1642 if ( aNewMode
!= aOldMode
)
1644 UpdateShow(); // before ActivatePart !!
1646 if ( aNewMode
== SC_SPLIT_NONE
)
1648 nOldDelta
= aViewData
.GetPosY( SC_SPLIT_TOP
);
1649 aViewData
.SetPosY( SC_SPLIT_BOTTOM
, nOldDelta
);
1651 if (aViewData
.GetActivePart() == SC_SPLIT_TOPLEFT
)
1652 ActivatePart( SC_SPLIT_BOTTOMLEFT
);
1653 if (aViewData
.GetActivePart() == SC_SPLIT_TOPRIGHT
)
1654 ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
1658 if ( aOldMode
== SC_SPLIT_NONE
)
1659 nOldDelta
= aViewData
.GetPosY( SC_SPLIT_BOTTOM
);
1661 nOldDelta
= aViewData
.GetPosY( SC_SPLIT_TOP
);
1663 aViewData
.SetPosY( SC_SPLIT_TOP
, nOldDelta
);
1664 long nTopHeight
= nSplitPos
- pColBar
[SC_SPLIT_LEFT
]->GetSizePixel().Height();
1665 if ( nTopHeight
< 0 ) nTopHeight
= 0;
1666 nNewDelta
= nOldDelta
+ aViewData
.CellsAtY( nOldDelta
, 1, SC_SPLIT_TOP
,
1667 (sal_uInt16
) nTopHeight
);
1668 if ( nNewDelta
> MAXROW
)
1670 aViewData
.SetPosY( SC_SPLIT_BOTTOM
, nNewDelta
);
1671 if ( nNewDelta
> aViewData
.GetCurY() )
1672 ActivatePart( (WhichH(aViewData
.GetActivePart()) == SC_SPLIT_LEFT
) ?
1673 SC_SPLIT_TOPLEFT
: SC_SPLIT_TOPRIGHT
);
1675 ActivatePart( (WhichH(aViewData
.GetActivePart()) == SC_SPLIT_LEFT
) ?
1676 SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
);
1679 // Form Layer needs to know the visible part of all windows
1680 // that is why MapMode must already be correct here
1681 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
1683 pWin
->SetMapMode( pWin
->GetDrawMapMode() );
1693 Point
ScTabView::GetInsertPos()
1695 ScDocument
* pDoc
= aViewData
.GetDocument();
1696 SCCOL nCol
= aViewData
.GetCurX();
1697 SCROW nRow
= aViewData
.GetCurY();
1698 SCTAB nTab
= aViewData
.GetTabNo();
1700 for (SCCOL i
=0; i
<nCol
; i
++)
1701 nPosX
+= pDoc
->GetColWidth(i
,nTab
);
1702 nPosX
= (long)(nPosX
* HMM_PER_TWIPS
);
1703 if ( pDoc
->IsNegativePage( nTab
) )
1705 long nPosY
= (long) pDoc
->GetRowHeight( 0, nRow
-1, nTab
);
1706 nPosY
= (long)(nPosY
* HMM_PER_TWIPS
);
1707 return Point(nPosX
,nPosY
);
1710 Point
ScTabView::GetChartInsertPos( const Size
& rSize
, const ScRange
& rCellRange
)
1713 const long nBorder
= 100; // leave 1mm for border
1714 long nNeededWidth
= rSize
.Width() + 2 * nBorder
;
1715 long nNeededHeight
= rSize
.Height() + 2 * nBorder
;
1717 // use the active window, or lower/right if frozen (as in CalcZoom)
1718 ScSplitPos eUsedPart
= aViewData
.GetActivePart();
1719 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
1720 eUsedPart
= (WhichV(eUsedPart
)==SC_SPLIT_TOP
) ? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
;
1721 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1722 eUsedPart
= (WhichH(eUsedPart
)==SC_SPLIT_LEFT
) ? SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
;
1724 ScGridWindow
* pWin
= pGridWin
[eUsedPart
].get();
1725 OSL_ENSURE( pWin
, "Window not found" );
1728 ActivatePart( eUsedPart
);
1730 // get the visible rectangle in logic units
1732 MapMode aDrawMode
= pWin
->GetDrawMapMode();
1733 tools::Rectangle
aVisible( pWin
->PixelToLogic( tools::Rectangle( Point(0,0), pWin
->GetOutputSizePixel() ), aDrawMode
) );
1735 ScDocument
* pDoc
= aViewData
.GetDocument();
1736 SCTAB nTab
= aViewData
.GetTabNo();
1737 bool bLayoutRTL
= pDoc
->IsLayoutRTL( nTab
);
1738 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1740 long nDocX
= (long)( (double) pDoc
->GetColOffset( MAXCOL
+ 1, nTab
) * HMM_PER_TWIPS
) * nLayoutSign
;
1741 long nDocY
= (long)( (double) pDoc
->GetRowOffset( MAXROW
+ 1, nTab
) * HMM_PER_TWIPS
);
1743 if ( aVisible
.Left() * nLayoutSign
> nDocX
* nLayoutSign
)
1744 aVisible
.Left() = nDocX
;
1745 if ( aVisible
.Right() * nLayoutSign
> nDocX
* nLayoutSign
)
1746 aVisible
.Right() = nDocX
;
1747 if ( aVisible
.Top() > nDocY
)
1748 aVisible
.Top() = nDocY
;
1749 if ( aVisible
.Bottom() > nDocY
)
1750 aVisible
.Bottom() = nDocY
;
1752 // get the logic position of the selection
1754 tools::Rectangle aSelection
= pDoc
->GetMMRect( rCellRange
.aStart
.Col(), rCellRange
.aStart
.Row(),
1755 rCellRange
.aEnd
.Col(), rCellRange
.aEnd
.Row(), nTab
);
1757 long nLeftSpace
= aSelection
.Left() - aVisible
.Left();
1758 long nRightSpace
= aVisible
.Right() - aSelection
.Right();
1759 long nTopSpace
= aSelection
.Top() - aVisible
.Top();
1760 long nBottomSpace
= aVisible
.Bottom() - aSelection
.Bottom();
1762 bool bFitLeft
= ( nLeftSpace
>= nNeededWidth
);
1763 bool bFitRight
= ( nRightSpace
>= nNeededWidth
);
1765 if ( bFitLeft
|| bFitRight
)
1767 // first preference: completely left or right of the selection
1769 // if both fit, prefer left in RTL mode, right otherwise
1770 bool bPutLeft
= bFitLeft
&& ( bLayoutRTL
|| !bFitRight
);
1773 aInsertPos
.X() = aSelection
.Left() - nNeededWidth
;
1775 aInsertPos
.X() = aSelection
.Right() + 1;
1777 // align with top of selection (is moved again if it doesn't fit)
1778 aInsertPos
.Y() = std::max( aSelection
.Top(), aVisible
.Top() );
1780 else if ( nTopSpace
>= nNeededHeight
|| nBottomSpace
>= nNeededHeight
)
1782 // second preference: completely above or below the selection
1784 if ( nBottomSpace
> nNeededHeight
) // bottom is preferred
1785 aInsertPos
.Y() = aSelection
.Bottom() + 1;
1787 aInsertPos
.Y() = aSelection
.Top() - nNeededHeight
;
1789 // align with (logic) left edge of selection (moved again if it doesn't fit)
1791 aInsertPos
.X() = std::min( aSelection
.Right(), aVisible
.Right() ) - nNeededWidth
+ 1;
1793 aInsertPos
.X() = std::max( aSelection
.Left(), aVisible
.Left() );
1797 // place to the (logic) right of the selection and move so it fits
1800 aInsertPos
.X() = aSelection
.Left() - nNeededWidth
;
1802 aInsertPos
.X() = aSelection
.Right() + 1;
1803 aInsertPos
.Y() = std::max( aSelection
.Top(), aVisible
.Top() );
1806 // move the position if the object doesn't fit in the screen
1808 tools::Rectangle
aCompareRect( aInsertPos
, Size( nNeededWidth
, nNeededHeight
) );
1809 if ( aCompareRect
.Right() > aVisible
.Right() )
1810 aInsertPos
.X() -= aCompareRect
.Right() - aVisible
.Right();
1811 if ( aCompareRect
.Bottom() > aVisible
.Bottom() )
1812 aInsertPos
.Y() -= aCompareRect
.Bottom() - aVisible
.Bottom();
1814 if ( aInsertPos
.X() < aVisible
.Left() )
1815 aInsertPos
.X() = aVisible
.Left();
1816 if ( aInsertPos
.Y() < aVisible
.Top() )
1817 aInsertPos
.Y() = aVisible
.Top();
1819 // nNeededWidth / nNeededHeight includes all borders - move aInsertPos to the
1820 // object position, inside the border
1822 aInsertPos
.X() += nBorder
;
1823 aInsertPos
.Y() += nBorder
;
1828 Point
ScTabView::GetChartDialogPos( const Size
& rDialogSize
, const tools::Rectangle
& rLogicChart
)
1830 // rDialogSize must be in pixels, rLogicChart in 1/100 mm. Return value is in pixels.
1834 // use the active window, or lower/right if frozen (as in CalcZoom)
1835 ScSplitPos eUsedPart
= aViewData
.GetActivePart();
1836 if ( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
1837 eUsedPart
= (WhichV(eUsedPart
)==SC_SPLIT_TOP
) ? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
;
1838 if ( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
1839 eUsedPart
= (WhichH(eUsedPart
)==SC_SPLIT_LEFT
) ? SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
;
1841 ScGridWindow
* pWin
= pGridWin
[eUsedPart
].get();
1842 OSL_ENSURE( pWin
, "Window not found" );
1845 MapMode aDrawMode
= pWin
->GetDrawMapMode();
1846 tools::Rectangle aObjPixel
= pWin
->LogicToPixel( rLogicChart
, aDrawMode
);
1847 tools::Rectangle
aObjAbs( pWin
->OutputToAbsoluteScreenPixel( aObjPixel
.TopLeft() ),
1848 pWin
->OutputToAbsoluteScreenPixel( aObjPixel
.BottomRight() ) );
1850 tools::Rectangle aDesktop
= pWin
->GetDesktopRectPixel();
1851 Size aSpace
= pWin
->LogicToPixel( Size(8, 12), MapMode(MapUnit::MapAppFont
));
1853 ScDocument
* pDoc
= aViewData
.GetDocument();
1854 SCTAB nTab
= aViewData
.GetTabNo();
1855 bool bLayoutRTL
= pDoc
->IsLayoutRTL( nTab
);
1857 bool bCenterHor
= false;
1859 if ( aDesktop
.Bottom() - aObjAbs
.Bottom() >= rDialogSize
.Height() + aSpace
.Height() )
1861 // first preference: below the chart
1863 aRet
.Y() = aObjAbs
.Bottom() + aSpace
.Height();
1866 else if ( aObjAbs
.Top() - aDesktop
.Top() >= rDialogSize
.Height() + aSpace
.Height() )
1868 // second preference: above the chart
1870 aRet
.Y() = aObjAbs
.Top() - rDialogSize
.Height() - aSpace
.Height();
1875 bool bFitLeft
= ( aObjAbs
.Left() - aDesktop
.Left() >= rDialogSize
.Width() + aSpace
.Width() );
1876 bool bFitRight
= ( aDesktop
.Right() - aObjAbs
.Right() >= rDialogSize
.Width() + aSpace
.Width() );
1878 if ( bFitLeft
|| bFitRight
)
1880 // if both fit, prefer right in RTL mode, left otherwise
1881 bool bPutRight
= bFitRight
&& ( bLayoutRTL
|| !bFitLeft
);
1883 aRet
.X() = aObjAbs
.Right() + aSpace
.Width();
1885 aRet
.X() = aObjAbs
.Left() - rDialogSize
.Width() - aSpace
.Width();
1887 // center vertically
1888 aRet
.Y() = aObjAbs
.Top() + ( aObjAbs
.GetHeight() - rDialogSize
.Height() ) / 2;
1892 // doesn't fit on any edge - put at the bottom of the screen
1893 aRet
.Y() = aDesktop
.Bottom() - rDialogSize
.Height();
1898 aRet
.X() = aObjAbs
.Left() + ( aObjAbs
.GetWidth() - rDialogSize
.Width() ) / 2;
1900 // limit to screen (centering might lead to invalid positions)
1901 if ( aRet
.X() + rDialogSize
.Width() - 1 > aDesktop
.Right() )
1902 aRet
.X() = aDesktop
.Right() - rDialogSize
.Width() + 1;
1903 if ( aRet
.X() < aDesktop
.Left() )
1904 aRet
.X() = aDesktop
.Left();
1905 if ( aRet
.Y() + rDialogSize
.Height() - 1 > aDesktop
.Bottom() )
1906 aRet
.Y() = aDesktop
.Bottom() - rDialogSize
.Height() + 1;
1907 if ( aRet
.Y() < aDesktop
.Top() )
1908 aRet
.Y() = aDesktop
.Top();
1914 void ScTabView::LockModifiers( sal_uInt16 nModifiers
)
1916 pSelEngine
->LockModifiers( nModifiers
);
1917 pHdrSelEng
->LockModifiers( nModifiers
);
1920 sal_uInt16
ScTabView::GetLockedModifiers() const
1922 return pSelEngine
->GetLockedModifiers();
1925 Point
ScTabView::GetMousePosPixel()
1928 ScGridWindow
* pWin
= GetActiveWin();
1931 aPos
= pWin
->GetMousePosPixel();
1936 void ScTabView::FreezeSplitters( bool bFreeze
, SplitMethod eSplitMetod
)
1938 ScSplitMode eOldH
= aViewData
.GetHSplitMode();
1939 ScSplitMode eOldV
= aViewData
.GetVSplitMode();
1941 ScSplitPos ePos
= SC_SPLIT_BOTTOMLEFT
;
1942 if ( eOldV
!= SC_SPLIT_NONE
)
1943 ePos
= SC_SPLIT_TOPLEFT
;
1944 vcl::Window
* pWin
= pGridWin
[ePos
];
1946 bool bLayoutRTL
= aViewData
.GetDocument()->IsLayoutRTL( aViewData
.GetTabNo() );
1950 Point aWinStart
= pWin
->GetPosPixel();
1951 aViewData
.GetDocShell()->SetDocumentModified();
1956 if (eOldV
!= SC_SPLIT_NONE
|| eOldH
!= SC_SPLIT_NONE
)
1958 if ( eOldV
!= SC_SPLIT_NONE
&& (eSplitMetod
== SC_SPLIT_METHOD_FIRST_ROW
|| eSplitMetod
== SC_SPLIT_METHOD_CURSOR
))
1959 aSplit
.Y() = aViewData
.GetVSplitPos() - aWinStart
.Y();
1961 if ( eOldH
!= SC_SPLIT_NONE
&& (eSplitMetod
== SC_SPLIT_METHOD_FIRST_COL
|| eSplitMetod
== SC_SPLIT_METHOD_CURSOR
))
1963 long nSplitPos
= aViewData
.GetHSplitPos();
1965 nSplitPos
= pFrameWin
->GetOutputSizePixel().Width() - nSplitPos
- 1;
1966 aSplit
.X() = nSplitPos
- aWinStart
.X();
1969 aViewData
.GetPosFromPixel( aSplit
.X(), aSplit
.Y(), ePos
, nPosX
, nPosY
);
1972 aViewData
.GetMouseQuadrant( aSplit
, ePos
, nPosX
, nPosY
, bLeft
, bTop
);
1973 if (eSplitMetod
== SC_SPLIT_METHOD_FIRST_COL
)
1977 if (eSplitMetod
== SC_SPLIT_METHOD_FIRST_ROW
)
1986 case SC_SPLIT_METHOD_FIRST_ROW
:
1992 case SC_SPLIT_METHOD_FIRST_COL
:
1998 case SC_SPLIT_METHOD_CURSOR
:
2000 nPosX
= aViewData
.GetCurX();
2001 nPosY
= aViewData
.GetCurY();
2007 SCROW nTopPos
= aViewData
.GetPosY(SC_SPLIT_BOTTOM
);
2008 SCROW nBottomPos
= nPosY
;
2009 SCCOL nLeftPos
= aViewData
.GetPosX(SC_SPLIT_LEFT
);
2010 SCCOL nRightPos
= nPosX
;
2012 if (eSplitMetod
== SC_SPLIT_METHOD_FIRST_ROW
|| eSplitMetod
== SC_SPLIT_METHOD_CURSOR
)
2014 if (eOldV
!= SC_SPLIT_NONE
)
2016 nTopPos
= aViewData
.GetPosY(SC_SPLIT_TOP
);
2017 if (aViewData
.GetPosY(SC_SPLIT_BOTTOM
) > nBottomPos
)
2018 nBottomPos
= aViewData
.GetPosY(SC_SPLIT_BOTTOM
);
2020 aSplit
= aViewData
.GetScrPos( nPosX
, nPosY
, ePos
, true );
2023 aViewData
.SetVSplitMode( SC_SPLIT_FIX
);
2024 aViewData
.SetVSplitPos( aSplit
.Y() + aWinStart
.Y() );
2025 aViewData
.SetFixPosY( nPosY
);
2027 aViewData
.SetPosY(SC_SPLIT_TOP
, nTopPos
);
2028 aViewData
.SetPosY(SC_SPLIT_BOTTOM
, nBottomPos
);
2031 aViewData
.SetVSplitMode( SC_SPLIT_NONE
);
2034 if (eSplitMetod
== SC_SPLIT_METHOD_FIRST_COL
|| eSplitMetod
== SC_SPLIT_METHOD_CURSOR
)
2036 if (eOldH
!= SC_SPLIT_NONE
)
2038 if (aViewData
.GetPosX(SC_SPLIT_RIGHT
) > nRightPos
)
2039 nRightPos
= aViewData
.GetPosX(SC_SPLIT_RIGHT
);
2041 aSplit
= aViewData
.GetScrPos( nPosX
, nPosY
, ePos
, true );
2042 if (nPosX
> aViewData
.GetPosX(SC_SPLIT_LEFT
)) // (aSplit.X() > 0) doesn't work for RTL
2044 long nSplitPos
= aSplit
.X() + aWinStart
.X();
2046 nSplitPos
= pFrameWin
->GetOutputSizePixel().Width() - nSplitPos
- 1;
2048 aViewData
.SetHSplitMode( SC_SPLIT_FIX
);
2049 aViewData
.SetHSplitPos( nSplitPos
);
2050 aViewData
.SetFixPosX( nPosX
);
2052 aViewData
.SetPosX(SC_SPLIT_LEFT
, nLeftPos
);
2053 aViewData
.SetPosX(SC_SPLIT_RIGHT
, nRightPos
);
2056 aViewData
.SetHSplitMode( SC_SPLIT_NONE
);
2061 if ( eOldH
== SC_SPLIT_FIX
)
2062 aViewData
.SetHSplitMode( SC_SPLIT_NORMAL
);
2063 if ( eOldV
== SC_SPLIT_FIX
)
2064 aViewData
.SetVSplitMode( SC_SPLIT_NORMAL
);
2067 // Form Layer needs to know the visible part of all windows
2068 // that is why MapMode must already be correct here
2069 for (VclPtr
<ScGridWindow
> & p
: pGridWin
)
2071 p
->SetMapMode( p
->GetDrawMapMode() );
2074 RepeatResize(false);
2081 // SC_FOLLOW_NONE: only update active part
2082 AlignToCursor( aViewData
.GetCurX(), aViewData
.GetCurY(), SC_FOLLOW_NONE
);
2083 UpdateAutoFillMark();
2088 void ScTabView::RemoveSplit()
2095 void ScTabView::SplitAtCursor()
2097 ScSplitPos ePos
= SC_SPLIT_BOTTOMLEFT
;
2098 if ( aViewData
.GetVSplitMode() != SC_SPLIT_NONE
)
2099 ePos
= SC_SPLIT_TOPLEFT
;
2100 vcl::Window
* pWin
= pGridWin
[ePos
];
2101 Point aWinStart
= pWin
->GetPosPixel();
2103 SCCOL nPosX
= aViewData
.GetCurX();
2104 SCROW nPosY
= aViewData
.GetCurY();
2105 Point aSplit
= aViewData
.GetScrPos( nPosX
, nPosY
, ePos
, true );
2107 DoHSplit( aSplit
.X() + aWinStart
.X() );
2111 DoVSplit( aSplit
.Y() + aWinStart
.Y() );
2117 void ScTabView::SplitAtPixel( const Point
& rPixel
)
2119 // pixel is relative to the entire View, not to the first GridWin
2121 if ( rPixel
.X() > 0 )
2122 DoHSplit( rPixel
.X() );
2125 if ( rPixel
.Y() > 0 )
2126 DoVSplit( rPixel
.Y() );
2132 void ScTabView::InvalidateSplit()
2134 SfxBindings
& rBindings
= aViewData
.GetBindings();
2135 rBindings
.Invalidate( SID_WINDOW_SPLIT
);
2136 rBindings
.Invalidate( SID_WINDOW_FIX
);
2137 rBindings
.Invalidate( SID_WINDOW_FIX_COL
);
2138 rBindings
.Invalidate( SID_WINDOW_FIX_ROW
);
2140 pHSplitter
->SetFixed( aViewData
.GetHSplitMode() == SC_SPLIT_FIX
);
2141 pVSplitter
->SetFixed( aViewData
.GetVSplitMode() == SC_SPLIT_FIX
);
2144 void ScTabView::SetNewVisArea()
2146 // Draw-MapMode must be set for Controls when VisAreaChanged
2147 // (also when Edit-MapMode is set instead)
2148 MapMode aOldMode
[4];
2149 MapMode aDrawMode
[4];
2154 aOldMode
[i
] = pGridWin
[i
]->GetMapMode();
2155 aDrawMode
[i
] = pGridWin
[i
]->GetDrawMapMode();
2156 if (aDrawMode
[i
] != aOldMode
[i
])
2157 pGridWin
[i
]->SetMapMode(aDrawMode
[i
]);
2160 vcl::Window
* pActive
= pGridWin
[aViewData
.GetActivePart()];
2162 aViewData
.GetViewShell()->VisAreaChanged();
2164 pDrawView
->VisAreaChanged(nullptr); // no window passed on -> for all windows
2166 UpdateAllOverlays(); // #i79909# with drawing MapMode set
2169 if (pGridWin
[i
] && aDrawMode
[i
] != aOldMode
[i
])
2171 pGridWin
[i
]->flushOverlayManager(); // #i79909# flush overlays before switching to edit MapMode
2172 pGridWin
[i
]->SetMapMode(aOldMode
[i
]);
2175 SfxViewFrame
* pViewFrame
= aViewData
.GetViewShell()->GetViewFrame();
2178 SfxFrame
& rFrame
= pViewFrame
->GetFrame();
2179 css::uno::Reference
<css::frame::XController
> xController
= rFrame
.GetController();
2180 if (xController
.is())
2182 ScTabViewObj
* pImp
= ScTabViewObj::getImplementation( xController
);
2184 pImp
->VisAreaChanged();
2187 if (aViewData
.GetViewShell()->HasAccessibilityObjects())
2188 aViewData
.GetViewShell()->BroadcastAccessibility(SfxHint(SfxHintId::ScAccVisAreaChanged
));
2191 bool ScTabView::HasPageFieldDataAtCursor() const
2193 ScGridWindow
* pWin
= pGridWin
[aViewData
.GetActivePart()].get();
2194 SCCOL nCol
= aViewData
.GetCurX();
2195 SCROW nRow
= aViewData
.GetCurY();
2197 return pWin
->GetDPFieldOrientation( nCol
, nRow
) == sheet::DataPilotFieldOrientation_PAGE
;
2202 void ScTabView::StartDataSelect()
2204 ScGridWindow
* pWin
= pGridWin
[aViewData
.GetActivePart()].get();
2205 SCCOL nCol
= aViewData
.GetCurX();
2206 SCROW nRow
= aViewData
.GetCurY();
2211 switch (pWin
->GetDPFieldOrientation(nCol
, nRow
))
2213 case sheet::DataPilotFieldOrientation_PAGE
:
2214 // #i36598# If the cursor is on a page field's data cell,
2215 // no meaningful input is possible anyway, so this function
2216 // can be used to select a page field entry.
2217 pWin
->LaunchPageFieldMenu( nCol
, nRow
);
2219 case sheet::DataPilotFieldOrientation_COLUMN
:
2220 case sheet::DataPilotFieldOrientation_ROW
:
2221 pWin
->LaunchDPFieldMenu( nCol
, nRow
);
2227 // Do autofilter if the current cell has autofilter button. Otherwise do
2228 // a normal data select popup.
2229 const ScMergeFlagAttr
* pAttr
= static_cast<const ScMergeFlagAttr
*>(
2230 aViewData
.GetDocument()->GetAttr(
2231 nCol
, nRow
, aViewData
.GetTabNo(), ATTR_MERGE_FLAG
));
2233 if (pAttr
->HasAutoFilter())
2234 pWin
->LaunchAutoFilterMenu(nCol
, nRow
);
2236 pWin
->LaunchDataSelectMenu(nCol
, nRow
);
2239 void ScTabView::EnableRefInput(bool bFlag
)
2241 aHScrollLeft
->EnableInput(bFlag
);
2242 aHScrollRight
->EnableInput(bFlag
);
2243 aVScrollBottom
->EnableInput(bFlag
);
2244 aVScrollTop
->EnableInput(bFlag
);
2245 aScrollBarBox
->EnableInput(bFlag
);
2247 // from here on dynamically created ones
2249 if(pTabControl
!=nullptr) pTabControl
->EnableInput(bFlag
);
2251 if(pGridWin
[SC_SPLIT_BOTTOMLEFT
]!=nullptr)
2252 pGridWin
[SC_SPLIT_BOTTOMLEFT
]->EnableInput(bFlag
,false);
2253 if(pGridWin
[SC_SPLIT_BOTTOMRIGHT
]!=nullptr)
2254 pGridWin
[SC_SPLIT_BOTTOMRIGHT
]->EnableInput(bFlag
,false);
2255 if(pGridWin
[SC_SPLIT_TOPLEFT
]!=nullptr)
2256 pGridWin
[SC_SPLIT_TOPLEFT
]->EnableInput(bFlag
,false);
2257 if(pGridWin
[SC_SPLIT_TOPRIGHT
]!=nullptr)
2258 pGridWin
[SC_SPLIT_TOPRIGHT
]->EnableInput(bFlag
,false);
2259 if(pColBar
[SC_SPLIT_RIGHT
]!=nullptr)
2260 pColBar
[SC_SPLIT_RIGHT
]->EnableInput(bFlag
,false);
2261 if(pRowBar
[SC_SPLIT_TOP
]!=nullptr)
2262 pRowBar
[SC_SPLIT_TOP
]->EnableInput(bFlag
,false);
2265 bool ScTabView::ContinueOnlineSpelling()
2267 bool bChanged
= false;
2268 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
2270 if (!pWin
|| !pWin
->IsVisible())
2273 if (pWin
->ContinueOnlineSpelling())
2280 void ScTabView::EnableAutoSpell( bool bEnable
)
2282 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
2287 pWin
->EnableAutoSpell(bEnable
);
2291 void ScTabView::ResetAutoSpell()
2293 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
2298 pWin
->ResetAutoSpell();
2302 void ScTabView::SetAutoSpellData( SCCOL nPosX
, SCROW nPosY
, const std::vector
<editeng::MisspellRanges
>* pRanges
)
2304 for (VclPtr
<ScGridWindow
> & pWin
: pGridWin
)
2309 pWin
->SetAutoSpellData(nPosX
, nPosY
, pRanges
);
2317 long lcl_GetRowHeightPx(const ScDocument
* pDoc
, SCROW nRow
, SCTAB nTab
)
2319 const sal_uInt16 nSize
= pDoc
->GetRowHeight(nRow
, nTab
);
2320 return ScViewData::ToPixel(nSize
, 1.0 / TWIPS_PER_PIXEL
);
2324 long lcl_GetColWidthPx(const ScDocument
* pDoc
, SCCOL nCol
, SCTAB nTab
)
2326 const sal_uInt16 nSize
= pDoc
->GetColWidth(nCol
, nTab
);
2327 return ScViewData::ToPixel(nSize
, 1.0 / TWIPS_PER_PIXEL
);
2330 void lcl_getGroupIndexes(const ScOutlineArray
& rArray
, SCCOLROW nStart
, SCCOLROW nEnd
, std::vector
<size_t>& rGroupIndexes
)
2332 rGroupIndexes
.clear();
2333 const size_t nGroupDepth
= rArray
.GetDepth();
2334 rGroupIndexes
.resize(nGroupDepth
);
2336 // Get first group per each level
2337 for (size_t nLevel
= 0; nLevel
< nGroupDepth
; ++nLevel
)
2339 if (rArray
.GetCount(nLevel
))
2341 // look for a group inside the [nStartRow+1, nEndRow] range
2343 bool bFound
= rArray
.GetEntryIndexInRange(nLevel
, nStart
+ 1, nEnd
, nIndex
);
2348 // is there a prevoius group not inside the range
2349 // but anyway intersecting it ?
2350 const ScOutlineEntry
* pPrevEntry
= rArray
.GetEntry(nLevel
, nIndex
- 1);
2351 if (pPrevEntry
&& nStart
< pPrevEntry
->GetEnd())
2359 // look for a group which contains nStartRow+1
2360 bFound
= rArray
.GetEntryIndex(nLevel
, nStart
+ 1, nIndex
);
2363 // look for a group which contains nEndRow
2364 bFound
= rArray
.GetEntryIndex(nLevel
, nEnd
, nIndex
);
2370 // skip groups with no visible control
2372 while (nIndex
< rArray
.GetCount(nLevel
))
2374 const ScOutlineEntry
* pEntry
= rArray
.GetEntry(nLevel
, nIndex
);
2375 if (pEntry
&& pEntry
->IsVisible())
2380 if (pEntry
&& pEntry
->GetStart() > nEnd
)
2388 rGroupIndexes
[nLevel
] = bFound
? nIndex
: -1;
2393 void lcl_createGroupsData(
2394 SCCOLROW nHeaderIndex
, SCCOLROW nEnd
, long nSizePx
, long nTotalTwips
,
2395 const ScOutlineArray
& rArray
, std::vector
<size_t>& rGroupIndexes
,
2396 std::vector
<long>& rGroupStartPositions
, OUString
& rGroupsBuffer
)
2398 const size_t nGroupDepth
= rArray
.GetDepth();
2399 // create string data for group controls
2400 for (size_t nLevel
= nGroupDepth
- 1; nLevel
!= size_t(-1); --nLevel
)
2402 size_t nIndex
= rGroupIndexes
[nLevel
];
2403 if (nIndex
== size_t(-1))
2405 const ScOutlineEntry
* pEntry
= rArray
.GetEntry(nLevel
, nIndex
);
2408 if (nHeaderIndex
< pEntry
->GetStart())
2412 else if (nHeaderIndex
== pEntry
->GetStart())
2414 rGroupStartPositions
[nLevel
] = nTotalTwips
- nSizePx
* TWIPS_PER_PIXEL
;
2416 else if (nHeaderIndex
> pEntry
->GetStart() && (nHeaderIndex
< nEnd
&& nHeaderIndex
< pEntry
->GetEnd()))
2418 // for handling group started before the current view range
2419 if (rGroupStartPositions
[nLevel
] < 0)
2420 rGroupStartPositions
[nLevel
] *= -TWIPS_PER_PIXEL
;
2423 if (nHeaderIndex
== pEntry
->GetEnd() || (nHeaderIndex
== nEnd
&& rGroupStartPositions
[nLevel
] != -1))
2425 // nHeaderIndex is the end col/row of a group or is the last col/row and a group started and not yet ended
2427 // append a new group control data
2428 if (rGroupsBuffer
.endsWith("}"))
2430 rGroupsBuffer
+= ", ";
2433 bool bGroupHidden
= pEntry
->IsHidden();
2435 OUString aGroupData
;
2436 aGroupData
+= "{ \"level\": \"" + OUString::number(nLevel
+ 1) + "\", ";
2437 aGroupData
+= "\"index\": \"" + OUString::number(nIndex
) + "\", ";
2438 aGroupData
+= "\"startPos\": \"" + OUString::number(rGroupStartPositions
[nLevel
]) + "\", ";
2439 aGroupData
+= "\"endPos\": \"" + OUString::number(nTotalTwips
) + "\", ";
2440 aGroupData
+= "\"hidden\": \"" + OUString::number(static_cast<unsigned int>(bGroupHidden
)) + "\" }";
2442 rGroupsBuffer
+= aGroupData
;
2444 // look for the next visible group control at level nLevel
2445 bool bFound
= false;
2447 while (nIndex
< rArray
.GetCount(nLevel
))
2449 pEntry
= rArray
.GetEntry(nLevel
, nIndex
);
2450 if (pEntry
&& pEntry
->IsVisible())
2455 if (pEntry
&& pEntry
->GetStart() > nEnd
)
2461 rGroupIndexes
[nLevel
] = bFound
? nIndex
: -1;
2462 rGroupStartPositions
[nLevel
] = -1;
2468 } // anonymous namespace
2470 OUString
ScTabView::getRowColumnHeaders(const tools::Rectangle
& rRectangle
)
2472 ScDocument
* pDoc
= aViewData
.GetDocument();
2476 if (rRectangle
.IsEmpty())
2479 bool bRangeHeaderSupport
= comphelper::LibreOfficeKit::isRangeHeaders();
2481 rtl::OUStringBuffer
aBuffer(256);
2482 aBuffer
.append("{ \"commandName\": \".uno:ViewRowColumnHeaders\",\n");
2484 SCTAB nTab
= aViewData
.GetTabNo();
2485 SCROW nStartRow
= -1;
2487 long nStartHeightPx
= 0;
2488 long nEndHeightPx
= 0;
2489 SCCOL nStartCol
= -1;
2491 long nStartWidthPx
= 0;
2492 long nEndWidthPx
= 0;
2494 tools::Rectangle
aOldVisArea(
2495 mnLOKStartHeaderCol
+ 1, mnLOKStartHeaderRow
+ 1,
2496 mnLOKEndHeaderCol
, mnLOKEndHeaderRow
);
2498 /// *** start collecting ROWS ***
2500 /// 1) compute start and end rows
2502 if (rRectangle
.Top() < rRectangle
.Bottom())
2504 SAL_INFO("sc.lok.header", "Row Header: compute start/end rows.");
2505 long nRectTopPx
= rRectangle
.Top() / TWIPS_PER_PIXEL
;
2506 long nRectBottomPx
= rRectangle
.Bottom() / TWIPS_PER_PIXEL
;
2508 const auto& rTopNearest
= aViewData
.GetLOKHeightHelper().getNearestByPosition(nRectTopPx
);
2509 const auto& rBottomNearest
= aViewData
.GetLOKHeightHelper().getNearestByPosition(nRectBottomPx
);
2511 ScBoundsProvider
aBoundingRowsProvider(pDoc
, nTab
, /*bColumnHeader: */ false);
2512 aBoundingRowsProvider
.Compute(rTopNearest
, rBottomNearest
, nRectTopPx
, nRectBottomPx
);
2513 aBoundingRowsProvider
.EnlargeBy(2);
2514 aBoundingRowsProvider
.GetStartIndexAndPosition(nStartRow
, nStartHeightPx
);
2515 aBoundingRowsProvider
.GetEndIndexAndPosition(nEndRow
, nEndHeightPx
);
2517 aViewData
.GetLOKHeightHelper().removeByIndex(mnLOKStartHeaderRow
);
2518 aViewData
.GetLOKHeightHelper().removeByIndex(mnLOKEndHeaderRow
);
2519 aViewData
.GetLOKHeightHelper().insert(nStartRow
, nStartHeightPx
);
2520 aViewData
.GetLOKHeightHelper().insert(nEndRow
, nEndHeightPx
);
2522 mnLOKStartHeaderRow
= nStartRow
;
2523 mnLOKEndHeaderRow
= nEndRow
;
2526 long nVisibleRows
= nEndRow
- nStartRow
;
2527 if (nVisibleRows
< 25)
2530 SAL_INFO("sc.lok.header", "Row Header: visible rows: " << nVisibleRows
);
2534 // per each level store the index of the first group intersecting
2535 // [nStartRow, nEndRow] range
2537 const ScOutlineTable
* pTable
= pDoc
->GetOutlineTable(nTab
);
2538 const ScOutlineArray
* pRowArray
= pTable
? &(pTable
->GetRowArray()) : nullptr;
2539 size_t nRowGroupDepth
= 0;
2540 std::vector
<size_t> aRowGroupIndexes
;
2541 if (bRangeHeaderSupport
&& pTable
)
2543 nRowGroupDepth
= pRowArray
->GetDepth();
2544 lcl_getGroupIndexes(*pRowArray
, nStartRow
, nEndRow
, aRowGroupIndexes
);
2547 /// 2) if we are approaching current max tiled row, signal a size changed event
2548 /// and invalidate the involved area
2550 if (nEndRow
> aViewData
.GetMaxTiledRow() - nVisibleRows
)
2552 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
2553 ScModelObj
* pModelObj
= pDocSh
? ScModelObj::getImplementation( pDocSh
->GetModel() ) : nullptr;
2554 Size
aOldSize(0, 0);
2556 aOldSize
= pModelObj
->getDocumentSize();
2558 aViewData
.SetMaxTiledRow(std::min(std::max(nEndRow
, aViewData
.GetMaxTiledRow()) + nVisibleRows
, (long)MAXTILEDROW
));
2560 Size
aNewSize(0, 0);
2562 aNewSize
= pModelObj
->getDocumentSize();
2564 SAL_INFO("sc.lok.header", "Row Header: a new height: " << aNewSize
.Height());
2567 // Provide size in the payload, so clients don't have to
2568 // call lok::Document::getDocumentSize().
2569 std::stringstream ss
;
2570 ss
<< aNewSize
.Width() << ", " << aNewSize
.Height();
2571 OString sSize
= ss
.str().c_str();
2572 aViewData
.GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
, sSize
.getStr());
2574 // New area extended to the bottom of the sheet after last row
2575 // excluding overlapping area with aNewColArea
2576 tools::Rectangle
aNewRowArea(0, aOldSize
.getHeight(), aOldSize
.getWidth(), aNewSize
.getHeight());
2578 // Only invalidate if spreadsheet extended to the bottom
2579 if (aNewRowArea
.getHeight())
2581 UpdateSelectionOverlay();
2582 SfxLokHelper::notifyInvalidation(aViewData
.GetViewShell(), aNewRowArea
.toString());
2588 /// 3) create string data for rows
2590 aBuffer
.append("\"rows\": [\n");
2592 long nTotalPixels
= nStartHeightPx
;
2593 SAL_INFO("sc.lok.header", "Row Header: [create string data for rows]: start row: "
2594 << nStartRow
<< " start height: " << nTotalPixels
);
2596 if (nStartRow
!= nEndRow
)
2598 OUString aText
= OUString::number(nStartRow
+ 1);
2599 aBuffer
.append("{ \"text\": \"").append(aText
).append("\", ");
2600 aBuffer
.append("\"size\": \"").append(OUString::number(nTotalPixels
* TWIPS_PER_PIXEL
)).append("\", ");
2601 aBuffer
.append("\"groupLevels\": \"").append(OUString::number(nRowGroupDepth
)).append("\" }");
2604 OUString aRowGroupsBuffer
;
2605 aRowGroupsBuffer
+= "\"rowGroups\": [\n";
2606 std::vector
<long> aRowGroupStartPositions(nRowGroupDepth
, -nTotalPixels
);
2607 long nPrevSizePx
= -1;
2608 for (SCROW nRow
= nStartRow
+ 1; nRow
<= nEndRow
; ++nRow
)
2610 // nSize will be 0 for hidden rows.
2611 const long nSizePx
= lcl_GetRowHeightPx(pDoc
, nRow
, nTab
);
2612 nTotalPixels
+= nSizePx
;
2613 const long nTotalTwips
= nTotalPixels
* TWIPS_PER_PIXEL
;
2615 if (bRangeHeaderSupport
&& nRowGroupDepth
> 0)
2617 lcl_createGroupsData(nRow
, nEndRow
, nSizePx
, nTotalTwips
,
2618 *pRowArray
, aRowGroupIndexes
, aRowGroupStartPositions
, aRowGroupsBuffer
);
2621 if (bRangeHeaderSupport
&& nRow
< nEndRow
&& nSizePx
== nPrevSizePx
)
2623 nPrevSizePx
= nSizePx
;
2625 OUString aText
= pRowBar
[SC_SPLIT_BOTTOM
]->GetEntryText(nRow
);
2626 aBuffer
.append(", ");
2627 aBuffer
.append("{ \"text\": \"").append(aText
).append("\", ");
2628 aBuffer
.append("\"size\": \"").append(OUString::number(nTotalTwips
)).append("\" }");
2631 aRowGroupsBuffer
+= "]";
2632 aBuffer
.append("]");
2633 if (nRowGroupDepth
> 0)
2634 aBuffer
.append(",\n").append(aRowGroupsBuffer
);
2635 /// end collecting ROWS
2638 aBuffer
.append(",\n");
2640 /// *** start collecting COLS ***
2642 /// 1) compute start and end columns
2644 if (rRectangle
.Left() < rRectangle
.Right())
2646 SAL_INFO("sc.lok.header", "Column Header: compute start/end columns.");
2647 long nRectLeftPx
= rRectangle
.Left() / TWIPS_PER_PIXEL
;
2648 long nRectRightPx
= rRectangle
.Right() / TWIPS_PER_PIXEL
;
2650 const auto& rLeftNearest
= aViewData
.GetLOKWidthHelper().getNearestByPosition(nRectLeftPx
);
2651 const auto& rRightNearest
= aViewData
.GetLOKWidthHelper().getNearestByPosition(nRectRightPx
);
2653 ScBoundsProvider
aBoundingColsProvider(pDoc
, nTab
, /*bColumnHeader: */ true);
2654 aBoundingColsProvider
.Compute(rLeftNearest
, rRightNearest
, nRectLeftPx
, nRectRightPx
);
2655 aBoundingColsProvider
.EnlargeBy(2);
2656 aBoundingColsProvider
.GetStartIndexAndPosition(nStartCol
, nStartWidthPx
);
2657 aBoundingColsProvider
.GetEndIndexAndPosition(nEndCol
, nEndWidthPx
);
2659 aViewData
.GetLOKWidthHelper().removeByIndex(mnLOKStartHeaderCol
);
2660 aViewData
.GetLOKWidthHelper().removeByIndex(mnLOKEndHeaderCol
);
2661 aViewData
.GetLOKWidthHelper().insert(nStartCol
, nStartWidthPx
);
2662 aViewData
.GetLOKWidthHelper().insert(nEndCol
, nEndWidthPx
);
2664 mnLOKStartHeaderCol
= nStartCol
;
2665 mnLOKEndHeaderCol
= nEndCol
;
2668 aBuffer
.ensureCapacity( aBuffer
.getCapacity() + (50 * (nEndCol
- nStartCol
+ 1)) );
2670 long nVisibleCols
= nEndCol
- nStartCol
;
2671 if (nVisibleCols
< 10)
2675 // Get column groups
2676 // per each level store the index of the first group intersecting
2677 // [nStartCol, nEndCol] range
2679 const ScOutlineArray
* pColArray
= pTable
? &(pTable
->GetColArray()) : nullptr;
2680 size_t nColGroupDepth
= 0;
2681 std::vector
<size_t> aColGroupIndexes
;
2682 if (bRangeHeaderSupport
&& pTable
)
2684 nColGroupDepth
= pColArray
->GetDepth();
2685 lcl_getGroupIndexes(*pColArray
, nStartCol
, nEndCol
, aColGroupIndexes
);
2688 /// 2) if we are approaching current max tiled column, signal a size changed event
2689 /// and invalidate the involved area
2691 if (nEndCol
> aViewData
.GetMaxTiledCol() - nVisibleCols
)
2693 ScDocShell
* pDocSh
= aViewData
.GetDocShell();
2694 ScModelObj
* pModelObj
= pDocSh
? ScModelObj::getImplementation( pDocSh
->GetModel() ) : nullptr;
2695 Size
aOldSize(0, 0);
2697 aOldSize
= pModelObj
->getDocumentSize();
2699 aViewData
.SetMaxTiledCol(std::min(std::max(nEndCol
, aViewData
.GetMaxTiledCol()) + nVisibleCols
, (long)MAXCOL
));
2701 Size
aNewSize(0, 0);
2703 aNewSize
= pModelObj
->getDocumentSize();
2707 // Provide size in the payload, so clients don't have to
2708 // call lok::Document::getDocumentSize().
2709 std::stringstream ss
;
2710 ss
<< aNewSize
.Width() << ", " << aNewSize
.Height();
2711 OString sSize
= ss
.str().c_str();
2712 aViewData
.GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED
, sSize
.getStr());
2714 // New area extended to the right of the sheet after last column
2715 // including overlapping area with aNewRowArea
2716 tools::Rectangle
aNewColArea(aOldSize
.getWidth(), 0, aNewSize
.getWidth(), aNewSize
.getHeight());
2718 // Only invalidate if spreadsheet extended to the bottom
2719 if (aNewColArea
.getWidth())
2721 UpdateSelectionOverlay();
2722 SfxLokHelper::notifyInvalidation(aViewData
.GetViewShell(), aNewColArea
.toString());
2727 /// 3) create string data for columns
2729 aBuffer
.append("\"columns\": [\n");
2731 nTotalPixels
= nStartWidthPx
;
2732 SAL_INFO("sc.lok.header", "Col Header: [create string data for cols]: start col: "
2733 << nStartRow
<< " start width: " << nTotalPixels
);
2735 if (nStartCol
!= nEndCol
)
2737 OUString aText
= OUString::number(nStartCol
+ 1);
2738 aBuffer
.append("{ \"text\": \"").append(aText
).append("\", ");
2739 aBuffer
.append("\"size\": \"").append(OUString::number(nTotalPixels
* TWIPS_PER_PIXEL
)).append("\", ");
2740 aBuffer
.append("\"groupLevels\": \"").append(OUString::number(nColGroupDepth
)).append("\" }");
2743 OUString aColGroupsBuffer
;
2744 aColGroupsBuffer
+= "\"columnGroups\": [\n";
2745 std::vector
<long> aColGroupStartPositions(nColGroupDepth
, -nTotalPixels
);
2747 for (SCCOL nCol
= nStartCol
+ 1; nCol
<= nEndCol
; ++nCol
)
2749 // nSize will be 0 for hidden columns.
2750 const long nSizePx
= lcl_GetColWidthPx(pDoc
, nCol
, nTab
);
2751 nTotalPixels
+= nSizePx
;
2752 const long nTotalTwips
= nTotalPixels
* TWIPS_PER_PIXEL
;
2754 if (bRangeHeaderSupport
&& nColGroupDepth
> 0)
2756 lcl_createGroupsData(nCol
, nEndCol
, nSizePx
, nTotalTwips
,
2757 *pColArray
, aColGroupIndexes
, aColGroupStartPositions
, aColGroupsBuffer
);
2760 if (bRangeHeaderSupport
&& nCol
< nEndCol
&& nSizePx
== nPrevSizePx
)
2762 nPrevSizePx
= nSizePx
;
2764 OUString aText
= bRangeHeaderSupport
?
2765 OUString::number(nCol
+ 1) : pColBar
[SC_SPLIT_LEFT
]->GetEntryText(nCol
);
2767 aBuffer
.append(", ");
2768 aBuffer
.append("{ \"text\": \"").append(aText
).append("\", ");
2769 aBuffer
.append("\"size\": \"").append(OUString::number(nTotalTwips
)).append("\" }");
2772 aColGroupsBuffer
+= "]";
2773 aBuffer
.append("]");
2774 if (nColGroupDepth
> 0)
2775 aBuffer
.append(",\n").append(aColGroupsBuffer
);
2776 /// end collecting COLs
2778 aBuffer
.append("\n}");
2779 OUString sRet
= aBuffer
.makeStringAndClear();
2781 vcl::Region
aNewVisArea(
2782 tools::Rectangle(mnLOKStartHeaderCol
+ 1, mnLOKStartHeaderRow
+ 1,
2783 mnLOKEndHeaderCol
, mnLOKEndHeaderRow
));
2784 aNewVisArea
.Exclude(aOldVisArea
);
2785 tools::Rectangle aChangedArea
= aNewVisArea
.GetBoundRect();
2786 if (!aChangedArea
.IsEmpty())
2788 UpdateFormulas(aChangedArea
.Left(), aChangedArea
.Top(), aChangedArea
.Right(), aChangedArea
.Bottom());
2794 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */