Update ooo320-m1
[ooovba.git] / sc / source / ui / view / hdrcont.cxx
blob5cfe8f8ab03a5a8192ca5984b1812e59bf231be4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hdrcont.cxx,v $
10 * $Revision: 1.21 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <sfx2/dispatch.hxx>
39 #include <vcl/help.hxx>
40 #include <tools/poly.hxx>
41 #include <svtools/colorcfg.hxx>
43 #include "scresid.hxx"
44 #include "sc.hrc"
45 #include "tabvwsh.hxx"
46 #include "hdrcont.hxx"
47 #include "scmod.hxx" // Optionen
48 #include "inputopt.hxx" // Optionen
49 #include "gridmerg.hxx"
50 #include "document.hxx"
52 // -----------------------------------------------------------------------
54 #define SC_DRAG_MIN 2
56 // passes in paint
57 // (selection left/right must be first because the continuous lines
58 // are partly overwritten later)
60 #define SC_HDRPAINT_SEL_RIGHT 0
61 #define SC_HDRPAINT_SEL_LEFT 1
62 #define SC_HDRPAINT_TOP 2
63 #define SC_HDRPAINT_SEL_TOP 3
64 #define SC_HDRPAINT_SEL_BOTTOM 4
65 #define SC_HDRPAINT_BOTTOM 5
66 #define SC_HDRPAINT_TEXT 6
67 #define SC_HDRPAINT_COUNT 7
69 //==================================================================
71 ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEngine,
72 SCCOLROW nNewSize, USHORT nNewFlags ) :
73 Window ( pParent ),
74 pSelEngine ( pSelectionEngine ),
75 nFlags ( nNewFlags ),
76 bVertical ( (nNewFlags & HDR_VERTICAL) != 0 ),
77 nSize ( nNewSize ),
78 nMarkStart ( 0 ),
79 nMarkEnd ( 0 ),
80 bMarkRange ( FALSE ),
81 bDragging ( FALSE ),
82 bIgnoreMove ( FALSE )
84 // --- RTL --- no default mirroring for this window, the spreadsheet itself
85 // is also not mirrored
86 // #107811# mirror the vertical window for correct border drawing
87 // #106948# table layout depends on sheet format, not UI setting, so the
88 // borders of the vertical window have to be handled manually, too.
89 EnableRTL( FALSE );
91 aNormFont = GetFont();
92 aNormFont.SetTransparent( TRUE ); //! WEIGHT_NORMAL hart setzen ???
93 aBoldFont = aNormFont;
94 aBoldFont.SetWeight( WEIGHT_BOLD );
96 SetFont(aBoldFont);
97 bBoldSet = TRUE;
99 Size aSize = LogicToPixel( Size(
100 GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888")) ),
101 GetTextHeight() ) );
102 aSize.Width() += 4; // Platz fuer hervorgehobene Umrandung
103 aSize.Height() += 3;
104 SetSizePixel( aSize );
106 nWidth = nSmallWidth = aSize.Width();
107 nBigWidth = LogicToPixel( Size( GetTextWidth(
108 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5;
110 SetBackground(); // sonst Probleme auf OS/2 !?!?!
113 void ScHeaderControl::SetWidth( long nNew )
115 DBG_ASSERT( bVertical, "SetDigits nur fuer Zeilenkoepfe erlaubt" );
116 if ( nNew != nWidth )
118 Size aSize( nNew, GetSizePixel().Height() ); // Hoehe nicht aendern
119 SetSizePixel( aSize );
121 nWidth = nNew;
123 Invalidate(); // neu zentrieren
127 __EXPORT ScHeaderControl::~ScHeaderControl()
131 void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd )
133 BOOL bLayoutRTL = IsLayoutRTL();
134 long nLayoutSign = bLayoutRTL ? -1 : 1;
136 Rectangle aRect( Point(0,0), GetOutputSizePixel() );
137 if ( bVertical )
139 aRect.Top() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line at top of selection
140 aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign;
142 else
144 aRect.Left() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line left of selection
145 aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign;
147 Invalidate(aRect);
150 void ScHeaderControl::SetMark( BOOL bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
152 BOOL bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader(); //! cachen?
153 if (!bEnabled)
154 bNewSet = FALSE;
156 // Variablen setzen
158 BOOL bOldSet = bMarkRange;
159 SCCOLROW nOldStart = nMarkStart;
160 SCCOLROW nOldEnd = nMarkEnd;
161 PutInOrder( nNewStart, nNewEnd );
162 bMarkRange = bNewSet;
163 nMarkStart = nNewStart;
164 nMarkEnd = nNewEnd;
166 // Paint
168 if ( bNewSet )
170 if ( bOldSet )
172 if ( nNewStart == nOldStart )
174 if ( nNewEnd != nOldEnd )
175 DoPaint( Min( nNewEnd, nOldEnd ) + 1, Max( nNewEnd, nOldEnd ) );
176 // sonst nix
178 else if ( nNewEnd == nOldEnd )
179 DoPaint( Min( nNewStart, nOldStart ), Max( nNewStart, nOldStart ) - 1 );
180 else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
182 // zwei Bereiche...
183 DoPaint( nOldStart, nOldEnd );
184 DoPaint( nNewStart, nNewEnd );
186 else // irgendwie ueberlappend... (kommt eh nicht oft vor)
187 DoPaint( Min( nNewStart, nOldStart ), Max( nNewEnd, nOldEnd ) );
189 else
190 DoPaint( nNewStart, nNewEnd ); // komplett neu
192 else if ( bOldSet )
193 DoPaint( nOldStart, nOldEnd ); // komplett aufheben
195 // sonst war nix, is nix
198 long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo )
200 long nScrPos;
202 long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
203 if (nEntryNo >= nSize)
204 nScrPos = nMax;
205 else
207 nScrPos = 0;
208 for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
210 USHORT nAdd = GetEntrySize(i);
211 if (nAdd)
212 nScrPos += nAdd;
213 else
215 SCCOLROW nHidden = GetHiddenCount(i);
216 if (nHidden > 0)
217 i += nHidden - 1;
222 if ( IsLayoutRTL() )
223 nScrPos = nMax - nScrPos - 2;
225 return nScrPos;
228 // draw a rectangle across the window's width/height, with the outer part in a lighter color
230 void ScHeaderControl::DrawShadedRect( long nStart, long nEnd, const Color& rBaseColor )
232 Color aWhite( COL_WHITE );
234 Color aInner( rBaseColor ); // highlight color, unchanged
235 Color aCenter( rBaseColor );
236 aCenter.Merge( aWhite, 0xd0 ); // lighten up a bit
237 Color aOuter( rBaseColor );
238 aOuter.Merge( aWhite, 0xa0 ); // lighten up more
240 if ( IsMirrored() )
241 std::swap( aInner, aOuter ); // just swap colors instead of positions
243 Size aWinSize = GetSizePixel();
244 long nBarSize = bVertical ? aWinSize.Width() : aWinSize.Height();
245 long nCenterPos = (nBarSize / 2) - 1;
247 SetLineColor();
248 SetFillColor( aOuter );
249 if (bVertical)
250 DrawRect( Rectangle( 0, nStart, nCenterPos-1, nEnd ) );
251 else
252 DrawRect( Rectangle( nStart, 0, nEnd, nCenterPos-1 ) );
253 SetFillColor( aCenter );
254 if (bVertical)
255 DrawRect( Rectangle( nCenterPos, nStart, nCenterPos, nEnd ) );
256 else
257 DrawRect( Rectangle( nStart, nCenterPos, nEnd, nCenterPos ) );
258 SetFillColor( aInner );
259 if (bVertical)
260 DrawRect( Rectangle( nCenterPos+1, nStart, nBarSize-1, nEnd ) );
261 else
262 DrawRect( Rectangle( nStart, nCenterPos+1, nEnd, nBarSize-1 ) );
266 // Paint
269 void __EXPORT ScHeaderControl::Paint( const Rectangle& rRect )
271 // fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren
272 // Linien zusammengefasst
274 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
275 BOOL bHighContrast = rStyleSettings.GetHighContrastMode();
276 BOOL bDark = rStyleSettings.GetFaceColor().IsDark();
277 // Use the same distinction for bDark as in Window::DrawSelectionBackground
279 Color aTextColor = rStyleSettings.GetButtonTextColor();
280 Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
281 aNormFont.SetColor( aTextColor );
282 if ( bHighContrast )
283 aBoldFont.SetColor( aTextColor );
284 else
285 aBoldFont.SetColor( aSelTextColor );
286 SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor );
288 Color aBlack( COL_BLACK );
289 Color aSelLineColor = rStyleSettings.GetHighlightColor();
290 aSelLineColor.Merge( aBlack, 0xe0 ); // darken just a little bit
292 BOOL bLayoutRTL = IsLayoutRTL();
293 long nLayoutSign = bLayoutRTL ? -1 : 1;
294 BOOL bMirrored = IsMirrored();
296 // const FunctionSet* pFuncSet = pSelEngine->GetFunctionSet();
297 String aString;
298 USHORT nBarSize;
299 Point aScrPos;
300 Size aTextSize;
301 // Size aSize = GetOutputSizePixel();
303 if (bVertical)
304 nBarSize = (USHORT) GetSizePixel().Width();
305 else
306 nBarSize = (USHORT) GetSizePixel().Height();
308 SCCOLROW nPos = GetPos();
310 long nPStart = bVertical ? rRect.Top() : rRect.Left();
311 long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();
313 long nTransStart = nPEnd + 1;
314 long nTransEnd = 0;
316 long nInitScrPos = 0;
317 if ( bLayoutRTL )
319 long nTemp = nPStart; // swap nPStart / nPEnd
320 nPStart = nPEnd;
321 nPEnd = nTemp;
322 nTemp = nTransStart; // swap nTransStart / nTransEnd
323 nTransStart = nTransEnd;
324 nTransEnd = nTemp;
325 if ( bVertical ) // start loops from the end
326 nInitScrPos = GetSizePixel().Height() - 1;
327 else
328 nInitScrPos = GetSizePixel().Width() - 1;
331 // aeussere Linien komplett durchzeichnen
332 // Zuerst Ende der letzten Zelle finden
334 // long nLineEnd = -1;
335 long nLineEnd = nInitScrPos - nLayoutSign;
337 for (SCCOLROW i=nPos; i<nSize; i++)
339 USHORT nSizePix = GetEntrySize( i );
340 if (nSizePix)
342 nLineEnd += nSizePix * nLayoutSign;
344 if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
346 long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
347 if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
348 nTransStart = nLineStart;
349 if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
350 nTransEnd = nLineEnd;
353 if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
355 nLineEnd = nPEnd;
356 break;
359 else
361 SCCOLROW nHidden = GetHiddenCount(i);
362 if (nHidden > 0)
363 i += nHidden - 1;
367 // background is different for entry area and behind the entries
369 Rectangle aFillRect;
370 SetLineColor();
372 if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
374 if ( bHighContrast )
376 // high contrast: single-color background
377 SetFillColor( rStyleSettings.GetFaceColor() );
378 if ( bVertical )
379 aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
380 else
381 aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
382 DrawRect( aFillRect );
384 else
386 // normal: 3-part background
387 DrawShadedRect( nInitScrPos, nLineEnd, rStyleSettings.GetFaceColor() );
391 if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
393 SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor );
394 if ( bVertical )
395 aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
396 else
397 aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
398 DrawRect( aFillRect );
401 if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
403 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
405 if ( bHighContrast )
407 if ( bDark )
409 // solid grey background for dark face color is drawn before lines
411 SetLineColor();
412 SetFillColor( COL_LIGHTGRAY );
413 if (bVertical)
414 DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) );
415 else
416 DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) );
419 else
421 // background for selection
423 DrawShadedRect( nTransStart, nTransEnd, rStyleSettings.GetHighlightColor() );
427 #if 0
428 // 3D border is no longer used
429 SetLineColor( rStyleSettings.GetLightColor() );
430 if (bVertical)
431 DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) );
432 else
433 DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) );
434 #endif
436 SetLineColor( rStyleSettings.GetDarkShadowColor() );
437 if (bVertical)
439 long nDarkPos = bMirrored ? 0 : nBarSize-1;
440 DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) );
442 else
443 DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) );
445 // line in different color for selection
446 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast )
448 SetLineColor( aSelLineColor );
449 if (bVertical)
451 long nDarkPos = bMirrored ? 0 : nBarSize-1;
452 DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) );
454 else
455 DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) );
460 // loop through entries several times to avoid changing the line color too often
461 // and to allow merging of lines
464 ScGridMerger aGrid( this, 1, 1 );
466 // start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different
467 // borders, light border at top isn't used anymore
468 // use SC_HDRPAINT_SEL_BOTTOM for different color
470 for (USHORT nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++)
472 // set line color etc. before entry loop
473 switch ( nPass )
475 case SC_HDRPAINT_SEL_BOTTOM:
476 // same as non-selected for high contrast
477 SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor );
478 break;
479 case SC_HDRPAINT_BOTTOM:
480 SetLineColor( rStyleSettings.GetDarkShadowColor() );
481 break;
482 case SC_HDRPAINT_TEXT:
483 // DrawSelectionBackground is used only for high contrast on light background
484 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
486 // Transparent selection background is drawn after lines, before text.
487 // #109814# Use DrawSelectionBackground to make sure there is a visible
488 // difference. The case of a dark face color, where DrawSelectionBackground
489 // would just paint over the lines, is handled separately (bDark).
490 // Otherwise, GetHighlightColor is used with 80% transparency.
491 // The window's background color (SetBackground) has to be the background
492 // of the cell area, for the contrast comparison in DrawSelectionBackground.
494 Rectangle aTransRect;
495 if (bVertical)
496 aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
497 else
498 aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
499 SetBackground( Color( rStyleSettings.GetFaceColor() ) );
500 DrawSelectionBackground( aTransRect, 0, TRUE, FALSE, FALSE );
501 SetBackground();
503 break;
506 SCCOLROW nCount=0;
507 long nScrPos=nInitScrPos;
510 if (bVertical)
511 aScrPos = Point( 0, nScrPos );
512 else
513 aScrPos = Point( nScrPos, 0 );
515 SCCOLROW nEntryNo = nCount + nPos;
516 if ( nEntryNo >= nSize ) // MAXCOL/MAXROW
517 nScrPos = nPEnd + nLayoutSign; // beyond nPEnd -> stop
518 else
520 USHORT nSizePix = GetEntrySize( nEntryNo );
522 if (nSizePix == 0)
524 SCCOLROW nHidden = GetHiddenCount(nEntryNo);
525 if (nHidden > 0)
526 nCount += nHidden - 1;
528 else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
530 Point aEndPos(aScrPos);
531 if (bVertical)
532 aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
533 else
534 aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );
536 BOOL bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
537 BOOL bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;
539 switch ( nPass )
541 case SC_HDRPAINT_SEL_BOTTOM:
542 case SC_HDRPAINT_BOTTOM:
543 if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) )
545 if (bVertical)
546 aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() );
547 else
548 aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() );
550 // thick bottom for hidden rows
551 // (drawn directly, without aGrid)
552 if ( nEntryNo+1 < nSize )
553 if ( GetEntrySize(nEntryNo+1)==0 )
555 if (bVertical)
556 DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
557 Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
558 else
559 DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
560 Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
563 break;
565 case SC_HDRPAINT_TEXT:
566 if ( nSizePix > 1 ) // minimal check for small columns/rows
568 if ( bMark != bBoldSet )
570 if (bMark)
571 SetFont(aBoldFont);
572 else
573 SetFont(aNormFont);
574 bBoldSet = bMark;
576 aString = GetEntryText( nEntryNo );
577 aTextSize.Width() = GetTextWidth( aString );
578 aTextSize.Height() = GetTextHeight();
580 Point aTxtPos(aScrPos);
581 if (bVertical)
583 aTxtPos.X() += (nBarSize-aTextSize.Width())/2;
584 aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2;
585 if ( bMirrored )
586 aTxtPos.X() += 1; // dark border is left instead of right
588 else
590 aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2;
591 aTxtPos.Y() += (nBarSize-aTextSize.Height())/2;
593 DrawText( aTxtPos, aString );
595 break;
598 // bei Selektion der ganzen Zeile/Spalte:
599 // InvertRect( Rectangle( aScrPos, aEndPos ) );
601 nScrPos += nSizePix * nLayoutSign; // also if before the visible area
603 ++nCount;
605 while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );
607 aGrid.Flush();
612 // Maus - Handling
615 SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, BOOL& rBorder )
617 BOOL bFound=FALSE;
618 SCCOLROW nCount = 1;
619 SCCOLROW nPos = GetPos();
620 SCCOLROW nHitNo = nPos;
621 long nScrPos;
622 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
623 long nDif;
624 Size aSize = GetOutputSizePixel();
625 long nWinSize = bVertical ? aSize.Height() : aSize.Width();
627 BOOL bLayoutRTL = IsLayoutRTL();
628 long nLayoutSign = bLayoutRTL ? -1 : 1;
629 long nEndPos = bLayoutRTL ? -1 : nWinSize;
631 nScrPos = GetScrPos( nPos ) - nLayoutSign;
634 SCCOLROW nEntryNo = nCount + nPos;
636 // nScrPos = GetScrPos( nEntryNo ) - 1;
638 if (nEntryNo > nSize)
639 nScrPos = nEndPos + nLayoutSign;
640 else
641 nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign; //! GetHiddenCount() ??
643 nDif = nMousePos - nScrPos;
644 if (nDif >= -2 && nDif <= 2 && nCount > 0)
646 bFound=TRUE;
647 nHitNo=nEntryNo-1;
649 else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
650 nHitNo = nEntryNo;
651 ++nCount;
653 while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );
655 rBorder = bFound;
656 return nHitNo;
659 bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const
661 ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
662 if (!pViewSh)
663 return false;
665 ScViewData* pViewData = pViewSh->GetViewData();
666 USHORT nTab = pViewData->GetTabNo();
667 ScDocument* pDoc = pViewData->GetDocument();
668 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
669 bool bSelectAllowed = true;
670 if ( pProtect && pProtect->isProtected() )
672 // This sheet is protected. Check if a context menu is allowed on this cell.
673 bool bCellsProtected = false;
674 if (bVertical)
675 // row header
676 bCellsProtected = pDoc->HasAttrib(0, nPos, nTab, MAXCOL, nPos, nTab, HASATTR_PROTECTED);
677 else
678 // column header
679 bCellsProtected = pDoc->HasAttrib(nPos, 0, nTab, nPos, MAXROW, nTab, HASATTR_PROTECTED);
681 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
682 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
684 if (bCellsProtected)
685 bSelectAllowed = bSelProtected;
686 else
687 bSelectAllowed = bSelUnprotected;
689 return bSelectAllowed;
692 void __EXPORT ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt )
694 if (IsDisabled())
695 return;
697 bIgnoreMove = FALSE;
698 SelectWindow();
700 BOOL bFound;
701 SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );
702 if (!IsSelectionAllowed(nHitNo))
703 return;
705 if ( bFound && rMEvt.IsLeft() && ResizeAllowed() )
707 nDragNo = nHitNo;
708 USHORT nClicks = rMEvt.GetClicks();
709 if ( nClicks && nClicks%2==0 )
711 SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM );
712 SetPointer( Pointer( POINTER_ARROW ) );
714 else
716 if (bVertical)
717 nDragStart = rMEvt.GetPosPixel().Y();
718 else
719 nDragStart = rMEvt.GetPosPixel().X();
720 nDragPos = nDragStart;
721 ShowDragHelp();
722 DrawInvert( nDragPos );
724 // CaptureMouse();
725 StartTracking();
726 bDragging = TRUE;
727 bDragMoved = FALSE;
730 else if (rMEvt.IsLeft())
732 pSelEngine->SetWindow( this );
733 Point aPoint;
734 Rectangle aVis( aPoint,GetOutputSizePixel() );
735 if (bVertical)
736 aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX;
737 else
738 aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX;
739 pSelEngine->SetVisibleArea( aVis );
741 SetMarking( TRUE ); // muss vor SelMouseButtonDown sein
742 pSelEngine->SelMouseButtonDown( rMEvt );
744 // #74215# In column/row headers a simple click already is a selection.
745 // -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
746 // if the next click is somewhere else with Control key).
747 pSelEngine->SelMouseMove( rMEvt );
749 if (IsMouseCaptured())
751 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
752 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
753 ReleaseMouse();
754 StartTracking();
759 void __EXPORT ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt )
761 if ( IsDisabled() )
762 return;
764 SetMarking( FALSE );
765 bIgnoreMove = FALSE;
766 // BOOL bFound;
767 // SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );
769 if ( bDragging )
771 DrawInvert( nDragPos );
772 ReleaseMouse();
773 bDragging = FALSE;
775 long nScrPos = GetScrPos( nDragNo );
776 long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
777 BOOL bLayoutRTL = IsLayoutRTL();
778 long nNewWidth = bLayoutRTL ? ( nScrPos - nMousePos + 1 )
779 : ( nMousePos + 2 - nScrPos );
781 if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ )
783 SCCOLROW nStart = 0;
784 SCCOLROW nEnd = nDragNo;
785 while (nNewWidth < 0)
787 nStart = nDragNo;
788 if (nDragNo>0)
790 --nDragNo;
791 nNewWidth += GetEntrySize( nDragNo ); //! GetHiddenCount() ???
793 else
794 nNewWidth = 0;
796 HideEntries( nStart, nEnd );
798 else
800 if (nNewWidth<0) nNewWidth=0;
801 if (bDragMoved)
802 SetEntrySize( nDragNo, (USHORT) nNewWidth );
805 else
807 pSelEngine->SelMouseButtonUp( rMEvt );
808 ReleaseMouse();
812 void __EXPORT ScHeaderControl::MouseMove( const MouseEvent& rMEvt )
814 if ( IsDisabled() )
816 SetPointer( Pointer( POINTER_ARROW ) );
817 return;
820 BOOL bFound;
821 (void)GetMousePos( rMEvt, bFound );
823 if ( bDragging )
825 long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
826 if ( nNewPos != nDragPos )
828 DrawInvert( nDragPos );
829 nDragPos = nNewPos;
830 ShowDragHelp();
831 DrawInvert( nDragPos );
833 if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
834 bDragMoved = TRUE;
837 else
839 if ( bFound && rMEvt.GetButtons()==0 && ResizeAllowed() )
840 SetPointer( Pointer( bVertical ? POINTER_VSIZEBAR : POINTER_HSIZEBAR ) );
841 else
842 SetPointer( Pointer( POINTER_ARROW ) );
844 if (!bIgnoreMove)
845 pSelEngine->SelMouseMove( rMEvt );
849 void ScHeaderControl::Tracking( const TrackingEvent& rTEvt )
851 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
852 // die verschiedenen MouseHandler verteilen...
854 if ( rTEvt.IsTrackingCanceled() )
855 StopMarking();
856 else if ( rTEvt.IsTrackingEnded() )
857 MouseButtonUp( rTEvt.GetMouseEvent() );
858 else
859 MouseMove( rTEvt.GetMouseEvent() );
862 void __EXPORT ScHeaderControl::Command( const CommandEvent& rCEvt )
864 USHORT nCmd = rCEvt.GetCommand();
865 if ( nCmd == COMMAND_CONTEXTMENU )
867 StopMarking(); // Selektion / Dragging beenden
869 // Popup ausfuehren
871 ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell,
872 SfxViewShell::Current() );
873 if ( pViewSh )
875 if ( rCEvt.IsMouseEvent() )
877 // #i18735# select the column/row under the mouse pointer
878 ScViewData* pViewData = pViewSh->GetViewData();
880 SelectWindow(); // also deselects drawing objects, stops draw text edit
881 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
882 SC_MOD()->InputEnterHandler(); // always end edit mode
884 MouseEvent aMEvt( rCEvt.GetMousePosPixel() );
885 BOOL bBorder;
886 SCCOLROW nPos = GetMousePos( aMEvt, bBorder );
887 if (!IsSelectionAllowed(nPos))
888 // Selecting this cell is not allowed, neither is context menu.
889 return;
891 SCTAB nTab = pViewData->GetTabNo();
892 ScRange aNewRange;
893 if ( bVertical )
894 aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
895 MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab );
896 else
897 aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
898 sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab );
900 // see if any part of the range is already selected
901 BOOL bSelected = FALSE;
902 ScRangeList aRanges;
903 pViewData->GetMarkData().FillRangeListWithMarks( &aRanges, FALSE );
904 ULONG nRangeCount = aRanges.Count();
905 for (ULONG i=0; i<nRangeCount && !bSelected; i++)
906 if ( aRanges.GetObject(i)->Intersects( aNewRange ) )
907 bSelected = TRUE;
909 // select the range if no part of it was selected
910 if ( !bSelected )
911 pViewSh->MarkRange( aNewRange );
914 ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER );
915 pViewSh->GetDispatcher()->ExecutePopup( aResId );
918 else if ( nCmd == COMMAND_STARTDRAG )
920 pSelEngine->Command( rCEvt );
924 void ScHeaderControl::StopMarking()
926 if ( bDragging )
928 DrawInvert( nDragPos );
929 bDragging = FALSE;
932 SetMarking( FALSE );
933 bIgnoreMove = TRUE;
935 // #86260# don't call pSelEngine->Reset, so selection across the parts of
936 // a split/frozen view is possible
938 ReleaseMouse();
941 void ScHeaderControl::ShowDragHelp()
943 if (Help::IsQuickHelpEnabled())
945 long nScrPos = GetScrPos( nDragNo );
946 BOOL bLayoutRTL = IsLayoutRTL();
947 long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
948 : ( nDragPos + 2 - nScrPos );
950 String aHelpStr = GetDragHelp( nVal );
951 Point aPos = OutputToScreenPixel( Point(0,0) );
952 Size aSize = GetSizePixel();
954 Point aMousePos = OutputToScreenPixel(GetPointerPosPixel());
956 Rectangle aRect;
957 USHORT nAlign;
958 if (!bVertical)
960 // oberhalb
961 aRect.Left() = aMousePos.X();
962 aRect.Top() = aPos.Y() - 4;
963 nAlign = QUICKHELP_BOTTOM|QUICKHELP_CENTER;
965 else
967 // rechts oben
968 aRect.Left() = aPos.X() + aSize.Width() + 8;
969 aRect.Top() = aMousePos.Y() - 2;
970 nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
973 aRect.Right() = aRect.Left();
974 aRect.Bottom() = aRect.Top();
976 Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign);
980 void __EXPORT ScHeaderControl::RequestHelp( const HelpEvent& rHEvt )
982 // Wenn eigene QuickHelp angezeigt wird, nicht durch RequestHelp
983 // wieder wegnehmen lassen
985 BOOL bOwn = bDragging && Help::IsQuickHelpEnabled();
986 if (!bOwn)
987 Window::RequestHelp(rHEvt);
990 // -----------------------------------------------------------------------
991 // Dummys fuer virtuelle Methoden
992 // -----------------------------------------------------------------------
994 SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo )
996 SCCOLROW nHidden = 0;
997 while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
999 ++nEntryNo;
1000 ++nHidden;
1002 return nHidden;
1005 BOOL ScHeaderControl::IsLayoutRTL()
1007 return FALSE;
1010 BOOL ScHeaderControl::IsMirrored()
1012 return FALSE;
1015 BOOL ScHeaderControl::IsDisabled()
1017 return FALSE;
1020 BOOL ScHeaderControl::ResizeAllowed()
1022 return TRUE;
1025 void ScHeaderControl::SelectWindow()
1029 void ScHeaderControl::DrawInvert( long /* nDragPos */ )
1033 String ScHeaderControl::GetDragHelp( long /* nVal */ )
1035 return EMPTY_STRING;
1038 void ScHeaderControl::SetMarking( BOOL /* bSet */ )