fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / hdrcont.cxx
blob1b094cbe34b222c5a5330056d1119a32f802a0f1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/dispatch.hxx>
21 #include <vcl/help.hxx>
22 #include <vcl/settings.hxx>
23 #include <tools/poly.hxx>
24 #include <svtools/colorcfg.hxx>
26 #include "scresid.hxx"
27 #include "sc.hrc"
28 #include "tabvwsh.hxx"
29 #include "hdrcont.hxx"
30 #include "scmod.hxx"
31 #include "inputopt.hxx"
32 #include "gridmerg.hxx"
33 #include "document.hxx"
34 #include "markdata.hxx"
36 #define SC_DRAG_MIN 2
38 // passes in paint
39 // (selection left/right must be first because the continuous lines
40 // are partly overwritten later)
42 #define SC_HDRPAINT_SEL_BOTTOM 4
43 #define SC_HDRPAINT_BOTTOM 5
44 #define SC_HDRPAINT_TEXT 6
45 #define SC_HDRPAINT_COUNT 7
47 ScHeaderControl::ScHeaderControl( vcl::Window* pParent, SelectionEngine* pSelectionEngine,
48 SCCOLROW nNewSize, bool bNewVertical ) :
49 Window ( pParent ),
50 pSelEngine ( pSelectionEngine ),
51 bVertical ( bNewVertical ),
52 nSize ( nNewSize ),
53 nMarkStart ( 0 ),
54 nMarkEnd ( 0 ),
55 bMarkRange ( false ),
56 bDragging ( false ),
57 nDragNo ( 0 ),
58 nDragStart ( 0 ),
59 nDragPos ( 0 ),
60 bDragMoved ( false ),
61 bIgnoreMove ( false )
63 // --- RTL --- no default mirroring for this window, the spreadsheet itself
64 // is also not mirrored
65 // mirror the vertical window for correct border drawing
66 // table layout depends on sheet format, not UI setting, so the
67 // borders of the vertical window have to be handled manually, too.
68 EnableRTL( false );
70 aNormFont = GetFont();
71 aNormFont.SetTransparent( true ); //! WEIGHT_NORMAL hart setzen ???
72 aBoldFont = aNormFont;
73 aBoldFont.SetWeight( WEIGHT_BOLD );
75 SetFont(aBoldFont);
76 bBoldSet = true;
78 Size aSize = LogicToPixel( Size(
79 GetTextWidth(OUString("8888")),
80 GetTextHeight() ) );
81 aSize.Width() += 4; // place for highlight border
82 aSize.Height() += 3;
83 SetSizePixel( aSize );
85 nWidth = nSmallWidth = aSize.Width();
86 nBigWidth = LogicToPixel( Size( GetTextWidth(OUString("8888888")), 0 ) ).Width() + 5;
88 SetBackground(); // sonst Probleme auf OS/2 !?!?!
91 void ScHeaderControl::SetWidth( long nNew )
93 OSL_ENSURE( bVertical, "SetWidth works only on row headers" );
94 if ( nNew != nWidth )
96 Size aSize( nNew, GetSizePixel().Height() );
97 SetSizePixel( aSize );
99 nWidth = nNew;
101 Invalidate();
105 ScHeaderControl::~ScHeaderControl()
109 void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd )
111 bool bLayoutRTL = IsLayoutRTL();
112 long nLayoutSign = bLayoutRTL ? -1 : 1;
114 Rectangle aRect( Point(0,0), GetOutputSizePixel() );
115 if ( bVertical )
117 aRect.Top() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line at top of selection
118 aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign;
120 else
122 aRect.Left() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line left of selection
123 aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign;
125 Invalidate(aRect);
128 void ScHeaderControl::SetMark( bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
130 bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader(); //! cachen?
131 if (!bEnabled)
132 bNewSet = false;
134 bool bOldSet = bMarkRange;
135 SCCOLROW nOldStart = nMarkStart;
136 SCCOLROW nOldEnd = nMarkEnd;
137 PutInOrder( nNewStart, nNewEnd );
138 bMarkRange = bNewSet;
139 nMarkStart = nNewStart;
140 nMarkEnd = nNewEnd;
142 // Paint
144 if ( bNewSet )
146 if ( bOldSet )
148 if ( nNewStart == nOldStart )
150 if ( nNewEnd != nOldEnd )
151 DoPaint( std::min( nNewEnd, nOldEnd ) + 1, std::max( nNewEnd, nOldEnd ) );
153 else if ( nNewEnd == nOldEnd )
154 DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewStart, nOldStart ) - 1 );
155 else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
157 // two areas
158 DoPaint( nOldStart, nOldEnd );
159 DoPaint( nNewStart, nNewEnd );
161 else // somehow overlapping... (it is not often)
162 DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewEnd, nOldEnd ) );
164 else
165 DoPaint( nNewStart, nNewEnd ); // completely new selection
167 else if ( bOldSet )
168 DoPaint( nOldStart, nOldEnd ); // cancel selection
171 long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo ) const
173 long nScrPos;
175 long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
176 if (nEntryNo >= nSize)
177 nScrPos = nMax;
178 else
180 nScrPos = 0;
181 for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
183 sal_uInt16 nAdd = GetEntrySize(i);
184 if (nAdd)
185 nScrPos += nAdd;
186 else
188 SCCOLROW nHidden = GetHiddenCount(i);
189 if (nHidden > 0)
190 i += nHidden - 1;
195 if ( IsLayoutRTL() )
196 nScrPos = nMax - nScrPos - 2;
198 return nScrPos;
201 // draw a rectangle across the window's width/height, with the outer part in a lighter color
203 void ScHeaderControl::DrawShadedRect( long nStart, long nEnd, const Color& rBaseColor )
205 Color aWhite( COL_WHITE );
207 Color aInner( rBaseColor ); // highlight color, unchanged
208 Color aCenter( rBaseColor );
209 aCenter.Merge( aWhite, 0xd0 ); // lighten up a bit
210 Color aOuter( rBaseColor );
211 aOuter.Merge( aWhite, 0xa0 ); // lighten up more
213 if ( IsMirrored() )
214 std::swap( aInner, aOuter ); // just swap colors instead of positions
216 Size aWinSize = GetSizePixel();
217 long nBarSize = bVertical ? aWinSize.Width() : aWinSize.Height();
218 long nCenterPos = (nBarSize / 2) - 1;
220 SetLineColor();
221 SetFillColor( aOuter );
222 if (bVertical)
223 DrawRect( Rectangle( 0, nStart, nCenterPos-1, nEnd ) );
224 else
225 DrawRect( Rectangle( nStart, 0, nEnd, nCenterPos-1 ) );
226 SetFillColor( aCenter );
227 if (bVertical)
228 DrawRect( Rectangle( nCenterPos, nStart, nCenterPos, nEnd ) );
229 else
230 DrawRect( Rectangle( nStart, nCenterPos, nEnd, nCenterPos ) );
231 SetFillColor( aInner );
232 if (bVertical)
233 DrawRect( Rectangle( nCenterPos+1, nStart, nBarSize-1, nEnd ) );
234 else
235 DrawRect( Rectangle( nStart, nCenterPos+1, nEnd, nBarSize-1 ) );
238 void ScHeaderControl::Paint( vcl::RenderContext& /*rRenderContext*/, const Rectangle& rRect )
240 // fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren
241 // Linien zusammengefasst
243 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
244 bool bHighContrast = rStyleSettings.GetHighContrastMode();
245 bool bDark = rStyleSettings.GetFaceColor().IsDark();
246 // Use the same distinction for bDark as in Window::DrawSelectionBackground
248 Color aTextColor = rStyleSettings.GetButtonTextColor();
249 Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
250 aNormFont.SetColor( aTextColor );
251 if ( bHighContrast )
252 aBoldFont.SetColor( aTextColor );
253 else
254 aBoldFont.SetColor( aSelTextColor );
255 SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor );
257 Color aBlack( COL_BLACK );
258 Color aSelLineColor = rStyleSettings.GetHighlightColor();
259 aSelLineColor.Merge( aBlack, 0xe0 ); // darken just a little bit
261 bool bLayoutRTL = IsLayoutRTL();
262 long nLayoutSign = bLayoutRTL ? -1 : 1;
263 bool bMirrored = IsMirrored();
265 OUString aString;
266 sal_uInt16 nBarSize;
267 Point aScrPos;
268 Size aTextSize;
270 if (bVertical)
271 nBarSize = (sal_uInt16) GetSizePixel().Width();
272 else
273 nBarSize = (sal_uInt16) GetSizePixel().Height();
275 SCCOLROW nPos = GetPos();
277 long nPStart = bVertical ? rRect.Top() : rRect.Left();
278 long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();
280 long nTransStart = nPEnd + 1;
281 long nTransEnd = 0;
283 long nInitScrPos = 0;
284 if ( bLayoutRTL )
286 long nTemp = nPStart; // swap nPStart / nPEnd
287 nPStart = nPEnd;
288 nPEnd = nTemp;
289 nTemp = nTransStart; // swap nTransStart / nTransEnd
290 nTransStart = nTransEnd;
291 nTransEnd = nTemp;
292 if ( bVertical ) // start loops from the end
293 nInitScrPos = GetSizePixel().Height() - 1;
294 else
295 nInitScrPos = GetSizePixel().Width() - 1;
298 // aeussere Linien komplett durchzeichnen
299 // Zuerst Ende der letzten Zelle finden
301 long nLineEnd = nInitScrPos - nLayoutSign;
303 for (SCCOLROW i=nPos; i<nSize; i++)
305 sal_uInt16 nSizePix = GetEntrySize( i );
306 if (nSizePix)
308 nLineEnd += nSizePix * nLayoutSign;
310 if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
312 long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
313 if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
314 nTransStart = nLineStart;
315 if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
316 nTransEnd = nLineEnd;
319 if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
321 nLineEnd = nPEnd;
322 break;
325 else
327 SCCOLROW nHidden = GetHiddenCount(i);
328 if (nHidden > 0)
329 i += nHidden - 1;
333 // background is different for entry area and behind the entries
335 Rectangle aFillRect;
336 SetLineColor();
338 if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
340 if ( bHighContrast )
342 // high contrast: single-color background
343 SetFillColor( rStyleSettings.GetFaceColor() );
344 if ( bVertical )
345 aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
346 else
347 aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
348 DrawRect( aFillRect );
350 else
352 // normal: 3-part background
353 DrawShadedRect( nInitScrPos, nLineEnd, rStyleSettings.GetFaceColor() );
357 if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
359 SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor );
360 if ( bVertical )
361 aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
362 else
363 aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
364 DrawRect( aFillRect );
367 if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
369 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
371 if ( bHighContrast )
373 if ( bDark )
375 // solid grey background for dark face color is drawn before lines
377 SetLineColor();
378 SetFillColor( COL_LIGHTGRAY );
379 if (bVertical)
380 DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) );
381 else
382 DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) );
385 else
387 // background for selection
389 DrawShadedRect( nTransStart, nTransEnd, rStyleSettings.GetHighlightColor() );
393 SetLineColor( rStyleSettings.GetDarkShadowColor() );
394 if (bVertical)
396 long nDarkPos = bMirrored ? 0 : nBarSize-1;
397 DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) );
399 else
400 DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) );
402 // line in different color for selection
403 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast )
405 SetLineColor( aSelLineColor );
406 if (bVertical)
408 long nDarkPos = bMirrored ? 0 : nBarSize-1;
409 DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) );
411 else
412 DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) );
416 // loop through entries several times to avoid changing the line color too often
417 // and to allow merging of lines
419 ScGridMerger aGrid( this, 1, 1 );
421 // start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different
422 // borders, light border at top isn't used anymore
423 // use SC_HDRPAINT_SEL_BOTTOM for different color
425 for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++)
427 // set line color etc. before entry loop
428 switch ( nPass )
430 case SC_HDRPAINT_SEL_BOTTOM:
431 // same as non-selected for high contrast
432 SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor );
433 break;
434 case SC_HDRPAINT_BOTTOM:
435 SetLineColor( rStyleSettings.GetDarkShadowColor() );
436 break;
437 case SC_HDRPAINT_TEXT:
438 // DrawSelectionBackground is used only for high contrast on light background
439 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
441 // Transparent selection background is drawn after lines, before text.
442 // Use DrawSelectionBackground to make sure there is a visible
443 // difference. The case of a dark face color, where DrawSelectionBackground
444 // would just paint over the lines, is handled separately (bDark).
445 // Otherwise, GetHighlightColor is used with 80% transparency.
446 // The window's background color (SetBackground) has to be the background
447 // of the cell area, for the contrast comparison in DrawSelectionBackground.
449 Rectangle aTransRect;
450 if (bVertical)
451 aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
452 else
453 aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
454 SetBackground( Color( rStyleSettings.GetFaceColor() ) );
455 DrawSelectionBackground( aTransRect, 0, true, false, false );
456 SetBackground();
458 break;
461 SCCOLROW nCount=0;
462 long nScrPos=nInitScrPos;
465 if (bVertical)
466 aScrPos = Point( 0, nScrPos );
467 else
468 aScrPos = Point( nScrPos, 0 );
470 SCCOLROW nEntryNo = nCount + nPos;
471 if ( nEntryNo >= nSize ) // MAXCOL/MAXROW
472 nScrPos = nPEnd + nLayoutSign; // beyond nPEnd -> stop
473 else
475 sal_uInt16 nSizePix = GetEntrySize( nEntryNo );
477 if (nSizePix == 0)
479 SCCOLROW nHidden = GetHiddenCount(nEntryNo);
480 if (nHidden > 0)
481 nCount += nHidden - 1;
483 else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
485 Point aEndPos(aScrPos);
486 if (bVertical)
487 aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
488 else
489 aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );
491 bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
492 bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;
494 switch ( nPass )
496 case SC_HDRPAINT_SEL_BOTTOM:
497 case SC_HDRPAINT_BOTTOM:
498 if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) )
500 if (bVertical)
501 aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() );
502 else
503 aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() );
505 // thick bottom for hidden rows
506 // (drawn directly, without aGrid)
507 if ( nEntryNo+1 < nSize )
508 if ( GetEntrySize(nEntryNo+1)==0 )
510 if (bVertical)
511 DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
512 Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
513 else
514 DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
515 Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
518 break;
520 case SC_HDRPAINT_TEXT:
521 if ( nSizePix > 1 ) // minimal check for small columns/rows
523 if ( bMark != bBoldSet )
525 if (bMark)
526 SetFont(aBoldFont);
527 else
528 SetFont(aNormFont);
529 bBoldSet = bMark;
531 aString = GetEntryText( nEntryNo );
532 aTextSize.Width() = GetTextWidth( aString );
533 aTextSize.Height() = GetTextHeight();
535 Point aTxtPos(aScrPos);
536 if (bVertical)
538 aTxtPos.X() += (nBarSize-aTextSize.Width())/2;
539 aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2;
540 if ( bMirrored )
541 aTxtPos.X() += 1; // dark border is left instead of right
543 else
545 aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2;
546 aTxtPos.Y() += (nBarSize-aTextSize.Height())/2;
548 DrawText( aTxtPos, aString );
550 break;
553 // bei Selektion der ganzen Zeile/Spalte:
554 // InvertRect( Rectangle( aScrPos, aEndPos ) );
556 nScrPos += nSizePix * nLayoutSign; // also if before the visible area
558 ++nCount;
560 while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );
562 aGrid.Flush();
566 SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, bool& rBorder ) const
568 bool bFound = false;
569 SCCOLROW nPos = GetPos();
570 SCCOLROW nHitNo = nPos;
571 SCCOLROW nEntryNo = 1 + nPos;
572 long nScrPos;
573 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
574 long nDif;
575 Size aSize = GetOutputSizePixel();
576 long nWinSize = bVertical ? aSize.Height() : aSize.Width();
578 bool bLayoutRTL = IsLayoutRTL();
579 long nLayoutSign = bLayoutRTL ? -1 : 1;
580 long nEndPos = bLayoutRTL ? -1 : nWinSize;
582 nScrPos = GetScrPos( nPos ) - nLayoutSign;
585 if (nEntryNo > nSize)
586 nScrPos = nEndPos + nLayoutSign;
587 else
588 nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign; //! GetHiddenCount() ??
590 nDif = nMousePos - nScrPos;
591 if (nDif >= -2 && nDif <= 2)
593 bFound = true;
594 nHitNo=nEntryNo-1;
596 else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
597 nHitNo = nEntryNo;
598 ++nEntryNo;
600 while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );
602 rBorder = bFound;
603 return nHitNo;
606 bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const
608 ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
609 if (!pViewSh)
610 return false;
612 ScViewData& rViewData = pViewSh->GetViewData();
613 sal_uInt16 nTab = rViewData.GetTabNo();
614 ScDocument* pDoc = rViewData.GetDocument();
615 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
616 bool bSelectAllowed = true;
617 if ( pProtect && pProtect->isProtected() )
619 // This sheet is protected. Check if a context menu is allowed on this cell.
620 bool bCellsProtected = false;
621 if (bVertical)
623 // row header
624 SCROW nRPos = static_cast<SCROW>(nPos);
625 bCellsProtected = pDoc->HasAttrib(0, nRPos, nTab, MAXCOL, nRPos, nTab, HASATTR_PROTECTED);
627 else
629 // column header
630 SCCOL nCPos = static_cast<SCCOL>(nPos);
631 bCellsProtected = pDoc->HasAttrib(nCPos, 0, nTab, nCPos, MAXROW, nTab, HASATTR_PROTECTED);
634 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
635 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
637 if (bCellsProtected)
638 bSelectAllowed = bSelProtected;
639 else
640 bSelectAllowed = bSelUnprotected;
642 return bSelectAllowed;
645 void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt )
647 if (IsDisabled())
648 return;
650 bIgnoreMove = false;
651 SelectWindow();
653 bool bIsBorder;
654 SCCOLROW nHitNo = GetMousePos( rMEvt, bIsBorder );
655 if (!IsSelectionAllowed(nHitNo))
656 return;
657 if ( ! rMEvt.IsLeft() )
658 return;
659 if ( bIsBorder && ResizeAllowed() )
661 nDragNo = nHitNo;
662 sal_uInt16 nClicks = rMEvt.GetClicks();
663 if ( nClicks && nClicks%2==0 )
665 SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM );
666 SetPointer( Pointer( PointerStyle::Arrow ) );
668 else
670 if (bVertical)
671 nDragStart = rMEvt.GetPosPixel().Y();
672 else
673 nDragStart = rMEvt.GetPosPixel().X();
674 nDragPos = nDragStart;
675 ShowDragHelp();
676 DrawInvert( nDragPos );
678 StartTracking();
679 bDragging = true;
680 bDragMoved = false;
683 else
685 pSelEngine->SetWindow( this );
686 Point aPoint;
687 Rectangle aVis( aPoint,GetOutputSizePixel() );
688 if (bVertical)
689 aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX;
690 else
691 aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX;
692 pSelEngine->SetVisibleArea( aVis );
694 SetMarking( true ); // must precede SelMouseButtonDown
695 pSelEngine->SelMouseButtonDown( rMEvt );
697 // In column/row headers a simple click already is a selection.
698 // -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
699 // if the next click is somewhere else with Control key).
700 pSelEngine->SelMouseMove( rMEvt );
702 if (IsMouseCaptured())
704 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
705 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
706 ReleaseMouse();
707 StartTracking();
712 void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt )
714 if ( IsDisabled() )
715 return;
717 SetMarking( false );
718 bIgnoreMove = false;
720 if ( bDragging )
722 DrawInvert( nDragPos );
723 ReleaseMouse();
724 bDragging = false;
726 long nScrPos = GetScrPos( nDragNo );
727 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
728 bool bLayoutRTL = IsLayoutRTL();
729 long nNewWidth = bLayoutRTL ? ( nScrPos - nMousePos + 1 )
730 : ( nMousePos + 2 - nScrPos );
732 if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ )
734 SCCOLROW nStart = 0;
735 SCCOLROW nEnd = nDragNo;
736 while (nNewWidth < 0)
738 nStart = nDragNo;
739 if (nDragNo>0)
741 --nDragNo;
742 nNewWidth += GetEntrySize( nDragNo ); //! GetHiddenCount() ???
744 else
745 nNewWidth = 0;
747 HideEntries( nStart, nEnd );
749 else
751 if (bDragMoved)
752 SetEntrySize( nDragNo, (sal_uInt16) nNewWidth );
755 else
757 pSelEngine->SelMouseButtonUp( rMEvt );
758 ReleaseMouse();
762 void ScHeaderControl::MouseMove( const MouseEvent& rMEvt )
764 if ( IsDisabled() )
766 SetPointer( Pointer( PointerStyle::Arrow ) );
767 return;
770 if ( bDragging )
772 long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
773 if ( nNewPos != nDragPos )
775 DrawInvert( nDragPos );
776 nDragPos = nNewPos;
777 ShowDragHelp();
778 DrawInvert( nDragPos );
780 if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
781 bDragMoved = true;
784 else
786 bool bIsBorder;
787 (void)GetMousePos( rMEvt, bIsBorder );
789 if ( bIsBorder && rMEvt.GetButtons()==0 && ResizeAllowed() )
790 SetPointer( Pointer( bVertical ? PointerStyle::VSizeBar : PointerStyle::HSizeBar ) );
791 else
792 SetPointer( Pointer( PointerStyle::Arrow ) );
794 if (!bIgnoreMove)
795 pSelEngine->SelMouseMove( rMEvt );
799 void ScHeaderControl::Tracking( const TrackingEvent& rTEvt )
801 // Distribute the tracking events to the various MouseEvents, because
802 // SelectionEngine does not know anything about Tracking
804 if ( rTEvt.IsTrackingCanceled() )
805 StopMarking();
806 else if ( rTEvt.IsTrackingEnded() )
807 MouseButtonUp( rTEvt.GetMouseEvent() );
808 else
809 MouseMove( rTEvt.GetMouseEvent() );
812 void ScHeaderControl::Command( const CommandEvent& rCEvt )
814 CommandEventId nCmd = rCEvt.GetCommand();
815 if ( nCmd == CommandEventId::ContextMenu )
817 StopMarking(); // finish selection / dragging
819 // execute popup menu
821 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell,
822 SfxViewShell::Current() );
823 if ( pViewSh )
825 if ( rCEvt.IsMouseEvent() )
827 // #i18735# select the column/row under the mouse pointer
828 ScViewData& rViewData = pViewSh->GetViewData();
830 SelectWindow(); // also deselects drawing objects, stops draw text edit
831 if ( rViewData.HasEditView( rViewData.GetActivePart() ) )
832 SC_MOD()->InputEnterHandler(); // always end edit mode
834 MouseEvent aMEvt( rCEvt.GetMousePosPixel() );
835 bool bBorder;
836 SCCOLROW nPos = GetMousePos( aMEvt, bBorder );
837 if (!IsSelectionAllowed(nPos))
838 // Selecting this cell is not allowed, neither is context menu.
839 return;
841 SCTAB nTab = rViewData.GetTabNo();
842 ScRange aNewRange;
843 if ( bVertical )
844 aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
845 MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab );
846 else
847 aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
848 sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab );
850 // see if any part of the range is already selected
851 ScRangeList aRanges;
852 rViewData.GetMarkData().FillRangeListWithMarks( &aRanges, false );
853 bool bSelected = aRanges.Intersects(aNewRange);
855 // select the range if no part of it was selected
856 if ( !bSelected )
857 pViewSh->MarkRange( aNewRange );
860 ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER );
861 pViewSh->GetDispatcher()->ExecutePopup( aResId );
864 else if ( nCmd == CommandEventId::StartDrag )
866 pSelEngine->Command( rCEvt );
870 void ScHeaderControl::StopMarking()
872 if ( bDragging )
874 DrawInvert( nDragPos );
875 bDragging = false;
878 SetMarking( false );
879 bIgnoreMove = true;
881 // don't call pSelEngine->Reset, so selection across the parts of
882 // a split/frozen view is possible
884 ReleaseMouse();
887 void ScHeaderControl::ShowDragHelp()
889 if (Help::IsQuickHelpEnabled())
891 long nScrPos = GetScrPos( nDragNo );
892 bool bLayoutRTL = IsLayoutRTL();
893 long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
894 : ( nDragPos + 2 - nScrPos );
896 OUString aHelpStr = GetDragHelp( nVal );
897 Point aPos = OutputToScreenPixel( Point(0,0) );
898 Size aSize = GetSizePixel();
900 Point aMousePos = OutputToScreenPixel(GetPointerPosPixel());
902 Rectangle aRect;
903 QuickHelpFlags nAlign;
904 if (!bVertical)
906 // above
907 aRect.Left() = aMousePos.X();
908 aRect.Top() = aPos.Y() - 4;
909 nAlign = QuickHelpFlags::Bottom|QuickHelpFlags::Center;
911 else
913 // top right
914 aRect.Left() = aPos.X() + aSize.Width() + 8;
915 aRect.Top() = aMousePos.Y() - 2;
916 nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
919 aRect.Right() = aRect.Left();
920 aRect.Bottom() = aRect.Top();
922 Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign);
926 void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt )
928 // If the own QuickHelp is displayed, don't let RequestHelp remove it
930 bool bOwn = bDragging && Help::IsQuickHelpEnabled();
931 if (!bOwn)
932 Window::RequestHelp(rHEvt);
935 // Dummys fuer virtuelle Methoden
937 SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo ) const
939 SCCOLROW nHidden = 0;
940 while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
942 ++nEntryNo;
943 ++nHidden;
945 return nHidden;
948 bool ScHeaderControl::IsLayoutRTL() const
950 return false;
953 bool ScHeaderControl::IsMirrored() const
955 return false;
958 bool ScHeaderControl::IsDisabled() const
960 return false;
963 bool ScHeaderControl::ResizeAllowed() const
965 return true;
968 void ScHeaderControl::SelectWindow()
972 void ScHeaderControl::DrawInvert( long /* nDragPos */ )
976 OUString ScHeaderControl::GetDragHelp( long /* nVal */ )
978 return EMPTY_OUSTRING;
981 void ScHeaderControl::SetMarking( bool /* bSet */ )
985 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */