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