Get the style color and number just once
[LibreOffice.git] / svtools / source / brwbox / brwbox2.cxx
blob0b6c622d490506d3027fc2e2fcec8073f827494e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/log.hxx>
21 #include <o3tl/safeint.hxx>
22 #include <osl/diagnose.h>
23 #include <tools/debug.hxx>
24 #include <svtools/brwbox.hxx>
25 #include <svtools/brwhead.hxx>
26 #include <svtools/colorcfg.hxx>
27 #include <svtools/scrolladaptor.hxx>
28 #include "datwin.hxx"
29 #include <vcl/commandevent.hxx>
30 #include <vcl/help.hxx>
31 #include <vcl/ptrstyle.hxx>
32 #include <vcl/settings.hxx>
34 #include <tools/multisel.hxx>
35 #include <tools/fract.hxx>
36 #include <algorithm>
37 #include <memory>
39 using namespace ::com::sun::star::datatransfer;
42 void BrowseBox::StartDrag( sal_Int8 /* _nAction */, const Point& /* _rPosPixel */ )
44 // not interested in this event
48 sal_Int8 BrowseBox::AcceptDrop( const AcceptDropEvent& _rEvt )
50 AcceptDropEvent aTransformed( _rEvt );
51 aTransformed.maPosPixel = pDataWin->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
52 return pDataWin->AcceptDrop( aTransformed );
56 sal_Int8 BrowseBox::ExecuteDrop( const ExecuteDropEvent& _rEvt )
58 ExecuteDropEvent aTransformed( _rEvt );
59 aTransformed.maPosPixel = pDataWin->ScreenToOutputPixel( OutputToScreenPixel( _rEvt.maPosPixel ) );
60 return pDataWin->ExecuteDrop( aTransformed );
64 sal_Int8 BrowseBox::AcceptDrop( const BrowserAcceptDropEvent& )
66 // not interested in this event
67 return DND_ACTION_NONE;
71 sal_Int8 BrowseBox::ExecuteDrop( const BrowserExecuteDropEvent& )
73 // not interested in this event
74 return DND_ACTION_NONE;
78 const DataFlavorExVector& BrowseBox::GetDataFlavors() const
80 if (pDataWin->bCallingDropCallback)
81 return pDataWin->GetDataFlavorExVector();
82 return GetDataFlavorExVector();
86 bool BrowseBox::IsDropFormatSupported( SotClipboardFormatId _nFormat ) const
88 if ( pDataWin->bCallingDropCallback )
89 return pDataWin->IsDropFormatSupported( _nFormat );
91 return DropTargetHelper::IsDropFormatSupported( _nFormat );
95 void BrowseBox::Command( const CommandEvent& rEvt )
97 if ( !pDataWin->bInCommand )
98 Control::Command( rEvt );
102 void BrowseBox::StateChanged( StateChangedType nStateChange )
104 Control::StateChanged( nStateChange );
106 if ( StateChangedType::Mirroring == nStateChange )
108 pDataWin->EnableRTL( IsRTLEnabled() );
110 HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
111 if ( pHeaderBar )
112 pHeaderBar->EnableRTL( IsRTLEnabled() );
113 aHScroll->EnableRTL( IsRTLEnabled() );
114 if( pVScroll )
115 pVScroll->EnableRTL( IsRTLEnabled() );
116 Resize();
118 else if ( StateChangedType::InitShow == nStateChange )
120 bBootstrapped = true; // must be set first!
122 Resize();
123 if ( bMultiSelection )
124 uRow.pSel->SetTotalRange( Range( 0, nRowCount - 1 ) );
125 if ( nRowCount == 0 )
126 nCurRow = BROWSER_ENDOFSELECTION;
127 else if ( nCurRow == BROWSER_ENDOFSELECTION )
128 nCurRow = 0;
131 if ( HasFocus() )
133 bSelectionIsVisible = true;
134 bHasFocus = true;
136 UpdateScrollbars();
137 AutoSizeLastColumn();
138 CursorMoved();
140 else if (StateChangedType::Zoom == nStateChange)
142 pDataWin->SetZoom(GetZoom());
143 HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
144 if (pHeaderBar)
145 pHeaderBar->SetZoom(GetZoom());
147 // let the columns calculate their new widths and adjust the header bar
148 for (auto & pCol : mvCols)
150 pCol->ZoomChanged(GetZoom());
151 if ( pHeaderBar )
152 pHeaderBar->SetItemSize( pCol->GetId(), pCol->Width() );
155 // all our controls have to be repositioned
156 Resize();
158 else if (StateChangedType::Enable == nStateChange)
160 // do we have a handle column?
161 bool bHandleCol = !mvCols.empty() && (0 == mvCols[ 0 ]->GetId());
162 // do we have a header bar?
163 bool bHeaderBar(pDataWin->pHeaderBar);
165 if ( nTitleLines
166 && ( !bHeaderBar
167 || bHandleCol
170 // we draw the text in our header bar in a color dependent on the enabled state. So if this state changed
171 // -> redraw
172 Invalidate(tools::Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetTitleHeight() - 1)));
177 void BrowseBox::Select()
182 void BrowseBox::DoubleClick( const BrowserMouseEvent & )
187 tools::Long BrowseBox::QueryMinimumRowHeight()
189 return CalcZoom( 5 );
193 void BrowseBox::ImplStartTracking()
198 void BrowseBox::ImplEndTracking()
203 void BrowseBox::RowHeightChanged()
208 void BrowseBox::ColumnResized( sal_uInt16 )
213 void BrowseBox::ColumnMoved( sal_uInt16 )
218 void BrowseBox::StartScroll()
220 DoHideCursor();
224 void BrowseBox::EndScroll()
226 UpdateScrollbars();
227 AutoSizeLastColumn();
228 DoShowCursor();
232 void BrowseBox::ToggleSelection()
235 // selection highlight-toggling allowed?
236 if ( bHideSelect )
237 return;
238 if ( bNotToggleSel || !IsUpdateMode() || !bSelectionIsVisible )
239 return;
241 // only highlight painted areas!
242 bNotToggleSel = true;
244 // accumulate areas of rows to highlight
245 std::vector<tools::Rectangle> aHighlightList;
246 sal_Int32 nLastRowInRect = 0; // for the CFront
248 // don't highlight handle column
249 BrowserColumn *pFirstCol = mvCols.empty() ? nullptr : mvCols[ 0 ].get();
250 tools::Long nOfsX = (!pFirstCol || pFirstCol->GetId()) ? 0 : pFirstCol->Width();
252 // accumulate old row selection
253 sal_Int32 nBottomRow = nTopRow +
254 pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight();
255 if ( nBottomRow > GetRowCount() && GetRowCount() )
256 nBottomRow = GetRowCount();
257 for ( sal_Int32 nRow = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
258 nRow != BROWSER_ENDOFSELECTION && nRow <= nBottomRow;
259 nRow = bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION )
261 if ( nRow < nTopRow )
262 continue;
264 tools::Rectangle aAddRect(
265 Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
266 Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
267 if ( !aHighlightList.empty() && nLastRowInRect == ( nRow - 1 ) )
268 aHighlightList[ 0 ].Union( aAddRect );
269 else
270 aHighlightList.emplace( aHighlightList.begin(), aAddRect );
271 nLastRowInRect = nRow;
274 // unhighlight the old selection (if any)
275 while ( !aHighlightList.empty() )
277 pDataWin->Invalidate( aHighlightList.back() );
278 aHighlightList.pop_back();
281 // unhighlight old column selection (if any)
282 for ( tools::Long nColId = pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
283 nColId != BROWSER_ENDOFSELECTION;
284 nColId = pColSel->NextSelected() )
286 tools::Rectangle aRect( GetFieldRectPixel(nCurRow,
287 mvCols[ nColId ]->GetId(),
288 false ) );
289 aRect.AdjustLeft( -(MIN_COLUMNWIDTH) );
290 aRect.AdjustRight(MIN_COLUMNWIDTH );
291 aRect.SetTop( 0 );
292 aRect.SetBottom( pDataWin->GetOutputSizePixel().Height() );
293 pDataWin->Invalidate( aRect );
296 bNotToggleSel = false;
300 void BrowseBox::DrawCursor()
302 bool bReallyHide = false;
303 if ( bHideCursor == TRISTATE_INDET )
305 if ( !GetSelectRowCount() && !GetSelectColumnCount() )
306 bReallyHide = true;
308 else if ( bHideCursor == TRISTATE_TRUE )
310 bReallyHide = true;
313 bReallyHide |= !bSelectionIsVisible || !IsUpdateMode() || bScrolling || nCurRow < 0;
315 if (PaintCursorIfHiddenOnce())
316 bReallyHide |= ( GetCursorHideCount() > 1 );
317 else
318 bReallyHide |= ( GetCursorHideCount() > 0 );
320 // no cursor on handle column
321 if ( nCurColId == HandleColumnId )
322 nCurColId = GetColumnId(1);
324 // calculate cursor rectangle
325 tools::Rectangle aCursor;
326 if ( bColumnCursor )
328 aCursor = GetFieldRectPixel( nCurRow, nCurColId, false );
329 aCursor.AdjustLeft( -(MIN_COLUMNWIDTH) );
330 aCursor.AdjustRight(1 );
331 aCursor.AdjustBottom(1 );
333 else
334 aCursor = tools::Rectangle(
335 Point( ( !mvCols.empty() && mvCols[ 0 ]->GetId() == 0 ) ?
336 mvCols[ 0 ]->Width() : 0,
337 (nCurRow - nTopRow) * GetDataRowHeight() + 1 ),
338 Size( pDataWin->GetOutputSizePixel().Width() + 1,
339 GetDataRowHeight() - 2 ) );
340 if ( bHLines )
342 if ( !bMultiSelection )
343 aCursor.AdjustTop( -1 );
344 aCursor.AdjustBottom( -1 );
347 if (m_aCursorColor == COL_TRANSPARENT)
349 // on these platforms, the StarView focus works correctly
350 if ( bReallyHide )
351 static_cast<Control*>(pDataWin.get())->HideFocus();
352 else
353 static_cast<Control*>(pDataWin.get())->ShowFocus( aCursor );
355 else
357 Color rCol = bReallyHide ? pDataWin->GetOutDev()->GetFillColor() : m_aCursorColor;
358 Color aOldFillColor = pDataWin->GetOutDev()->GetFillColor();
359 Color aOldLineColor = pDataWin->GetOutDev()->GetLineColor();
360 pDataWin->GetOutDev()->SetFillColor();
361 pDataWin->GetOutDev()->SetLineColor( rCol );
362 pDataWin->GetOutDev()->DrawRect( aCursor );
363 pDataWin->GetOutDev()->SetLineColor( aOldLineColor );
364 pDataWin->GetOutDev()->SetFillColor( aOldFillColor );
369 tools::Long BrowseBox::GetColumnWidth( sal_uInt16 nId ) const
372 sal_uInt16 nItemPos = GetColumnPos( nId );
373 if ( nItemPos >= mvCols.size() )
374 return 0;
375 return mvCols[ nItemPos ]->Width();
379 sal_uInt16 BrowseBox::GetColumnId( sal_uInt16 nPos ) const
382 if ( nPos >= mvCols.size() )
383 return BROWSER_INVALIDID;
384 return mvCols[ nPos ]->GetId();
388 sal_uInt16 BrowseBox::GetColumnPos( sal_uInt16 nId ) const
390 for ( size_t nPos = 0; nPos < mvCols.size(); ++nPos )
391 if ( mvCols[ nPos ]->GetId() == nId )
392 return nPos;
393 return BROWSER_INVALIDID;
397 bool BrowseBox::IsFrozen( sal_uInt16 nColumnId ) const
399 for (auto const & pCol : mvCols)
400 if ( pCol->GetId() == nColumnId )
401 return pCol->IsFrozen();
402 return false;
406 void BrowseBox::ExpandRowSelection( const BrowserMouseEvent& rEvt )
408 DoHideCursor();
410 // expand the last selection
411 if ( bMultiSelection )
413 Range aJustifiedRange( aSelRange );
414 aJustifiedRange.Normalize();
416 bool bSelectThis = ( bSelect != aJustifiedRange.Contains( rEvt.GetRow() ) );
418 if ( aJustifiedRange.Contains( rEvt.GetRow() ) )
420 // down and up
421 while ( rEvt.GetRow() < aSelRange.Max() )
422 { // ZTC/Mac bug - don't put these statements together!
423 SelectRow( aSelRange.Max(), bSelectThis );
424 --aSelRange.Max();
426 while ( rEvt.GetRow() > aSelRange.Max() )
427 { // ZTC/Mac bug - don't put these statements together!
428 SelectRow( aSelRange.Max(), bSelectThis );
429 ++aSelRange.Max();
432 else
434 // up and down
435 bool bOldSelecting = bSelecting;
436 bSelecting = true;
437 while ( rEvt.GetRow() < aSelRange.Max() )
438 { // ZTC/Mac bug - don't put these statements together!
439 --aSelRange.Max();
440 if ( !IsRowSelected( aSelRange.Max() ) )
442 SelectRow( aSelRange.Max(), bSelectThis );
443 bSelect = true;
446 while ( rEvt.GetRow() > aSelRange.Max() )
447 { // ZTC/Mac bug - don't put these statements together!
448 ++aSelRange.Max();
449 if ( !IsRowSelected( aSelRange.Max() ) )
451 SelectRow( aSelRange.Max(), bSelectThis );
452 bSelect = true;
455 bSelecting = bOldSelecting;
456 if ( bSelect )
457 Select();
460 else
461 if (!IsRowSelected(rEvt.GetRow()))
462 SelectRow( rEvt.GetRow() );
464 GoToRow( rEvt.GetRow(), false );
465 DoShowCursor();
469 void BrowseBox::Resize()
471 if ( !bBootstrapped && IsReallyVisible() )
472 BrowseBox::StateChanged( StateChangedType::InitShow );
473 if ( mvCols.empty() )
475 pDataWin->bResizeOnPaint = true;
476 return;
478 pDataWin->bResizeOnPaint = false;
480 // calc the size of the scrollbars
481 tools::Long nSBHeight = GetBarHeight();
482 tools::Long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
483 if (IsZoom())
485 nSBHeight = static_cast<tools::Long>(nSBHeight * static_cast<double>(GetZoom()));
486 nSBWidth = static_cast<tools::Long>(nSBWidth * static_cast<double>(GetZoom()));
489 DoHideCursor();
490 sal_uInt16 nOldVisibleRows = 0;
491 //fdo#42694, post #i111125# GetDataRowHeight() can be 0
492 if (GetDataRowHeight())
493 nOldVisibleRows = static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
495 // did we need a horizontal scroll bar or is there a Control Area?
496 if ( !pDataWin->bNoHScroll &&
497 ( ( mvCols.size() - FrozenColCount() ) > 1 ) )
498 aHScroll->Show();
499 else
500 aHScroll->Hide();
502 // calculate the size of the data window
503 tools::Long nDataHeight = GetOutputSizePixel().Height() - GetTitleHeight();
504 if ( aHScroll->IsVisible() || ( nControlAreaWidth != USHRT_MAX ) )
505 nDataHeight -= nSBHeight;
507 tools::Long nDataWidth = GetOutputSizePixel().Width();
508 if ( pVScroll->IsVisible() )
509 nDataWidth -= nSBWidth;
511 // adjust position and size of data window
512 pDataWin->SetPosSizePixel(
513 Point( 0, GetTitleHeight() ),
514 Size( nDataWidth, nDataHeight ) );
516 sal_uInt16 nVisibleRows = 0;
518 if (GetDataRowHeight())
519 nVisibleRows = static_cast<sal_uInt16>(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
521 // TopRow is unchanged, but the number of visible lines has changed.
522 if ( nVisibleRows != nOldVisibleRows )
523 VisibleRowsChanged(nTopRow, nVisibleRows);
525 UpdateScrollbars();
527 // Control-Area
528 tools::Rectangle aInvalidArea( GetControlArea() );
529 aInvalidArea.SetRight( GetOutputSizePixel().Width() );
530 aInvalidArea.SetLeft( 0 );
531 Invalidate( aInvalidArea );
533 // external header-bar
534 HeaderBar* pHeaderBar = pDataWin->pHeaderBar;
535 if ( pHeaderBar )
537 // take the handle column into account
538 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
539 tools::Long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
540 pHeaderBar->SetPosSizePixel( Point( nOfsX, 0 ), Size( GetOutputSizePixel().Width() - nOfsX, GetTitleHeight() ) );
543 AutoSizeLastColumn(); // adjust last column width
544 DoShowCursor();
548 void BrowseBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
550 // initializations
551 if (!bBootstrapped && IsReallyVisible())
552 BrowseBox::StateChanged(StateChangedType::InitShow);
553 if (mvCols.empty())
554 return;
556 BrowserColumn *pFirstCol = mvCols[ 0 ].get();
557 bool bHandleCol = pFirstCol && pFirstCol->GetId() == 0;
558 bool bHeaderBar(pDataWin->pHeaderBar);
560 // draw delimitational lines
561 if (!pDataWin->bNoHScroll)
562 rRenderContext.DrawLine(Point(0, aHScroll->GetPosPixel().Y()),
563 Point(GetOutputSizePixel().Width(),
564 aHScroll->GetPosPixel().Y()));
566 if (nTitleLines)
568 if (!bHeaderBar)
570 rRenderContext.DrawLine(Point(0, GetTitleHeight() - 1),
571 Point(GetOutputSizePixel().Width(), GetTitleHeight() - 1));
573 else if (bHandleCol)
575 rRenderContext.DrawLine(Point(0, GetTitleHeight() - 1),
576 Point(pFirstCol->Width(), GetTitleHeight() - 1));
580 // Title Bar
581 // If there is a handle column and if the header bar is available, only
582 // take the HandleColumn into account
583 if (!(nTitleLines && (!bHeaderBar || bHandleCol)))
584 return;
586 // iterate through columns to redraw
587 tools::Long nX = 0;
588 size_t nCol;
589 for (nCol = 0; nCol < mvCols.size() && nX < rRect.Right(); ++nCol)
591 // skip invisible columns between frozen and scrollable area
592 if (nCol < nFirstCol && !mvCols[nCol]->IsFrozen())
593 nCol = nFirstCol;
595 // only the handle column?
596 if (bHeaderBar && bHandleCol && nCol > 0)
597 break;
599 BrowserColumn* pCol = mvCols[nCol].get();
601 // draw the column and increment position
602 if ( pCol->Width() > 4 )
604 ButtonFrame aButtonFrame( Point( nX, 0 ),
605 Size( pCol->Width()-1, GetTitleHeight()-1 ),
606 pCol->Title(), !IsEnabled());
607 aButtonFrame.Draw(rRenderContext);
608 rRenderContext.DrawLine(Point(nX + pCol->Width() - 1, 0),
609 Point(nX + pCol->Width() - 1, GetTitleHeight() - 1));
611 else
613 rRenderContext.Push(vcl::PushFlags::FILLCOLOR);
614 rRenderContext.SetFillColor(COL_BLACK);
615 rRenderContext.DrawRect(tools::Rectangle(Point(nX, 0), Size(pCol->Width(), GetTitleHeight() - 1)));
616 rRenderContext.Pop();
619 // skip column
620 nX += pCol->Width();
623 // retouching
624 if ( !bHeaderBar && nCol == mvCols.size() )
626 const StyleSettings &rSettings = rRenderContext.GetSettings().GetStyleSettings();
627 Color aColFace(rSettings.GetFaceColor());
628 rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
629 rRenderContext.SetFillColor(aColFace);
630 rRenderContext.SetLineColor(aColFace);
631 rRenderContext.DrawRect(tools::Rectangle(Point(nX, 0),
632 Point(rRect.Right(), GetTitleHeight() - 2 )));
633 rRenderContext.Pop();
636 if (m_nActualCornerWidth)
638 const StyleSettings &rSettings = rRenderContext.GetSettings().GetStyleSettings();
639 Color aColFace(rSettings.GetFaceColor());
640 rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
641 rRenderContext.SetFillColor(aColFace);
642 rRenderContext.SetLineColor(aColFace);
643 rRenderContext.DrawRect(tools::Rectangle(Point(GetOutputSizePixel().Width() - m_nActualCornerWidth, aHScroll->GetPosPixel().Y()),
644 Size(m_nActualCornerWidth, m_nCornerHeight)));
645 rRenderContext.Pop();
649 void BrowseBox::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
651 // we need pixel coordinates
652 Size aRealSize = GetSizePixel();
653 Point aRealPos = pDev->LogicToPixel(rPos);
655 if ((aRealSize.Width() < 3) || (aRealSize.Height() < 3))
656 // we want to have two pixels frame ...
657 return;
659 vcl::Font aFont = pDataWin->GetDrawPixelFont( pDev );
660 // the 'normal' painting uses always the data window as device to output to, so we have to calc the new font
661 // relative to the data wins current settings
663 pDev->Push();
664 pDev->SetMapMode();
665 pDev->SetFont( aFont );
666 if (nFlags & SystemTextColorFlags::Mono)
667 pDev->SetTextColor(COL_BLACK);
668 else
669 pDev->SetTextColor(pDataWin->GetTextColor());
671 // draw a frame
672 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
673 pDev->SetLineColor(rStyleSettings.GetDarkShadowColor());
674 pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
675 Point(aRealPos.X(), aRealPos.Y() + aRealSize.Height() - 1));
676 pDev->DrawLine(Point(aRealPos.X(), aRealPos.Y()),
677 Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y()));
678 pDev->SetLineColor(rStyleSettings.GetShadowColor());
679 pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + 1),
680 Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1));
681 pDev->DrawLine(Point(aRealPos.X() + aRealSize.Width() - 1, aRealPos.Y() + aRealSize.Height() - 1),
682 Point(aRealPos.X() + 1, aRealPos.Y() + aRealSize.Height() - 1));
684 HeaderBar* pBar = pDataWin->pHeaderBar;
686 // we're drawing onto a foreign device, so we have to fake the DataRowHeight for the subsequent ImplPaintData
687 // (as it is based on the settings of our data window, not the foreign device)
688 if (!m_nDataRowHeight)
689 ImpGetDataRowHeight();
690 tools::Long nHeightLogic = PixelToLogic(Size(0, m_nDataRowHeight), MapMode(MapUnit::Map10thMM)).Height();
691 tools::Long nForeignHeightPixel = pDev->LogicToPixel(Size(0, nHeightLogic), MapMode(MapUnit::Map10thMM)).Height();
693 tools::Long nOriginalHeight = m_nDataRowHeight;
694 m_nDataRowHeight = nForeignHeightPixel;
696 // this counts for the column widths, too
697 size_t nPos;
698 for ( nPos = 0; nPos < mvCols.size(); ++nPos )
700 BrowserColumn* pCurrent = mvCols[ nPos ].get();
702 tools::Long nWidthLogic = PixelToLogic(Size(pCurrent->Width(), 0), MapMode(MapUnit::Map10thMM)).Width();
703 tools::Long nForeignWidthPixel = pDev->LogicToPixel(Size(nWidthLogic, 0), MapMode(MapUnit::Map10thMM)).Width();
705 pCurrent->SetWidth(nForeignWidthPixel, GetZoom());
706 if ( pBar )
707 pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
710 // a smaller area for the content
711 aRealPos.AdjustX( 1 );
712 aRealPos.AdjustY( 1 );
713 aRealSize.AdjustWidth( -2 );
714 aRealSize.AdjustHeight( -2 );
716 // let the header bar draw itself
717 if ( pBar )
719 // the title height with respect to the font set for the given device
720 tools::Long nTitleHeight = PixelToLogic(Size(0, GetTitleHeight()), MapMode(MapUnit::Map10thMM)).Height();
721 nTitleHeight = pDev->LogicToPixel(Size(0, nTitleHeight), MapMode(MapUnit::Map10thMM)).Height();
723 BrowserColumn* pFirstCol = !mvCols.empty() ? mvCols[ 0 ].get() : nullptr;
725 Point aHeaderPos(pFirstCol && (pFirstCol->GetId() == 0) ? pFirstCol->Width() : 0, 0);
726 Size aHeaderSize(aRealSize.Width() - aHeaderPos.X(), nTitleHeight);
728 aHeaderPos += aRealPos;
729 // do this before converting to logics !
731 // the header's draw expects logic coordinates, again
732 aHeaderPos = pDev->PixelToLogic(aHeaderPos);
734 Size aOrigSize(pBar->GetSizePixel());
735 pBar->SetSizePixel(aHeaderSize);
736 pBar->Draw(pDev, aHeaderPos, nFlags);
737 pBar->SetSizePixel(aOrigSize);
739 // draw the "upper left cell" (the intersection between the header bar and the handle column)
740 if (pFirstCol && (pFirstCol->GetId() == 0) && (pFirstCol->Width() > 4))
742 ButtonFrame aButtonFrame( aRealPos,
743 Size( pFirstCol->Width()-1, nTitleHeight-1 ),
744 pFirstCol->Title(), !IsEnabled());
745 aButtonFrame.Draw( *pDev );
747 pDev->Push( vcl::PushFlags::LINECOLOR );
748 pDev->SetLineColor( COL_BLACK );
750 pDev->DrawLine( Point( aRealPos.X(), aRealPos.Y() + nTitleHeight-1 ),
751 Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );
752 pDev->DrawLine( Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() ),
753 Point( aRealPos.X() + pFirstCol->Width() - 1, aRealPos.Y() + nTitleHeight-1 ) );
755 pDev->Pop();
758 aRealPos.AdjustY(aHeaderSize.Height() );
759 aRealSize.AdjustHeight( -(aHeaderSize.Height()) );
762 // draw our own content (with clipping)
763 vcl::Region aRegion(tools::Rectangle(aRealPos, aRealSize));
764 pDev->SetClipRegion( pDev->PixelToLogic( aRegion ) );
766 // do we have to paint the background
767 bool bBackground = pDataWin->IsControlBackground();
768 if ( bBackground )
770 tools::Rectangle aRect( aRealPos, aRealSize );
771 pDev->SetFillColor( pDataWin->GetControlBackground() );
772 pDev->DrawRect( aRect );
775 ImplPaintData( *pDev, tools::Rectangle( aRealPos, aRealSize ), true );
777 // restore the column widths/data row height
778 m_nDataRowHeight = nOriginalHeight;
779 for ( nPos = 0; nPos < mvCols.size(); ++nPos )
781 BrowserColumn* pCurrent = mvCols[ nPos ].get();
783 tools::Long nForeignWidthLogic = pDev->PixelToLogic(Size(pCurrent->Width(), 0), MapMode(MapUnit::Map10thMM)).Width();
784 tools::Long nWidthPixel = LogicToPixel(Size(nForeignWidthLogic, 0), MapMode(MapUnit::Map10thMM)).Width();
786 pCurrent->SetWidth(nWidthPixel, GetZoom());
787 if ( pBar )
788 pBar->SetItemSize( pCurrent->GetId(), pCurrent->Width() );
791 pDev->Pop();
794 void BrowseBox::ImplPaintData(OutputDevice& _rOut, const tools::Rectangle& _rRect, bool _bForeignDevice)
796 Point aOverallAreaPos = _bForeignDevice ? _rRect.TopLeft() : Point(0,0);
797 Size aOverallAreaSize = _bForeignDevice ? _rRect.GetSize() : pDataWin->GetOutputSizePixel();
798 Point aOverallAreaBRPos = _bForeignDevice ? _rRect.BottomRight() : Point( aOverallAreaSize.Width(), aOverallAreaSize.Height() );
800 tools::Long nDataRowHeight = GetDataRowHeight();
802 // compute relative rows to redraw
803 sal_Int32 nRelTopRow = 0;
804 sal_Int32 nRelBottomRow = aOverallAreaSize.Height();
805 if (!_bForeignDevice && nDataRowHeight)
807 nRelTopRow = static_cast<sal_Int32>((_rRect.Top()) / nDataRowHeight);
808 nRelBottomRow = static_cast<sal_Int32>((_rRect.Bottom()) / nDataRowHeight);
811 // cache frequently used values
812 Point aPos( aOverallAreaPos.X(), nRelTopRow * nDataRowHeight + aOverallAreaPos.Y() );
813 _rOut.SetLineColor( COL_WHITE );
814 const AllSettings& rAllSets = _rOut.GetSettings();
815 const StyleSettings &rSettings = rAllSets.GetStyleSettings();
816 const Color &rHighlightTextColor = rSettings.GetHighlightTextColor();
817 const Color &rHighlightFillColor = rSettings.GetHighlightColor();
818 Color aOldTextColor = _rOut.GetTextColor();
819 Color aOldFillColor = _rOut.GetFillColor();
820 Color aOldLineColor = _rOut.GetLineColor();
821 tools::Long nHLineX = 0 == mvCols[ 0 ]->GetId() ? mvCols[ 0 ]->Width() : 0;
822 nHLineX += aOverallAreaPos.X();
824 Color aDelimiterLineColor( ::svtools::ColorConfig().GetColorValue( ::svtools::CALCGRID ).nColor );
826 // redraw the invalid fields
827 for ( sal_Int32 nRelRow = nRelTopRow;
828 nRelRow <= nRelBottomRow && nTopRow+nRelRow < nRowCount;
829 ++nRelRow, aPos.AdjustY(nDataRowHeight ) )
831 // get row
832 // check valid area, to be on the safe side:
833 DBG_ASSERT( static_cast<sal_uInt16>(nTopRow+nRelRow) < nRowCount, "BrowseBox::ImplPaintData: invalid seek" );
834 if ( (nTopRow+tools::Long(nRelRow)) < 0 || static_cast<sal_uInt16>(nTopRow+nRelRow) >= nRowCount )
835 continue;
837 // prepare row
838 sal_Int32 nRow = nTopRow+nRelRow;
839 if ( !SeekRow( nRow) ) {
840 OSL_FAIL("BrowseBox::ImplPaintData: SeekRow failed");
842 _rOut.SetClipRegion();
843 aPos.setX( aOverallAreaPos.X() );
846 // #73325# don't paint the row outside the painting rectangle (DG)
847 // prepare auto-highlight
848 tools::Rectangle aRowRect( Point( _rRect.Left(), aPos.Y() ),
849 Size( _rRect.GetSize().Width(), nDataRowHeight ) );
851 bool bRowSelected = !bHideSelect
852 && IsRowSelected( nRow );
853 if ( bRowSelected )
855 _rOut.SetTextColor( rHighlightTextColor );
856 _rOut.SetFillColor( rHighlightFillColor );
857 _rOut.SetLineColor();
858 _rOut.DrawRect( aRowRect );
861 // iterate through columns to redraw
862 size_t nCol;
863 for ( nCol = 0; nCol < mvCols.size(); ++nCol )
865 // get column
866 BrowserColumn *pCol = mvCols[ nCol ].get();
868 // at end of invalid area
869 if ( aPos.X() >= _rRect.Right() )
870 break;
872 // skip invisible columns between frozen and scrollable area
873 if ( nCol < nFirstCol && !pCol->IsFrozen() )
875 nCol = nFirstCol;
876 pCol = (nCol < mvCols.size() ) ? mvCols[ nCol ].get() : nullptr;
877 if (!pCol)
878 { // FS - 21.05.99 - 66325
879 // actually this has been fixed elsewhere (in the right place),
880 // but let's make sure...
881 OSL_FAIL("BrowseBox::PaintData : nFirstCol is probably invalid !");
882 break;
886 // prepare Column-AutoHighlight
887 bool bColAutoHighlight = bColumnCursor
888 && IsColumnSelected( pCol->GetId() );
889 if ( bColAutoHighlight )
891 _rOut.SetClipRegion();
892 _rOut.SetTextColor( rHighlightTextColor );
893 _rOut.SetFillColor( rHighlightFillColor );
894 _rOut.SetLineColor();
895 tools::Rectangle aFieldRect( aPos,
896 Size( pCol->Width(), nDataRowHeight ) );
897 _rOut.DrawRect( aFieldRect );
900 if (!m_bFocusOnlyCursor && (pCol->GetId() == GetCurColumnId()) && (nRow == GetCurRow()))
901 DrawCursor();
903 // draw a single field.
904 // else something is drawn to, e.g. handle column
905 if (pCol->Width())
907 // clip the column's output to the field area
908 if (_bForeignDevice)
909 { // (not necessary if painting onto the data window)
910 Size aFieldSize(pCol->Width(), nDataRowHeight);
912 if (aPos.X() + aFieldSize.Width() > aOverallAreaBRPos.X())
913 aFieldSize.setWidth( aOverallAreaBRPos.X() - aPos.X() );
915 if (aPos.Y() + aFieldSize.Height() > aOverallAreaBRPos.Y() + 1)
917 // for non-handle cols we don't clip vertically : we just don't draw the cell if the line isn't completely visible
918 if (pCol->GetId() != 0)
919 continue;
920 aFieldSize.setHeight( aOverallAreaBRPos.Y() + 1 - aPos.Y() );
923 vcl::Region aClipToField(tools::Rectangle(aPos, aFieldSize));
924 _rOut.SetClipRegion(aClipToField);
926 pCol->Draw( *this, _rOut, aPos );
927 if (_bForeignDevice)
928 _rOut.SetClipRegion();
931 // reset Column-auto-highlight
932 if ( bColAutoHighlight )
934 _rOut.SetTextColor( aOldTextColor );
935 _rOut.SetFillColor( aOldFillColor );
936 _rOut.SetLineColor( aOldLineColor );
939 // skip column
940 aPos.AdjustX(pCol->Width() );
943 // reset auto-highlight
944 if ( bRowSelected )
946 _rOut.SetTextColor( aOldTextColor );
947 _rOut.SetFillColor( aOldFillColor );
948 _rOut.SetLineColor( aOldLineColor );
951 if ( bHLines )
953 // draw horizontal delimitation lines
954 _rOut.SetClipRegion();
955 _rOut.Push( vcl::PushFlags::LINECOLOR );
956 _rOut.SetLineColor( aDelimiterLineColor );
957 tools::Long nY = aPos.Y() + nDataRowHeight - 1;
958 if (nY <= aOverallAreaBRPos.Y())
959 _rOut.DrawLine( Point( nHLineX, nY ),
960 Point( bVLines
961 ? std::min(tools::Long(aPos.X() - 1), aOverallAreaBRPos.X())
962 : aOverallAreaBRPos.X(),
963 nY ) );
964 _rOut.Pop();
968 if (aPos.Y() > aOverallAreaBRPos.Y() + 1)
969 aPos.setY( aOverallAreaBRPos.Y() + 1 );
970 // needed for some of the following drawing
972 // retouching
973 _rOut.SetClipRegion();
974 aOldLineColor = _rOut.GetLineColor();
975 aOldFillColor = _rOut.GetFillColor();
976 _rOut.SetFillColor( rSettings.GetFaceColor() );
977 if ( !mvCols.empty() && ( mvCols[ 0 ]->GetId() == 0 ) && ( aPos.Y() <= _rRect.Bottom() ) )
979 // fill rectangle gray below handle column
980 // DG: fill it only until the end of the drawing rect and not to the end, as this may overpaint handle columns
981 _rOut.SetLineColor( COL_BLACK );
982 _rOut.DrawRect( tools::Rectangle(
983 Point( aOverallAreaPos.X() - 1, aPos.Y() - 1 ),
984 Point( aOverallAreaPos.X() + mvCols[ 0 ]->Width() - 1,
985 _rRect.Bottom() + 1) ) );
987 _rOut.SetFillColor( aOldFillColor );
989 // draw vertical delimitational line between frozen and scrollable cols
990 _rOut.SetLineColor( COL_BLACK );
991 tools::Long nFrozenWidth = GetFrozenWidth()-1;
992 _rOut.DrawLine( Point( aOverallAreaPos.X() + nFrozenWidth, aPos.Y() ),
993 Point( aOverallAreaPos.X() + nFrozenWidth, bHLines
994 ? aPos.Y() - 1
995 : aOverallAreaBRPos.Y() ) );
997 // draw vertical delimitational lines?
998 if ( bVLines )
1000 _rOut.SetLineColor( aDelimiterLineColor );
1001 Point aVertPos( aOverallAreaPos.X() - 1, aOverallAreaPos.Y() );
1002 tools::Long nDeltaY = aOverallAreaBRPos.Y();
1003 for ( size_t nCol = 0; nCol < mvCols.size(); ++nCol )
1005 // get column
1006 BrowserColumn *pCol = mvCols[ nCol ].get();
1008 // skip invisible columns between frozen and scrollable area
1009 if ( nCol < nFirstCol && !pCol->IsFrozen() )
1011 nCol = nFirstCol;
1012 pCol = mvCols[ nCol ].get();
1015 // skip column
1016 aVertPos.AdjustX(pCol->Width() );
1018 // at end of invalid area
1019 // invalid area is first reached when X > Right
1020 // and not >=
1021 if ( aVertPos.X() > _rRect.Right() )
1022 break;
1024 // draw a single line
1025 if ( pCol->GetId() != 0 )
1026 _rOut.DrawLine( aVertPos, Point( aVertPos.X(),
1027 bHLines
1028 ? aPos.Y() - 1
1029 : aPos.Y() + nDeltaY ) );
1033 _rOut.SetLineColor( aOldLineColor );
1036 void BrowseBox::PaintData( vcl::Window const & rWin, vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect )
1038 if (!bBootstrapped && IsReallyVisible())
1039 BrowseBox::StateChanged(StateChangedType::InitShow);
1041 // initializations
1042 if (mvCols.empty() || !rWin.IsUpdateMode())
1043 return;
1044 if (pDataWin->bResizeOnPaint)
1045 Resize();
1046 // MI: who was that? Window::Update();
1048 ImplPaintData(rRenderContext, rRect, false);
1051 void BrowseBox::UpdateScrollbars()
1054 if ( !bBootstrapped || !IsUpdateMode() )
1055 return;
1057 // protect against recursion
1058 if ( pDataWin->bInUpdateScrollbars )
1060 pDataWin->bHadRecursion = true;
1061 return;
1063 pDataWin->bInUpdateScrollbars = true;
1065 // the size of the corner window (and the width of the VSB/height of the HSB)
1066 m_nCornerHeight = GetBarHeight();
1067 m_nCornerWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
1068 if (IsZoom())
1070 m_nCornerHeight = static_cast<tools::Long>(m_nCornerHeight * static_cast<double>(GetZoom()));
1071 m_nCornerWidth = static_cast<tools::Long>(m_nCornerWidth * static_cast<double>(GetZoom()));
1074 bool bNeedsVScroll = false;
1075 sal_Int32 nMaxRows = 0;
1076 if (GetDataRowHeight())
1078 // needs VScroll?
1079 nMaxRows = (pDataWin->GetSizePixel().Height()) / GetDataRowHeight();
1080 bNeedsVScroll = pDataWin->bAutoVScroll
1081 ? nTopRow || ( nRowCount > nMaxRows )
1082 : !pDataWin->bNoVScroll;
1084 Size aDataWinSize = pDataWin->GetSizePixel();
1085 if ( !bNeedsVScroll )
1087 if ( pVScroll->IsVisible() )
1089 pVScroll->Hide();
1090 Size aNewSize( aDataWinSize );
1091 aNewSize.setWidth( GetOutputSizePixel().Width() );
1092 aDataWinSize = aNewSize;
1095 else if ( !pVScroll->IsVisible() )
1097 Size aNewSize( aDataWinSize );
1098 aNewSize.setWidth( GetOutputSizePixel().Width() - m_nCornerWidth );
1099 aDataWinSize = aNewSize;
1102 // needs HScroll?
1103 sal_uInt16 nLastCol = GetColumnAtXPosPixel( aDataWinSize.Width() - 1 );
1105 sal_uInt16 nFrozenCols = FrozenColCount();
1106 bool bNeedsHScroll = pDataWin->bAutoHScroll
1107 ? ( nFirstCol > nFrozenCols ) || ( nLastCol <= mvCols.size() )
1108 : !pDataWin->bNoHScroll;
1109 if ( !bNeedsHScroll )
1111 if ( aHScroll->IsVisible() )
1113 aHScroll->Hide();
1115 aDataWinSize.setHeight( GetOutputSizePixel().Height() - GetTitleHeight() );
1116 if ( nControlAreaWidth != USHRT_MAX )
1117 aDataWinSize.AdjustHeight( -sal_Int32(m_nCornerHeight) );
1119 else if ( !aHScroll->IsVisible() )
1121 Size aNewSize( aDataWinSize );
1122 aNewSize.setHeight( GetOutputSizePixel().Height() - GetTitleHeight() - m_nCornerHeight );
1123 aDataWinSize = aNewSize;
1126 // adjust position and Width of horizontal scrollbar
1127 tools::Long nHScrX = nControlAreaWidth == USHRT_MAX
1129 : nControlAreaWidth;
1131 aHScroll->SetPosSizePixel(
1132 Point( nHScrX, GetOutputSizePixel().Height() - m_nCornerHeight ),
1133 Size( aDataWinSize.Width() - nHScrX, m_nCornerHeight ) );
1135 // total scrollable columns
1136 short nScrollCols = short(mvCols.size()) - static_cast<short>(nFrozenCols);
1138 // visible columns
1139 short nVisibleHSize = nLastCol == BROWSER_INVALIDID
1140 ? static_cast<short>( mvCols.size() - nFirstCol )
1141 : static_cast<short>( nLastCol - nFirstCol );
1143 if (nVisibleHSize)
1145 short nRange = std::max( nScrollCols, short(0) );
1146 aHScroll->SetVisibleSize( nVisibleHSize );
1147 aHScroll->SetRange( Range( 0, nRange ));
1149 else
1151 // ensure scrollbar is shown as fully filled
1152 aHScroll->SetVisibleSize(1);
1153 aHScroll->SetRange(Range(0, 1));
1155 if ( bNeedsHScroll && !aHScroll->IsVisible() )
1156 aHScroll->Show();
1158 // adjust position and height of vertical scrollbar
1159 pVScroll->SetPageSize( nMaxRows );
1161 if ( nTopRow > nRowCount )
1163 nTopRow = nRowCount - 1;
1164 OSL_FAIL("BrowseBox: nTopRow > nRowCount");
1167 if ( pVScroll->GetThumbPos() != nTopRow )
1168 pVScroll->SetThumbPos( nTopRow );
1169 tools::Long nVisibleSize = std::min( std::min( nRowCount, nMaxRows ), (nRowCount-nTopRow) );
1170 pVScroll->SetVisibleSize( nVisibleSize ? nVisibleSize : 1 );
1171 pVScroll->SetRange( Range( 0, nRowCount ) );
1172 pVScroll->SetPosSizePixel(
1173 Point( aDataWinSize.Width(), GetTitleHeight() ),
1174 Size( m_nCornerWidth, aDataWinSize.Height()) );
1175 tools::Long nLclDataRowHeight = GetDataRowHeight();
1176 if ( nLclDataRowHeight > 0 && nRowCount < tools::Long( aDataWinSize.Height() / nLclDataRowHeight ) )
1177 ScrollRows( -nTopRow );
1178 if ( bNeedsVScroll && !pVScroll->IsVisible() )
1179 pVScroll->Show();
1181 pDataWin->SetPosSizePixel(
1182 Point( 0, GetTitleHeight() ),
1183 aDataWinSize );
1185 // needs corner-window?
1186 // (do that AFTER positioning BOTH scrollbars)
1187 m_nActualCornerWidth = 0;
1188 if (aHScroll->IsVisible() && pVScroll && pVScroll->IsVisible() )
1190 // if we have both scrollbars, the corner window fills the point of intersection of these two
1191 m_nActualCornerWidth = m_nCornerWidth;
1193 else if ( !aHScroll->IsVisible() && ( nControlAreaWidth != USHRT_MAX ) )
1195 // if we have no horizontal scrollbar, but a control area, we need the corner window to
1196 // fill the space between the control are and the right border
1197 m_nActualCornerWidth = GetOutputSizePixel().Width() - nControlAreaWidth;
1200 // scroll headerbar, if necessary
1201 if ( pDataWin->pHeaderBar )
1203 tools::Long nWidth = 0;
1204 for ( size_t nCol = 0;
1205 nCol < mvCols.size() && nCol < nFirstCol;
1206 ++nCol )
1208 // not the handle column
1209 if ( mvCols[ nCol ]->GetId() )
1210 nWidth += mvCols[ nCol ]->Width();
1213 pDataWin->pHeaderBar->SetOffset( nWidth );
1216 pDataWin->bInUpdateScrollbars = false;
1217 if ( pDataWin->bHadRecursion )
1219 pDataWin->bHadRecursion = false;
1220 UpdateScrollbars();
1225 void BrowseBox::SetUpdateMode( bool bUpdate )
1228 bool bWasUpdate = IsUpdateMode();
1229 if ( bWasUpdate == bUpdate )
1230 return;
1232 Control::SetUpdateMode( bUpdate );
1233 // If WB_CLIPCHILDREN is st at the BrowseBox (to minimize flicker),
1234 // the data window is not invalidated by SetUpdateMode.
1235 if( bUpdate )
1236 pDataWin->Invalidate();
1237 pDataWin->SetUpdateMode( bUpdate );
1240 if ( bUpdate )
1242 if ( bBootstrapped )
1244 UpdateScrollbars();
1245 AutoSizeLastColumn();
1247 DoShowCursor();
1249 else
1250 DoHideCursor();
1254 bool BrowseBox::GetUpdateMode() const
1257 return pDataWin->IsUpdateMode();
1261 tools::Long BrowseBox::GetFrozenWidth() const
1264 tools::Long nWidth = 0;
1265 for ( size_t nCol = 0;
1266 nCol < mvCols.size() && mvCols[ nCol ]->IsFrozen();
1267 ++nCol )
1268 nWidth += mvCols[ nCol ]->Width();
1269 return nWidth;
1272 void BrowseBox::ColumnInserted( sal_uInt16 nPos )
1274 if ( pColSel )
1275 pColSel->Insert( nPos );
1276 UpdateScrollbars();
1279 sal_uInt16 BrowseBox::FrozenColCount() const
1281 std::size_t nCol;
1282 for ( nCol = 0;
1283 nCol < mvCols.size() && mvCols[ nCol ]->IsFrozen();
1284 ++nCol )
1285 /* empty loop */;
1286 return nCol; //TODO: BrowserColumns::size_type -> sal_uInt16!
1289 IMPL_LINK(BrowseBox, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
1291 auto nCurScrollRow = nTopRow;
1292 auto nPos = rScrollbar.adjustment_get_value();
1293 ScrollRows(nPos - nCurScrollRow);
1295 bool bShowTooltip = ((m_nCurrentMode & BrowserMode::TRACKING_TIPS) == BrowserMode::TRACKING_TIPS);
1296 if (bShowTooltip &&
1297 rScrollbar.get_scroll_type() == ScrollType::Drag &&
1298 Help::IsQuickHelpEnabled())
1300 OUString aTip = OUString::number(nPos) + "/";
1301 if (!pDataWin->GetRealRowCount().isEmpty())
1302 aTip += pDataWin->GetRealRowCount();
1303 else
1304 aTip += OUString::number(rScrollbar.adjustment_get_upper());
1305 tools::Rectangle aRect(GetPointerPosPixel(), Size(GetTextWidth(aTip), GetTextHeight()));
1306 Help::ShowQuickHelp(this, aRect, aTip);
1310 IMPL_LINK(BrowseBox, HorzScrollHdl, weld::Scrollbar&, rScrollbar, void)
1312 auto nCurScrollCol = nFirstCol - FrozenColCount();
1313 ScrollColumns(rScrollbar.adjustment_get_value() - nCurScrollCol);
1316 IMPL_LINK( BrowseBox, StartDragHdl, HeaderBar*, pBar, void )
1318 pBar->SetDragSize( pDataWin->GetOutputSizePixel().Height() );
1321 // usually only the first column was resized
1322 void BrowseBox::MouseButtonDown( const MouseEvent& rEvt )
1325 GrabFocus();
1327 // only mouse events in the title-line are supported
1328 const Point &rEvtPos = rEvt.GetPosPixel();
1329 if ( rEvtPos.Y() >= GetTitleHeight() )
1330 return;
1332 tools::Long nX = 0;
1333 tools::Long nWidth = GetOutputSizePixel().Width();
1334 for ( size_t nCol = 0; nCol < mvCols.size() && nX < nWidth; ++nCol )
1336 // is this column visible?
1337 BrowserColumn *pCol = mvCols[ nCol ].get();
1338 if ( pCol->IsFrozen() || nCol >= nFirstCol )
1340 // compute right end of column
1341 tools::Long nR = nX + pCol->Width() - 1;
1343 // at the end of a column (and not handle column)?
1344 if ( pCol->GetId() && std::abs( nR - rEvtPos.X() ) < 2 )
1346 // start resizing the column
1347 bResizing = true;
1348 nResizeCol = nCol;
1349 nDragX = nResizeX = rEvtPos.X();
1350 SetPointer( PointerStyle::HSplit );
1351 CaptureMouse();
1352 pDataWin->GetOutDev()->DrawLine( Point( nDragX, 0 ),
1353 Point( nDragX, pDataWin->GetSizePixel().Height() ) );
1354 nMinResizeX = nX + MIN_COLUMNWIDTH;
1355 return;
1357 else if ( nX < rEvtPos.X() && nR > rEvtPos.X() )
1359 MouseButtonDown( BrowserMouseEvent(
1360 this, rEvt, -1, nCol, pCol->GetId(), tools::Rectangle() ) );
1361 return;
1363 nX = nR + 1;
1367 // event occurred out of data area
1368 if ( rEvt.IsRight() )
1369 pDataWin->Command(
1370 CommandEvent( Point( 1, LONG_MAX ), CommandEventId::ContextMenu, true ) );
1371 else
1372 SetNoSelection();
1376 void BrowseBox::MouseMove( const MouseEvent& rEvt )
1378 SAL_INFO("svtools", "BrowseBox::MouseMove( MouseEvent )" );
1380 PointerStyle aNewPointer = PointerStyle::Arrow;
1382 sal_uInt16 nX = 0;
1383 for ( size_t nCol = 0;
1384 nCol < mvCols.size() &&
1385 ( nX + mvCols[ nCol ]->Width() ) < GetOutputSizePixel().Width();
1386 ++nCol )
1387 // is this column visible?
1388 if ( mvCols[ nCol ]->IsFrozen() || nCol >= nFirstCol )
1390 // compute right end of column
1391 BrowserColumn *pCol = mvCols[ nCol ].get();
1392 sal_uInt16 nR = static_cast<sal_uInt16>(nX + pCol->Width() - 1);
1394 // show resize-pointer?
1395 if ( bResizing || ( pCol->GetId() &&
1396 std::abs( static_cast<tools::Long>(nR) - rEvt.GetPosPixel().X() ) < MIN_COLUMNWIDTH ) )
1398 aNewPointer = PointerStyle::HSplit;
1399 if ( bResizing )
1401 // delete old auxiliary line
1402 pDataWin->HideTracking() ;
1404 // check allowed width and new delta
1405 nDragX = std::max( rEvt.GetPosPixel().X(), nMinResizeX );
1406 tools::Long nDeltaX = nDragX - nResizeX;
1407 sal_uInt16 nId = GetColumnId(nResizeCol);
1408 tools::Long nOldWidth = GetColumnWidth(nId);
1409 nDragX = nOldWidth + nDeltaX + nResizeX - nOldWidth;
1411 // draw new auxiliary line
1412 pDataWin->ShowTracking( tools::Rectangle( Point( nDragX, 0 ),
1413 Size( 1, pDataWin->GetSizePixel().Height() ) ),
1414 ShowTrackFlags::Split|ShowTrackFlags::TrackWindow );
1419 nX = nR + 1;
1422 SetPointer( aNewPointer );
1426 void BrowseBox::MouseButtonUp( const MouseEvent & rEvt )
1429 if ( bResizing )
1431 // delete auxiliary line
1432 pDataWin->HideTracking();
1434 // width changed?
1435 nDragX = std::max( rEvt.GetPosPixel().X(), nMinResizeX );
1436 if ( (nDragX - nResizeX) != mvCols[ nResizeCol ]->Width() )
1438 // resize column
1439 tools::Long nMaxX = pDataWin->GetSizePixel().Width();
1440 nDragX = std::min( nDragX, nMaxX );
1441 tools::Long nDeltaX = nDragX - nResizeX;
1442 sal_uInt16 nId = GetColumnId(nResizeCol);
1443 SetColumnWidth( GetColumnId(nResizeCol), GetColumnWidth(nId) + nDeltaX );
1444 ColumnResized( nId );
1447 // end action
1448 SetPointer( PointerStyle::Arrow );
1449 ReleaseMouse();
1450 bResizing = false;
1452 else
1453 MouseButtonUp( BrowserMouseEvent( pDataWin,
1454 MouseEvent( Point( rEvt.GetPosPixel().X(),
1455 rEvt.GetPosPixel().Y() - pDataWin->GetPosPixel().Y() ),
1456 rEvt.GetClicks(), rEvt.GetMode(), rEvt.GetButtons(),
1457 rEvt.GetModifier() ) ) );
1461 static bool bExtendedMode = false;
1462 static bool bFieldMode = false;
1464 void BrowseBox::MouseButtonDown( const BrowserMouseEvent& rEvt )
1467 GrabFocus();
1469 // adjust selection while and after double-click
1470 if ( rEvt.GetClicks() == 2 )
1472 SetNoSelection();
1473 if ( rEvt.GetRow() >= 0 )
1475 GoToRow( rEvt.GetRow() );
1476 SelectRow( rEvt.GetRow(), true, false );
1478 else
1480 if ( bColumnCursor && rEvt.GetColumn() != 0 )
1482 if ( rEvt.GetColumn() < mvCols.size() )
1483 SelectColumnPos( rEvt.GetColumn(), true, false);
1486 DoubleClick( rEvt );
1488 // selections
1489 else if ( ( rEvt.GetMode() & ( MouseEventModifiers::SELECT | MouseEventModifiers::SIMPLECLICK ) ) &&
1490 ( bColumnCursor || rEvt.GetRow() >= 0 ) )
1492 if ( rEvt.GetClicks() == 1 )
1494 // initialise flags
1495 bHit = false;
1497 // selection out of range?
1498 if ( rEvt.GetRow() >= nRowCount ||
1499 rEvt.GetColumnId() == BROWSER_INVALIDID )
1501 SetNoSelection();
1502 return;
1505 // while selecting, no cursor
1506 bSelecting = true;
1507 DoHideCursor();
1509 // DataRow?
1510 if ( rEvt.GetRow() >= 0 )
1512 // line selection?
1513 if ( rEvt.GetColumnId() == HandleColumnId || !bColumnCursor )
1515 if ( bMultiSelection )
1517 // remove column-selection, if exists
1518 if ( pColSel && pColSel->GetSelectCount() )
1520 ToggleSelection();
1521 if ( bMultiSelection )
1522 uRow.pSel->SelectAll(false);
1523 else
1524 uRow.nSel = BROWSER_ENDOFSELECTION;
1525 if ( pColSel )
1526 pColSel->SelectAll(false);
1527 bSelect = true;
1530 // expanding mode?
1531 if ( rEvt.GetMode() & MouseEventModifiers::RANGESELECT )
1533 // select the further touched rows too
1534 bSelect = true;
1535 ExpandRowSelection( rEvt );
1536 return;
1539 // click in the selected area?
1540 else if ( IsRowSelected( rEvt.GetRow() ) )
1542 // wait for Drag&Drop
1543 bHit = true;
1544 bExtendedMode = bool( rEvt.GetMode() & MouseEventModifiers::MULTISELECT );
1545 return;
1548 // extension mode?
1549 else if ( rEvt.GetMode() & MouseEventModifiers::MULTISELECT )
1551 // determine the new selection range
1552 // and selection/deselection
1553 aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1554 SelectRow( rEvt.GetRow(),
1555 !uRow.pSel->IsSelected( rEvt.GetRow() ) );
1556 bSelect = true;
1557 return;
1561 // select directly
1562 SetNoSelection();
1563 GoToRow( rEvt.GetRow() );
1564 SelectRow( rEvt.GetRow() );
1565 aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1566 bSelect = true;
1568 else // Column/Field-Selection
1570 // click in selected column
1571 if ( IsColumnSelected( rEvt.GetColumn() ) ||
1572 IsRowSelected( rEvt.GetRow() ) )
1574 bHit = true;
1575 bFieldMode = true;
1576 return;
1579 SetNoSelection();
1580 GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
1581 bSelect = true;
1584 else
1586 if ( bMultiSelection && rEvt.GetColumnId() == HandleColumnId )
1588 // toggle all-selection
1589 if ( uRow.pSel->GetSelectCount() > ( GetRowCount() / 2 ) )
1590 SetNoSelection();
1591 else
1592 SelectAll();
1594 else
1595 SelectColumnPos( GetColumnPos(rEvt.GetColumnId()), true, false);
1598 // turn cursor on again, if necessary
1599 bSelecting = false;
1600 DoShowCursor();
1601 if ( bSelect )
1602 Select();
1608 void BrowseBox::MouseButtonUp( const BrowserMouseEvent &rEvt )
1611 // D&D was possible, but did not occur
1612 if ( bHit )
1614 aSelRange = Range( rEvt.GetRow(), rEvt.GetRow() );
1615 if ( bExtendedMode )
1616 SelectRow( rEvt.GetRow(), false );
1617 else
1619 SetNoSelection();
1620 if ( bFieldMode )
1621 GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
1622 else
1624 GoToRow( rEvt.GetRow() );
1625 SelectRow( rEvt.GetRow() );
1628 bSelect = true;
1629 bExtendedMode = false;
1630 bFieldMode = false;
1631 bHit = false;
1634 // activate cursor
1635 if ( bSelecting )
1637 bSelecting = false;
1638 DoShowCursor();
1639 if ( bSelect )
1640 Select();
1645 void BrowseBox::KeyInput( const KeyEvent& rEvt )
1647 if ( !ProcessKey( rEvt ) )
1648 Control::KeyInput( rEvt );
1652 bool BrowseBox::ProcessKey( const KeyEvent& rEvt )
1655 sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
1656 bool bShift = rEvt.GetKeyCode().IsShift();
1657 bool bCtrl = rEvt.GetKeyCode().IsMod1();
1658 bool bAlt = rEvt.GetKeyCode().IsMod2();
1660 sal_uInt16 nId = BROWSER_NONE;
1662 if ( !bAlt && !bCtrl && !bShift )
1664 switch ( nCode )
1666 case KEY_DOWN: nId = BROWSER_CURSORDOWN; break;
1667 case KEY_UP: nId = BROWSER_CURSORUP; break;
1668 case KEY_HOME: nId = BROWSER_CURSORHOME; break;
1669 case KEY_END: nId = BROWSER_CURSOREND; break;
1670 case KEY_TAB:
1671 if ( !bColumnCursor )
1672 break;
1673 [[fallthrough]];
1674 case KEY_RIGHT: nId = BROWSER_CURSORRIGHT; break;
1675 case KEY_LEFT: nId = BROWSER_CURSORLEFT; break;
1676 case KEY_SPACE: nId = BROWSER_SELECT; break;
1678 if ( BROWSER_NONE != nId )
1679 SetNoSelection();
1681 switch ( nCode )
1683 case KEY_PAGEDOWN: nId = BROWSER_CURSORPAGEDOWN; break;
1684 case KEY_PAGEUP: nId = BROWSER_CURSORPAGEUP; break;
1688 if ( !bAlt && !bCtrl && bShift )
1689 switch ( nCode )
1691 case KEY_DOWN: nId = BROWSER_SELECTDOWN; break;
1692 case KEY_UP: nId = BROWSER_SELECTUP; break;
1693 case KEY_TAB:
1694 if ( !bColumnCursor )
1695 break;
1696 nId = BROWSER_CURSORLEFT; break;
1697 case KEY_HOME: nId = BROWSER_SELECTHOME; break;
1698 case KEY_END: nId = BROWSER_SELECTEND; break;
1702 if ( !bAlt && bCtrl && !bShift )
1703 switch ( nCode )
1705 case KEY_DOWN: nId = BROWSER_CURSORDOWN; break;
1706 case KEY_UP: nId = BROWSER_CURSORUP; break;
1707 case KEY_PAGEDOWN: nId = BROWSER_CURSORENDOFFILE; break;
1708 case KEY_PAGEUP: nId = BROWSER_CURSORTOPOFFILE; break;
1709 case KEY_HOME: nId = BROWSER_CURSORTOPOFSCREEN; break;
1710 case KEY_END: nId = BROWSER_CURSORENDOFSCREEN; break;
1711 case KEY_SPACE: nId = BROWSER_ENHANCESELECTION; break;
1712 case KEY_LEFT: nId = BROWSER_MOVECOLUMNLEFT; break;
1713 case KEY_RIGHT: nId = BROWSER_MOVECOLUMNRIGHT; break;
1716 if ( nId != BROWSER_NONE )
1717 Dispatch( nId );
1718 return nId != BROWSER_NONE;
1721 void BrowseBox::ChildFocusIn()
1725 void BrowseBox::ChildFocusOut()
1729 void BrowseBox::Dispatch( sal_uInt16 nId )
1732 tools::Long nRowsOnPage = pDataWin->GetSizePixel().Height() / GetDataRowHeight();
1734 switch ( nId )
1736 case BROWSER_SELECTCOLUMN:
1737 if ( ColCount() )
1738 SelectColumnId( GetCurColumnId() );
1739 break;
1741 case BROWSER_CURSORDOWN:
1742 if ( ( GetCurRow() + 1 ) < nRowCount )
1743 GoToRow( GetCurRow() + 1, false );
1744 break;
1745 case BROWSER_CURSORUP:
1746 if ( GetCurRow() > 0 )
1747 GoToRow( GetCurRow() - 1, false );
1748 break;
1749 case BROWSER_SELECTHOME:
1750 if ( GetRowCount() )
1752 DoHideCursor();
1753 for ( sal_Int32 nRow = GetCurRow(); nRow >= 0; --nRow )
1754 SelectRow( nRow );
1755 GoToRow( 0, true );
1756 DoShowCursor();
1758 break;
1759 case BROWSER_SELECTEND:
1760 if ( GetRowCount() )
1762 DoHideCursor();
1763 sal_Int32 nRows = GetRowCount();
1764 for ( sal_Int32 nRow = GetCurRow(); nRow < nRows; ++nRow )
1765 SelectRow( nRow );
1766 GoToRow( GetRowCount() - 1, true );
1767 DoShowCursor();
1769 break;
1770 case BROWSER_SELECTDOWN:
1772 if ( GetRowCount() && ( GetCurRow() + 1 ) < nRowCount )
1774 // deselect the current row, if it isn't the first
1775 // and there is no other selected row above
1776 sal_Int32 nRow = GetCurRow();
1777 bool bLocalSelect = ( !IsRowSelected( nRow ) ||
1778 GetSelectRowCount() == 1 || IsRowSelected( nRow - 1 ) );
1779 SelectRow( nRow, bLocalSelect );
1780 bool bDone = GoToRow( GetCurRow() + 1, false );
1781 if ( bDone )
1782 SelectRow( GetCurRow() );
1784 else
1785 ScrollRows( 1 );
1786 break;
1788 case BROWSER_SELECTUP:
1789 if ( GetRowCount() )
1791 // deselect the current row, if it isn't the first
1792 // and there is no other selected row under
1793 sal_Int32 nRow = GetCurRow();
1794 bool bLocalSelect = ( !IsRowSelected( nRow ) ||
1795 GetSelectRowCount() == 1 || IsRowSelected( nRow + 1 ) );
1796 SelectRow( nCurRow, bLocalSelect );
1797 bool bDone = GoToRow( nRow - 1, false );
1798 if ( bDone )
1799 SelectRow( GetCurRow() );
1801 break;
1802 case BROWSER_CURSORPAGEDOWN:
1803 ScrollRows( nRowsOnPage );
1804 break;
1805 case BROWSER_CURSORPAGEUP:
1806 ScrollRows( -nRowsOnPage );
1807 break;
1808 case BROWSER_CURSOREND:
1809 if ( bColumnCursor )
1811 sal_uInt16 nNewId = GetColumnId(ColCount() -1);
1812 nNewId != HandleColumnId && GoToColumnId( nNewId );
1813 break;
1815 [[fallthrough]];
1816 case BROWSER_CURSORENDOFFILE:
1817 GoToRow( nRowCount - 1, false );
1818 break;
1819 case BROWSER_CURSORRIGHT:
1820 if ( bColumnCursor )
1822 sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) + 1;
1823 sal_uInt16 nNewId = GetColumnId( nNewPos );
1824 if (nNewId != BROWSER_INVALIDID) // At end of row ?
1825 GoToColumnId( nNewId );
1826 else
1828 sal_uInt16 nColId = GetColumnId(0);
1829 if ( nColId == BROWSER_INVALIDID || nColId == HandleColumnId )
1830 nColId = GetColumnId(1);
1831 if ( GetRowCount() )
1833 if ( nCurRow < GetRowCount() - 1 )
1835 GoToRowColumnId( nCurRow + 1, nColId );
1838 else if ( ColCount() )
1839 GoToColumnId( nColId );
1842 else
1843 ScrollColumns( 1 );
1844 break;
1845 case BROWSER_CURSORHOME:
1846 if ( bColumnCursor )
1848 sal_uInt16 nNewId = GetColumnId(1);
1849 if (nNewId != HandleColumnId)
1851 GoToColumnId( nNewId );
1853 break;
1855 [[fallthrough]];
1856 case BROWSER_CURSORTOPOFFILE:
1857 GoToRow( 0, false );
1858 break;
1859 case BROWSER_CURSORLEFT:
1860 if ( bColumnCursor )
1862 sal_uInt16 nNewPos = GetColumnPos( GetCurColumnId() ) - 1;
1863 sal_uInt16 nNewId = GetColumnId( nNewPos );
1864 if (nNewId != HandleColumnId)
1865 GoToColumnId( nNewId );
1866 else
1868 if ( GetRowCount() )
1870 if (nCurRow > 0)
1872 GoToRowColumnId(nCurRow - 1, GetColumnId(ColCount() -1));
1875 else if ( ColCount() )
1876 GoToColumnId( GetColumnId(ColCount() -1) );
1879 else
1880 ScrollColumns( -1 );
1881 break;
1882 case BROWSER_ENHANCESELECTION:
1883 if ( GetRowCount() )
1884 SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ) );
1885 break;
1886 case BROWSER_SELECT:
1887 if ( GetRowCount() )
1888 SelectRow( GetCurRow(), !IsRowSelected( GetCurRow() ), false );
1889 break;
1890 case BROWSER_MOVECOLUMNLEFT:
1891 case BROWSER_MOVECOLUMNRIGHT:
1892 { // check if column moving is allowed
1893 BrowserHeader* pHeaderBar = pDataWin->pHeaderBar;
1894 if ( pHeaderBar && pHeaderBar->IsDragable() )
1896 sal_uInt16 nColId = GetCurColumnId();
1897 bool bColumnSelected = IsColumnSelected(nColId);
1898 sal_uInt16 nNewPos = GetColumnPos(nColId);
1899 bool bMoveAllowed = false;
1900 if ( BROWSER_MOVECOLUMNLEFT == nId && nNewPos > 1 )
1902 --nNewPos;
1903 bMoveAllowed = true;
1905 else if ( BROWSER_MOVECOLUMNRIGHT == nId && nNewPos < (ColCount()-1) )
1907 ++nNewPos;
1908 bMoveAllowed = true;
1911 if ( bMoveAllowed )
1913 SetColumnPos( nColId, nNewPos );
1914 ColumnMoved( nColId );
1915 MakeFieldVisible(GetCurRow(), nColId);
1916 if ( bColumnSelected )
1917 SelectColumnId(nColId);
1921 break;
1926 void BrowseBox::SetCursorColor(const Color& _rCol)
1928 if (_rCol == m_aCursorColor)
1929 return;
1931 // ensure the cursor is hidden
1932 DoHideCursor();
1933 if (!m_bFocusOnlyCursor)
1934 DoHideCursor();
1936 m_aCursorColor = _rCol;
1938 if (!m_bFocusOnlyCursor)
1939 DoShowCursor();
1940 DoShowCursor();
1943 tools::Rectangle BrowseBox::calcHeaderRect(bool _bIsColumnBar, bool _bOnScreen)
1945 vcl::Window* pParent = nullptr;
1946 if ( !_bOnScreen )
1947 pParent = GetAccessibleParentWindow();
1949 Point aTopLeft;
1950 tools::Long nWidth;
1951 tools::Long nHeight;
1952 if ( _bIsColumnBar )
1954 nWidth = pDataWin->GetOutputSizePixel().Width();
1955 nHeight = GetDataRowHeight();
1957 else
1959 aTopLeft.setY( GetDataRowHeight() );
1960 nWidth = GetColumnWidth(0);
1961 if (pParent)
1962 nHeight = GetWindowExtentsRelative( *pParent ).GetHeight() - aTopLeft.Y() - GetControlArea().GetSize().Height();
1963 else
1964 nHeight = GetWindowExtentsAbsolute().GetHeight() - aTopLeft.Y() - GetControlArea().GetSize().Height();
1966 if (pParent)
1967 aTopLeft += GetWindowExtentsRelative( *pParent ).TopLeft();
1968 else
1969 aTopLeft += Point(GetWindowExtentsAbsolute().TopLeft());
1970 return tools::Rectangle(aTopLeft,Size(nWidth,nHeight));
1973 tools::Rectangle BrowseBox::calcTableRect(bool _bOnScreen)
1975 vcl::Window* pParent = nullptr;
1976 if ( !_bOnScreen )
1977 pParent = GetAccessibleParentWindow();
1979 tools::Rectangle aRect;
1980 if (pParent)
1981 aRect = GetWindowExtentsRelative( *pParent );
1982 else
1983 aRect = tools::Rectangle(GetWindowExtentsAbsolute());
1984 tools::Rectangle aRowBar = calcHeaderRect(false, pParent == nullptr);
1986 tools::Long nX = aRowBar.Right() - aRect.Left();
1987 tools::Long nY = aRowBar.Top() - aRect.Top();
1988 Size aSize(aRect.GetSize());
1990 return tools::Rectangle(aRowBar.TopRight(), Size(aSize.Width() - nX, aSize.Height() - nY - GetBarHeight()) );
1993 tools::Rectangle BrowseBox::GetFieldRectPixel( sal_Int32 _nRowId, sal_uInt16 _nColId, bool /*_bIsHeader*/, bool _bOnScreen )
1995 vcl::Window* pParent = nullptr;
1996 if ( !_bOnScreen )
1997 pParent = GetAccessibleParentWindow();
1999 tools::Rectangle aRect = GetFieldRectPixel(_nRowId,_nColId,_bOnScreen);
2001 Point aTopLeft = aRect.TopLeft();
2002 if (pParent)
2003 aTopLeft += GetWindowExtentsRelative( *pParent ).TopLeft();
2004 else
2005 aTopLeft += Point(GetWindowExtentsAbsolute().TopLeft());
2007 return tools::Rectangle(aTopLeft,aRect.GetSize());
2010 // ------------------------------------------------------------------------- EOF
2012 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */