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