xref: /AOO41X/main/sc/source/ui/view/hdrcont.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include <sfx2/dispatch.hxx>
32 #include <vcl/help.hxx>
33 #include <tools/poly.hxx>
34 #include <svtools/colorcfg.hxx>
35 
36 #include "scresid.hxx"
37 #include "sc.hrc"
38 #include "tabvwsh.hxx"
39 #include "hdrcont.hxx"
40 #include "scmod.hxx"        // Optionen
41 #include "inputopt.hxx"     // Optionen
42 #include "gridmerg.hxx"
43 #include "document.hxx"
44 
45 // -----------------------------------------------------------------------
46 
47 #define SC_DRAG_MIN     2
48 
49 //  passes in paint
50 //  (selection left/right must be first because the continuous lines
51 //  are partly overwritten later)
52 
53 #define SC_HDRPAINT_SEL_RIGHT   0
54 #define SC_HDRPAINT_SEL_LEFT    1
55 #define SC_HDRPAINT_TOP         2
56 #define SC_HDRPAINT_SEL_TOP     3
57 #define SC_HDRPAINT_SEL_BOTTOM  4
58 #define SC_HDRPAINT_BOTTOM      5
59 #define SC_HDRPAINT_TEXT        6
60 #define SC_HDRPAINT_COUNT       7
61 
62 //==================================================================
63 
ScHeaderControl(Window * pParent,SelectionEngine * pSelectionEngine,SCCOLROW nNewSize,sal_uInt16 nNewFlags)64 ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEngine,
65                                     SCCOLROW nNewSize, sal_uInt16 nNewFlags ) :
66             Window      ( pParent ),
67             pSelEngine  ( pSelectionEngine ),
68             nFlags      ( nNewFlags ),
69             bVertical   ( (nNewFlags & HDR_VERTICAL) != 0 ),
70             nSize       ( nNewSize ),
71             nMarkStart  ( 0 ),
72             nMarkEnd    ( 0 ),
73             bMarkRange  ( sal_False ),
74             bDragging   ( sal_False ),
75             bIgnoreMove ( sal_False )
76 {
77     // --- RTL --- no default mirroring for this window, the spreadsheet itself
78     // is also not mirrored
79     // #107811# mirror the vertical window for correct border drawing
80     // #106948# table layout depends on sheet format, not UI setting, so the
81     // borders of the vertical window have to be handled manually, too.
82     EnableRTL( sal_False );
83 
84     aNormFont = GetFont();
85     aNormFont.SetTransparent( sal_True );       //! WEIGHT_NORMAL hart setzen ???
86     aBoldFont = aNormFont;
87     aBoldFont.SetWeight( WEIGHT_BOLD );
88 
89     SetFont(aBoldFont);
90     bBoldSet = sal_True;
91 
92     Size aSize = LogicToPixel( Size(
93         GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888")) ),
94         GetTextHeight() ) );
95     aSize.Width()  += 4;    // Platz fuer hervorgehobene Umrandung
96     aSize.Height() += 3;
97     SetSizePixel( aSize );
98 
99     nWidth = nSmallWidth = aSize.Width();
100     nBigWidth = LogicToPixel( Size( GetTextWidth(
101         String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5;
102 
103     SetBackground();    // sonst Probleme auf OS/2 !?!?!
104 }
105 
SetWidth(long nNew)106 void ScHeaderControl::SetWidth( long nNew )
107 {
108     DBG_ASSERT( bVertical, "SetDigits nur fuer Zeilenkoepfe erlaubt" );
109     if ( nNew != nWidth )
110     {
111         Size aSize( nNew, GetSizePixel().Height() );    // Hoehe nicht aendern
112         SetSizePixel( aSize );
113 
114         nWidth = nNew;
115 
116         Invalidate();       // neu zentrieren
117     }
118 }
119 
~ScHeaderControl()120 ScHeaderControl::~ScHeaderControl()
121 {
122 }
123 
DoPaint(SCCOLROW nStart,SCCOLROW nEnd)124 void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd )
125 {
126     sal_Bool bLayoutRTL = IsLayoutRTL();
127     long nLayoutSign = bLayoutRTL ? -1 : 1;
128 
129     Rectangle aRect( Point(0,0), GetOutputSizePixel() );
130     if ( bVertical )
131     {
132         aRect.Top() = GetScrPos( nStart )-nLayoutSign;      // extra pixel for line at top of selection
133         aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign;
134     }
135     else
136     {
137         aRect.Left() = GetScrPos( nStart )-nLayoutSign;     // extra pixel for line left of selection
138         aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign;
139     }
140     Invalidate(aRect);
141 }
142 
SetMark(sal_Bool bNewSet,SCCOLROW nNewStart,SCCOLROW nNewEnd)143 void ScHeaderControl::SetMark( sal_Bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
144 {
145     sal_Bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader();    //! cachen?
146     if (!bEnabled)
147         bNewSet = sal_False;
148 
149     //  Variablen setzen
150 
151     sal_Bool bOldSet     = bMarkRange;
152     SCCOLROW nOldStart = nMarkStart;
153     SCCOLROW nOldEnd     = nMarkEnd;
154     PutInOrder( nNewStart, nNewEnd );
155     bMarkRange = bNewSet;
156     nMarkStart = nNewStart;
157     nMarkEnd   = nNewEnd;
158 
159     //  Paint
160 
161     if ( bNewSet )
162     {
163         if ( bOldSet )
164         {
165             if ( nNewStart == nOldStart )
166             {
167                 if ( nNewEnd != nOldEnd )
168                     DoPaint( Min( nNewEnd, nOldEnd ) + 1, Max( nNewEnd, nOldEnd ) );
169                 // sonst nix
170             }
171             else if ( nNewEnd == nOldEnd )
172                 DoPaint( Min( nNewStart, nOldStart ), Max( nNewStart, nOldStart ) - 1 );
173             else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
174             {
175                 //  zwei Bereiche...
176                 DoPaint( nOldStart, nOldEnd );
177                 DoPaint( nNewStart, nNewEnd );
178             }
179             else                //  irgendwie ueberlappend... (kommt eh nicht oft vor)
180                 DoPaint( Min( nNewStart, nOldStart ), Max( nNewEnd, nOldEnd ) );
181         }
182         else
183             DoPaint( nNewStart, nNewEnd );      //  komplett neu
184     }
185     else if ( bOldSet )
186         DoPaint( nOldStart, nOldEnd );          //  komplett aufheben
187 
188     //  sonst war nix, is nix
189 }
190 
GetScrPos(SCCOLROW nEntryNo)191 long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo )
192 {
193     long nScrPos;
194 
195     long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
196     if (nEntryNo >= nSize)
197         nScrPos = nMax;
198     else
199     {
200         nScrPos = 0;
201         for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
202         {
203             sal_uInt16 nAdd = GetEntrySize(i);
204             if (nAdd)
205                 nScrPos += nAdd;
206             else
207             {
208                 SCCOLROW nHidden = GetHiddenCount(i);
209                 if (nHidden > 0)
210                     i += nHidden - 1;
211             }
212         }
213     }
214 
215     if ( IsLayoutRTL() )
216         nScrPos = nMax - nScrPos - 2;
217 
218     return nScrPos;
219 }
220 
221 // draw a rectangle across the window's width/height, with the outer part in a lighter color
222 
DrawShadedRect(long nStart,long nEnd,const Color & rBaseColor)223 void ScHeaderControl::DrawShadedRect( long nStart, long nEnd, const Color& rBaseColor )
224 {
225     Color aWhite( COL_WHITE );
226 
227     Color aInner( rBaseColor );             // highlight color, unchanged
228     Color aCenter( rBaseColor );
229     aCenter.Merge( aWhite, 0xd0 );          // lighten up a bit
230     Color aOuter( rBaseColor );
231     aOuter.Merge( aWhite, 0xa0 );           // lighten up more
232 
233     if ( IsMirrored() )
234         std::swap( aInner, aOuter );        // just swap colors instead of positions
235 
236     Size aWinSize = GetSizePixel();
237     long nBarSize = bVertical ? aWinSize.Width() : aWinSize.Height();
238     long nCenterPos = (nBarSize / 2) - 1;
239 
240     SetLineColor();
241     SetFillColor( aOuter );
242     if (bVertical)
243         DrawRect( Rectangle( 0, nStart, nCenterPos-1, nEnd ) );
244     else
245         DrawRect( Rectangle( nStart, 0, nEnd, nCenterPos-1 ) );
246     SetFillColor( aCenter );
247     if (bVertical)
248         DrawRect( Rectangle( nCenterPos, nStart, nCenterPos, nEnd ) );
249     else
250         DrawRect( Rectangle( nStart, nCenterPos, nEnd, nCenterPos ) );
251     SetFillColor( aInner );
252     if (bVertical)
253         DrawRect( Rectangle( nCenterPos+1, nStart, nBarSize-1, nEnd ) );
254     else
255         DrawRect( Rectangle( nStart, nCenterPos+1, nEnd, nBarSize-1 ) );
256 }
257 
258 //
259 //      Paint
260 //
261 
Paint(const Rectangle & rRect)262 void ScHeaderControl::Paint( const Rectangle& rRect )
263 {
264     //  fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren
265     //  Linien zusammengefasst
266 
267     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
268     sal_Bool bHighContrast = rStyleSettings.GetHighContrastMode();
269     sal_Bool bDark = rStyleSettings.GetFaceColor().IsDark();
270     // Use the same distinction for bDark as in Window::DrawSelectionBackground
271 
272     Color aTextColor = rStyleSettings.GetButtonTextColor();
273     Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
274     aNormFont.SetColor( aTextColor );
275     if ( bHighContrast )
276         aBoldFont.SetColor( aTextColor );
277     else
278         aBoldFont.SetColor( aSelTextColor );
279     SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor );
280 
281     Color aBlack( COL_BLACK );
282     Color aSelLineColor = rStyleSettings.GetHighlightColor();
283     aSelLineColor.Merge( aBlack, 0xe0 );        // darken just a little bit
284 
285     sal_Bool bLayoutRTL = IsLayoutRTL();
286     long nLayoutSign = bLayoutRTL ? -1 : 1;
287     sal_Bool bMirrored = IsMirrored();
288 
289 //  const FunctionSet*  pFuncSet = pSelEngine->GetFunctionSet();
290     String              aString;
291     sal_uInt16              nBarSize;
292     Point               aScrPos;
293     Size                aTextSize;
294 //  Size                aSize = GetOutputSizePixel();
295 
296     if (bVertical)
297         nBarSize = (sal_uInt16) GetSizePixel().Width();
298     else
299         nBarSize = (sal_uInt16) GetSizePixel().Height();
300 
301     SCCOLROW    nPos = GetPos();
302 
303     long nPStart = bVertical ? rRect.Top() : rRect.Left();
304     long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();
305 
306     long nTransStart = nPEnd + 1;
307     long nTransEnd = 0;
308 
309     long nInitScrPos = 0;
310     if ( bLayoutRTL )
311     {
312         long nTemp = nPStart;       // swap nPStart / nPEnd
313         nPStart = nPEnd;
314         nPEnd = nTemp;
315         nTemp = nTransStart;        // swap nTransStart / nTransEnd
316         nTransStart = nTransEnd;
317         nTransEnd = nTemp;
318         if ( bVertical )            // start loops from the end
319             nInitScrPos = GetSizePixel().Height() - 1;
320         else
321             nInitScrPos = GetSizePixel().Width() - 1;
322     }
323 
324     //  aeussere Linien komplett durchzeichnen
325     //  Zuerst Ende der letzten Zelle finden
326 
327 //  long nLineEnd = -1;
328     long nLineEnd = nInitScrPos - nLayoutSign;
329 
330     for (SCCOLROW i=nPos; i<nSize; i++)
331     {
332         sal_uInt16 nSizePix = GetEntrySize( i );
333         if (nSizePix)
334         {
335             nLineEnd += nSizePix * nLayoutSign;
336 
337             if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
338             {
339                 long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
340                 if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
341                     nTransStart = nLineStart;
342                 if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
343                     nTransEnd = nLineEnd;
344             }
345 
346             if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
347             {
348                 nLineEnd = nPEnd;
349                 break;
350             }
351         }
352         else
353         {
354             SCCOLROW nHidden = GetHiddenCount(i);
355             if (nHidden > 0)
356                 i += nHidden - 1;
357         }
358     }
359 
360     //  background is different for entry area and behind the entries
361 
362     Rectangle aFillRect;
363     SetLineColor();
364 
365     if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
366     {
367         if ( bHighContrast )
368         {
369             // high contrast: single-color background
370             SetFillColor( rStyleSettings.GetFaceColor() );
371             if ( bVertical )
372                 aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
373             else
374                 aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
375             DrawRect( aFillRect );
376         }
377         else
378         {
379             // normal: 3-part background
380             DrawShadedRect( nInitScrPos, nLineEnd, rStyleSettings.GetFaceColor() );
381         }
382     }
383 
384     if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
385     {
386         SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor );
387         if ( bVertical )
388             aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
389         else
390             aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
391         DrawRect( aFillRect );
392     }
393 
394     if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
395     {
396         if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
397         {
398             if ( bHighContrast )
399             {
400                 if ( bDark )
401                 {
402                     //  solid grey background for dark face color is drawn before lines
403 
404                     SetLineColor();
405                     SetFillColor( COL_LIGHTGRAY );
406                     if (bVertical)
407                         DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) );
408                     else
409                         DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) );
410                 }
411             }
412             else
413             {
414                 // background for selection
415 
416                 DrawShadedRect( nTransStart, nTransEnd, rStyleSettings.GetHighlightColor() );
417             }
418         }
419 
420 #if 0
421         // 3D border is no longer used
422         SetLineColor( rStyleSettings.GetLightColor() );
423         if (bVertical)
424             DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) );
425         else
426             DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) );
427 #endif
428 
429         SetLineColor( rStyleSettings.GetDarkShadowColor() );
430         if (bVertical)
431         {
432             long nDarkPos = bMirrored ? 0 : nBarSize-1;
433             DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) );
434         }
435         else
436             DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) );
437 
438         // line in different color for selection
439         if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast )
440         {
441             SetLineColor( aSelLineColor );
442             if (bVertical)
443             {
444                 long nDarkPos = bMirrored ? 0 : nBarSize-1;
445                 DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) );
446             }
447             else
448                 DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) );
449         }
450     }
451 
452     //
453     //  loop through entries several times to avoid changing the line color too often
454     //  and to allow merging of lines
455     //
456 
457     ScGridMerger aGrid( this, 1, 1 );
458 
459     //  start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different
460     //  borders, light border at top isn't used anymore
461     //  use SC_HDRPAINT_SEL_BOTTOM for different color
462 
463     for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++)
464     {
465         //  set line color etc. before entry loop
466         switch ( nPass )
467         {
468             case SC_HDRPAINT_SEL_BOTTOM:
469                 // same as non-selected for high contrast
470                 SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor );
471                 break;
472             case SC_HDRPAINT_BOTTOM:
473                 SetLineColor( rStyleSettings.GetDarkShadowColor() );
474                 break;
475             case SC_HDRPAINT_TEXT:
476                 // DrawSelectionBackground is used only for high contrast on light background
477                 if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
478                 {
479                     //  Transparent selection background is drawn after lines, before text.
480                     //  #109814# Use DrawSelectionBackground to make sure there is a visible
481                     //  difference. The case of a dark face color, where DrawSelectionBackground
482                     //  would just paint over the lines, is handled separately (bDark).
483                     //  Otherwise, GetHighlightColor is used with 80% transparency.
484                     //  The window's background color (SetBackground) has to be the background
485                     //  of the cell area, for the contrast comparison in DrawSelectionBackground.
486 
487                     Rectangle aTransRect;
488                     if (bVertical)
489                         aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
490                     else
491                         aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
492                     SetBackground( Color( rStyleSettings.GetFaceColor() ) );
493                     DrawSelectionBackground( aTransRect, 0, sal_True, sal_False, sal_False );
494                     SetBackground();
495                 }
496                 break;
497         }
498 
499         SCCOLROW    nCount=0;
500         long    nScrPos=nInitScrPos;
501         do
502         {
503             if (bVertical)
504                 aScrPos = Point( 0, nScrPos );
505             else
506                 aScrPos = Point( nScrPos, 0 );
507 
508             SCCOLROW    nEntryNo = nCount + nPos;
509             if ( nEntryNo >= nSize )                // MAXCOL/MAXROW
510                 nScrPos = nPEnd + nLayoutSign;      //  beyond nPEnd -> stop
511             else
512             {
513                 sal_uInt16 nSizePix = GetEntrySize( nEntryNo );
514 
515                 if (nSizePix == 0)
516                 {
517                     SCCOLROW nHidden = GetHiddenCount(nEntryNo);
518                     if (nHidden > 0)
519                         nCount += nHidden - 1;
520                 }
521                 else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
522                 {
523                     Point aEndPos(aScrPos);
524                     if (bVertical)
525                         aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
526                     else
527                         aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );
528 
529                     sal_Bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
530                     sal_Bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;
531 
532                     switch ( nPass )
533                     {
534                         case SC_HDRPAINT_SEL_BOTTOM:
535                         case SC_HDRPAINT_BOTTOM:
536                             if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) )
537                             {
538                                 if (bVertical)
539                                     aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() );
540                                 else
541                                     aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() );
542 
543                                 //  thick bottom for hidden rows
544                                 //  (drawn directly, without aGrid)
545                                 if ( nEntryNo+1 < nSize )
546                                     if ( GetEntrySize(nEntryNo+1)==0 )
547                                     {
548                                         if (bVertical)
549                                             DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
550                                                       Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
551                                         else
552                                             DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
553                                                       Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
554                                     }
555                             }
556                             break;
557 
558                         case SC_HDRPAINT_TEXT:
559                             if ( nSizePix > 1 )     // minimal check for small columns/rows
560                             {
561                                 if ( bMark != bBoldSet )
562                                 {
563                                     if (bMark)
564                                         SetFont(aBoldFont);
565                                     else
566                                         SetFont(aNormFont);
567                                     bBoldSet = bMark;
568                                 }
569                                 aString = GetEntryText( nEntryNo );
570                                 aTextSize.Width() = GetTextWidth( aString );
571                                 aTextSize.Height() = GetTextHeight();
572 
573                                 Point aTxtPos(aScrPos);
574                                 if (bVertical)
575                                 {
576                                     aTxtPos.X() += (nBarSize-aTextSize.Width())/2;
577                                     aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2;
578                                     if ( bMirrored )
579                                         aTxtPos.X() += 1;   // dark border is left instead of right
580                                 }
581                                 else
582                                 {
583                                     aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2;
584                                     aTxtPos.Y() += (nBarSize-aTextSize.Height())/2;
585                                 }
586                                 DrawText( aTxtPos, aString );
587                             }
588                             break;
589                     }
590 
591                     //  bei Selektion der ganzen Zeile/Spalte:
592                     //  InvertRect( Rectangle( aScrPos, aEndPos ) );
593                 }
594                 nScrPos += nSizePix * nLayoutSign;      // also if before the visible area
595             }
596             ++nCount;
597         }
598         while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );
599 
600         aGrid.Flush();
601     }
602 }
603 
604 //
605 //      Maus - Handling
606 //
607 
GetMousePos(const MouseEvent & rMEvt,sal_Bool & rBorder)608 SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, sal_Bool& rBorder )
609 {
610     sal_Bool    bFound=sal_False;
611     SCCOLROW    nCount = 1;
612     SCCOLROW    nPos = GetPos();
613     SCCOLROW    nHitNo = nPos;
614     long    nScrPos;
615     long    nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
616     long    nDif;
617     Size    aSize = GetOutputSizePixel();
618     long    nWinSize = bVertical ? aSize.Height() : aSize.Width();
619 
620     sal_Bool bLayoutRTL = IsLayoutRTL();
621     long nLayoutSign = bLayoutRTL ? -1 : 1;
622     long nEndPos = bLayoutRTL ? -1 : nWinSize;
623 
624     nScrPos = GetScrPos( nPos ) - nLayoutSign;
625     do
626     {
627         SCCOLROW nEntryNo = nCount + nPos;
628 
629 //      nScrPos = GetScrPos( nEntryNo ) - 1;
630 
631         if (nEntryNo > nSize)
632             nScrPos = nEndPos + nLayoutSign;
633         else
634             nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign;      //! GetHiddenCount() ??
635 
636         nDif = nMousePos - nScrPos;
637         if (nDif >= -2 && nDif <= 2 && nCount > 0)
638         {
639             bFound=sal_True;
640             nHitNo=nEntryNo-1;
641         }
642         else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
643             nHitNo = nEntryNo;
644         ++nCount;
645     }
646     while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );
647 
648     rBorder = bFound;
649     return nHitNo;
650 }
651 
IsSelectionAllowed(SCCOLROW nPos) const652 bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const
653 {
654     ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
655     if (!pViewSh)
656         return false;
657 
658     ScViewData* pViewData = pViewSh->GetViewData();
659     sal_uInt16 nTab = pViewData->GetTabNo();
660     ScDocument* pDoc = pViewData->GetDocument();
661     const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
662     bool bSelectAllowed = true;
663     if ( pProtect && pProtect->isProtected() )
664     {
665         // This sheet is protected.  Check if a context menu is allowed on this cell.
666         bool bCellsProtected = false;
667         if (bVertical)
668         {
669             // row header
670             SCROW nRPos = static_cast<SCROW>(nPos);
671             bCellsProtected = pDoc->HasAttrib(0, nRPos, nTab, MAXCOL, nRPos, nTab, HASATTR_PROTECTED);
672         }
673         else
674         {
675             // column header
676             SCCOL nCPos = static_cast<SCCOL>(nPos);
677             bCellsProtected = pDoc->HasAttrib(nCPos, 0, nTab, nCPos, MAXROW, nTab, HASATTR_PROTECTED);
678         }
679 
680         bool bSelProtected   = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
681         bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
682 
683         if (bCellsProtected)
684             bSelectAllowed = bSelProtected;
685         else
686             bSelectAllowed = bSelUnprotected;
687     }
688     return bSelectAllowed;
689 }
690 
MouseButtonDown(const MouseEvent & rMEvt)691 void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt )
692 {
693     if (IsDisabled())
694         return;
695 
696     bIgnoreMove = sal_False;
697     SelectWindow();
698 
699     sal_Bool bFound;
700     SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );
701     if (!IsSelectionAllowed(nHitNo))
702         return;
703 
704     if ( bFound && rMEvt.IsLeft() && ResizeAllowed() )
705     {
706         nDragNo = nHitNo;
707         sal_uInt16 nClicks = rMEvt.GetClicks();
708         if ( nClicks && nClicks%2==0 )
709         {
710             SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM );
711             SetPointer( Pointer( POINTER_ARROW ) );
712         }
713         else
714         {
715             if (bVertical)
716                 nDragStart = rMEvt.GetPosPixel().Y();
717             else
718                 nDragStart = rMEvt.GetPosPixel().X();
719             nDragPos = nDragStart;
720             ShowDragHelp();
721             DrawInvert( nDragPos );
722 
723             // CaptureMouse();
724             StartTracking();
725             bDragging = sal_True;
726             bDragMoved = sal_False;
727         }
728     }
729     else if (rMEvt.IsLeft())
730     {
731         pSelEngine->SetWindow( this );
732         Point aPoint;
733         Rectangle aVis( aPoint,GetOutputSizePixel() );
734         if (bVertical)
735             aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX;
736         else
737             aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX;
738         pSelEngine->SetVisibleArea( aVis );
739 
740         SetMarking( sal_True );     //  muss vor SelMouseButtonDown sein
741         pSelEngine->SelMouseButtonDown( rMEvt );
742 
743         //  #74215# In column/row headers a simple click already is a selection.
744         //  -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
745         //  if the next click is somewhere else with Control key).
746         pSelEngine->SelMouseMove( rMEvt );
747 
748         if (IsMouseCaptured())
749         {
750             //  Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
751             //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
752             ReleaseMouse();
753             StartTracking();
754         }
755     }
756 }
757 
MouseButtonUp(const MouseEvent & rMEvt)758 void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt )
759 {
760     if ( IsDisabled() )
761         return;
762 
763     SetMarking( sal_False );
764     bIgnoreMove = sal_False;
765 //    sal_Bool bFound;
766 //    SCCOLROW nHitNo = GetMousePos( rMEvt, bFound );
767 
768     if ( bDragging )
769     {
770         DrawInvert( nDragPos );
771         ReleaseMouse();
772         bDragging   = sal_False;
773 
774         long nScrPos    = GetScrPos( nDragNo );
775         long nMousePos  = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
776         sal_Bool bLayoutRTL = IsLayoutRTL();
777         long nNewWidth  = bLayoutRTL ? ( nScrPos - nMousePos + 1 )
778                                      : ( nMousePos + 2 - nScrPos );
779 
780         if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ )
781         {
782             SCCOLROW nStart = 0;
783             SCCOLROW nEnd = nDragNo;
784             while (nNewWidth < 0)
785             {
786                 nStart = nDragNo;
787                 if (nDragNo>0)
788                 {
789                     --nDragNo;
790                     nNewWidth += GetEntrySize( nDragNo );   //! GetHiddenCount() ???
791                 }
792                 else
793                     nNewWidth = 0;
794             }
795             HideEntries( nStart, nEnd );
796         }
797         else
798         {
799             if (nNewWidth<0) nNewWidth=0;
800             if (bDragMoved)
801                 SetEntrySize( nDragNo, (sal_uInt16) nNewWidth );
802         }
803     }
804     else
805     {
806         pSelEngine->SelMouseButtonUp( rMEvt );
807         ReleaseMouse();
808     }
809 }
810 
MouseMove(const MouseEvent & rMEvt)811 void ScHeaderControl::MouseMove( const MouseEvent& rMEvt )
812 {
813     if ( IsDisabled() )
814     {
815         SetPointer( Pointer( POINTER_ARROW ) );
816         return;
817     }
818 
819     sal_Bool bFound;
820     (void)GetMousePos( rMEvt, bFound );
821 
822     if ( bDragging )
823     {
824         long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
825         if ( nNewPos != nDragPos )
826         {
827             DrawInvert( nDragPos );
828             nDragPos = nNewPos;
829             ShowDragHelp();
830             DrawInvert( nDragPos );
831 
832             if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
833                 bDragMoved = sal_True;
834         }
835     }
836     else
837     {
838         if ( bFound && rMEvt.GetButtons()==0 && ResizeAllowed() )
839             SetPointer( Pointer( bVertical ? POINTER_VSIZEBAR : POINTER_HSIZEBAR ) );
840         else
841             SetPointer( Pointer( POINTER_ARROW ) );
842 
843         if (!bIgnoreMove)
844             pSelEngine->SelMouseMove( rMEvt );
845     }
846 }
847 
Tracking(const TrackingEvent & rTEvt)848 void ScHeaderControl::Tracking( const TrackingEvent& rTEvt )
849 {
850     //  Weil die SelectionEngine kein Tracking kennt, die Events nur auf
851     //  die verschiedenen MouseHandler verteilen...
852 
853     if ( rTEvt.IsTrackingCanceled() )
854         StopMarking();
855     else if ( rTEvt.IsTrackingEnded() )
856         MouseButtonUp( rTEvt.GetMouseEvent() );
857     else
858         MouseMove( rTEvt.GetMouseEvent() );
859 }
860 
Command(const CommandEvent & rCEvt)861 void ScHeaderControl::Command( const CommandEvent& rCEvt )
862 {
863     sal_uInt16 nCmd = rCEvt.GetCommand();
864     if ( nCmd == COMMAND_CONTEXTMENU )
865     {
866         StopMarking();      // Selektion / Dragging beenden
867 
868         //  Popup ausfuehren
869 
870         ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell,
871                                             SfxViewShell::Current() );
872         if ( pViewSh )
873         {
874             if ( rCEvt.IsMouseEvent() )
875             {
876                 // #i18735# select the column/row under the mouse pointer
877                 ScViewData* pViewData = pViewSh->GetViewData();
878 
879                 SelectWindow();     // also deselects drawing objects, stops draw text edit
880                 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
881                     SC_MOD()->InputEnterHandler();  // always end edit mode
882 
883                 MouseEvent aMEvt( rCEvt.GetMousePosPixel() );
884                 sal_Bool bBorder;
885                 SCCOLROW nPos = GetMousePos( aMEvt, bBorder );
886                 if (!IsSelectionAllowed(nPos))
887                     // Selecting this cell is not allowed, neither is context menu.
888                     return;
889 
890                 SCTAB nTab = pViewData->GetTabNo();
891                 ScRange aNewRange;
892                 if ( bVertical )
893                     aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
894                                          MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab );
895                 else
896                     aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
897                                          sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab );
898 
899                 // see if any part of the range is already selected
900                 sal_Bool bSelected = sal_False;
901                 ScRangeList aRanges;
902                 pViewData->GetMarkData().FillRangeListWithMarks( &aRanges, sal_False );
903                 sal_uLong nRangeCount = aRanges.Count();
904                 for (sal_uLong i=0; i<nRangeCount && !bSelected; i++)
905                     if ( aRanges.GetObject(i)->Intersects( aNewRange ) )
906                         bSelected = sal_True;
907 
908                 // select the range if no part of it was selected
909                 if ( !bSelected )
910                     pViewSh->MarkRange( aNewRange );
911             }
912 
913             ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER );
914             pViewSh->GetDispatcher()->ExecutePopup( aResId );
915         }
916     }
917     else if ( nCmd == COMMAND_STARTDRAG )
918     {
919         pSelEngine->Command( rCEvt );
920     }
921 }
922 
StopMarking()923 void ScHeaderControl::StopMarking()
924 {
925     if ( bDragging )
926     {
927         DrawInvert( nDragPos );
928         bDragging = sal_False;
929     }
930 
931     SetMarking( sal_False );
932     bIgnoreMove = sal_True;
933 
934     //  #86260# don't call pSelEngine->Reset, so selection across the parts of
935     //  a split/frozen view is possible
936 
937     ReleaseMouse();
938 }
939 
ShowDragHelp()940 void ScHeaderControl::ShowDragHelp()
941 {
942     if (Help::IsQuickHelpEnabled())
943     {
944         long nScrPos    = GetScrPos( nDragNo );
945         sal_Bool bLayoutRTL = IsLayoutRTL();
946         long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
947                                : ( nDragPos + 2 - nScrPos );
948 
949         String aHelpStr = GetDragHelp( nVal );
950         Point aPos = OutputToScreenPixel( Point(0,0) );
951         Size aSize = GetSizePixel();
952 
953         Point aMousePos = OutputToScreenPixel(GetPointerPosPixel());
954 
955         Rectangle aRect;
956         sal_uInt16 nAlign;
957         if (!bVertical)
958         {
959             //  oberhalb
960             aRect.Left() = aMousePos.X();
961             aRect.Top()  = aPos.Y() - 4;
962             nAlign       = QUICKHELP_BOTTOM|QUICKHELP_CENTER;
963         }
964         else
965         {
966             //  rechts oben
967             aRect.Left() = aPos.X() + aSize.Width() + 8;
968             aRect.Top()  = aMousePos.Y() - 2;
969             nAlign       = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
970         }
971 
972         aRect.Right()   = aRect.Left();
973         aRect.Bottom()  = aRect.Top();
974 
975         Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign);
976     }
977 }
978 
RequestHelp(const HelpEvent & rHEvt)979 void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt )
980 {
981     //  Wenn eigene QuickHelp angezeigt wird, nicht durch RequestHelp
982     //  wieder wegnehmen lassen
983 
984     sal_Bool bOwn = bDragging && Help::IsQuickHelpEnabled();
985     if (!bOwn)
986         Window::RequestHelp(rHEvt);
987 }
988 
989 // -----------------------------------------------------------------------
990 //                  Dummys fuer virtuelle Methoden
991 // -----------------------------------------------------------------------
992 
GetHiddenCount(SCCOLROW nEntryNo)993 SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo )
994 {
995     SCCOLROW nHidden = 0;
996     while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
997     {
998         ++nEntryNo;
999         ++nHidden;
1000     }
1001     return nHidden;
1002 }
1003 
IsLayoutRTL()1004 sal_Bool ScHeaderControl::IsLayoutRTL()
1005 {
1006     return sal_False;
1007 }
1008 
IsMirrored()1009 sal_Bool ScHeaderControl::IsMirrored()
1010 {
1011     return sal_False;
1012 }
1013 
IsDisabled()1014 sal_Bool ScHeaderControl::IsDisabled()
1015 {
1016     return sal_False;
1017 }
1018 
ResizeAllowed()1019 sal_Bool ScHeaderControl::ResizeAllowed()
1020 {
1021     return sal_True;
1022 }
1023 
SelectWindow()1024 void ScHeaderControl::SelectWindow()
1025 {
1026 }
1027 
DrawInvert(long)1028 void ScHeaderControl::DrawInvert( long /* nDragPos */ )
1029 {
1030 }
1031 
GetDragHelp(long)1032 String ScHeaderControl::GetDragHelp( long /* nVal */ )
1033 {
1034     return EMPTY_STRING;
1035 }
1036 
SetMarking(sal_Bool)1037 void ScHeaderControl::SetMarking( sal_Bool /* bSet */ )
1038 {
1039 }
1040 
1041 
1042 
1043