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