LibreOffice Module sc (master)  1
hdrcont.cxx
Go to the documentation of this file.
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/commandevent.hxx>
22 #include <vcl/help.hxx>
23 #include <vcl/settings.hxx>
24 #include <svtools/colorcfg.hxx>
25 
26 #include <tabvwsh.hxx>
27 #include <hdrcont.hxx>
28 #include <scmod.hxx>
29 #include <inputopt.hxx>
30 #include <gridmerg.hxx>
31 #include <document.hxx>
32 #include <markdata.hxx>
33 #include <tabview.hxx>
34 #include <viewdata.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 
48  SCCOLROW nNewSize, bool bNewVertical, ScTabView* pTab ) :
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  nTipVisible ( nullptr ),
61  bDragMoved ( false ),
62  bIgnoreMove ( false ),
63  bInRefMode ( false ),
64  pTabView ( pTab )
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  EnableRTL( false );
72 
73  aNormFont = GetFont();
74  aNormFont.SetTransparent( true );
77 
79  bBoldSet = true;
80 
81  Size aSize = LogicToPixel( Size(
82  GetTextWidth("8888"),
83  GetTextHeight() ) );
84  aSize.AdjustWidth(4 ); // place for highlight border
85  aSize.AdjustHeight(3 );
86  SetSizePixel( aSize );
87 
88  nWidth = nSmallWidth = aSize.Width();
89  nBigWidth = LogicToPixel( Size( GetTextWidth("8888888"), 0 ) ).Width() + 5;
90 
91  SetBackground();
92 }
93 
94 void ScHeaderControl::SetWidth( long nNew )
95 {
96  OSL_ENSURE( bVertical, "SetWidth works only on row headers" );
97  if ( nNew != nWidth )
98  {
99  Size aSize( nNew, GetSizePixel().Height() );
100  SetSizePixel( aSize );
101 
102  nWidth = nNew;
103 
104  Invalidate();
105  }
106 }
107 
109 {
110 }
111 
113 {
114  bool bLayoutRTL = IsLayoutRTL();
115  long nLayoutSign = bLayoutRTL ? -1 : 1;
116 
117  tools::Rectangle aRect( Point(0,0), GetOutputSizePixel() );
118  if ( bVertical )
119  {
120  aRect.SetTop( GetScrPos( nStart )-nLayoutSign ); // extra pixel for line at top of selection
121  aRect.SetBottom( GetScrPos( nEnd+1 )-nLayoutSign );
122  }
123  else
124  {
125  aRect.SetLeft( GetScrPos( nStart )-nLayoutSign ); // extra pixel for line left of selection
126  aRect.SetRight( GetScrPos( nEnd+1 )-nLayoutSign );
127  }
128  Invalidate(aRect);
129 }
130 
131 void ScHeaderControl::SetMark( bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd )
132 {
133  bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader();
134  if (!bEnabled)
135  bNewSet = false;
136 
137  bool bOldSet = bMarkRange;
138  SCCOLROW nOldStart = nMarkStart;
139  SCCOLROW nOldEnd = nMarkEnd;
140  PutInOrder( nNewStart, nNewEnd );
141  bMarkRange = bNewSet;
142  nMarkStart = nNewStart;
143  nMarkEnd = nNewEnd;
144 
145  // Paint
146 
147  if ( bNewSet )
148  {
149  if ( bOldSet )
150  {
151  if ( nNewStart == nOldStart )
152  {
153  if ( nNewEnd != nOldEnd )
154  DoPaint( std::min( nNewEnd, nOldEnd ) + 1, std::max( nNewEnd, nOldEnd ) );
155  }
156  else if ( nNewEnd == nOldEnd )
157  DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewStart, nOldStart ) - 1 );
158  else if ( nNewStart > nOldEnd || nNewEnd < nOldStart )
159  {
160  // two areas
161  DoPaint( nOldStart, nOldEnd );
162  DoPaint( nNewStart, nNewEnd );
163  }
164  else // somehow overlapping... (it is not often)
165  DoPaint( std::min( nNewStart, nOldStart ), std::max( nNewEnd, nOldEnd ) );
166  }
167  else
168  DoPaint( nNewStart, nNewEnd ); // completely new selection
169  }
170  else if ( bOldSet )
171  DoPaint( nOldStart, nOldEnd ); // cancel selection
172 }
173 
174 long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo ) const
175 {
176  long nScrPos;
177 
178  long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1;
179  if (nEntryNo >= nSize)
180  nScrPos = nMax;
181  else
182  {
183  nScrPos = 0;
184  for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++)
185  {
186  sal_uInt16 nAdd = GetEntrySize(i);
187  if (nAdd)
188  nScrPos += nAdd;
189  else
190  {
191  SCCOLROW nHidden = GetHiddenCount(i);
192  if (nHidden > 0)
193  i += nHidden - 1;
194  }
195  }
196  }
197 
198  if ( IsLayoutRTL() )
199  nScrPos = nMax - nScrPos - 2;
200 
201  return nScrPos;
202 }
203 
204 void ScHeaderControl::Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect )
205 {
206  // It is important for VCL to have few calls, that is why the outer lines are
207  // grouped together
208 
209  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
210  bool bHighContrast = rStyleSettings.GetHighContrastMode();
211  bool bDark = rStyleSettings.GetFaceColor().IsDark();
212  // Use the same distinction for bDark as in Window::DrawSelectionBackground
213 
214  Color aTextColor = rStyleSettings.GetButtonTextColor();
215  Color aSelTextColor = rStyleSettings.GetHighlightTextColor();
216  aNormFont.SetColor( aTextColor );
217  if ( bHighContrast )
218  aBoldFont.SetColor( aTextColor );
219  else
220  aBoldFont.SetColor( aSelTextColor );
221  SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor );
222 
223  Color aSelLineColor = rStyleSettings.GetHighlightColor();
224  aSelLineColor.Merge( COL_BLACK, 0xe0 ); // darken just a little bit
225 
226  bool bLayoutRTL = IsLayoutRTL();
227  long nLayoutSign = bLayoutRTL ? -1 : 1;
228  bool bMirrored = IsMirrored();
229 
230  OUString aString;
231  sal_uInt16 nBarSize;
232  Point aScrPos;
233  Size aTextSize;
234 
235  if (bVertical)
236  nBarSize = static_cast<sal_uInt16>(GetSizePixel().Width());
237  else
238  nBarSize = static_cast<sal_uInt16>(GetSizePixel().Height());
239 
240  SCCOLROW nPos = GetPos();
241 
242  long nPStart = bVertical ? rRect.Top() : rRect.Left();
243  long nPEnd = bVertical ? rRect.Bottom() : rRect.Right();
244 
245  long nTransStart = nPEnd + 1;
246  long nTransEnd = 0;
247 
248  long nInitScrPos = 0;
249  if ( bLayoutRTL )
250  {
251  long nTemp = nPStart; // swap nPStart / nPEnd
252  nPStart = nPEnd;
253  nPEnd = nTemp;
254  nTemp = nTransStart; // swap nTransStart / nTransEnd
255  nTransStart = nTransEnd;
256  nTransEnd = nTemp;
257  if ( bVertical ) // start loops from the end
258  nInitScrPos = GetSizePixel().Height() - 1;
259  else
260  nInitScrPos = GetSizePixel().Width() - 1;
261  }
262 
263  // complete the painting of the outer lines
264  // first find the end of the last cell
265 
266  long nLineEnd = nInitScrPos - nLayoutSign;
267 
268  for (SCCOLROW i=nPos; i<nSize; i++)
269  {
270  sal_uInt16 nSizePix = GetEntrySize( i );
271  if (nSizePix)
272  {
273  nLineEnd += nSizePix * nLayoutSign;
274 
275  if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd )
276  {
277  long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign;
278  if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign )
279  nTransStart = nLineStart;
280  if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign )
281  nTransEnd = nLineEnd;
282  }
283 
284  if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign )
285  {
286  nLineEnd = nPEnd;
287  break;
288  }
289  }
290  else
291  {
292  SCCOLROW nHidden = GetHiddenCount(i);
293  if (nHidden > 0)
294  i += nHidden - 1;
295  }
296  }
297 
298  // background is different for entry area and behind the entries
299 
300  tools::Rectangle aFillRect;
301  SetLineColor();
302 
303  if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign )
304  {
305  SetFillColor( rStyleSettings.GetFaceColor() );
306  if ( bVertical )
307  aFillRect = tools::Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd );
308  else
309  aFillRect = tools::Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 );
310  DrawRect( aFillRect );
311  }
312 
313  if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign )
314  {
315  SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor );
316  if ( bVertical )
317  aFillRect = tools::Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd );
318  else
319  aFillRect = tools::Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 );
320  DrawRect( aFillRect );
321  }
322 
323  if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign )
324  {
325  if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign )
326  {
327  if (bVertical)
328  aFillRect = tools::Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
329  else
330  aFillRect = tools::Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
331 
332  if ( bHighContrast )
333  {
334  if ( bDark )
335  {
336  // solid grey background for dark face color is drawn before lines
337  SetLineColor();
339  DrawRect( aFillRect );
340  }
341  }
342  else
343  {
344  // background for selection
345  SetLineColor();
346  SetFillColor( rStyleSettings.GetHighlightColor() );
347  DrawRect( aFillRect );
348  }
349  }
350 
351  SetLineColor( rStyleSettings.GetDarkShadowColor() );
352  if (bVertical)
353  {
354  long nDarkPos = bMirrored ? 0 : nBarSize-1;
355  DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) );
356  }
357  else
358  DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) );
359 
360  // line in different color for selection
361  if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast )
362  {
363  SetLineColor( aSelLineColor );
364  if (bVertical)
365  {
366  long nDarkPos = bMirrored ? 0 : nBarSize-1;
367  DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) );
368  }
369  else
370  DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) );
371  }
372  }
373 
374  // loop through entries several times to avoid changing the line color too often
375  // and to allow merging of lines
376 
377  ScGridMerger aGrid( this, 1, 1 );
378 
379  // start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different
380  // borders, light border at top isn't used anymore
381  // use SC_HDRPAINT_SEL_BOTTOM for different color
382 
383  for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++)
384  {
385  // set line color etc. before entry loop
386  switch ( nPass )
387  {
389  // same as non-selected for high contrast
390  SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor );
391  break;
392  case SC_HDRPAINT_BOTTOM:
393  SetLineColor( rStyleSettings.GetDarkShadowColor() );
394  break;
395  case SC_HDRPAINT_TEXT:
396  // DrawSelectionBackground is used only for high contrast on light background
397  if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark )
398  {
399  // Transparent selection background is drawn after lines, before text.
400  // Use DrawSelectionBackground to make sure there is a visible
401  // difference. The case of a dark face color, where DrawSelectionBackground
402  // would just paint over the lines, is handled separately (bDark).
403  // Otherwise, GetHighlightColor is used with 80% transparency.
404  // The window's background color (SetBackground) has to be the background
405  // of the cell area, for the contrast comparison in DrawSelectionBackground.
406 
407  tools::Rectangle aTransRect;
408  if (bVertical)
409  aTransRect = tools::Rectangle( 0, nTransStart, nBarSize-1, nTransEnd );
410  else
411  aTransRect = tools::Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 );
412  SetBackground( rStyleSettings.GetFaceColor() );
413  DrawSelectionBackground( aTransRect, 0, true, false );
414  SetBackground();
415  }
416  break;
417  }
418 
419  SCCOLROW nCount=0;
420  long nScrPos=nInitScrPos;
421  do
422  {
423  if (bVertical)
424  aScrPos = Point( 0, nScrPos );
425  else
426  aScrPos = Point( nScrPos, 0 );
427 
428  SCCOLROW nEntryNo = nCount + nPos;
429  if ( nEntryNo >= nSize ) // rDoc.MaxCol()/rDoc.MaxRow()
430  nScrPos = nPEnd + nLayoutSign; // beyond nPEnd -> stop
431  else
432  {
433  sal_uInt16 nSizePix = GetEntrySize( nEntryNo );
434 
435  if (nSizePix == 0)
436  {
437  SCCOLROW nHidden = GetHiddenCount(nEntryNo);
438  if (nHidden > 0)
439  nCount += nHidden - 1;
440  }
441  else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign)
442  {
443  Point aEndPos(aScrPos);
444  if (bVertical)
445  aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign );
446  else
447  aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 );
448 
449  bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd;
450  bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd;
451 
452  switch ( nPass )
453  {
455  case SC_HDRPAINT_BOTTOM:
456  if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) )
457  {
458  if (bVertical)
459  aGrid.AddHorLine(/* here we work in pixels */ true, aScrPos.X(), aEndPos.X(), aEndPos.Y());
460  else
461  aGrid.AddVerLine(/* here we work in pixels */ true, aEndPos.X(), aScrPos.Y(), aEndPos.Y());
462 
463  // thick bottom for hidden rows
464  // (drawn directly, without aGrid)
465  if ( nEntryNo+1 < nSize )
466  if ( GetEntrySize(nEntryNo+1)==0 )
467  {
468  if (bVertical)
469  DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign),
470  Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) );
471  else
472  DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()),
473  Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) );
474  }
475  }
476  break;
477 
478  case SC_HDRPAINT_TEXT:
479  if ( nSizePix > 1 ) // minimal check for small columns/rows
480  {
481  if ( bMark != bBoldSet )
482  {
483  if (bMark)
485  else
487  bBoldSet = bMark;
488  }
489  aString = GetEntryText( nEntryNo );
490  aTextSize.setWidth( GetTextWidth( aString ) );
491  aTextSize.setHeight( GetTextHeight() );
492 
493  Point aTxtPos(aScrPos);
494  if (bVertical)
495  {
496  aTxtPos.AdjustX((nBarSize-aTextSize.Width())/2 );
497  aTxtPos.AdjustY((nSizePix*nLayoutSign-aTextSize.Height())/2 );
498  if ( bMirrored )
499  aTxtPos.AdjustX(1 ); // dark border is left instead of right
500  }
501  else
502  {
503  aTxtPos.AdjustX((nSizePix*nLayoutSign-aTextSize.Width()+1)/2 );
504  aTxtPos.AdjustY((nBarSize-aTextSize.Height())/2 );
505  }
506  DrawText( aTxtPos, aString );
507  }
508  break;
509  }
510 
511  // when selecting the complete row/column:
512  // InvertRect( Rectangle( aScrPos, aEndPos ) );
513  }
514  nScrPos += nSizePix * nLayoutSign; // also if before the visible area
515  }
516  ++nCount;
517  }
518  while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign );
519 
520  aGrid.Flush();
521  }
522 }
523 
524 SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, bool& rBorder ) const
525 {
526  bool bFound = false;
527  SCCOLROW nPos = GetPos();
528  SCCOLROW nHitNo = nPos;
529  SCCOLROW nEntryNo = 1 + nPos;
530  long nScrPos;
531  long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
532  long nDif;
533  Size aSize = GetOutputSizePixel();
534  long nWinSize = bVertical ? aSize.Height() : aSize.Width();
535 
536  bool bLayoutRTL = IsLayoutRTL();
537  long nLayoutSign = bLayoutRTL ? -1 : 1;
538  long nEndPos = bLayoutRTL ? -1 : nWinSize;
539 
540  nScrPos = GetScrPos( nPos ) - nLayoutSign;
541  do
542  {
543  if (nEntryNo > nSize)
544  nScrPos = nEndPos + nLayoutSign;
545  else
546  nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign;
547 
548  nDif = nMousePos - nScrPos;
549  if (nDif >= -2 && nDif <= 2)
550  {
551  bFound = true;
552  nHitNo=nEntryNo-1;
553  }
554  else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize)
555  nHitNo = nEntryNo;
556  ++nEntryNo;
557  }
558  while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 );
559 
560  rBorder = bFound;
561  return nHitNo;
562 }
563 
565 {
566  ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
567  if (!pViewSh)
568  return false;
569 
570  ScViewData& rViewData = pViewSh->GetViewData();
571  sal_uInt16 nTab = rViewData.GetTabNo();
572  ScDocument& rDoc = rViewData.GetDocument();
573  const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
574  bool bSelectAllowed = true;
575  if ( pProtect && pProtect->isProtected() )
576  {
577  // This sheet is protected. Check if a context menu is allowed on this cell.
578  bool bCellsProtected = false;
579  if (bVertical)
580  {
581  // row header
582  SCROW nRPos = static_cast<SCROW>(nPos);
583  bCellsProtected = rDoc.HasAttrib(0, nRPos, nTab, rDoc.MaxCol(), nRPos, nTab, HasAttrFlags::Protected);
584  }
585  else
586  {
587  // column header
588  SCCOL nCPos = static_cast<SCCOL>(nPos);
589  bCellsProtected = rDoc.HasAttrib(nCPos, 0, nTab, nCPos, rDoc.MaxRow(), nTab, HasAttrFlags::Protected);
590  }
591 
592  bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
593  bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
594 
595  if (bCellsProtected)
596  bSelectAllowed = bSelProtected;
597  else
598  bSelectAllowed = bSelUnprotected;
599  }
600  return bSelectAllowed;
601 }
602 
604 {
605  if (IsDisabled())
606  return;
607 
608  bIgnoreMove = false;
609  SelectWindow();
610 
611  bool bIsBorder;
612  SCCOLROW nHitNo = GetMousePos( rMEvt, bIsBorder );
613  if (!IsSelectionAllowed(nHitNo))
614  return;
615  if ( ! rMEvt.IsLeft() )
616  return;
617  if ( SC_MOD()->IsFormulaMode() )
618  {
619  if( !pTabView )
620  return;
621  SCTAB nTab = pTabView->GetViewData().GetTabNo();
622  if( !rMEvt.IsShift() )
623  pTabView->DoneRefMode( rMEvt.IsMod1() );
624  ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
625  ScDocument& rDoc = pViewSh->GetViewData().GetDocument();
626  if( !bVertical )
627  {
628  pTabView->InitRefMode( nHitNo, 0, nTab, SC_REFTYPE_REF );
629  pTabView->UpdateRef( nHitNo, rDoc.MaxRow(), nTab );
630  }
631  else
632  {
633  pTabView->InitRefMode( 0, nHitNo, nTab, SC_REFTYPE_REF );
634  pTabView->UpdateRef( rDoc.MaxCol(), nHitNo, nTab );
635  }
636  bInRefMode = true;
637  return;
638  }
639  if ( bIsBorder && ResizeAllowed() )
640  {
641  nDragNo = nHitNo;
642  sal_uInt16 nClicks = rMEvt.GetClicks();
643  if ( nClicks && nClicks%2==0 )
644  {
646  SetPointer( PointerStyle::Arrow );
647  }
648  else
649  {
650  if (bVertical)
651  nDragStart = rMEvt.GetPosPixel().Y();
652  else
653  nDragStart = rMEvt.GetPosPixel().X();
655  ShowDragHelp();
656  DrawInvert( nDragPos );
657 
658  StartTracking();
659  bDragging = true;
660  bDragMoved = false;
661  }
662  }
663  else
664  {
665  pSelEngine->SetWindow( this );
667  if (bVertical)
668  {
669  aVis.SetLeft( LONG_MIN );
670  aVis.SetRight( LONG_MAX );
671  }
672  else
673  {
674  aVis.SetTop( LONG_MIN );
675  aVis.SetBottom( LONG_MAX );
676  }
677  pSelEngine->SetVisibleArea( aVis );
678 
679  SetMarking( true ); // must precede SelMouseButtonDown
680  pSelEngine->SelMouseButtonDown( rMEvt );
681 
682  // In column/row headers a simple click already is a selection.
683  // -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor
684  // if the next click is somewhere else with Control key).
685  pSelEngine->SelMouseMove( rMEvt );
686 
687  if (IsMouseCaptured())
688  {
689  // tracking instead of CaptureMouse, so it can be cancelled cleanly
691  ReleaseMouse();
692  StartTracking();
693  }
694  }
695 }
696 
698 {
699  if ( IsDisabled() )
700  return;
701 
702  if ( SC_MOD()->IsFormulaMode() )
703  {
704  SC_MOD()->EndReference();
705  bInRefMode = false;
706  return;
707  }
708 
709  SetMarking( false );
710  bIgnoreMove = false;
711 
712  if ( bDragging )
713  {
714  DrawInvert( nDragPos );
715  ReleaseMouse();
716  if (nTipVisible)
717  {
719  nTipVisible = nullptr;
720  }
721  bDragging = false;
722 
723  long nScrPos = GetScrPos( nDragNo );
724  long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
725  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 );
740  }
741  else
742  nNewWidth = 0;
743  }
744  HideEntries( nStart, nEnd );
745  }
746  else
747  {
748  if (bDragMoved)
749  SetEntrySize( nDragNo, static_cast<sal_uInt16>(nNewWidth) );
750  }
751  }
752  else
753  {
754  pSelEngine->SelMouseButtonUp( rMEvt );
755  ReleaseMouse();
756  }
757 }
758 
760 {
761  if ( IsDisabled() )
762  {
763  SetPointer( PointerStyle::Arrow );
764  return;
765  }
766 
767  if ( bInRefMode && rMEvt.IsLeft() && SC_MOD()->IsFormulaMode() )
768  {
769  if( !pTabView )
770  return;
771  bool bTmp;
772  SCCOLROW nHitNo = GetMousePos( rMEvt, bTmp );
773  SCTAB nTab = pTabView->GetViewData().GetTabNo();
774  ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
775  ScDocument& rDoc = pViewSh->GetViewData().GetDocument();
776  if( !bVertical )
777  pTabView->UpdateRef( nHitNo, rDoc.MaxRow(), nTab );
778  else
779  pTabView->UpdateRef( rDoc.MaxCol(), nHitNo, nTab );
780 
781  return;
782  }
783 
784  if ( bDragging )
785  {
786  long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X();
787  if ( nNewPos != nDragPos )
788  {
789  DrawInvert( nDragPos );
790  nDragPos = nNewPos;
791  ShowDragHelp();
792  DrawInvert( nDragPos );
793 
794  if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN)
795  bDragMoved = true;
796  }
797  }
798  else
799  {
800  bool bIsBorder;
801  (void)GetMousePos( rMEvt, bIsBorder );
802 
803  if ( bIsBorder && rMEvt.GetButtons()==0 && ResizeAllowed() )
804  SetPointer( bVertical ? PointerStyle::VSizeBar : PointerStyle::HSizeBar );
805  else
806  SetPointer( PointerStyle::Arrow );
807 
808  if (!bIgnoreMove)
809  pSelEngine->SelMouseMove( rMEvt );
810  }
811 }
812 
814 {
815  // Distribute the tracking events to the various MouseEvents, because
816  // SelectionEngine does not know anything about Tracking
817 
818  if ( rTEvt.IsTrackingCanceled() )
819  StopMarking();
820  else if ( rTEvt.IsTrackingEnded() )
821  MouseButtonUp( rTEvt.GetMouseEvent() );
822  else
823  MouseMove( rTEvt.GetMouseEvent() );
824 }
825 
827 {
828  CommandEventId nCmd = rCEvt.GetCommand();
829  if ( nCmd == CommandEventId::ContextMenu )
830  {
831  StopMarking(); // finish selection / dragging
832 
833  // execute popup menu
834 
835  ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( SfxViewShell::Current() );
836  if ( pViewSh )
837  {
838  if ( rCEvt.IsMouseEvent() )
839  {
840  // #i18735# select the column/row under the mouse pointer
841  ScViewData& rViewData = pViewSh->GetViewData();
842 
843  SelectWindow(); // also deselects drawing objects, stops draw text edit
844  if ( rViewData.HasEditView( rViewData.GetActivePart() ) )
845  SC_MOD()->InputEnterHandler(); // always end edit mode
846 
847  MouseEvent aMEvt( rCEvt.GetMousePosPixel() );
848  bool bBorder;
849  SCCOLROW nPos = GetMousePos( aMEvt, bBorder );
850  if (!IsSelectionAllowed(nPos))
851  // Selecting this cell is not allowed, neither is context menu.
852  return;
853 
854  SCTAB nTab = rViewData.GetTabNo();
855  ScDocument& rDoc = pViewSh->GetViewData().GetDocument();
856  ScRange aNewRange;
857  if ( bVertical )
858  aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab,
859  rDoc.MaxCol(), sal::static_int_cast<SCROW>(nPos), nTab );
860  else
861  aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab,
862  sal::static_int_cast<SCCOL>(nPos), rDoc.MaxRow(), nTab );
863 
864  // see if any part of the range is already selected
865  ScRangeList aRanges;
866  rViewData.GetMarkData().FillRangeListWithMarks( &aRanges, false );
867  bool bSelected = aRanges.Intersects(aNewRange);
868 
869  // select the range if no part of it was selected
870  if ( !bSelected )
871  pViewSh->MarkRange( aNewRange );
872  }
873 
874  pViewSh->GetDispatcher()->ExecutePopup( bVertical ? OUString( "rowheader" ) : OUString( "colheader" ) );
875  }
876  }
877  else if ( nCmd == CommandEventId::StartDrag )
878  {
879  pSelEngine->Command( rCEvt );
880  }
881 }
882 
884 {
885  if ( bDragging )
886  {
887  DrawInvert( nDragPos );
888  if (nTipVisible)
889  {
891  nTipVisible = nullptr;
892  }
893  bDragging = false;
894  }
895 
896  SetMarking( false );
897  bIgnoreMove = true;
898 
899  // don't call pSelEngine->Reset, so selection across the parts of
900  // a split/frozen view is possible
901  if (IsMouseCaptured())
902  ReleaseMouse();
903 }
904 
906 {
908  return;
909 
910  long nScrPos = GetScrPos( nDragNo );
911  bool bLayoutRTL = IsLayoutRTL();
912  long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 )
913  : ( nDragPos + 2 - nScrPos );
914 
915  OUString aHelpStr = GetDragHelp( nVal );
916  Point aPos = OutputToScreenPixel( Point(0,0) );
917  Size aSize = GetSizePixel();
918 
920 
921  tools::Rectangle aRect;
922  QuickHelpFlags nAlign;
923  if (!bVertical)
924  {
925  // above
926  aRect.SetLeft( aMousePos.X() );
927  aRect.SetTop( aPos.Y() - 4 );
928  nAlign = QuickHelpFlags::Bottom|QuickHelpFlags::Center;
929  }
930  else
931  {
932  // top right
933  aRect.SetLeft( aPos.X() + aSize.Width() + 8 );
934  aRect.SetTop( aMousePos.Y() - 2 );
935  nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
936  }
937 
938  aRect.SetRight( aRect.Left() );
939  aRect.SetBottom( aRect.Top() );
940 
941  if (nTipVisible)
943  nTipVisible = Help::ShowPopover(this, aRect, aHelpStr, nAlign);
944 }
945 
947 {
948  // If the own QuickHelp is displayed, don't let RequestHelp remove it
949 
950  bool bOwn = bDragging && Help::IsQuickHelpEnabled();
951  if (!bOwn)
952  Window::RequestHelp(rHEvt);
953 }
954 
955 // dummies for virtual methods
956 
958 {
959  SCCOLROW nHidden = 0;
960  while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 )
961  {
962  ++nEntryNo;
963  ++nHidden;
964  }
965  return nHidden;
966 }
967 
969 {
970  return false;
971 }
972 
974 {
975  return false;
976 }
977 
979 {
980  return false;
981 }
982 
984 {
985  return true;
986 }
987 
989 {
990 }
991 
992 void ScHeaderControl::DrawInvert( long /* nDragPos */ )
993 {
994 }
995 
996 OUString ScHeaderControl::GetDragHelp( long /* nVal */ )
997 {
998  return EMPTY_OUSTRING;
999 }
1000 
1001 void ScHeaderControl::SetMarking( bool /* bSet */ )
1002 {
1003 }
1004 
1006 {
1007  rStart = nMarkStart;
1008  rEnd = nMarkEnd;
1009 }
1010 
1011 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3027
void SetWidth(long nNew)
Definition: hdrcont.cxx:94
long Width() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
#define SC_HDRPAINT_BOTTOM
Definition: hdrcont.cxx:43
bool SelMouseButtonDown(const MouseEvent &rMEvt)
void InitRefMode(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScRefType eType)
Definition: tabview4.cxx:311
#define HDR_SIZE_OPTIMUM
Definition: hdrcont.hxx:27
Point GetPointerPosPixel()
bool bIgnoreMove
Definition: hdrcont.hxx:62
ScHeaderControl(vcl::Window *pParent, SelectionEngine *pSelectionEngine, SCCOLROW nNewSize, bool bNewVertical, ScTabView *pTab)
Definition: hdrcont.cxx:47
SCCOLROW nDragNo
Definition: hdrcont.hxx:56
#define EMPTY_OUSTRING
Definition: global.hxx:214
virtual bool IsDisabled() const
Definition: hdrcont.cxx:978
void * nTipVisible
Definition: hdrcont.hxx:59
long AdjustWidth(long n)
CommandEventId
void Merge(const Color &rMergeColor, sal_uInt8 cTransparency)
virtual bool IsMirrored() const
Definition: hdrcont.cxx:973
const Color & GetHighlightTextColor() const
long Height() const
void MarkRange(const ScRange &rRange, bool bSetCursor=true, bool bContinue=false)
Definition: tabview3.cxx:1682
sheet protection state container
void DoneRefMode(bool bContinue=false)
Definition: tabview4.cxx:161
long GetScrPos(SCCOLROW nEntryNo) const
Definition: hdrcont.cxx:174
const StyleSettings & GetStyleSettings() const
const Color & GetFaceColor() const
virtual Size GetSizePixel() const
virtual void SetSizePixel(const Size &rNewSize)
void FillRangeListWithMarks(ScRangeList *pList, bool bClear, SCTAB nForTab=-1) const
Create a range list of marks.
Definition: markdata.cxx:387
void SetWeight(FontWeight)
bool IsShift() const
bool HasEditView(ScSplitPos eWhich) const
Definition: viewdata.hxx:569
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
void SetMark(bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd)
Definition: hdrcont.cxx:131
void GetMarkRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: hdrcont.cxx:1005
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
void Command(const CommandEvent &rCEvt)
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
bool IsSelectionAllowed(SCCOLROW nPos) const
Definition: hdrcont.cxx:564
SCCOLROW nSize
Definition: hdrcont.hxx:49
long AdjustHeight(long n)
void StartTracking(StartTrackingFlags nFlags=StartTrackingFlags::NONE)
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5179
void ExecutePopup(const OUString &rResName, vcl::Window *pWin=nullptr, const Point *pPos=nullptr)
const Color & GetHighlightColor() const
WEIGHT_BOLD
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Definition: hdrcont.cxx:697
sal_uInt16 GetClicks() const
void SetBackground()
long Right() const
bool isOptionEnabled(Option eOption) const
SelectionEngine * pSelEngine
Definition: hdrcont.hxx:38
void StopMarking()
Definition: hdrcont.cxx:883
sal_uInt16 GetButtons() const
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:24
const vcl::Font & GetFont() const
bool IsMouseEvent() const
int nCount
static SfxViewShell * Current()
static void * ShowPopover(vcl::Window *pParent, const tools::Rectangle &rScreenRect, const OUString &rText, QuickHelpFlags nStyle)
bool GetHighContrastMode() const
virtual void Tracking(const TrackingEvent &rTEvt) override
Definition: hdrcont.cxx:813
virtual OUString GetDragHelp(long nVal)
Definition: hdrcont.cxx:996
void DoPaint(SCCOLROW nStart, SCCOLROW nEnd)
Definition: hdrcont.cxx:112
long Top() const
void DrawLine(const Point &rStartPt, const Point &rEndPt)
ScViewData & GetViewData()
Definition: tabview.hxx:332
void DrawRect(const tools::Rectangle &rRect)
void PutInOrder(T &nStart, T &nEnd)
Definition: address.hxx:954
const Color & GetDarkShadowColor() const
SCCOLROW nMarkEnd
Definition: hdrcont.hxx:52
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:872
void SetLineColor()
virtual bool IsLayoutRTL() const
Definition: hdrcont.cxx:968
void SetTop(long v)
virtual void RequestHelp(const HelpEvent &rHEvt) override
Definition: hdrcont.cxx:946
static void HidePopover(vcl::Window const *pParent, void *nId)
SfxDispatcher * GetDispatcher() const
virtual void SetMarking(bool bSet)
Definition: hdrcont.cxx:1001
int i
virtual SCCOLROW GetHiddenCount(SCCOLROW nEntryNo) const
Definition: hdrcont.cxx:957
void ShowDragHelp()
Definition: hdrcont.cxx:905
bool IsDark() const
void DrawSelectionBackground(const tools::Rectangle &rRect, sal_uInt16 highlight, bool bChecked, bool bDrawBorder)
sal_Int16 SCCOL
Definition: types.hxx:22
bool SelMouseMove(const MouseEvent &rMEvt)
SCCOLROW GetMousePos(const MouseEvent &rMEvt, bool &rBorder) const
Definition: hdrcont.cxx:524
#define SC_MOD()
Definition: scmod.hxx:253
static bool IsQuickHelpEnabled()
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
bool SelMouseButtonUp(const MouseEvent &rMEvt)
QuickHelpFlags
void SetRight(long v)
void SetFillColor()
CommandEventId GetCommand() const
void AddHorLine(bool bWorksInPixels, long nX1, long nX2, long nY, bool bDashed=false)
Definition: gridmerg.cxx:96
SCCOLROW nMarkStart
Definition: hdrcont.hxx:51
void SetTextColor(const Color &rColor)
long Bottom() const
virtual void Command(const CommandEvent &rCEvt) override
Definition: hdrcont.cxx:826
ScTabView * pTabView
Definition: hdrcont.hxx:74
bool IsMouseCaptured() const
const AllSettings & GetSettings() const
Size GetOutputSizePixel() const
long GetTextHeight() const
virtual SCCOLROW GetPos() const =0
virtual bool isProtected() const override
bool IsTrackingEnded() const
void SetWindow(vcl::Window *)
const long LONG_MAX
void SetColor(const Color &)
const Point & GetMousePosPixel() const
Point LogicToPixel(const Point &rLogicPt) const
#define SC_HDRPAINT_COUNT
Definition: hdrcont.cxx:45
void ReleaseMouse()
void SetVisibleArea(const tools::Rectangle &rNewArea)
vcl::Font aNormFont
Definition: hdrcont.hxx:39
#define SC_HDRPAINT_SEL_BOTTOM
Definition: hdrcont.cxx:42
void SetPointer(PointerStyle)
sal_Int32 SCROW
Definition: types.hxx:18
virtual ~ScHeaderControl() override
Definition: hdrcont.cxx:108
virtual void HideEntries(SCCOLROW nStart, SCCOLROW nEnd)=0
vcl::Font aBoldFont
Definition: hdrcont.hxx:40
const Color & GetButtonTextColor() const
void SetFont(const vcl::Font &rNewFont)
virtual void EnableRTL(bool bEnable=true) override
void SetTransparent(bool bTransparent)
virtual bool ResizeAllowed() const
Definition: hdrcont.cxx:983
virtual sal_uInt16 GetEntrySize(SCCOLROW nEntryNo) const =0
bool IsLeft() const
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: hdrcont.cxx:603
void SetBottom(long v)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
const Point & GetPosPixel() const
long Left() const
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void AddVerLine(bool bWorksInPixels, long nX, long nY1, long nY2, bool bDashed=false)
Definition: gridmerg.cxx:140
SC_DLLPUBLIC ScTableProtection * GetTabProtection(SCTAB nTab) const
Definition: documen3.cxx:1885
void SetLeft(long v)
void Flush()
Definition: gridmerg.cxx:184
bool IsTrackingCanceled() const
Point OutputToScreenPixel(const Point &rPos) const
void UpdateRef(SCCOL nCurX, SCROW nCurY, SCTAB nCurZ)
Definition: tabview4.cxx:188
#define SC_HDRPAINT_TEXT
Definition: hdrcont.cxx:44
const MouseEvent & GetMouseEvent() const
virtual void DrawInvert(long nDragPos)
Definition: hdrcont.cxx:992
#define SC_DRAG_MIN
Definition: hdrcont.cxx:36
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: hdrcont.cxx:204
void setWidth(long nWidth)
virtual void MouseMove(const MouseEvent &rMEvt) override
Definition: hdrcont.cxx:759
virtual void SetEntrySize(SCCOLROW nPos, sal_uInt16 nNewWidth)=0
long nSmallWidth
Definition: hdrcont.hxx:46
sal_uInt16 nPos
virtual OUString GetEntryText(SCCOLROW nEntryNo) const =0
sal_Int16 SCTAB
Definition: types.hxx:23
bool IsMod1() const
virtual void SelectWindow()
Definition: hdrcont.cxx:988
void setHeight(long nHeight)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo