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